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.
This commit is contained in:
Pasi Kallinen
2022-03-22 09:16:19 +02:00
parent 6fb0c8a82e
commit 27898340b9
19 changed files with 240 additions and 173 deletions
+1 -2
View File
@@ -95,6 +95,5 @@ des.monster("giant eel", 39, 15)
-- Monsters on siege duty. -- Monsters on siege duty.
local ogrelocs = selection.floodfill(37,7) & selection.area(40,03, 45,20) local ogrelocs = selection.floodfill(37,7) & selection.area(40,03, 45,20)
for i = 0, 11 do for i = 0, 11 do
local x,y = ogrelocs:rndcoord(1); des.monster({ id = "ogre", coord = ogrelocs:rndcoord(1), peaceful = 0 })
des.monster({ id = "ogre", coord={x,y}, peaceful=0 })
end end
+3 -6
View File
@@ -88,8 +88,7 @@ des.monster("abbot", 33, 12)
des.non_diggable(selection.area(18,03,55,16)) des.non_diggable(selection.area(18,03,55,16))
-- Random traps -- Random traps
for i = 1, 2 do for i = 1, 2 do
local x,y = spacelocs:rndcoord(1); des.trap("dart", spacelocs:rndcoord(1))
des.trap("dart",x,y)
end end
des.trap() des.trap()
des.trap() des.trap()
@@ -97,10 +96,8 @@ des.trap()
des.trap() des.trap()
-- Monsters on siege duty. -- Monsters on siege duty.
for i = 1, 8 do for i = 1, 8 do
local x,y = spacelocs:rndcoord(1); des.monster("earth elemental", spacelocs:rndcoord(1))
des.monster("earth elemental", x, y)
end end
for i = 1, 4 do for i = 1, 4 do
local x,y = spacelocs:rndcoord(1); des.monster("xorn", spacelocs:rndcoord(1))
des.monster("xorn", x, y)
end end
+2 -4
View File
@@ -90,8 +90,7 @@ des.monster("acolyte", 33, 12)
des.non_diggable(selection.area(18,03,55,16)) des.non_diggable(selection.area(18,03,55,16))
-- Random traps -- Random traps
for i = 1, 2 do for i = 1, 2 do
local x,y = spacelocs:rndcoord(1); des.trap("dart", spacelocs:rndcoord(1))
des.trap("dart",x,y)
end end
des.trap() des.trap()
des.trap() des.trap()
@@ -99,6 +98,5 @@ des.trap()
des.trap() des.trap()
-- Monsters on siege duty. -- Monsters on siege duty.
for i = 1, 12 do for i = 1, 12 do
local x,y = spacelocs:rndcoord(1); des.monster("human zombie", spacelocs:rndcoord(1));
des.monster("human zombie", x, y);
end end
+3 -3
View File
@@ -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 }) des.monster({ id = "water nymph", x=25, y=18, peaceful=0 })
-- Wandering the streets. -- Wandering the streets.
for i=1,4 + math.random(1 - 1,1*3) do 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 = "water nymph", coord = streets:rndcoord(1), peaceful=0 })
des.monster({ id = "leprechaun", coord = {streets:rndcoord(1)}, peaceful=0 }) des.monster({ id = "leprechaun", coord = streets:rndcoord(1), peaceful=0 })
end end
for i=1,7 + math.random(1 - 1,1*3) do 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 end
+5 -5
View File
@@ -59,9 +59,9 @@ for i=1,2 do
end end
-- extra monsters; was [6 + 3d4] when both wings were opened up at once -- extra monsters; was [6 + 3d4] when both wings were opened up at once
for i=1,3 + math.random(2 - 1,2*3) do 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 if percent(50) then
des.monster({ coord = { hall:rndcoord(1) }, peaceful=0 }) des.monster({ coord = hall:rndcoord(1), peaceful=0 })
end end
end 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 = "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=09,align="noalign", peaceful=0 })
des.monster({ id = "Angel",x=20,y=10,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 -- South-central round room
des.monster({ id = "aligned cleric",x=36,y=12,align="noalign", peaceful=0 }) 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 }) 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 = "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=38,y=13,align="noalign", peaceful=0 })
des.monster({ id = "Angel",x=37,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 -- East round room
des.monster({ id = "aligned cleric",x=56,y=09,align="noalign", peaceful=0 }) 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 }) 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 = "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=09,align="noalign", peaceful=0 })
des.monster({ id = "Angel",x=54,y=10,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 -- The aligned horde
-- --
+1 -2
View File
@@ -140,8 +140,7 @@ des.object(object[4],53,11)
des.object(object[4],54,11) des.object(object[4],54,11)
des.object(object[4],55,11) des.object(object[4],55,11)
-- THE WAND OF WISHING in 1 of the 4 towers -- THE WAND OF WISHING in 1 of the 4 towers
local px, py = place:rndcoord(1); des.object({ id = "chest", trapped = 0, locked = 1, coord = place:rndcoord(1),
des.object({ id = "chest", trapped = 0, locked = 1, x = px, y = py,
contents = function() contents = function()
des.object("wishing"); des.object("wishing");
end end
+3 -3
View File
@@ -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 = {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.teleport_region({ region = {69,00,79,20}, region_islev=1, exclude={0,0,50,17},dir="down" })
des.feature("fountain", place:rndcoord(1)) 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 -- The demon of the swamp
des.monster("Juiblex",25,08) des.monster("Juiblex",25,08)
-- And a couple demons -- And a couple demons
+4 -6
View File
@@ -53,18 +53,16 @@ des.non_diggable(selection.area(44,13,48,17))
-- restricting the placement when teleporting from levels below this. -- restricting the placement when teleporting from levels below this.
des.teleport_region({ region = {33,02,38,07}, dir="down" }) des.teleport_region({ region = {33,02,38,07}, dir="down" })
des.levregion({ region = {32,01,39,07}, type="stair-up" }); 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",08,08)
des.door("locked",64,05) des.door("locked",64,05)
des.door("random",50,13) des.door("random",50,13)
des.door("locked",48,15) des.door("locked",48,15)
-- --
local px, py = place:rndcoord(1); des.feature("fountain", place:rndcoord(1));
des.feature("fountain", px,py);
-- --
local px, py = place:rndcoord(1); des.object({ id="statue", coord=place:rndcoord(1), buc = "uncursed",
des.object({ id="statue",x=px, y=py, buc="uncursed",
montype="knight", historic=1, male=1,name="Perseus", montype="knight", historic=1, male=1,name="Perseus",
contents = function() contents = function()
if percent(75) then if percent(75) then
+3 -4
View File
@@ -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.teleport_region({ region = {02,02,18,13}, dir="up" });
-- --
des.levregion({ region = {67,01,74,20}, type="stair-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,06)
des.door("locked",04,10) des.door("locked",04,10)
@@ -66,8 +66,7 @@ des.non_diggable(selection.area(01,01,22,14));
-- --
des.object("crystal ball", 07,08) des.object("crystal ball", 07,08)
-- --
local px, py = place:rndcoord(1); des.object({ id="statue",coord=place:rndcoord(1), buc="uncursed",
des.object({ id="statue",x=px, y=py, buc="uncursed",
montype="knight", historic=1, male=1,name="Perseus", montype="knight", historic=1, male=1,name="Perseus",
contents = function() contents = function()
if percent(75) then if percent(75) then
+4 -4
View File
@@ -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 for i=1,5 + math.random(1 - 1,1*10) do
if percent(50) then 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 else
if percent(80) then 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 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 end
end end
-- shamans can be hanging out in/near the temple -- shamans can be hanging out in/near the temple
for i=1,math.random(2 - 1,2*3) do 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 end
-- these are not such a big deal -- these are not such a big deal
-- to run into outside the bars -- to run into outside the bars
+5 -5
View File
@@ -96,14 +96,14 @@ des.door("closed", 17, 15);
des.region({ region={18,10, 22,16}, lit = 1, type = "zoo", filled = 1, irregular = 1 }); 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 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 }); buc="not-cursed", achievement=1 });
else else
des.object({ id="amulet of reflection", x=px, y=py, des.object({ id="amulet of reflection", coord=pt,
buc="not-cursed", achievement=1 }); buc="not-cursed", achievement=1 });
end end
des.engraving({ x = px, y = py, type = "burn", text = "Elbereth" }); des.engraving({ coord = pt, type = "burn", text = "Elbereth" });
des.object({ id = "scare monster", x = px, y = py, buc = "cursed" }); des.object({ id = "scare monster", coord = pt, buc = "cursed" });
+5 -5
View File
@@ -98,13 +98,13 @@ des.door("closed",17,12)
des.door("closed",17,14) des.door("closed",17,14)
des.region({ region={18,09, 22,15}, lit = 1, type = "zoo", filled = 1, irregular = 1 }); 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 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 }); buc="not-cursed", achievement=1 });
else else
des.object({ id="amulet of reflection", x=px, y=py, des.object({ id="amulet of reflection", coord=pt,
buc="not-cursed", achievement=1 }); buc="not-cursed", achievement=1 });
end end
des.engraving({ x = px, y = py, type = "burn", text = "Elbereth" }); des.engraving({ coord = pt, type = "burn", text = "Elbereth" });
des.object({ id = "scare monster", x = px, y = py, buc = "cursed" }); des.object({ id = "scare monster", coord = pt, buc = "cursed" });
+16 -6
View File
@@ -8,13 +8,16 @@ Functions exposed from the NetHack core. They are all in the `nh` table.
=== abscoord === 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. des-routines tend to use relative coordinates, nh and obj use absolute.
(This mess is still very much in need of improvement.) (This mess is still very much in need of improvement.)
Example: Example:
local ax, ay = nh.abscoord(x, y); local ax, ay = nh.abscoord(x, y);
local coord = nh.abscoord({ x = 10, y = 15 });
=== an === an
@@ -135,7 +138,8 @@ Example:
local x = 20; local x = 20;
local y = 10; local y = 10;
local loc = nh.getmap(x,y); 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 === get_config
@@ -166,7 +170,8 @@ Returns a table with the following elements:
Example: Example:
local t = nh.gettrap(x, y); local t1 = nh.gettrap(x, y);
local t2 = nh.gettrap({ x = 10, y = 15 });
=== has_timer_at === has_timer_at
@@ -185,6 +190,7 @@ Delete a trap at x,y
Example: Example:
nh.deltrap(x, y); nh.deltrap(x, y);
nh.deltrap({ x = 10, y = 10 });
=== impossible === impossible
@@ -281,6 +287,7 @@ When does timer at location at x,y trigger?
Example: Example:
local melttime = nh.peek_timer_at(x,y, "melt-ice"); local melttime = nh.peek_timer_at(x,y, "melt-ice");
local melttime = nh.peek_timer_at({x=5,y=6}, "melt-ice");
=== pline === pline
@@ -353,6 +360,7 @@ Start a timer at location x,y, with trigger time of `when` - relative to current
Example: Example:
nh.start_timer_at(x,y, "melt-ice", when); nh.start_timer_at(x,y, "melt-ice", when);
nh.start_timer_at({x=7,y=8}, "melt-ice", when);
=== stop_timer_at === stop_timer_at
@@ -362,6 +370,7 @@ Stop a timer at location x,y.
Example: Example:
nh.stop_timer_at(x,y, "melt-ice"); nh.stop_timer_at(x,y, "melt-ice");
nh.stop_timer_at({x=5,y=6}, "melt-ice");
=== verbalize === verbalize
@@ -1033,13 +1042,14 @@ Example:
=== rndcoord === 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 the optional second argument is 1, removes the location from the selection.
If there are no coordinates in the selection, returns -1, -1.
Example: Example:
local x,y = selection.rndcoord(sel); local coord = selection.rndcoord(sel);
local x,y = selection.rndcoord(sel, 1); local coord = selection.rndcoord(sel, 1);
=== set === set
+2
View File
@@ -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(lua_State *, const char *);
extern schar get_table_mapchr_opt(lua_State *, const char *, schar); extern schar get_table_mapchr_opt(lua_State *, const char *, schar);
extern short nhl_get_timertype(lua_State *, int); 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_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_char(lua_State *, const char *, char);
extern void nhl_add_table_entry_str(lua_State *, const char *, const 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); long, long, long, long, long);
extern int lspo_reset_level(lua_State *); extern int lspo_reset_level(lua_State *);
extern int lspo_finalize_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 int nhl_abs_coord(lua_State *);
extern void update_croom(void); extern void update_croom(void);
extern const char *get_trapname_bytype(int); extern const char *get_trapname_bytype(int);
+8 -7
View File
@@ -320,8 +320,8 @@ l_selection_filter_percent(lua_State *L)
return 1; return 1;
} }
/* local x,y = selection.rndcoord(sel); */ /* local pt = selection.rndcoord(sel); */
/* local x,y = selection.rndcoord(sel, 1); */ /* local pt = selection.rndcoord(sel, 1); */
static int static int
l_selection_rndcoord(lua_State *L) l_selection_rndcoord(lua_State *L)
{ {
@@ -338,9 +338,10 @@ l_selection_rndcoord(lua_State *L)
y -= g.ystart; y -= g.ystart;
} }
lua_settop(L, 0); lua_settop(L, 0);
lua_pushnumber(L, x); lua_newtable(L);
lua_pushnumber(L, y); nhl_add_table_entry_int(L, "x", x);
return 2; nhl_add_table_entry_int(L, "y", y);
return 1;
} }
/* internal function to get a selection and 4 integer values from lua stack. /* 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 (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); selection_setpoint(x, y, sel, mapfrag_match(mf, x,y) ? 1 : 0);
mapfrag_free(&mf); mapfrag_free(&mf);
@@ -801,7 +802,7 @@ l_selection_iterate(lua_State *L)
if (argc == 2 && lua_type(L, 2) == LUA_TFUNCTION) { if (argc == 2 && lua_type(L, 2) == LUA_TFUNCTION) {
sel = l_selection_check(L, 1); sel = l_selection_check(L, 1);
for (y = 0; y < sel->hei; y++) 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 (selection_getpoint(x, y, sel)) {
lua_pushvalue(L, 2); lua_pushvalue(L, 2);
lua_pushinteger(L, x - g.xstart); lua_pushinteger(L, x - g.xstart);
+99 -72
View File
@@ -329,17 +329,19 @@ splev_typ2chr(schar typ)
return 'x'; return 'x';
} }
/* local t = gettrap(x,y); */ /* local t = nh.gettrap(x,y); */
/* local t = nh.gettrap({ x = 10, y = 10 }); */
static int static int
nhl_gettrap(lua_State *L) nhl_gettrap(lua_State *L)
{ {
int argc = lua_gettop(L); int x, y;
if (argc == 2) { if (!nhl_get_xy_params(L, &x, &y)) {
int x = (int) lua_tointeger(L, 1); nhl_error(L, "Incorrect arguments");
int y = (int) lua_tointeger(L, 2); return 0;
}
if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { if (isok(x, y)) {
struct trap *ttmp = t_at(x,y); struct trap *ttmp = t_at(x,y);
if (ttmp) { if (ttmp) {
@@ -372,44 +374,68 @@ nhl_gettrap(lua_State *L)
nhl_error(L, "No trap at location"); nhl_error(L, "No trap at location");
} else } else
nhl_error(L, "Coordinates out of range"); nhl_error(L, "Coordinates out of range");
} else
nhl_error(L, "Wrong args");
return 0; return 0;
} }
/* deltrap(x,y); */ /* nh.deltrap(x,y); nh.deltrap({ x = 10, y = 15 }); */
static int static int
nhl_deltrap(lua_State *L) nhl_deltrap(lua_State *L)
{ {
int argc = lua_gettop(L); int x, y;
if (argc == 2) { if (!nhl_get_xy_params(L, &x, &y)) {
int x = (int) lua_tointeger(L, 1); nhl_error(L, "Incorrect arguments");
int y = (int) lua_tointeger(L, 2); return 0;
}
if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { if (isok(x, y)) {
struct trap *ttmp = t_at(x,y); struct trap *ttmp = t_at(x,y);
if (ttmp) if (ttmp)
deltrap(ttmp); deltrap(ttmp);
}
} }
return 0; 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 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 static int
nhl_getmap(lua_State *L) nhl_getmap(lua_State *L)
{ {
int argc = lua_gettop(L); int x, y;
if (argc == 2) { if (!nhl_get_xy_params(L, &x, &y)) {
int x = (int) lua_tointeger(L, 1); nhl_error(L, "Incorrect arguments");
int y = (int) lua_tointeger(L, 2); return 0;
}
if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) { if (isok(x, y)) {
char buf[BUFSZ]; char buf[BUFSZ];
lua_newtable(L); lua_newtable(L);
@@ -478,16 +504,11 @@ nhl_getmap(lua_State *L)
lua_settable(L, -3); lua_settable(L, -3);
return 1; return 1;
} else {
/* TODO: return zerorm instead? */
nhl_error(L, "Coordinates out of range");
return 0;
}
} else { } else {
nhl_error(L, "Incorrect arguments"); /* TODO: return zerorm instead? */
nhl_error(L, "Coordinates out of range");
return 0; return 0;
} }
return 1;
} }
RESTORE_WARNING_CONDEXPR_IS_CONSTANT RESTORE_WARNING_CONDEXPR_IS_CONSTANT
@@ -1067,62 +1088,68 @@ nhl_debug_flags(lua_State *L)
/* does location at x,y have timer? */ /* 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,y, "melt-ice"); */
/* local has_melttimer = nh.has_timer_at({x=4,y=7}, "melt-ice"); */
static int static int
nhl_timer_has_at(lua_State *L) nhl_timer_has_at(lua_State *L)
{ {
int argc = lua_gettop(L);
boolean ret = FALSE; boolean ret = FALSE;
short timertype = nhl_get_timertype(L, -1);
int x, y;
long when;
if (argc == 3) { lua_pop(L, 1); /* remove timertype */
xchar x = (xchar) lua_tointeger(L, 1); if (!nhl_get_xy_params(L, &x, &y)) {
xchar y = (xchar) lua_tointeger(L, 2);
short timertype = nhl_get_timertype(L, 3);
long when = spot_time_expires(x, y, timertype);
ret = (when > 0L);
} else
nhl_error(L, "nhl_timer_has_at: Wrong args"); 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);
}
lua_pushboolean(L, ret); lua_pushboolean(L, ret);
return 1; return 1;
} }
/* when does location at x,y timer trigger? */ /* 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,y, "melt-ice"); */
/* local melttime = nh.peek_timer_at({x=5,y=6}, "melt-ice"); */
static int static int
nhl_timer_peek_at(lua_State *L) nhl_timer_peek_at(lua_State *L)
{ {
int argc = lua_gettop(L);
long when = 0L; long when = 0L;
short timertype = nhl_get_timertype(L, -1);
int x, y;
if (argc == 3) { lua_pop(L, 1); /* remove timertype */
xchar x = (xchar) lua_tointeger(L, 1); if (!nhl_get_xy_params(L, &x, &y)) {
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
nhl_error(L, "nhl_timer_peek_at: Wrong args"); 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); lua_pushinteger(L, when);
return 1; return 1;
} }
/* stop timer at location x,y */ /* stop timer at location x,y */
/* nh.stop_timer_at(x,y, "melt-ice"); */ /* nh.stop_timer_at(x,y, "melt-ice"); */
/* nh.stop_timer_at({x=6,y=8}, "melt-ice"); */
static int static int
nhl_timer_stop_at(lua_State *L) nhl_timer_stop_at(lua_State *L)
{ {
int argc = lua_gettop(L); short timertype = nhl_get_timertype(L, -1);
int x, y;
if (argc == 3) { lua_pop(L, 1); /* remove timertype */
xchar x = (xchar) lua_tointeger(L, 1); if (!nhl_get_xy_params(L, &x, &y)) {
xchar y = (xchar) lua_tointeger(L, 2);
short timertype = nhl_get_timertype(L, 3);
if (timer_is_pos(timertype))
spot_stop_timers(x, y, timertype);
} else
nhl_error(L, "nhl_timer_stop_at: Wrong args"); 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; return 0;
} }
@@ -1131,23 +1158,23 @@ nhl_timer_stop_at(lua_State *L)
static int static int
nhl_timer_start_at(lua_State *L) 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) { lua_pop(L, 2); /* remove when and timertype */
xchar x = (xchar) lua_tointeger(L, 1); if (!nhl_get_xy_params(L, &x, &y)) {
xchar y = (xchar) lua_tointeger(L, 2); nhl_error(L, "nhl_timer_start_at: Wrong args");
short timertype = nhl_get_timertype(L, 3); return 0;
long when = lua_tointeger(L, 4); }
if (timer_is_pos(timertype)) { if (timer_is_pos(timertype) && isok(x, y)) {
long where = ((long) x << 16) | (long) y; long where = ((long) x << 16) | (long) y;
spot_stop_timers(x, y, timertype); spot_stop_timers(x, y, timertype);
(void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY, (void) start_timer((long) when, TIMER_LEVEL, MELT_ICE_AWAY,
long_to_any(where)); long_to_any(where));
} }
} else
nhl_error(L, "nhl_timer_stop_at: Wrong args");
return 0; return 0;
} }
+68 -33
View File
@@ -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_ter(int, int, genericptr_t);
static void sel_set_door(int, int, genericptr_t); static void sel_set_door(int, int, genericptr_t);
static void sel_set_feature(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 levregion_add(lev_region *);
static void get_table_xy_or_coord(lua_State *, lua_Integer *, lua_Integer *); 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 *, 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); lvlfill_solid(bg, lit);
/* "relaxed blockwise maze" algorithm, Jamis Buck */ /* "relaxed blockwise maze" algorithm, Jamis Buck */
for (x = 2; x <= g.x_maze_max; x += 2) for (x = 2; x <= min(g.x_maze_max, COLNO-2); x += 2)
for (y = 0; y <= g.y_maze_max; y += 2) { for (y = 0; y <= min(g.y_maze_max, ROWNO-2); y += 2) {
int c = 0; int c = 0;
(void) set_levltyp_lit(x, y, fg, lit); (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) { if (mx == -1 && my == -1) {
lua_getfield(L, 1, "coord"); lua_getfield(L, 1, "coord");
get_coord(L, -1, &mx, &my); (void) get_coord(L, -1, &mx, &my);
lua_pop(L, 1); lua_pop(L, 1);
} }
@@ -3062,7 +3061,7 @@ lspo_monster(lua_State *L)
&& lua_type(L, 2) == LUA_TTABLE) { && lua_type(L, 2) == LUA_TTABLE) {
const char *paramstr = luaL_checkstring(L, 1); const char *paramstr = luaL_checkstring(L, 1);
get_coord(L, 2, &mx, &my); (void) get_coord(L, 2, &mx, &my);
if (strlen(paramstr) == 1) { if (strlen(paramstr) == 1) {
tmpmons.class = *paramstr; tmpmons.class = *paramstr;
@@ -3325,7 +3324,7 @@ lspo_object(lua_State *L)
&& lua_type(L, 2) == LUA_TTABLE) { && lua_type(L, 2) == LUA_TTABLE) {
const char *paramstr = luaL_checkstring(L, 1); const char *paramstr = luaL_checkstring(L, 1);
get_coord(L, 2, &ox, &oy); (void) get_coord(L, 2, &ox, &oy);
if (strlen(paramstr) == 1) { if (strlen(paramstr) == 1) {
tmpobj.class = *paramstr; tmpobj.class = *paramstr;
@@ -3592,7 +3591,7 @@ lspo_engraving(lua_State *L)
txt = get_table_str(L, "text"); txt = get_table_str(L, "text");
} else if (argc == 3) { } else if (argc == 3) {
lua_Integer ex, ey; lua_Integer ex, ey;
get_coord(L, 1, &ex, &ey); (void) get_coord(L, 1, &ex, &ey);
x = ex; x = ex;
y = ey; y = ey;
etyp = engrtypes2i[luaL_checkoption(L, 2, "engrave", engrtypes)]; etyp = engrtypes2i[luaL_checkoption(L, 2, "engrave", engrtypes)];
@@ -4069,7 +4068,7 @@ lspo_trap(lua_State *L)
const char *trapstr = luaL_checkstring(L, 1); const char *trapstr = luaL_checkstring(L, 1);
tmptrap.type = get_traptype_byname(trapstr); tmptrap.type = get_traptype_byname(trapstr);
get_coord(L, 2, &x, &y); (void) get_coord(L, 2, &x, &y);
} else if (argc == 3) { } else if (argc == 3) {
const char *trapstr = luaL_checkstring(L, 1); const char *trapstr = luaL_checkstring(L, 1);
@@ -4088,7 +4087,7 @@ lspo_trap(lua_State *L)
if (lua_type(L, -1) == LUA_TTABLE) { if (lua_type(L, -1) == LUA_TTABLE) {
lua_Integer lx = -1, ly = -1; lua_Integer lx = -1, ly = -1;
get_coord(L, -1, &lx, &ly); (void) get_coord(L, -1, &lx, &ly);
lua_pop(L, 1); lua_pop(L, 1);
g.launchplace.x = lx; g.launchplace.x = lx;
g.launchplace.y = ly; g.launchplace.y = ly;
@@ -4131,7 +4130,7 @@ lspo_gold(lua_State *L)
y = gy = luaL_checkinteger(L, 2); y = gy = luaL_checkinteger(L, 2);
} else if (argc == 2 && lua_type(L, 2) == LUA_TTABLE) { } else if (argc == 2 && lua_type(L, 2) == LUA_TTABLE) {
amount = luaL_checkinteger(L, 1); amount = luaL_checkinteger(L, 1);
get_coord(L, 2, &gx, &gy); (void) get_coord(L, 2, &gx, &gy);
x = gx; x = gx;
y = gy; y = gy;
} else if (argc == 0 || (argc == 1 && lua_type(L, 1) == LUA_TTABLE)) { } 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) if (!ov || !ret)
return NULL; return NULL;
for (x = 0; x < ret->wid; x++) for (x = 1; x < ret->wid; x++)
for (y = 0; y < ret->hei; y++) for (y = 0; y < ret->hei; y++)
if (selection_getpoint(x, y, ov) if (selection_getpoint(x, y, ov)
&& match_maptyps(typ, levl[x][y].typ)) { && 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 c;
int dx, dy; int dx, dy;
for (dx = 0; dx < ov->wid; dx++) for (dx = 1; dx < ov->wid; dx++)
for (dy = 0; dy < ov->hei; dy++) for (dy = 0; dy < ov->hei; dy++)
if (selection_getpoint(dx, dy, ov)) if (selection_getpoint(dx, dy, ov))
idx++; idx++;
if (idx) { if (idx) {
c = rn2(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++) for (dy = 0; dy < ov->hei; dy++)
if (selection_getpoint(dx, dy, ov)) { if (selection_getpoint(dx, dy, ov)) {
if (!c) { if (!c) {
@@ -4791,7 +4790,7 @@ selection_iterate(
/* yes, this is very naive, but it's not _that_ expensive. */ /* yes, this is very naive, but it's not _that_ expensive. */
for (x = 0; x < ov->wid; x++) for (x = 0; x < ov->wid; x++)
for (y = 0; y < ov->hei; y++) 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); (*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 int
nhl_abs_coord(lua_State *L) nhl_abs_coord(lua_State *L)
{ {
@@ -4936,11 +4938,22 @@ nhl_abs_coord(lua_State *L)
y = (xchar) lua_tointeger(L, 2); y = (xchar) lua_tointeger(L, 2);
x += g.xstart; x += g.xstart;
y += g.ystart; 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"); nhl_error(L, "nhl_abs_coord: Wrong args");
lua_pushinteger(L, x); return 0;
lua_pushinteger(L, y); }
return 2;
} }
/* feature("fountain", x, y); */ /* feature("fountain", x, y); */
@@ -4966,7 +4979,7 @@ lspo_feature(lua_State *L)
&& lua_type(L, 2) == LUA_TTABLE) { && lua_type(L, 2) == LUA_TTABLE) {
lua_Integer fx, fy; lua_Integer fx, fy;
typ = features2i[luaL_checkoption(L, 1, NULL, features)]; typ = features2i[luaL_checkoption(L, 1, NULL, features)];
get_coord(L, 2, &fx, &fy); (void) get_coord(L, 2, &fx, &fy);
x = fx; x = fx;
y = fy; y = fy;
} else if (argc == 3) { } else if (argc == 3) {
@@ -5056,7 +5069,7 @@ lspo_terrain(lua_State *L)
lua_Integer tx, ty; lua_Integer tx, ty;
tmpterrain.ter = check_mapchr(luaL_checkstring(L, 2)); tmpterrain.ter = check_mapchr(luaL_checkstring(L, 2));
lua_pop(L, 1); lua_pop(L, 1);
get_coord(L, 1, &tx, &ty); (void) get_coord(L, 1, &tx, &ty);
x = tx; x = tx;
y = ty; y = ty;
} else if (argc == 2) { } else if (argc == 2) {
@@ -5165,7 +5178,7 @@ lspo_replace_terrain(lua_State *L)
} }
for (y = 0; y <= sel->hei; y++) 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 (selection_getpoint(x, y,sel)) {
if (mf) { if (mf) {
if (mapfrag_match(mf, x, y) && (rn2(100)) < chance) if (mapfrag_match(mf, x, y) && (rn2(100)) < chance)
@@ -5354,26 +5367,48 @@ get_table_region(
return 1; return 1;
} }
static int boolean
get_coord(lua_State *L, int i, lua_Integer *x, lua_Integer *y) get_coord(lua_State *L, int i, lua_Integer *x, lua_Integer *y)
{ {
boolean ret = FALSE;
if (lua_type(L, i) == LUA_TTABLE) { if (lua_type(L, i) == LUA_TTABLE) {
int arrlen; int arrlen;
boolean gotx = FALSE;
lua_len(L, i); lua_getfield(L, i, "x");
arrlen = lua_tointeger(L, -1); if (!lua_isnil(L, -1)) {
lua_pop(L, 1); *x = luaL_checkinteger(L, -1);
if (arrlen != 2) { gotx = TRUE;
nhl_error(L, "Not a coordinate");
return 0;
} }
lua_pop(L, 1);
*x = get_table_intarray_entry(L, i, 1); if (gotx) {
*y = get_table_intarray_entry(L, i, 2); 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 static void
+1
View File
@@ -521,4 +521,5 @@ function run_tests()
des.level_init(); des.level_init();
end end
nh.debug_flags({mongen = false, hunger = false, overwrite_stairs = true });
run_tests(); run_tests();
+7 -6
View File
@@ -61,14 +61,14 @@ function test_selection_params()
sel:set(1, 2); sel:set(1, 2);
sel_pt_ne(sel, 1,2, 1, "test_selection_params 2"); sel_pt_ne(sel, 1,2, 1, "test_selection_params 2");
local x,y = sel:rndcoord(1); local pt = sel:rndcoord(1);
if x ~= 1 or y ~= 2 then if pt.x ~= 1 or pt.y ~= 2 then
error("sel:rndcoord returned unset coordinate"); error("sel:rndcoord returned unset coordinate (" .. pt.x .. "," .. pt.y .. ")");
end end
x,y = sel:rndcoord(1); pt = sel:rndcoord(1);
if x ~= -2 and y ~= -1 then if pt.x ~= -2 or pt.y ~= -1 then
error("sel:rndcoord returned (" .. x .. "," .. y .. ") coordinate"); error("sel:rndcoord returned (" .. pt.x .. "," .. pt.y .. ") coordinate");
end end
-- OO style -- OO style
@@ -466,6 +466,7 @@ function test_sel_iterate()
is_map_at(9,5, "L"); is_map_at(9,5, "L");
end end
nh.debug_flags({mongen = false, hunger = false, overwrite_stairs = true });
test_selection_params(); test_selection_params();
test_sel_negate(); test_sel_negate();
test_sel_logical_and(); test_sel_logical_and();