From: Pasi Kallinen Date: Tue, 22 Mar 2022 07:16:15 +0000 (+0200) Subject: Lua: coordinate tweaking X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=27898340b987db09231a46cf32b7507b717d2668;p=nethack Lua: coordinate tweaking Make selection rndcoord return a table with x and y keys. Allow (most) coordinate parameters accept such a table. Fix selection and des lua tests broken by the above changes and an earlier change, because selections tried to set terrain at column 0, and it now causes a complaint. --- diff --git a/dat/Bar-strt.lua b/dat/Bar-strt.lua index 57297b73a..37d7face1 100644 --- a/dat/Bar-strt.lua +++ b/dat/Bar-strt.lua @@ -95,6 +95,5 @@ des.monster("giant eel", 39, 15) -- Monsters on siege duty. local ogrelocs = selection.floodfill(37,7) & selection.area(40,03, 45,20) for i = 0, 11 do - local x,y = ogrelocs:rndcoord(1); - des.monster({ id = "ogre", coord={x,y}, peaceful=0 }) + des.monster({ id = "ogre", coord = ogrelocs:rndcoord(1), peaceful = 0 }) end diff --git a/dat/Mon-strt.lua b/dat/Mon-strt.lua index 0ae685a69..0bbdfcf00 100644 --- a/dat/Mon-strt.lua +++ b/dat/Mon-strt.lua @@ -88,8 +88,7 @@ des.monster("abbot", 33, 12) des.non_diggable(selection.area(18,03,55,16)) -- Random traps for i = 1, 2 do - local x,y = spacelocs:rndcoord(1); - des.trap("dart",x,y) + des.trap("dart", spacelocs:rndcoord(1)) end des.trap() des.trap() @@ -97,10 +96,8 @@ des.trap() des.trap() -- Monsters on siege duty. for i = 1, 8 do - local x,y = spacelocs:rndcoord(1); - des.monster("earth elemental", x, y) + des.monster("earth elemental", spacelocs:rndcoord(1)) end for i = 1, 4 do - local x,y = spacelocs:rndcoord(1); - des.monster("xorn", x, y) + des.monster("xorn", spacelocs:rndcoord(1)) end diff --git a/dat/Pri-strt.lua b/dat/Pri-strt.lua index fb66e6492..696941cc3 100644 --- a/dat/Pri-strt.lua +++ b/dat/Pri-strt.lua @@ -90,8 +90,7 @@ des.monster("acolyte", 33, 12) des.non_diggable(selection.area(18,03,55,16)) -- Random traps for i = 1, 2 do - local x,y = spacelocs:rndcoord(1); - des.trap("dart",x,y) + des.trap("dart", spacelocs:rndcoord(1)) end des.trap() des.trap() @@ -99,6 +98,5 @@ des.trap() des.trap() -- Monsters on siege duty. for i = 1, 12 do - local x,y = spacelocs:rndcoord(1); - des.monster("human zombie", x, y); + des.monster("human zombie", spacelocs:rndcoord(1)); end diff --git a/dat/Rog-strt.lua b/dat/Rog-strt.lua index b2fd32a79..e0431b47c 100644 --- a/dat/Rog-strt.lua +++ b/dat/Rog-strt.lua @@ -158,9 +158,9 @@ des.monster({ id = "leprechaun", x=25, y=19, peaceful=0 }) des.monster({ id = "water nymph", x=25, y=18, peaceful=0 }) -- Wandering the streets. for i=1,4 + math.random(1 - 1,1*3) do - des.monster({ id = "water nymph", coord = {streets:rndcoord(1)}, peaceful=0 }) - des.monster({ id = "leprechaun", coord = {streets:rndcoord(1)}, peaceful=0 }) + des.monster({ id = "water nymph", coord = streets:rndcoord(1), peaceful=0 }) + des.monster({ id = "leprechaun", coord = streets:rndcoord(1), peaceful=0 }) end for i=1,7 + math.random(1 - 1,1*3) do - des.monster({ id = "chameleon", coord = {streets:rndcoord(1)}, peaceful=0 }) + des.monster({ id = "chameleon", coord = streets:rndcoord(1), peaceful=0 }) end diff --git a/dat/astral.lua b/dat/astral.lua index cbf2bc0ae..2624a578d 100644 --- a/dat/astral.lua +++ b/dat/astral.lua @@ -59,9 +59,9 @@ for i=1,2 do end -- extra monsters; was [6 + 3d4] when both wings were opened up at once for i=1,3 + math.random(2 - 1,2*3) do - des.monster({ id="Angel", coord = { hall:rndcoord(1) }, align="noalign", peaceful=0 }) + des.monster({ id="Angel", coord = hall:rndcoord(1), align="noalign", peaceful=0 }) if percent(50) then - des.monster({ coord = { hall:rndcoord(1) }, peaceful=0 }) + des.monster({ coord = hall:rndcoord(1), peaceful=0 }) end end end @@ -110,7 +110,7 @@ des.monster({ id = "aligned cleric",x=19,y=09,align="noalign", peaceful=0 }) des.monster({ id = "aligned cleric",x=19,y=10,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=20,y=09,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=20,y=10,align="noalign", peaceful=0 }) -des.monster({ id = "Pestilence", coord = { place:rndcoord(1) }, peaceful=0 }) +des.monster({ id = "Pestilence", coord = place:rndcoord(1), peaceful=0 }) -- South-central round room des.monster({ id = "aligned cleric",x=36,y=12,align="noalign", peaceful=0 }) des.monster({ id = "aligned cleric",x=37,y=12,align="noalign", peaceful=0 }) @@ -118,7 +118,7 @@ des.monster({ id = "aligned cleric",x=38,y=12,align="noalign", peaceful=0 }) des.monster({ id = "aligned cleric",x=36,y=13,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=38,y=13,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=37,y=13,align="noalign", peaceful=0 }) -des.monster({ id = "Death", coord = { place:rndcoord(1) }, peaceful=0 }) +des.monster({ id = "Death", coord = place:rndcoord(1), peaceful=0 }) -- East round room des.monster({ id = "aligned cleric",x=56,y=09,align="noalign", peaceful=0 }) des.monster({ id = "aligned cleric",x=55,y=08,align="noalign", peaceful=0 }) @@ -126,7 +126,7 @@ des.monster({ id = "aligned cleric",x=55,y=09,align="noalign", peaceful=0 }) des.monster({ id = "aligned cleric",x=55,y=10,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=54,y=09,align="noalign", peaceful=0 }) des.monster({ id = "Angel",x=54,y=10,align="noalign", peaceful=0 }) -des.monster({ id = "Famine", coord = { place:rndcoord(1) }, peaceful=0 }) +des.monster({ id = "Famine", coord = place:rndcoord(1), peaceful=0 }) -- -- The aligned horde -- diff --git a/dat/castle.lua b/dat/castle.lua index c2f05f02f..585aa5e6d 100644 --- a/dat/castle.lua +++ b/dat/castle.lua @@ -140,8 +140,7 @@ des.object(object[4],53,11) des.object(object[4],54,11) des.object(object[4],55,11) -- THE WAND OF WISHING in 1 of the 4 towers -local px, py = place:rndcoord(1); -des.object({ id = "chest", trapped = 0, locked = 1, x = px, y = py, +des.object({ id = "chest", trapped = 0, locked = 1, coord = place:rndcoord(1), contents = function() des.object("wishing"); end diff --git a/dat/juiblex.lua b/dat/juiblex.lua index 2eff9ec79..4fa120444 100644 --- a/dat/juiblex.lua +++ b/dat/juiblex.lua @@ -63,9 +63,9 @@ des.levregion({ region = {01,00,11,20}, region_islev=1, exclude={0,0,50,17}, typ des.teleport_region({ region = {01,00,11,20}, region_islev=1, exclude={0,0,50,17},dir="up" }) des.teleport_region({ region = {69,00,79,20}, region_islev=1, exclude={0,0,50,17},dir="down" }) des.feature("fountain", place:rndcoord(1)) -des.monster({ id = "giant mimic", coord = { place:rndcoord(1) }, appear_as = "ter:fountain" }) -des.monster({ id = "giant mimic", coord = { place:rndcoord(1) }, appear_as = "ter:fountain" }) -des.monster({ id = "giant mimic", coord = { place:rndcoord(1) }, appear_as = "ter:fountain" }) +des.monster({ id = "giant mimic", coord = place:rndcoord(1), appear_as = "ter:fountain" }) +des.monster({ id = "giant mimic", coord = place:rndcoord(1), appear_as = "ter:fountain" }) +des.monster({ id = "giant mimic", coord = place:rndcoord(1), appear_as = "ter:fountain" }) -- The demon of the swamp des.monster("Juiblex",25,08) -- And a couple demons diff --git a/dat/medusa-3.lua b/dat/medusa-3.lua index 65da48b76..143c1f86b 100644 --- a/dat/medusa-3.lua +++ b/dat/medusa-3.lua @@ -53,18 +53,16 @@ des.non_diggable(selection.area(44,13,48,17)) -- restricting the placement when teleporting from levels below this. des.teleport_region({ region = {33,02,38,07}, dir="down" }) des.levregion({ region = {32,01,39,07}, type="stair-up" }); -local mx, my = place:rndcoord(1); -des.stair("down", mx, my) + +des.stair("down", place:rndcoord(1)) des.door("locked",08,08) des.door("locked",64,05) des.door("random",50,13) des.door("locked",48,15) -- -local px, py = place:rndcoord(1); -des.feature("fountain", px,py); +des.feature("fountain", place:rndcoord(1)); -- -local px, py = place:rndcoord(1); -des.object({ id="statue",x=px, y=py, buc="uncursed", +des.object({ id="statue", coord=place:rndcoord(1), buc = "uncursed", montype="knight", historic=1, male=1,name="Perseus", contents = function() if percent(75) then diff --git a/dat/medusa-4.lua b/dat/medusa-4.lua index 75e910bf5..d716fe952 100644 --- a/dat/medusa-4.lua +++ b/dat/medusa-4.lua @@ -49,8 +49,8 @@ des.teleport_region({ region = {64,01,74,17}, dir="down" }); des.teleport_region({ region = {02,02,18,13}, dir="up" }); -- des.levregion({ region = {67,01,74,20}, type="stair-up" }); -local mx, my = place:rndcoord(1); -des.stair("down", mx, my) + +des.stair("down", place:rndcoord(1)) -- des.door("locked",04,06) des.door("locked",04,10) @@ -66,8 +66,7 @@ des.non_diggable(selection.area(01,01,22,14)); -- des.object("crystal ball", 07,08) -- -local px, py = place:rndcoord(1); -des.object({ id="statue",x=px, y=py, buc="uncursed", +des.object({ id="statue",coord=place:rndcoord(1), buc="uncursed", montype="knight", historic=1, male=1,name="Perseus", contents = function() if percent(75) then diff --git a/dat/minetn-1.lua b/dat/minetn-1.lua index 187b09b46..a1a9e43ed 100644 --- a/dat/minetn-1.lua +++ b/dat/minetn-1.lua @@ -120,18 +120,18 @@ local near_temple = selection.area(17,8, 23,14) & inside for i=1,5 + math.random(1 - 1,1*10) do if percent(50) then - des.monster({ id = "orc-captain", coord = { inside:rndcoord(1) }, peaceful=0 }); + des.monster({ id = "orc-captain", coord = inside:rndcoord(1), peaceful=0 }); else if percent(80) then - des.monster({ id = "Uruk-hai", coord = { inside:rndcoord(1) }, peaceful=0 }) + des.monster({ id = "Uruk-hai", coord = inside:rndcoord(1), peaceful=0 }) else - des.monster({ id = "Mordor orc", coord = { inside:rndcoord(1) }, peaceful=0 }) + des.monster({ id = "Mordor orc", coord = inside:rndcoord(1), peaceful=0 }) end end end -- shamans can be hanging out in/near the temple for i=1,math.random(2 - 1,2*3) do - des.monster({ id = "orc shaman", coord = { near_temple:rndcoord(0) }, peaceful=0 }); + des.monster({ id = "orc shaman", coord = near_temple:rndcoord(0), peaceful=0 }); end -- these are not such a big deal -- to run into outside the bars diff --git a/dat/soko1-1.lua b/dat/soko1-1.lua index 1d6b7c09b..bedcf13ca 100644 --- a/dat/soko1-1.lua +++ b/dat/soko1-1.lua @@ -96,14 +96,14 @@ des.door("closed", 17, 15); des.region({ region={18,10, 22,16}, lit = 1, type = "zoo", filled = 1, irregular = 1 }); -px, py = selection.rndcoord(place); +local pt = selection.rndcoord(place); if percent(75) then - des.object({ id="bag of holding", x=px, y=py, + des.object({ id="bag of holding", coord=pt, buc="not-cursed", achievement=1 }); else - des.object({ id="amulet of reflection", x=px, y=py, + des.object({ id="amulet of reflection", coord=pt, buc="not-cursed", achievement=1 }); end -des.engraving({ x = px, y = py, type = "burn", text = "Elbereth" }); -des.object({ id = "scare monster", x = px, y = py, buc = "cursed" }); +des.engraving({ coord = pt, type = "burn", text = "Elbereth" }); +des.object({ id = "scare monster", coord = pt, buc = "cursed" }); diff --git a/dat/soko1-2.lua b/dat/soko1-2.lua index 3b54a231e..8a82b02e9 100644 --- a/dat/soko1-2.lua +++ b/dat/soko1-2.lua @@ -98,13 +98,13 @@ des.door("closed",17,12) des.door("closed",17,14) des.region({ region={18,09, 22,15}, lit = 1, type = "zoo", filled = 1, irregular = 1 }); -px, py = selection.rndcoord(place); +local pt = selection.rndcoord(place); if percent(25) then - des.object({ id="bag of holding", x=px, y=py, + des.object({ id="bag of holding", coord=pt, buc="not-cursed", achievement=1 }); else - des.object({ id="amulet of reflection", x=px, y=py, + des.object({ id="amulet of reflection", coord=pt, buc="not-cursed", achievement=1 }); end -des.engraving({ x = px, y = py, type = "burn", text = "Elbereth" }); -des.object({ id = "scare monster", x = px, y = py, buc = "cursed" }); +des.engraving({ coord = pt, type = "burn", text = "Elbereth" }); +des.object({ id = "scare monster", coord = pt, buc = "cursed" }); diff --git a/doc/lua.adoc b/doc/lua.adoc index 584895bd6..322f55cb5 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -8,13 +8,16 @@ Functions exposed from the NetHack core. They are all in the `nh` table. === abscoord -Convert a relative coordinate to absolute. +Convert a room-relative coordinate to map-absolute. +Can accept one table with x and y keys (and in that case, returns similar), +or two integer values (and returns two integer values) des-routines tend to use relative coordinates, nh and obj use absolute. (This mess is still very much in need of improvement.) Example: local ax, ay = nh.abscoord(x, y); + local coord = nh.abscoord({ x = 10, y = 15 }); === an @@ -135,7 +138,8 @@ Example: local x = 20; local y = 10; local loc = nh.getmap(x,y); - nh.pline("Map location at (" .. x .. "," .. y .. ) is " .. (loc.lit ? "lit" : "unlit") ); + nh.pline("Map location at (" .. x .. "," .. y .. ) is " .. (loc.lit and "lit" or "unlit") ); + local loc2 = nh.getmap({ x = 18, y = 16 }); === get_config @@ -166,7 +170,8 @@ Returns a table with the following elements: Example: - local t = nh.gettrap(x, y); + local t1 = nh.gettrap(x, y); + local t2 = nh.gettrap({ x = 10, y = 15 }); === has_timer_at @@ -185,6 +190,7 @@ Delete a trap at x,y Example: nh.deltrap(x, y); + nh.deltrap({ x = 10, y = 10 }); === impossible @@ -281,6 +287,7 @@ When does timer at location at x,y trigger? Example: local melttime = nh.peek_timer_at(x,y, "melt-ice"); + local melttime = nh.peek_timer_at({x=5,y=6}, "melt-ice"); === pline @@ -353,6 +360,7 @@ Start a timer at location x,y, with trigger time of `when` - relative to current Example: nh.start_timer_at(x,y, "melt-ice", when); + nh.start_timer_at({x=7,y=8}, "melt-ice", when); === stop_timer_at @@ -362,6 +370,7 @@ Stop a timer at location x,y. Example: nh.stop_timer_at(x,y, "melt-ice"); + nh.stop_timer_at({x=5,y=6}, "melt-ice"); === verbalize @@ -1033,13 +1042,14 @@ Example: === rndcoord -Choose one of the selected locations, and return the x,y coordinates. +Choose one of the selected locations, and return a table with x and y keys. If the optional second argument is 1, removes the location from the selection. +If there are no coordinates in the selection, returns -1, -1. Example: - local x,y = selection.rndcoord(sel); - local x,y = selection.rndcoord(sel, 1); + local coord = selection.rndcoord(sel); + local coord = selection.rndcoord(sel, 1); === set diff --git a/include/extern.h b/include/extern.h index 6ec6fc16a..fdd2abe60 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1767,6 +1767,7 @@ extern void lcheck_param_table(lua_State *); extern schar get_table_mapchr(lua_State *, const char *); extern schar get_table_mapchr_opt(lua_State *, const char *, schar); extern short nhl_get_timertype(lua_State *, int); +extern boolean nhl_get_xy_params(lua_State *, int *, int *); extern void nhl_add_table_entry_int(lua_State *, const char *, lua_Integer); extern void nhl_add_table_entry_char(lua_State *, const char *, char); extern void nhl_add_table_entry_str(lua_State *, const char *, const char *); @@ -2537,6 +2538,7 @@ extern void selection_do_gradient(struct selectionvar *, long, long, long, long, long, long, long, long); extern int lspo_reset_level(lua_State *); extern int lspo_finalize_level(lua_State *); +extern boolean get_coord(lua_State *, int, lua_Integer *, lua_Integer *); extern int nhl_abs_coord(lua_State *); extern void update_croom(void); extern const char *get_trapname_bytype(int); diff --git a/src/nhlsel.c b/src/nhlsel.c index 04d63c739..619156917 100644 --- a/src/nhlsel.c +++ b/src/nhlsel.c @@ -320,8 +320,8 @@ l_selection_filter_percent(lua_State *L) return 1; } -/* local x,y = selection.rndcoord(sel); */ -/* local x,y = selection.rndcoord(sel, 1); */ +/* local pt = selection.rndcoord(sel); */ +/* local pt = selection.rndcoord(sel, 1); */ static int l_selection_rndcoord(lua_State *L) { @@ -338,9 +338,10 @@ l_selection_rndcoord(lua_State *L) y -= g.ystart; } lua_settop(L, 0); - lua_pushnumber(L, x); - lua_pushnumber(L, y); - return 2; + lua_newtable(L); + nhl_add_table_entry_int(L, "x", x); + nhl_add_table_entry_int(L, "y", y); + return 1; } /* internal function to get a selection and 4 integer values from lua stack. @@ -585,7 +586,7 @@ l_selection_match(lua_State *L) } for (y = 0; y <= sel->hei; y++) - for (x = 0; x < sel->wid; x++) + for (x = 1; x < sel->wid; x++) selection_setpoint(x, y, sel, mapfrag_match(mf, x,y) ? 1 : 0); mapfrag_free(&mf); @@ -801,7 +802,7 @@ l_selection_iterate(lua_State *L) if (argc == 2 && lua_type(L, 2) == LUA_TFUNCTION) { sel = l_selection_check(L, 1); for (y = 0; y < sel->hei; y++) - for (x = 0; x < sel->wid; x++) + for (x = 1; x < sel->wid; x++) if (selection_getpoint(x, y, sel)) { lua_pushvalue(L, 2); lua_pushinteger(L, x - g.xstart); diff --git a/src/nhlua.c b/src/nhlua.c index 1faef20bf..1853b067c 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -329,17 +329,19 @@ splev_typ2chr(schar typ) return 'x'; } -/* local t = gettrap(x,y); */ +/* local t = nh.gettrap(x,y); */ +/* local t = nh.gettrap({ x = 10, y = 10 }); */ static int nhl_gettrap(lua_State *L) { - int argc = lua_gettop(L); + int x, y; - if (argc == 2) { - int x = (int) lua_tointeger(L, 1); - int y = (int) lua_tointeger(L, 2); + if (!nhl_get_xy_params(L, &x, &y)) { + nhl_error(L, "Incorrect arguments"); + return 0; + } - if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { + if (isok(x, y)) { struct trap *ttmp = t_at(x,y); if (ttmp) { @@ -372,44 +374,68 @@ nhl_gettrap(lua_State *L) nhl_error(L, "No trap at location"); } else nhl_error(L, "Coordinates out of range"); - } else - nhl_error(L, "Wrong args"); return 0; } -/* deltrap(x,y); */ +/* nh.deltrap(x,y); nh.deltrap({ x = 10, y = 15 }); */ static int nhl_deltrap(lua_State *L) { - int argc = lua_gettop(L); + int x, y; - if (argc == 2) { - int x = (int) lua_tointeger(L, 1); - int y = (int) lua_tointeger(L, 2); + if (!nhl_get_xy_params(L, &x, &y)) { + nhl_error(L, "Incorrect arguments"); + return 0; + } - if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { - struct trap *ttmp = t_at(x,y); + if (isok(x, y)) { + struct trap *ttmp = t_at(x,y); - if (ttmp) - deltrap(ttmp); - } + if (ttmp) + deltrap(ttmp); } return 0; } +/* get parameters (XX,YY) or ({ x = XX, y = YY }) or ({ XX, YY }), + and set the x and y values. + return TRUE if there are such params in the stack. + */ +boolean +nhl_get_xy_params(lua_State *L, int *x, int *y) +{ + int argc = lua_gettop(L); + boolean ret = FALSE; + + if (argc == 2) { + *x = (int) lua_tointeger(L, 1); + *y = (int) lua_tointeger(L, 2); + ret = TRUE; + } else if (argc == 1 && lua_type(L, 1) == LUA_TTABLE) { + lua_Integer ax, ay; + + ret = get_coord(L, 1, &ax, &ay); + *x = (int) ax; + *y = (int) ay; + } + return ret; +} + DISABLE_WARNING_UNREACHABLE_CODE -/* local loc = getmap(x,y) */ +/* local loc = nh.getmap(x,y); */ +/* local loc = nh.getmap({ x = 10, y = 35 }); */ static int nhl_getmap(lua_State *L) { - int argc = lua_gettop(L); + int x, y; - if (argc == 2) { - int x = (int) lua_tointeger(L, 1); - int y = (int) lua_tointeger(L, 2); + if (!nhl_get_xy_params(L, &x, &y)) { + nhl_error(L, "Incorrect arguments"); + return 0; + } - if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { + if (isok(x, y)) { char buf[BUFSZ]; lua_newtable(L); @@ -478,16 +504,11 @@ nhl_getmap(lua_State *L) lua_settable(L, -3); return 1; - } else { - /* TODO: return zerorm instead? */ - nhl_error(L, "Coordinates out of range"); - return 0; - } } else { - nhl_error(L, "Incorrect arguments"); + /* TODO: return zerorm instead? */ + nhl_error(L, "Coordinates out of range"); return 0; } - return 1; } RESTORE_WARNING_CONDEXPR_IS_CONSTANT @@ -1067,62 +1088,68 @@ nhl_debug_flags(lua_State *L) /* does location at x,y have timer? */ /* local has_melttimer = nh.has_timer_at(x,y, "melt-ice"); */ +/* local has_melttimer = nh.has_timer_at({x=4,y=7}, "melt-ice"); */ static int nhl_timer_has_at(lua_State *L) { - int argc = lua_gettop(L); boolean ret = FALSE; + short timertype = nhl_get_timertype(L, -1); + int x, y; + long when; - if (argc == 3) { - xchar x = (xchar) lua_tointeger(L, 1); - xchar y = (xchar) lua_tointeger(L, 2); - short timertype = nhl_get_timertype(L, 3); - long when = spot_time_expires(x, y, timertype); + lua_pop(L, 1); /* remove timertype */ + if (!nhl_get_xy_params(L, &x, &y)) { + nhl_error(L, "nhl_timer_has_at: Wrong args"); + return 0; + } + if (isok(x, y)) { + when = spot_time_expires(x, y, timertype); ret = (when > 0L); - } else - nhl_error(L, "nhl_timer_has_at: Wrong args"); + } lua_pushboolean(L, ret); return 1; } /* when does location at x,y timer trigger? */ /* local melttime = nh.peek_timer_at(x,y, "melt-ice"); */ +/* local melttime = nh.peek_timer_at({x=5,y=6}, "melt-ice"); */ static int nhl_timer_peek_at(lua_State *L) { - int argc = lua_gettop(L); long when = 0L; + short timertype = nhl_get_timertype(L, -1); + int x, y; - if (argc == 3) { - xchar x = (xchar) lua_tointeger(L, 1); - xchar y = (xchar) lua_tointeger(L, 2); - short timertype = nhl_get_timertype(L, 3); - - if (timer_is_pos(timertype)) - when = spot_time_expires(x, y, timertype); - } else + lua_pop(L, 1); /* remove timertype */ + if (!nhl_get_xy_params(L, &x, &y)) { nhl_error(L, "nhl_timer_peek_at: Wrong args"); + return 0; + } + + if (timer_is_pos(timertype) && isok(x, y)) + when = spot_time_expires(x, y, timertype); lua_pushinteger(L, when); return 1; } /* stop timer at location x,y */ /* nh.stop_timer_at(x,y, "melt-ice"); */ +/* nh.stop_timer_at({x=6,y=8}, "melt-ice"); */ static int nhl_timer_stop_at(lua_State *L) { - int argc = lua_gettop(L); - - if (argc == 3) { - xchar x = (xchar) lua_tointeger(L, 1); - xchar y = (xchar) lua_tointeger(L, 2); - short timertype = nhl_get_timertype(L, 3); + short timertype = nhl_get_timertype(L, -1); + int x, y; - if (timer_is_pos(timertype)) - spot_stop_timers(x, y, timertype); - } else + lua_pop(L, 1); /* remove timertype */ + if (!nhl_get_xy_params(L, &x, &y)) { nhl_error(L, "nhl_timer_stop_at: Wrong args"); + return 0; + } + + if (timer_is_pos(timertype) && isok(x, y)) + spot_stop_timers(x, y, timertype); return 0; } @@ -1131,23 +1158,23 @@ nhl_timer_stop_at(lua_State *L) static int nhl_timer_start_at(lua_State *L) { - int argc = lua_gettop(L); + short timertype = nhl_get_timertype(L, -2); + long when = lua_tointeger(L, -1); + int x, y; - if (argc == 4) { - xchar x = (xchar) lua_tointeger(L, 1); - xchar y = (xchar) lua_tointeger(L, 2); - short timertype = nhl_get_timertype(L, 3); - long when = lua_tointeger(L, 4); + lua_pop(L, 2); /* remove when and timertype */ + if (!nhl_get_xy_params(L, &x, &y)) { + nhl_error(L, "nhl_timer_start_at: Wrong args"); + return 0; + } - if (timer_is_pos(timertype)) { - long where = ((long) x << 16) | (long) y; + if (timer_is_pos(timertype) && isok(x, y)) { + long where = ((long) x << 16) | (long) y; - spot_stop_timers(x, y, timertype); - (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY, - long_to_any(where)); - } - } else - nhl_error(L, "nhl_timer_stop_at: Wrong args"); + spot_stop_timers(x, y, timertype); + (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY, + long_to_any(where)); + } return 0; } diff --git a/src/sp_lev.c b/src/sp_lev.c index 2c2641a0b..e1193e045 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -93,7 +93,6 @@ static void selection_iterate(struct selectionvar *, select_iter_func, static void sel_set_ter(int, int, genericptr_t); static void sel_set_door(int, int, genericptr_t); static void sel_set_feature(int, int, genericptr_t); -static int get_coord(lua_State *, int, lua_Integer *, lua_Integer *); static void levregion_add(lev_region *); static void get_table_xy_or_coord(lua_State *, lua_Integer *, lua_Integer *); static int get_table_region(lua_State *, const char *, lua_Integer *, lua_Integer *, lua_Integer *, @@ -347,8 +346,8 @@ lvlfill_swamp(schar fg, schar bg, schar lit) lvlfill_solid(bg, lit); /* "relaxed blockwise maze" algorithm, Jamis Buck */ - for (x = 2; x <= g.x_maze_max; x += 2) - for (y = 0; y <= g.y_maze_max; y += 2) { + for (x = 2; x <= min(g.x_maze_max, COLNO-2); x += 2) + for (y = 0; y <= min(g.y_maze_max, ROWNO-2); y += 2) { int c = 0; (void) set_levltyp_lit(x, y, fg, lit); @@ -2999,7 +2998,7 @@ get_table_xy_or_coord(lua_State *L, lua_Integer *x, lua_Integer *y) if (mx == -1 && my == -1) { lua_getfield(L, 1, "coord"); - get_coord(L, -1, &mx, &my); + (void) get_coord(L, -1, &mx, &my); lua_pop(L, 1); } @@ -3062,7 +3061,7 @@ lspo_monster(lua_State *L) && lua_type(L, 2) == LUA_TTABLE) { const char *paramstr = luaL_checkstring(L, 1); - get_coord(L, 2, &mx, &my); + (void) get_coord(L, 2, &mx, &my); if (strlen(paramstr) == 1) { tmpmons.class = *paramstr; @@ -3325,7 +3324,7 @@ lspo_object(lua_State *L) && lua_type(L, 2) == LUA_TTABLE) { const char *paramstr = luaL_checkstring(L, 1); - get_coord(L, 2, &ox, &oy); + (void) get_coord(L, 2, &ox, &oy); if (strlen(paramstr) == 1) { tmpobj.class = *paramstr; @@ -3592,7 +3591,7 @@ lspo_engraving(lua_State *L) txt = get_table_str(L, "text"); } else if (argc == 3) { lua_Integer ex, ey; - get_coord(L, 1, &ex, &ey); + (void) get_coord(L, 1, &ex, &ey); x = ex; y = ey; etyp = engrtypes2i[luaL_checkoption(L, 2, "engrave", engrtypes)]; @@ -4069,7 +4068,7 @@ lspo_trap(lua_State *L) const char *trapstr = luaL_checkstring(L, 1); tmptrap.type = get_traptype_byname(trapstr); - get_coord(L, 2, &x, &y); + (void) get_coord(L, 2, &x, &y); } else if (argc == 3) { const char *trapstr = luaL_checkstring(L, 1); @@ -4088,7 +4087,7 @@ lspo_trap(lua_State *L) if (lua_type(L, -1) == LUA_TTABLE) { lua_Integer lx = -1, ly = -1; - get_coord(L, -1, &lx, &ly); + (void) get_coord(L, -1, &lx, &ly); lua_pop(L, 1); g.launchplace.x = lx; g.launchplace.y = ly; @@ -4131,7 +4130,7 @@ lspo_gold(lua_State *L) y = gy = luaL_checkinteger(L, 2); } else if (argc == 2 && lua_type(L, 2) == LUA_TTABLE) { amount = luaL_checkinteger(L, 1); - get_coord(L, 2, &gx, &gy); + (void) get_coord(L, 2, &gx, &gy); x = gx; y = gy; } else if (argc == 0 || (argc == 1 && lua_type(L, 1) == LUA_TTABLE)) { @@ -4290,7 +4289,7 @@ selection_filter_mapchar(struct selectionvar* ov, xchar typ, int lit) if (!ov || !ret) return NULL; - for (x = 0; x < ret->wid; x++) + for (x = 1; x < ret->wid; x++) for (y = 0; y < ret->hei; y++) if (selection_getpoint(x, y, ov) && match_maptyps(typ, levl[x][y].typ)) { @@ -4332,14 +4331,14 @@ selection_rndcoord(struct selectionvar* ov, xchar *x, xchar *y, boolean removeit int c; int dx, dy; - for (dx = 0; dx < ov->wid; dx++) + for (dx = 1; dx < ov->wid; dx++) for (dy = 0; dy < ov->hei; dy++) if (selection_getpoint(dx, dy, ov)) idx++; if (idx) { c = rn2(idx); - for (dx = 0; dx < ov->wid; dx++) + for (dx = 1; dx < ov->wid; dx++) for (dy = 0; dy < ov->hei; dy++) if (selection_getpoint(dx, dy, ov)) { if (!c) { @@ -4791,7 +4790,7 @@ selection_iterate( /* yes, this is very naive, but it's not _that_ expensive. */ for (x = 0; x < ov->wid; x++) for (y = 0; y < ov->hei; y++) - if (selection_getpoint(x, y, ov)) + if (isok(x,y) && selection_getpoint(x, y, ov)) (*func)(x, y, arg); } @@ -4924,7 +4923,10 @@ l_table_getset_feature_flag( } } -/* convert relative coordinate to absolute */ +/* convert relative coordinate to map-absolute. + local ax,ay = nh.abscoord(rx, ry); + local pt = nh.abscoord({ x = 10, y = 5 }); + */ int nhl_abs_coord(lua_State *L) { @@ -4936,11 +4938,22 @@ nhl_abs_coord(lua_State *L) y = (xchar) lua_tointeger(L, 2); x += g.xstart; y += g.ystart; - } else + lua_pushinteger(L, x); + lua_pushinteger(L, y); + return 2; + } else if (argc == 1 && lua_type(L, 1) == LUA_TTABLE) { + x = (xchar) get_table_int(L, "x"); + y = (xchar) get_table_int(L, "y"); + x += g.xstart; + y += g.ystart; + lua_newtable(L); + nhl_add_table_entry_int(L, "x", x); + nhl_add_table_entry_int(L, "y", y); + return 1; + } else { nhl_error(L, "nhl_abs_coord: Wrong args"); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - return 2; + return 0; + } } /* feature("fountain", x, y); */ @@ -4966,7 +4979,7 @@ lspo_feature(lua_State *L) && lua_type(L, 2) == LUA_TTABLE) { lua_Integer fx, fy; typ = features2i[luaL_checkoption(L, 1, NULL, features)]; - get_coord(L, 2, &fx, &fy); + (void) get_coord(L, 2, &fx, &fy); x = fx; y = fy; } else if (argc == 3) { @@ -5056,7 +5069,7 @@ lspo_terrain(lua_State *L) lua_Integer tx, ty; tmpterrain.ter = check_mapchr(luaL_checkstring(L, 2)); lua_pop(L, 1); - get_coord(L, 1, &tx, &ty); + (void) get_coord(L, 1, &tx, &ty); x = tx; y = ty; } else if (argc == 2) { @@ -5165,7 +5178,7 @@ lspo_replace_terrain(lua_State *L) } for (y = 0; y <= sel->hei; y++) - for (x = 0; x < sel->wid; x++) + for (x = 1; x < sel->wid; x++) if (selection_getpoint(x, y,sel)) { if (mf) { if (mapfrag_match(mf, x, y) && (rn2(100)) < chance) @@ -5354,26 +5367,48 @@ get_table_region( return 1; } -static int +boolean get_coord(lua_State *L, int i, lua_Integer *x, lua_Integer *y) { + boolean ret = FALSE; + if (lua_type(L, i) == LUA_TTABLE) { int arrlen; + boolean gotx = FALSE; - lua_len(L, i); - arrlen = lua_tointeger(L, -1); - lua_pop(L, 1); - if (arrlen != 2) { - nhl_error(L, "Not a coordinate"); - return 0; + lua_getfield(L, i, "x"); + if (!lua_isnil(L, -1)) { + *x = luaL_checkinteger(L, -1); + gotx = TRUE; } + lua_pop(L, 1); - *x = get_table_intarray_entry(L, i, 1); - *y = get_table_intarray_entry(L, i, 2); + if (gotx) { + lua_getfield(L, i, "y"); + if (!lua_isnil(L, -1)) { + *y = luaL_checkinteger(L, -1); + lua_pop(L, 1); + ret = TRUE; + } else { + nhl_error(L, "Not a coordinate"); + return FALSE; + } + } else { + lua_len(L, i); + arrlen = lua_tointeger(L, -1); + lua_pop(L, 1); + if (arrlen != 2) { + nhl_error(L, "Not a coordinate"); + return FALSE; + } - return 1; + *x = get_table_intarray_entry(L, i, 1); + *y = get_table_intarray_entry(L, i, 2); + + return TRUE; + } } - return 0; + return ret; } static void diff --git a/test/test_des.lua b/test/test_des.lua index acc378c76..4a5698aed 100644 --- a/test/test_des.lua +++ b/test/test_des.lua @@ -521,4 +521,5 @@ function run_tests() des.level_init(); end +nh.debug_flags({mongen = false, hunger = false, overwrite_stairs = true }); run_tests(); diff --git a/test/test_sel.lua b/test/test_sel.lua index a6a3295b5..eaccba54f 100644 --- a/test/test_sel.lua +++ b/test/test_sel.lua @@ -61,14 +61,14 @@ function test_selection_params() sel:set(1, 2); sel_pt_ne(sel, 1,2, 1, "test_selection_params 2"); - local x,y = sel:rndcoord(1); - if x ~= 1 or y ~= 2 then - error("sel:rndcoord returned unset coordinate"); + local pt = sel:rndcoord(1); + if pt.x ~= 1 or pt.y ~= 2 then + error("sel:rndcoord returned unset coordinate (" .. pt.x .. "," .. pt.y .. ")"); end - x,y = sel:rndcoord(1); - if x ~= -2 and y ~= -1 then - error("sel:rndcoord returned (" .. x .. "," .. y .. ") coordinate"); + pt = sel:rndcoord(1); + if pt.x ~= -2 or pt.y ~= -1 then + error("sel:rndcoord returned (" .. pt.x .. "," .. pt.y .. ") coordinate"); end -- OO style @@ -466,6 +466,7 @@ function test_sel_iterate() is_map_at(9,5, "L"); end +nh.debug_flags({mongen = false, hunger = false, overwrite_stairs = true }); test_selection_params(); test_sel_negate(); test_sel_logical_and();