From: Pasi Kallinen Date: Mon, 13 Apr 2020 16:59:03 +0000 (+0300) Subject: Allow matching any wall map terrain in lua scripts X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d78dcdcb9b280a0872c8848a73c7fa800f808641;p=nethack Allow matching any wall map terrain in lua scripts When matching a terrain, allow using a "w" placeholder that matches any solid wall: For example: local s = selection.match([[w.w]]); would match all floor locations with a wall to the left and right of it. The walls can be solid stone, horizontal, vertical, etc. This applies to selection.match(), selection.filter_mapchar(), and des.replace_terrain() --- diff --git a/include/rm.h b/include/rm.h index 5a1b5e92d..62d34ed06 100644 --- a/include/rm.h +++ b/include/rm.h @@ -74,6 +74,7 @@ enum levl_typ_types { CLOUD = 35, MAX_TYPE = 36, + MATCH_WALL = 37, INVALID_TYPE = 127 }; diff --git a/src/nhlua.c b/src/nhlua.c index 098d74324..23713deb6 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -206,6 +206,7 @@ const struct { { 'F', IRONBARS }, /* Fe = iron */ { 'x', MAX_TYPE }, /* "see-through" */ { 'B', CROSSWALL }, /* hack: boundary location */ + { 'w', MATCH_WALL }, /* IS_STWALL() */ { '\0', STONE }, }; diff --git a/src/sp_lev.c b/src/sp_lev.c index 0830bbeff..817a93ba5 100755 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -194,6 +194,19 @@ static struct monst *invent_carrying_monster = (struct monst *) 0; * end of no 'g.' */ +/* Does typ match with levl[][].typ, considering special types + MATCH_WALL and MAX_TYPE (aka transparency)? */ +boolean +match_maptyps(typ, levltyp) +xchar typ, levltyp; +{ + if ((typ == MATCH_WALL) && !IS_STWALL(levltyp)) + return FALSE; + if ((typ < MAX_TYPE) && (typ != levltyp)) + return FALSE; + return TRUE; +} + struct mapfragment * mapfrag_fromstr(str) char *str; @@ -279,7 +292,7 @@ int x,y; for (ry = -(mf->hei / 2); ry <= (mf->hei / 2); ry++) { schar mapc = mapfrag_get(mf, rx + (mf->wid / 2) , ry + (mf->hei / 2)); schar levc = isok(x+rx, y+ry) ? levl[x+rx][y+ry].typ : STONE; - if ((mapc < MAX_TYPE) && (mapc != levc)) + if (!match_maptyps(mapc, levc)) return FALSE; } return TRUE; @@ -4337,7 +4350,7 @@ int lit; for (x = 0; x < ret->wid; x++) for (y = 0; y < ret->hei; y++) - if (selection_getpoint(x, y, ov) && (levl[x][y].typ == typ)) { + if (selection_getpoint(x, y, ov) && match_maptyps(typ, levl[x][y].typ)) { switch (lit) { default: case -2: @@ -5142,7 +5155,6 @@ lua_State *L; free(tmpstr); if ((err = mapfrag_error(mf)) != NULL) { - mapfrag_free(&mf); nhl_error(L, err); /*NOTREACHED*/ } diff --git a/test/test_des.lua b/test/test_des.lua index b66478675..8cb281bce 100644 --- a/test/test_des.lua +++ b/test/test_des.lua @@ -447,6 +447,7 @@ function test_replace_terrain() des.replace_terrain({ region={1,1, 70,19}, fromterrain=".", toterrain="L", chance=25 }); des.replace_terrain({ selection=selection.area(2,5, 10,15), fromterrain="L", toterrain="." }); des.replace_terrain({ mapfragment=[[...]], toterrain="T" }); + des.replace_terrain({ mapfragment=[[w.w]], toterrain="L" }); end function test_corridor() diff --git a/test/test_sel.lua b/test/test_sel.lua index 66b7c30dd..91f4754f5 100644 --- a/test/test_sel.lua +++ b/test/test_sel.lua @@ -334,6 +334,15 @@ function test_sel_filter_mapchar() sel_has_n_points(selb, 2, __func__); sel_pt_ne(selb, 5,5, 1, __func__); sel_pt_ne(selb, 15,10, 1, __func__); + + des.reset_level(); + des.level_init({ style = "solidfill", fg = " " }); + des.replace_terrain({ selection=sela, fromterrain=" ", toterrain="-", chance=50 }); + des.replace_terrain({ selection=sela, fromterrain=" ", toterrain="|", chance=50 }); + + -- test filtering by "w" (match any solid wall) + local seld = sela:filter_mapchar("w"); + sel_has_n_points(seld, 1659, __func__); end -- test_sel_filter_mapchar function test_sel_flood() @@ -355,7 +364,41 @@ function test_sel_flood() end -- test_sel_flood function test_sel_match() - local sel = selection.match([[...]]); + local __func__ = "test_sel_match"; + des.reset_level(); + des.level_init({ style = "solidfill", fg = " " }); + + -- test horizontal map fragment + des.terrain(5,5, "."); + des.terrain(6,5, "."); + des.terrain(7,5, "."); + local sela = selection.match([[...]]); + sel_has_n_points(sela, 1, __func__); + sel_pt_ne(sela, 6,5, 1, __func__); + + -- test vertical map fragment + local mapfragv = " \n.\n "; + local selb = selection.match(mapfragv); + sel_has_n_points(selb, 3, __func__); + sel_pt_ne(selb, 5,5, 1, __func__); + sel_pt_ne(selb, 6,5, 1, __func__); + sel_pt_ne(selb, 7,5, 1, __func__); + + -- test matching with "w" to match any wall + des.terrain(5,4, "-"); + des.terrain(6,6, "|"); + local mapfragv = "w\n.\nw"; + local selc = selection.match(mapfragv); + sel_has_n_points(selc, 3, __func__); + sel_pt_ne(selc, 5,5, 1, __func__); + sel_pt_ne(selc, 6,5, 1, __func__); + sel_pt_ne(selc, 7,5, 1, __func__); + + -- test a 3x3 map fragment + local mapfrag = "www\n...\nwww"; + local seld = selection.match(mapfrag); + sel_has_n_points(seld, 1, __func__); + sel_pt_ne(seld, 6,5, 1, __func__); end -- test_sel_match test_selection_params();