From: Pasi Kallinen Date: Wed, 4 Mar 2020 18:04:01 +0000 (+0200) Subject: Lua: Add contents function to room and map X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6dfbfca2f809550ff7e37e5b28bba67204fa04a;p=nethack Lua: Add contents function to room and map The function will get the map/room width and height as a parameter. --- diff --git a/doc/lua.adoc b/doc/lua.adoc index 56cb2e4a7..1d9007ab9 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -316,12 +316,33 @@ Example: === map +Construct a piece of the level from text map. Takes one parameter, either a text string +describing the map, or a table with multiple parameters. + +[options="header"] +|=== +| parameter | description +| x, y | Coordinates on the level. +| coord | Coordinates in table format. +| halign | Horizontal alignment on a rough 3x3 grid. +| valign | Vertical alignment on a rough 3x3 grid. +| map | Multi-line string describing the map. +| contents | A function called with one parameter, a table with "width" and "height", the map width and height. All coordinates in the function will be relative to the map. +|=== + Example: des.map({ x = 10, y = 10, map = [[...]] }); des.map({ coord = {10, 10}, map = [[...]] }); des.map({ halign = "center", valign = "center", map = [[...]] }); - des.map([[...]]) + des.map([[...]]); + des.map({ halign = "center", valign = "center", map = [[ + .... + .... + ....]], contents = function(map) + des.terrain(0,0, "L"); + des.terrain(map.width-1, map.height-1, "T"); + end }); === mazewalk @@ -409,10 +430,34 @@ Example: === room +Create a room of certain type and size. Takes one parameter, a table with the following +fields: + +[options="header"] +|=== +| parameter | description +| type | The room type. Default is "ordinary" +| chance | Percentage chance this room is of type, otherwise it will be created as ordinary room. Default is 100. +| x,y | Room coordinates. +| coord | Room coordinates, in table format. +| w, h | Width and height. Both default to -1 (random). If one is set, then both must be set. +| xalign | Horizontal alignment on a rough 3x3 grid. Default is "random". +| yalign | Vertical alignment on a rough 3x3 grid. Default is "random". +| lit | Is the room lit or unlit? Defaults to -1 (random). +| filled | Is the room filled as per the room type. Defaults to 1 (filled). +| joined | Is the room joined to the rest of the level with corridors? Default is 1 (joined). +| contents | A function called with one parameter, a table with "width" and "height", the room width and height, excluding the walls. All coordinates in the function will be relative to the room. +|=== + + Example: des.room({ type="ordinary", lit=1, x=3,y=3, xalign="center",yalign="center", w=11,h=9 }); des.room({ lit=1, coord={3,3}, xalign="center",yalign="center", w=11,h=9 }); + des.room({ type="ordinary", contents=function(room) + des.terrain(0,0, "L"); + des.terrain(room.width, room.height, "T"); + end }); === stair diff --git a/src/sp_lev.c b/src/sp_lev.c index 079c0747a..9c4ba3e96 100755 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -99,6 +99,7 @@ static int FDECL(get_table_region, (lua_State *, const char *, static void FDECL(set_wallprop_in_selection, (lua_State *, int)); static int FDECL(floodfillchk_match_under, (int, int)); static int FDECL(floodfillchk_match_accessible, (int, int)); +static void FDECL(l_push_wid_hei_table, (lua_State *, int, int)); /* lua_CFunction prototypes */ int FDECL(lspo_altar, (lua_State *)); @@ -2799,6 +2800,23 @@ spo_pop_container() } } +/* push a table on lua stack: {width=wid, height=hei} */ +static void +l_push_wid_hei_table(L, wid, hei) +lua_State *L; +int wid, hei; +{ + lua_newtable(L); + + lua_pushstring(L, "width"); + lua_pushinteger(L, wid); + lua_rawset(L, -3); + + lua_pushstring(L, "height"); + lua_pushinteger(L, hei); + lua_rawset(L, -3); +} + /* message("What a strange feeling!"); */ int lspo_message(L) @@ -3570,6 +3588,7 @@ int defval; /* room({ type="ordinary", lit=1, x=3,y=3, xalign="center",yalign="center", w=11,h=9 }); */ /* room({ lit=1, coord={3,3}, xalign="center",yalign="center", w=11,h=9 }); */ +/* room({ coord={3,3}, xalign="center",yalign="center", w=11,h=9, contents=function(room) ... end }); */ int lspo_room(L) lua_State *L; @@ -3627,7 +3646,8 @@ lua_State *L; lua_getfield(L, 1, "contents"); if (lua_type(L, -1) == LUA_TFUNCTION) { lua_remove(L, -2); - lua_call(L, 0, 0); + l_push_wid_hei_table(L, tmpcr->hx - tmpcr->lx, tmpcr->hy - tmpcr->ly); + lua_call(L, 1, 0); } else lua_pop(L, 1); spo_endroom(g.coder); @@ -5851,6 +5871,7 @@ lua_State *L UNUSED; /* map({ x = 10, y = 10, map = [[...]] }); */ /* map({ coord = {10, 10}, map = [[...]] }); */ /* map({ halign = "center", valign = "center", map = [[...]] }); */ +/* map({ map = [[...]], contents = function(map) ... end }); */ /* map([[...]]) */ int lspo_map(L) @@ -5874,9 +5895,10 @@ TODO: g.coder->croom needs to be updated "top", "center", "bottom", "none", NULL }; static const int t_or_b2i[] = { TOP, CENTER, BOTTOM, -1, -1 }; - int lr, tb, keepregion = 1, x = -1, y = -1; + int lr, tb, x = -1, y = -1; struct mapfragment *mf; int argc = lua_gettop(L); + boolean has_contents = FALSE; create_des_coder(); @@ -5890,9 +5912,15 @@ TODO: g.coder->croom needs to be updated lcheck_param_table(L); lr = l_or_r2i[get_table_option(L, "halign", "none", left_or_right)]; tb = t_or_b2i[get_table_option(L, "valign", "none", top_or_bot)]; - keepregion = get_table_boolean_opt(L, "keepregion", 1); /* TODO: maybe rename? */ get_table_xy_or_coord(L, &x, &y); tmpstr = get_table_str(L, "map"); + lua_getfield(L, 1, "contents"); + if (lua_type(L, -1) == LUA_TFUNCTION) { + lua_remove(L, -2); + has_contents = TRUE; + } else { + lua_pop(L, 1); + } mf = mapfrag_fromstr(tmpstr); free(tmpstr); } @@ -5902,15 +5930,11 @@ TODO: g.coder->croom needs to be updated return 0; } - /* keepregion restricts the coordinates of the commands coming after - the map into the map region */ - /* for keepregion */ tmpxsize = g.xsize; tmpysize = g.ysize; tmpxstart = g.xstart; tmpystart = g.ystart; - g.xsize = mf->wid; g.ysize = mf->hei; @@ -6033,15 +6057,19 @@ TODO: g.coder->croom needs to be updated remove_rooms(g.xstart, g.ystart, g.xstart + g.xsize, g.ystart + g.ysize); } - if (!keepregion) { - g.xstart = tmpxstart; - g.ystart = tmpystart; - g.xsize = tmpxsize; - g.ysize = tmpysize; - } mapfrag_free(&mf); + if (has_contents) { + l_push_wid_hei_table(L, g.xsize, g.ysize); + lua_call(L, 1, 0); + } + + tmpxsize = g.xsize; + tmpysize = g.ysize; + tmpxstart = g.xstart; + tmpystart = g.ystart; + return 0; }