Skip to content
Snippets Groups Projects
Commit fca5cf90 authored by dg's avatar dg
Browse files

profiler availble at all times by CTRL+SHIFT+ALT+P

Class interface changed from dynamic lookup to cached.
THis means interfaces which load data and define class properties/methods
MUST BE require'd before the class implementing them

This is quite the speedup


git-svn-id: http://svn.net-core.org/repos/t-engine4@88 51575b47-30f0-44d4-a5cc-537603b46e54
parent ca5c4d6e
No related branches found
No related tags found
No related merge requests found
Showing
with 138 additions and 106 deletions
......@@ -30,16 +30,20 @@ function _M:move(map, x, y, force)
if y < 0 then y = 0 end
if y >= map.h then y = map.h - 1 end
self.x, self.y = x, y
-- if self.levelid then
-- game.level.c_level:moveActor(self.levelid, x, y)
-- end
map(x, y, Map.ACTOR, self)
game.level:idleProcessActor(self)
return true
end
function _M:canMove(x, y, terrain_only)
if terrain_only then
return game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move")
return not game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move")
else
return game.level.map:checkAllEntities(x, y, "block_move")
return not game.level.map:checkAllEntities(x, y, "block_move")
end
end
......
......@@ -34,5 +34,11 @@ function _M:tick()
end
end
end
-- Run the level distancer
if self.level.distancer_co then
local ok, err = coroutine.resume(self.level.distancer_co)
if not ok and err then error(err) end
end
end
end
......@@ -19,12 +19,6 @@ function _M:tick()
if self.paused then
-- If we are paused do not get energy, but still process frames if needed
engine.Game.tick(self)
-- Run the level distancer
if self.level and self.level.distancer_co then
local ok, err = coroutine.resume(self.level.distancer_co)
if not ok and err then error(err) end
end
else
while not self.paused do
engine.GameEnergyBased.tick(self)
......
......@@ -11,6 +11,18 @@ function _M:init()
-- Fullscreen toggle
self:addCommand(self._RETURN, {"alt"}, function() core.display.fullscreen() end)
-- Profiler
self:addCommand(self._p, {"ctrl","alt","shift"}, function()
if not _G.profiling then
print("Starting profiler")
_G.profiling = true
profiler.start("profiler.log")
else
profiler.stop()
print("Stopped profiler")
end
end)
end
function _M:receiveKey(sym, ctrl, shift, alt, meta, unicode)
......
require "engine.class"
local Map = require "engine.Map"
--- Define a level
module(..., package.seeall, class.make)
......@@ -7,10 +8,12 @@ module(..., package.seeall, class.make)
function _M:init(level, map)
self.level = level
self.map = map
-- self.c_level = core.map.newLevel(500)
self.e_array = {}
self.entities = {}
-- This stores the distance for each actors to each other actors
-- this is computed by either the "distancer" coroutine or manualy when needed if not available
self.e_toprocess = {}
self.e_distances = {}
self.distancer_co = self:createDistancer()
......@@ -21,6 +24,7 @@ end
function _M:addEntity(e)
if self.entities[e.uid] then error("Entity "..e.uid.." already present on the level") end
self.entities[e.uid] = e
-- e.levelid = self.c_level:addActor(e.uid, e.x, e.y)
table.insert(self.e_array, e)
end
......@@ -34,6 +38,7 @@ function _M:removeEntity(e)
break
end
end
-- self.c_level:removeActor(e.levelid)
-- Tells it to delete itself if needed
if e.deleteFromMap then e:deleteFromMap(self.map) end
end
......@@ -50,6 +55,7 @@ function _M:save()
distancer_co = true,
-- dont save the distances table either it will be recomputed on the fly
e_distances = true,
c_level = true,
})
end
function _M:loaded()
......@@ -58,9 +64,11 @@ function _M:loaded()
local nes = {}
for uid, e in pairs(self.entities) do
nes[e.uid] = e
-- self.c_level:addActor(e.uid, e.x, e.y)
end
self.entities = nes
self.e_distances = {}
self.distancer_co = self:createDistancer()
end
......@@ -74,15 +82,13 @@ function _M:createDistancer()
local co = coroutine.create(function()
-- Infinite coroutine
while true do
local arr = self.e_array
for i = 1, #arr do
local e = arr[i]
if e then
self:computeDistances(e)
-- print("distancer ran for", i, e.uid)
coroutine.yield()
end
local e = table.remove(self.e_toprocess)
if e then
-- print("distancer for", e.uid)
self:computeDistances(e)
-- print("distancer ran for", i, e.uid)
end
coroutine.yield()
end
end)
return co
......@@ -92,15 +98,29 @@ local dist_sort = function(a, b) return a.dist < b.dist end
--- Compute distances to all other actors
function _M:computeDistances(e)
local arr = self.e_array
self.e_distances[e.uid] = {}
for j = 1, #arr do
local dst = arr[j]
if dst ~= e then
table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
for i = e.x - e.sight, e.x + e.sight do
for j = e.y - e.sight, e.y + e.sight do
local dst = self.map(i, j, Map.ACTOR)
if dst and dst ~= e then
-- check los
local l = line.new(e.x, e.y, dst.x, dst.y)
local lx, ly = l()
while lx and ly do
if self.map:checkEntity(lx, ly, Map.TERRAIN, "block_sight") then break end
lx, ly = l()
end
-- At the end ?
if not lx then
table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
-- if e.uid ~= 9 then print("found LOS", e.uid, dst.uid) end
end
end
end
end
table.sort(self.e_distances[e.uid], dist_sort)
-- if e.uid ~= 9 then print("processed", e.uid) end
end
--- Get distances to all other actors
......@@ -109,3 +129,10 @@ function _M:getDistances(e)
-- if not self.e_distances[e.uid] then self:computeDistances(e) end
return self.e_distances[e.uid]
end
--- Insert an actor to process
function _M:idleProcessActor(act)
-- print("to process", act.uid)
table.insert(self.e_toprocess, 1, act)
-- print("add distancer for", act.uid)
end
......@@ -3,7 +3,7 @@
newAI("move_simple", function(self)
if self.ai_target.actor then
local act = __uids[self.ai_target.actor]
local act = self.ai_target.actor
local l = line.new(self.x, self.y, act.x, act.y)
local lx, ly = l()
if lx and ly then
......@@ -19,30 +19,32 @@ newAI("move_simple", function(self)
end)
newAI("target_simple", function(self)
-- Find new target every 10 +0speed turns or when no target exist
if self.got_target then return end
if self.ai_target.actor and not self.ai_target.actor.dead and rng.percent(90) then return end
-- Find closer ennemy and target it
self.ai_target.actor = nil
-- Get list of actors ordered by distance
local arr = game.level:getDistances(self)
local act
if not arr or #arr == 0 then print("target abording, waiting on distancer") return end
if not arr or #arr == 0 then
-- No target? Ask the distancer to find one
game.level:idleProcessActor(self)
return
end
for i = 1, #arr do
act = __uids[arr[i].uid]
-- find the closest ennemy
if self:reactionToward(act) < 0 then
self.ai_target.actor = act.uid
print("selected target", act.uid, "at dist", arr[i].dist)
if act and self:reactionToward(act) < 0 then
self.ai_target.actor = act
break
end
end
self.got_target = true
--print("target=>", self.ai_target.actor)
end)
newAI("target_player", function(self)
self.ai_target.actor = game.player
end)
newAI("simple", function(self)
self:runAI("target_simple")
-- self.ai_target.actor = game.player
self:runAI("move_simple")
end)
......@@ -28,8 +28,15 @@ function inherit(base, ...)
if #ifs == 0 then
setmetatable(c, {__index=base})
else
table.insert(ifs, 1, base)
setmetatable(c, {__index=function(t, k) return search(k, ifs) end})
for i, _if in ipairs(ifs) do
for k, e in pairs(_if) do
if k ~= "init" and k ~= "_NAME" and k ~= "_M" and k ~= "_PACKAGE" and k ~= "new" then
c[k] = e
print(("caching interface value %s (%s) from %s to %s"):format(k, tostring(e), _if._NAME, c._NAME))
end
end
end
setmetatable(c, {__index=base})
end
c.new = function(...)
local obj = {}
......
......@@ -28,5 +28,3 @@ game = false
local Menu = require("special.mainmenu.class.Game")
game = Menu.new()
game:run()
--profiler.start("/tmp/profiler.log")
......@@ -30,53 +30,23 @@ function _M:init(t)
self.ai_state = {}
self.ai_target = {}
-- Make the table with weak values, so that threat list does not prevent garbage collection
-- setmetatable(self.ai_target, {__mode='v'})
setmetatable(self.ai_target, {__mode='v'})
end
function _M:aiFindTarget()
self.ai_target.actor = game.player
end
function _M:onTakeHit(value, src)
end
--- Main entry point for AIs
function _M:doAI()
-- if not self.ai then return end
if not self.ai then return end
if self.x < game.player.x - 10 or self.x > game.player.x + 10 or self.y < game.player.y - 10 or self.y > game.player.y + 10 then return end
-- If we have a target but it is dead (it was not yet garbage collected but it'll come)
-- we forget it
-- if self.ai_target.actor and self.ai_target.actor.dead then self.ai_target.actor = nil end
-- self:runAI(self.ai)
if self.ai_target.actor and self.ai_target.actor.dead then self.ai_target.actor = nil end
-- Find closer ennemy and target it
local tgt = nil
-- Get list of actors ordered by distance
local arr = game.level:getDistances(self)
local act
if not arr or #arr == 0 then
-- print("target abording, waiting on distancer")
return
end
for i = 1, #arr do
act = __uids[arr[i].uid]
-- find the closest ennemy
if self:reactionToward(act) < 0 then
tgt = act.uid
-- print("selected target", act.uid, "at dist", arr[i].dist)
break
end
end
if tgt then
local act = __uids[tgt]
local l = line.new(self.x, self.y, act.x, act.y)
local lx, ly = l()
if lx and ly then
self:move(lx, ly)
end
end
self:runAI(self.ai)
end
function _M:runAI(ai)
......
......@@ -139,17 +139,19 @@ local hex_to_dec = {
["e"] = 14,
["f"] = 15,
}
local hexcache = {}
function string.parseHex(str)
if hexcache[str] then return hexcache[str] end
local res = 0
local power = 1
for i = 1, #str do
res = res + power * (hex_to_dec[str:sub(#str-i+1,#str-i+1):lower()] or 0)
power = power * 16
end
hexcache[str] = res
return res
end
do
local tmps = core.display.newSurface(1, 1)
getmetatable(tmps).__index.drawColorString = function(s, font, str, x, y, r, g, b)
local list = str:split("#%x%x%x%x%x%x#", true)
......@@ -174,8 +176,6 @@ getmetatable(tmps).__index.drawColorStringCentered = function(s, font, str, dx,
s:drawColorString(font, str, x, y, r, g, b)
end
end
dir_to_coord = {
[1] = {-1, 1},
[2] = { 0, 1},
......
......@@ -42,25 +42,6 @@ function _M:init()
end
function _M:run()
-- Damage types
DamageType:loadDefinition("/data/damage_types.lua")
-- Talents
ActorTalents:loadDefinition("/data/talents.lua")
-- Actor resources
ActorResource:defineResource("Mana", "mana", ActorTalents.T_MANA_POOL, "mana_regen", "Mana represents your reserve of magical energies. Each spell cast consumes mana and each sustained spell reduces your maximun mana.")
ActorResource:defineResource("Stamina", "stamina", ActorTalents.T_STAMINA_POOL, "stamina_regen", "Stamina represents your physical fatigue. Each physical ability used reduces it.")
-- Actor stats
ActorStats:defineStat("Strength", "str", 10, 1, 100, "Strength defines your character's ability to apply physical force. It increases your melee damage, damage with heavy weapons, your chance to resist physical effects, and carrying capacity.")
ActorStats:defineStat("Dexterity", "dex", 10, 1, 100, "Dexterity defines your character's ability to be agile and alert. It increases your chance to hit, your ability to avoid attacks and your damage with light weapons.")
ActorStats:defineStat("Magic", "mag", 10, 1, 100, "Magic defines your character's ability to manipulate the magic of the world. It increases your spell power, the effect of spells and other magic items.")
ActorStats:defineStat("Willpower", "wil", 10, 1, 100, "Willpower defines your character's ability to concentrate. It increases your mana and stamina capacity, and your chance to resist mental attacks.")
ActorStats:defineStat("Cunning", "cun", 10, 1, 100, "Cunning defines your character's ability to learn and think. It allows you to learn many wordly abilities, increases your mental resistance and armor penetration.")
ActorStats:defineStat("Constitution", "con", 10, 1, 100, "Constitution defines your character's ability to withstand and resist damage. It increases your maximun life and physical resistance.")
-- Actor autolevel schemes
dofile("/data/autolevel_schemes.lua")
-- Actor AIs
ActorAI:loadDefinition("/engine/ai/")
self.log = LogDisplay.new(0, self.h * 0.8, self.w * 0.5, self.h * 0.2, nil, nil, nil, {255,255,255}, {30,30,30})
self.player_display = PlayerDisplay.new(0, 0, self.w * 0.2, self.h * 0.8, {30,30,0})
self.talents_display = TalentsDisplay.new(self.w * 0.5, self.h * 0.8, self.w * 0.5, self.h * 0.2, {30,30,0})
......
......@@ -20,5 +20,13 @@ end
--- Called by ActorLife interface
-- We use it to pass aggression values to the AIs
function _M:onTakeHit(value, src)
-- self:aiAddThreat(value, src)
print("took hit from", src.name, "::", self.ai_target.actor)
if not self.ai_target.actor then
self.ai_target.actor = src
end
end
function _M:tooltip()
local str = mod.class.Actor.tooltip(self)
return str..("\nTarget: %s\nUID: %d"):format(self.ai_target.actor and self.ai_target.actor.name or "none", self.uid)
end
require "engine.class"
require "mod.class.Actor"
local ActorTalents = require "engine.interface.ActorTalents"
module(..., package.seeall, class.inherit(mod.class.Actor))
......@@ -15,7 +16,7 @@ function _M:init(t)
["spell/fire"]=true,
["physical/1hweapon"]=true
}
self.talents = {[self.T_MANA_POOL]=true, [self.T_STAMINA_POOL]=true}
self.talents = {[ActorTalents.T_MANA_POOL]=true, [ActorTalents.T_STAMINA_POOL]=true}
self.mana_regen = 1
self.stamina_regen = 1
self.regen_life = 1
......
return {
name = "ancient ruins",
max_level = 5,
width = 100, height = 100,
width = 50, height = 50,
-- all_remembered = true,
all_lited = true,
-- persistant = true,
......@@ -16,7 +16,7 @@ return {
},
actor = {
class = "engine.generator.actor.Random",
nb_npc = {400, 400},
nb_npc = {40, 40},
level_range = {5, 10},
adjust_level_to_player = {-2, 2},
},
......
......@@ -30,4 +30,4 @@ old places, venture into the unknown for wealth and glory.
But beware, the eastern troubles could be yours all too soon...
]]
version = {4,0,0}
starter = "mod.class.Game"
starter = "mod.load"
-- This file loads the game module, if you name you main Game class
-- the same you do not need to change this file at all
-- This file loads the game module, and loads data
local DamageType = require "engine.DamageType"
local ActorStats = require "engine.interface.ActorStats"
local ActorResource = require "engine.interface.ActorResource"
local ActorTalents = require "engine.interface.ActorTalents"
local ActorAI = require "engine.interface.ActorAI"
-- Damage types
DamageType:loadDefinition("/data/damage_types.lua")
-- Talents
ActorTalents:loadDefinition("/data/talents.lua")
-- Actor resources
ActorResource:defineResource("Mana", "mana", ActorTalents.T_MANA_POOL, "mana_regen", "Mana represents your reserve of magical energies. Each spell cast consumes mana and each sustained spell reduces your maximun mana.")
ActorResource:defineResource("Stamina", "stamina", ActorTalents.T_STAMINA_POOL, "stamina_regen", "Stamina represents your physical fatigue. Each physical ability used reduces it.")
-- Actor stats
ActorStats:defineStat("Strength", "str", 10, 1, 100, "Strength defines your character's ability to apply physical force. It increases your melee damage, damage with heavy weapons, your chance to resist physical effects, and carrying capacity.")
ActorStats:defineStat("Dexterity", "dex", 10, 1, 100, "Dexterity defines your character's ability to be agile and alert. It increases your chance to hit, your ability to avoid attacks and your damage with light weapons.")
ActorStats:defineStat("Magic", "mag", 10, 1, 100, "Magic defines your character's ability to manipulate the magic of the world. It increases your spell power, the effect of spells and other magic items.")
ActorStats:defineStat("Willpower", "wil", 10, 1, 100, "Willpower defines your character's ability to concentrate. It increases your mana and stamina capacity, and your chance to resist mental attacks.")
ActorStats:defineStat("Cunning", "cun", 10, 1, 100, "Cunning defines your character's ability to learn and think. It allows you to learn many wordly abilities, increases your mental resistance and armor penetration.")
ActorStats:defineStat("Constitution", "con", 10, 1, 100, "Constitution defines your character's ability to withstand and resist damage. It increases your maximun life and physical resistance.")
-- Actor autolevel schemes
dofile("/data/autolevel_schemes.lua")
-- Actor AIs
ActorAI:loadDefinition("/engine/ai/")
local Game = require "mod.class.Game"
-- Global
local game = Game.new()
return game
return require "mod.class.Game"
......@@ -40,8 +40,10 @@ function CreateSummary(lines, summary)
for i = 2, table.getn(lines) do
word = string.match(lines[i], "[^\t]+\t[^\t]+\t([^\t]+)")
local_time, total_time = string.match(lines[i], "[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\t[^\t]+\t([^\t]+)\t([^\t]+)")
if not (local_time and total_time) then return global_time end
if summary[word] == nil then
local_time = tonumber(local_time)
total_time = tonumber(total_time)
if not (local_time and total_time) then return global_time end
if summary[word] == nil then
summary[word] = {};
summary[word]["info"] = {}
summary[word]["info"]["calls"] = 1
......
......@@ -308,6 +308,7 @@ int main(int argc, char *argv[])
luaopen_mime_core(L);
luaopen_struct(L);
luaopen_profiler(L);
// luaopen_map(L);
// Make the uids repository
lua_newtable(L);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment