Lunatic: grabbag of different things.

- fix error handing with recursing events
- wallsofsect iterator, sector[]:contains()
- more codegen; mangle function names
- m32: compinside

git-svn-id: https://svn.eduke32.com/eduke32@3375 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-01-05 13:09:31 +00:00
parent e72557d9d9
commit 8ed4667265
12 changed files with 234 additions and 60 deletions

View file

@ -186,7 +186,9 @@ int L_RunString(L_State *estate, char *buf, int dofreebuf)
lua_State *L = estate->L;
// -- lua --
Bassert(lua_gettop(L)==1); // on top: a traceback function
Bassert(lua_gettop(L)==1);
// on top: a traceback function
Bassert(lua_iscfunction(L, 1));
i = luaL_loadstring(L, buf);
Bassert(lua_gettop(L)==2);

View file

@ -2157,6 +2157,13 @@ void C_DefineVolumeName(int32_t vol, const char *name)
g_numVolumes = max(g_numVolumes, vol+1);
}
void C_DefineSkillName(int32_t skill, const char *name)
{
Bassert((unsigned)skill < MAXSKILLS);
Bstrncpyz(SkillNames[skill], name, sizeof(SkillNames[skill]));
g_numSkills = max(g_numSkills, skill+1);
}
void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
int32_t partime, int32_t designertime,
const char *levelname)

View file

@ -36,6 +36,8 @@ extern int32_t OSD_errors;
void Gv_RefreshPointers(void);
extern void G_FreeMapState(int32_t mapnum);
#if !defined LUNATIC_ONLY
static void Gv_Free(void) /* called from Gv_ReadSave() and Gv_ResetVars() */
{
// call this function as many times as needed.
@ -68,7 +70,6 @@ static void Gv_Free(void) /* called from Gv_ReadSave() and Gv_ResetVars() */
return;
}
#if !defined LUNATIC_ONLY
static void Gv_Clear(void)
{
// only call this function ONCE...
@ -1109,7 +1110,7 @@ static weapondata_t weapondefaults[MAX_WEAPONS] = {
{
PISTOL_WEAPON, /*NAM?20:*/12, /*NAM?50:*/27, 2, 5, 0,
/*NAM?WEAPON_HOLSTER_CLEARS_CLIP:*/0 | WEAPON_RELOAD_TIMING,
/*(NAM?WEAPON_HOLSTER_CLEARS_CLIP:0) |*/ WEAPON_RELOAD_TIMING,
SHOTSPARK1__STATIC, 2, SHELL__STATIC, 0, 0, PISTOL_FIRE, 0, 0,
EJECT_CLIP, INSERT_CLIP, INSERT_CLIP, 255+(95<<8)
},

View file

@ -30,9 +30,9 @@ module(...)
local lastid = { action=0, move=0, ai=0 }
local def = {
action = {NO=ffi.new("con_action_t")},
move = {NO=ffi.new("con_move_t")},
ai = {NO=ffi.new("con_ai_t")},
action = { NO=ffi.new("con_action_t") },
move = { NO=ffi.new("con_move_t") },
ai = { NO=ffi.new("con_ai_t") },
}
local function forbidden() error("newindex forbidden", 2) end
@ -278,7 +278,7 @@ end
local function P_AddWeaponAmmoCommon(ps, weap, amount)
P_AddAmmo(ps, weap, amount)
if (ps.curr_weapon==ffiC.KNEE_WEAPON and have_weapon(weap)) then
if (ps.curr_weapon==ffiC.KNEE_WEAPON and have_weapon(ps, weap)) then
ffiC.P_AddWeaponMaybeSwitch(ps, weap);
end
end
@ -398,7 +398,7 @@ function _debris(i, dtile, n)
local jj = insertsprite{ dtile+picofs, pos, spr.sectnum, i, 5,
shade=spr.shade, xrepeat=32+krandand(15), yrepeat=32+krandand(15),
ang=krandand(2047), xvel=32+krandand(127), zvel=-krandand(2047) }
-- NOTE: BlimpSpawnSprites[14] (its array size if 15) will never be chosen
-- NOTE: BlimpSpawnSprites[14] (its array size is 15) will never be chosen
sprite[jj]:set_yvel(isblimpscrap and ffiC.BlimpSpawnSprites[math.mod(jj, 14)] or -1)
sprite[jj].pal = spr.pal
end
@ -441,7 +441,7 @@ function _sizeto(i, xr, yr)
spr.yrepeat = spr.yrepeat + ((dr == 0) and 0 or (dr < 0 and -1 or 1))
end
-- NOTE: function args have overloaded meaning
-- NOTE: function args of the C function have overloaded meaning
function _A_Spawn(j, pn)
local bound_check = sector[sprite[j].sectnum] -- two in one whack
check_tile_idx(pn)
@ -458,7 +458,7 @@ function _pstomp(ps, i)
end
end
ps.actorsqu = i
ps.knee_incs = -1
ps.knee_incs = 1
if (ps.weapon_pos == 0) then
ps.weapon_pos = -1
end

View file

@ -500,6 +500,7 @@ int32_t C_DefineSound(int32_t sndidx, const char *fn, int32_t args[5]);
void C_DefineMusic(int32_t vol, int32_t lev, const char *fn);
void C_DefineQuote(int32_t qnum, const char *qstr);
void C_DefineVolumeName(int32_t vol, const char *name);
void C_DefineSkillName(int32_t skill, const char *name);
void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
int32_t partime, int32_t designertime,
const char *levelname);
@ -1114,7 +1115,7 @@ local function our_gameevent(event, func)
if (oldfunc ~= nil) then
newfunc = function(aci, pli, dist)
func(aci, pli, dist)
oldfunc(aci, pli, dist)
return oldfunc(aci, pli, dist)
end
end

View file

@ -2,6 +2,7 @@
-- This file contains LuaJIT definitions of stuff that's common to the game and
-- editor. The 'decl' function is expected to be defined in the global
-- environment.
-- See the included license file "BUILDLIC.TXT" for license info.
local ffi = require("ffi")
local ffiC = ffi.C
@ -253,6 +254,9 @@ local ivec3_mt = {
}
ivec3_ = ffi.metatype("vec3_t", ivec3_mt)
local xor = bit.bxor
local wallsofsec -- fwd-decl
local sectortype_mt = {
__index = {
ceilingzat = function(s, pos)
@ -262,6 +266,29 @@ local sectortype_mt = {
floorzat = function(s, pos)
return ffiC.getflorzofslopeptr(s, pos.x, pos.y)
end,
-- inside() port
contains = function(s, pos)
local x, y = pos.x, pos.y
local cnt = 0
for w in wallsofsec(s) do
local wal2 = ffiC.wall[ffiC.wall[w].point2]
local y1, y2 = ffiC.wall[w].y-y, wal2.y-y
if (xor(y1, y2) < 0) then
local x1, x2 = ffiC.wall[w].x-x, wal2.x-x
if (xor(x1, x2)>=0) then
cnt = xor(cnt, x1)
else
cnt = xor(cnt, xor(x1*y2-x2*y1, y2))
end
end
end
return (cnt < 0)
end,
}
}
ffi.metatype("sectortype", sectortype_mt)
@ -385,6 +412,22 @@ function check_sector_idx(sectnum)
end
end
local function iter_wallsofsec(endwall, w)
w = w+1
if (w < endwall) then
return w
end
end
wallsofsec = function(sec) -- local
return iter_wallsofsec, sec.wallptr+sec.wallnum, sec.wallptr-1
end
function wallsofsect(sect)
check_sector_idx(sect)
return iter_wallsofsec, sector[sect].wallptr+sector[sect].wallnum, sector[sect].wallptr-1
end
--== Per-sector/per-statnum sprite iterators ==--
local function iter_spritesofsect(sect, i)
if (i < 0) then
@ -431,10 +474,10 @@ local function iter_sectorsofbunch(cf, i)
end
function sectorsofbunch(bunchnum, cf)
if (bunchnum < 0 or bunchnum >= ffiC.numyaxbunches) then
if (bunchnum >= ffiC.numyaxbunches+0ULL) then
error("passed invalid bunchnum to sectorsofbunch iterator", 2)
end
if (cf ~= 0 and cf ~= 1) then
if (not (cf == 0 or cf == 1)) then
error("passed invalid 'cf' to sectorsofbunch iterator, must be 0 or 1", 2)
end
@ -443,7 +486,7 @@ end
function getbunch(sectnum, cf)
check_sector_idx(sectnum)
if (cf ~= 0 and cf ~= 1) then
if (not (cf == 0 or cf == 1)) then
error("passed invalid 'cf' to getbunch, must be 0 or 1", 2)
end
@ -495,9 +538,6 @@ function neartag(pos, sectnum, ang, range, tagsearch)
return neartag_ret_ct(a[0], b[0], c[0], d[0])
end
-- TODO: reimplement in Lua (benefit: no int overflow)? On the engine side,
-- make it take a sectortype pointer, and add as metamethod to our LuaJIT
-- sector type ("contains"?)
function inside(pos, sectnum)
check_sector_idx(sectnum)
return (ffiC.inside(pos.x, pos.y, sectnum)==1)
@ -526,9 +566,13 @@ function updatesectorz(pos, sectnum)
return sect[0]
end
function printf(fmt, ...)
print(string.format(fmt, ...))
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.
-- over the non-local variables from here into its global environment.
function create_globals(_G_their)
local _G_our = getfenv(1)
vars_to_ignore["create_globals"] = true

View file

@ -69,6 +69,7 @@ C_DefineSound;
C_DefineMusic;
C_DefineQuote;
C_DefineVolumeName;
C_DefineSkillName;
C_DefineLevelName;
actor;

View file

@ -52,7 +52,7 @@ lpeg.setmaxstack(1024);
local Pat, Set, Range, Var = lpeg.P, lpeg.S, lpeg.R, lpeg.V
local POS = lpeg.Cp
---- All keywords pattern -- needed for CON syntax
-- CON language definitions (among other things, all keywords pattern).
local conl = require("con_lang")
@ -95,6 +95,9 @@ local g_iflevel = 0
local g_ifelselevel = 0
---=== Code generation ===---
-- CON --> mangled Lua function name, also existence check:
local g_funcname = {}
local g_have_file = {} -- [filename]=true
local g_curcode = nil -- a table of string pieces or other "gencode" tables
@ -109,11 +112,13 @@ local function new_initial_codetab()
return {
"local _con, _bit, _math = require'con', require'bit', require'math';",
"local sector, sprite, actor, player = sector, sprite, actor, player;",
"local gameactor=gameactor;"
"local gameactor, gameevent = gameactor, gameevent;"
}
end
local function reset_codegen()
g_funcname = {}
g_have_file = {}
g_curcode = new_initial_codetab()
g_actor_code, g_event_code, g_loadactor_code = {}, {}, {}
@ -160,9 +165,26 @@ local function on_actor_end(usertype, tsamm, codetab)
g_actor_code[tilenum] = codetab
end
local function on_state_end(statename, codetab)
-- TODO: mangle names
addcodef("local function %s(_aci, _pli, _dist)", statename)
local BAD_ID_CHARS0 = "_/\\*?" -- allowed 1st identifier chars
local BAD_ID_CHARS1 = "_/\\*-+?" -- allowed following identifier chars
local function mangle_name(name, prefix)
-- NOTE: the underscore char has to be replaced too, because we're using
-- it as the escape char.
for i=1,#BAD_ID_CHARS1 do
name = name:gsub(BAD_ID_CHARS1:sub(i,i), "_"..i)
end
return prefix..name
end
local function on_state_begin(statename)
local ourname = mangle_name(statename, "F")
g_funcname[statename] = ourname
return ourname
end
local function on_state_end(funcname, codetab)
addcodef("local function %s(_aci, _pli, _dist)", funcname)
add_code_and_end(codetab, "end")
end
@ -215,7 +237,7 @@ local function warnprintf(fmt, ...)
end
local function parse_number(pos, numstr)
local num = tonumber(numstr)
local num = tonumber((numstr:gsub("h$", "")))
if (num==nil or num < -0x80000000 or num > 0xffffffff) then
perrprintf(pos, "number %s out of the range of a 32-bit integer", numstr)
@ -441,7 +463,7 @@ local function do_include_file(dirname, filename)
g_filename = oldfilename
end
function cmd_include(filename)
local function cmd_include(filename)
do_include_file(g_directory, filename)
end
@ -498,13 +520,25 @@ local function cmd_definelevelname(vol, lev, fn, ptstr, dtstr, levname)
g_data.level[EPMUL*vol+lev] = map
end
local function defineXname(what, ffiCfuncname, X, name)
name = name:upper()
if (ffi) then
ffiC[ffiCfuncname](X, name)
if (#name > 32) then
warnprintf("%s %d name truncated to 32 characters.", what, X)
end
end
return name
end
local function cmd_defineskillname(skillnum, name)
if (skillnum < 0 or skillnum >= conl.MAXSKILLS) then
errprintf("volume number is negative or exceeds maximum skill count.")
errprintf("skill number is negative or exceeds maximum skill count.")
return
end
g_data.skillname[skillnum] = name:upper()
name = defineXname("skill", "C_DefineSkillName", skillnum, name)
g_data.skillname[skillnum] = name
end
local function cmd_definevolumename(vol, name)
@ -513,14 +547,7 @@ local function cmd_definevolumename(vol, name)
return
end
name = name:upper()
if (ffi) then
ffiC.C_DefineVolumeName(vol, name)
if (#name > 32) then
warnprintf("volume %d name truncated to 32 characters.", vol)
end
end
name = defineXname("volume", "C_DefineVolumeName", vol, name)
g_data.volname[vol] = name
end
@ -640,7 +667,8 @@ local alphanum = alpha + Range("09")
--- basic lexical elements ("tokens")
local t_maybe_minus = (Pat("-") * sp0)^-1;
local t_number = POS() * lpeg.C(
t_maybe_minus * ((Pat("0x") + "0X")*Range("09", "af", "AF")^1 + Range("09")^1)
t_maybe_minus * ((Pat("0x") + "0X") * Range("09", "af", "AF")^1 * Pat("h")^-1
+ Range("09")^1)
) / parse_number
-- Valid identifier names are disjunct from keywords!
-- XXX: CON is more permissive with identifier name characters:
@ -836,6 +864,14 @@ local function handle_debug(val)
return format("print('%s:%d: debug %d')", g_filename, getlinecol(g_lastkwpos), val)
end
local function handle_state(statename)
if (g_funcname[statename]==nil) then
errprintf("state `%s' not found.", statename)
return "_NULLSTATE()"
end
return format("%s(_aci,_pli,_dist)", g_funcname[statename])
end
-- NOTE about prefixes: most is handled by all_alt_pattern(), however commands
-- that have no arguments and that are prefixes of other commands MUST be
-- suffixed with a "* #sp1" pattern.
@ -845,10 +881,10 @@ local Ci = {
["break"] = cmd()
/ "do return end",
["return"] = cmd() -- NLCF
/ "_con.longjmp()", -- TODO: test with code from Wiki "return" entry
/ "_con.longjmp()",
state = cmd(I)
/ "%1(_aci, _pli, _dist)", -- TODO: mangle names
/ handle_state,
--- 1. get*, set*
getactor = getstructcmd,
@ -943,7 +979,8 @@ local Ci = {
/ SPS".extra=%1",
addstrength = cmd(D)
/ (SPS".extra="..SPS".extra+%1"),
spritepal = cmd(D),
spritepal = cmd(D)
/ SPS".pal=%1",
hitradius = cmd(D,D,D,D,D)
/ "_con._A_RadiusDamage(_aci,%1,%2,%3,%4,%5)",
@ -975,8 +1012,7 @@ local Ci = {
savegamevar = cmd(R),
readgamevar = cmd(R),
userquote = cmd(R),
echo = cmd(D) / "_con._echo(%1)", -- XXX: TEMP
-- echo = cmd(R),
echo = cmd(R) / "_con._echo(%1)",
starttrackvar = cmd(R),
clearmapstate = cmd(R),
activatecheat = cmd(R),
@ -1546,7 +1582,7 @@ local Cb = {
onevent = sp1 * t_define * sp1 * stmt_list_or_eps * "endevent"
/ on_event_end,
state = sp1 * t_identifier * sp1 * stmt_list_or_eps * "ends"
state = sp1 * (t_identifier/on_state_begin) * sp1 * stmt_list_or_eps * "ends"
/ on_state_end,
}
@ -1563,7 +1599,7 @@ local t_good_identifier = Range("AZ", "az", "__") * Range("AZ", "az", "__", "09"
-- in CON, so a trailing "-" is "OK", too.)
-- This is broken in itself, so we ought to make a compatibility/modern CON switch.
local t_broken_identifier = BadIdent(-((t_number + t_good_identifier) * (sp1 + Set("[]:"))) *
(alphanum + Set("_/\\*?")) * (alphanum + Set("_/\\*-+?"))^0)
(alphanum + Set(BAD_ID_CHARS0)) * (alphanum + Set(BAD_ID_CHARS1))^0)
-- These two tables hold code to be inserted at a later point: either at
-- the end of the "if" body, or the end of the whole "if [else]" block.

View file

@ -234,6 +234,7 @@ static void El_StateSetup(lua_State *L)
Bassert(lua_gettop(L)==0);
// This is for engine-side Lua:
lua_pushcfunction(L, &our_traceback_CF);
}
@ -307,10 +308,12 @@ static int32_t SetActor_CF(lua_State *L)
static int32_t call_regd_function3(lua_State *L, void *keyaddr,
int32_t iActor, int32_t iPlayer, int32_t lDist)
{
int32_t i;
#if !defined NDEBUG
int32_t i, haveerr;
int32_t top = lua_gettop(L);
#endif
lua_pushcfunction(L, &our_traceback_CF);
// get the Lua function from the registry
lua_pushlightuserdata(L, keyaddr);
lua_gettable(L, LUA_REGISTRYINDEX);
@ -320,11 +323,10 @@ static int32_t call_regd_function3(lua_State *L, void *keyaddr,
lua_pushinteger(L, lDist);
// -- call it! --
#ifdef DEBUGGINGAIDS
i = lua_pcall(L, 3, 0, 1);
#else
i = lua_pcall(L, 3, 0, 0);
#endif
i = lua_pcall(L, 3, 0, -5);
haveerr = (i != 0);
Bassert(lua_iscfunction(L, -1-haveerr));
lua_remove(L, -1-haveerr);
Bassert(lua_gettop(L) == top+(i!=0));

View file

@ -0,0 +1,85 @@
local ffi = require("ffi")
local ffiC = ffi.C
local sector = sector
local inside = inside
local math = require("math")
local geom = require("geom")
local stat = require("stat")
local function resetseed()
math.randomseed(834572183572)
end
local function getmapbounds()
local inf = 1/0
local min = { x=inf, y=inf }
local max = { x=-inf, y=-inf }
for i=0,ffiC.numsectors-1 do
for w in wallsofsect(i) do
local wal = wall[w]
min.x = math.min(wal.x, min.x)
max.x = math.max(wal.x, max.x)
min.y = math.min(wal.y, min.y)
max.y = math.max(wal.y, max.y)
end
end
return min, max
end
local function getpoints(n, min, max)
local posns, sects = {}, {}
resetseed()
for i=1,n do
local x = math.random(min.x, max.x)
local y= math.random(min.y, max.y)
posns[i] = geom.vec2(x, y)
sects[i] = math.random(0, ffiC.numsectors-1)
end
return posns, sects
end
-- Compare 'inside' implementations
--
-- N: number of calls
function compinside(n)
if (type(n) ~= "number") then
error("N must be a number")
end
local sti = stat.new()
local sts = stat.new()
local min, max = getmapbounds()
local posns, sects = getpoints(n, min, max)
local isi, iss = {}, {}
for i=1,n do
local t = ffiC.gethitickms()
isi[i] = inside(posns[i], sects[i])
t = ffiC.gethitickms()-t
sti:add(t)
local t = ffiC.gethitickms()
iss[i] = sector[sects[i]]:contains(posns[i])
t = ffiC.gethitickms()-t
sts:add(t)
-- if (isi[i]~=iss[i]) then
-- print("unequal: "..i.." "..sects[i].." "..posns[i].x.." "..posns[i].y.." ("..tostring(isi[i])..","..tostring(iss[i])..")")
-- end
assert(isi[i]==iss[i])
end
print("====================")
print("inside(): " .. tostring(sti:getstats()))
print("contains(): " .. tostring(sts:getstats()))
end

View file

@ -7,8 +7,6 @@ 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 = {}

View file

@ -15,11 +15,8 @@ onevent EVENT_EGS
}
endevent
onevent EVENT_LOADACTOR
ifvarvare THISACTOR 0
{
// the concrete actor is irrelevant, only placeholder
spawn HEAVYHBOMB // --> EVENT_EGS
userquote 125
}
onevent EVENT_FIRE
// the concrete actor is irrelevant, only placeholder
spawn HEAVYHBOMB // --> EVENT_EGS
userquote 125
endevent