diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua index f2dd5b90c..a64313f4d 100644 --- a/polymer/eduke32/source/lunatic/defs_common.lua +++ b/polymer/eduke32/source/lunatic/defs_common.lua @@ -172,6 +172,10 @@ int16_t yax_getbunch(int16_t i, int16_t cf); int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz, hitdata_t *hitinfo, uint32_t cliptype); +void updatesector(int32_t x, int32_t y, int16_t *sectnum); +void updatesectorbreadth(int32_t x, int32_t y, int16_t *sectnum); +void updatesectorz(int32_t x, int32_t y, int32_t z, int16_t *sectnum); + void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, char dapalnum, int32_t dastat, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2); @@ -338,6 +342,29 @@ function hitscan(pos, sectnum, vx,vy,vz, cliptype) return hitdata end +-- TODO: should these rather be one function, and the specific kind of updating +-- controlled by an argument? +function updatesector(pos, sectnum) + local sect = ffi.new("int16_t [1]") + sect[0] = sectnum + ffiC.updatesector(pos.x, pos.y, sect) + return sect[0] +end + +function updatesectorbreadth(pos, sectnum) + local sect = ffi.new("int16_t [1]") + sect[0] = sectnum + ffiC.updatesectorbreadth(pos.x, pos.y, sect) + return sect[0] +end + +function updatesectorz(pos, sectnum) + local sect = ffi.new("int16_t [1]") + sect[0] = sectnum + ffiC.updatesectorz(pos.x, pos.y, pos.z, sect) + return sect[0] +end + -- This is supposed to be run from the file that 'require's this module to take -- over the non-local variables from here into the global environment. diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist index 8800f0c8d..f3bfe8a27 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist +++ b/polymer/eduke32/source/lunatic/dynsymlist @@ -31,6 +31,10 @@ ksqrt; hitscan; rotatesprite; +updatesector; +updatesectorz; +updatesectorbreadth; + gethitickms; diff --git a/polymer/eduke32/source/lunatic/dynsymlist_m32 b/polymer/eduke32/source/lunatic/dynsymlist_m32 index 125db55df..bba715f52 100644 --- a/polymer/eduke32/source/lunatic/dynsymlist_m32 +++ b/polymer/eduke32/source/lunatic/dynsymlist_m32 @@ -31,6 +31,10 @@ ksqrt; hitscan; rotatesprite; +updatesector; +updatesectorz; +updatesectorbreadth; + gethitickms; diff --git a/polymer/eduke32/source/lunatic/randwalk.lua b/polymer/eduke32/source/lunatic/randwalk.lua new file mode 100644 index 000000000..4179bcd3e --- /dev/null +++ b/polymer/eduke32/source/lunatic/randwalk.lua @@ -0,0 +1,115 @@ +-- Random walker as updatesector() timing test, for Lunatic-m32 +-- Load with: lua "require 'randwalk'" + +local ffi = require "ffi" +local ffiC = ffi.C + +local geom = require "geom" +local stat = require "stat" + +local function printf(fmt, ...) print(string.format(fmt, ...)) end + + +-- set to nil to disable saving positions +g_posns = {} + +-- [STATS, TIMES] = RANDWALK(N, SPRITENUM, MINLEN, MAXLEN [, RANDOFS [, FUNCI [, LOGFN]]]) +function randwalk(N, spritenum, minlen, maxlen, randofs, funci, logfn) + -- Set the random seed to an arbitrary but fixed value so that the "random" walk + -- is deterministically reproducible for particular arguments. + math.randomseed(834572183572) + + randofs = randofs or 0 + + for i=1,randofs do + math.random() + end + + local funcnames = { "updatesector", "updatesectorbreadth", "updatesectorz" } + local funcs = { updatesector, updatesectorbreadth, updatesectorz } + local updatesectorfunc = funcs[funci] + + -- stats + local st = { all=stat.new(), succ=stat.new(), fail=stat.new() } + + local times = {} + local successp = {} + + local pos = geom.tovec3(sprite[spritenum]) + local sectnum = sprite[spritenum].sectnum + + for i=1,N do +--[[ + -- get random integers for the displacement + local ax,ay,az = math.random(minlen,maxlen), math.random(minlen,maxlen), math.random(minlen,maxlen) + + -- random signs + local sx,sy,sz = math.random(0,1), math.random(0,1), math.random(0,1) + sx, sy, sz = 2*sx-1, 2*sy-1, 2*sz-1 -- {0,1} -> {-1,1} + ax, ay, az = sx*ax, sy*ay, sz*az +--]] +---[[ + local ang = 2*math.pi*math.random() + local len = math.random(minlen, maxlen) + local ax, ay, az = len*math.cos(ang), len*math.sin(ang), 0 +--]] + local newpos = pos + geom.ivec3(ax,ay,az) + + local t = ffiC.gethitickms() + local newsect = updatesectorfunc(newpos, sectnum) + t = ffiC.gethitickms()-t + + st.all:add(t) + times[i] = t + + successp[i] = (newsect >= 0) + + if (newsect >= 0) then + st.succ:add(t) + + pos = newpos + sectnum = newsect + else + st.fail:add(t) + end + + if (g_posns ~= nil) then + g_posns[i] = pos + end + end + + local stallres = st.all:getstats() + + print("====================") + printf("Random %s walk starting with sprite %d", + funcnames[funci], spritenum) + printf("Hop length: [%d .. %d], RNG offset: %d, %s", + minlen, maxlen, randofs, logfn) + printf("-- Times [ms] (total=%f)", N*stallres.mean) + print("All: ".. tostring(stallres)) + print("Succeeded: ".. tostring(st.succ:getstats())) + print("Failed: ".. tostring(st.fail:getstats())) + + if (logfn ~= nil) then + local logfile, errmsg = io.open(logfn, "w") + if (logfile == nil) then + printf("Couldn't open log file \"%s\" for writing: %s", + logfn, errmsg) + else + logfile:write(" \t \t \t\t\n") + for i=1,N do + if (g_posns ~= nil) then + logfile:write(string.format("%s %d %d %d %d\n", + tostring(times[i]), successp[i] and 1 or 0, + g_posns[i].x, g_posns[i].y, g_posns[i].z)) + else + logfile:write(string.format("%s %d\n", tostring(times[i]), successp[i] and 1 or 0)) + end + end + + logfile:close() + end + end + + return st, ts +end