]> granicus.if.org Git - nethack/commitdiff
Allow matching any wall map terrain in lua scripts
authorPasi Kallinen <paxed@alt.org>
Mon, 13 Apr 2020 16:59:03 +0000 (19:59 +0300)
committerPasi Kallinen <paxed@alt.org>
Mon, 13 Apr 2020 17:00:34 +0000 (20:00 +0300)
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()

include/rm.h
src/nhlua.c
src/sp_lev.c
test/test_des.lua
test/test_sel.lua

index 5a1b5e92d673c39db25b8bfae8d54d176eb2508e..62d34ed0647a6616e54ae980bd3bba45efabf498 100644 (file)
@@ -74,6 +74,7 @@ enum levl_typ_types {
     CLOUD     = 35,
 
     MAX_TYPE  = 36,
+    MATCH_WALL = 37,
     INVALID_TYPE = 127
 };
 
index 098d743249ee2b1cd039f6769fe1740fb787458d..23713deb696b232f895684f8030e661f1bb02519 100644 (file)
@@ -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 },
 };
 
index 0830bbeff90127a2380b73897467ba53e984e097..817a93ba5bce25aece0f68f91a8310c98a232446 100755 (executable)
@@ -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*/
         }
index b664786759fa76fbea10cc5ec8893ff14a341252..8cb281bce3e3f0e72dff33a4b5ead24cd9eefce8 100644 (file)
@@ -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()
index 66b7c30ddcf5fc03bf2b1819fcd8e2bf1c77a00d..91f4754f58526550903fd1bfe57f97339cba9f30 100644 (file)
@@ -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();