From: copperwater Date: Tue, 15 Mar 2022 00:54:23 +0000 (-0400) Subject: Fix selection "random" grow direction, and other code cleanup X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc04bf9d8fc25c944deeac8693a7bdac34b6f667;p=nethack Fix selection "random" grow direction, and other code cleanup Noticed that when I set a selection to grow in a random direction, it instead grew in all directions, which is not what I wanted. Turns out the -1 random dir ended up being passed straight to the code which checks bitmasks, without any form of randomizing among directions. So this adds code to do that, and defines W_RANDOM as -1 rather than using a magic number. In the process I also noticed that specifying "random" as the wall for a door in a room made it rerandomize the direction every iteration of its loop, essentially rolling two rn2(4)s and only proceeding if they matched. That was pointless so I cleaned it up a bit. Also added safety checks in the form of an impossible for des.corridor() being called with "random" as either walldir, because this is not implemented currently. And lastly, I noticed that create_secret_door was entirely unused (secret door creation is handled in create_door), so I deleted it. The only behavior change caused by this is that the Valkyrie quest lava pools will be a little smaller, which is the only place grow is currently used. If it's desired to keep them the same, that should be changed to "all". --- diff --git a/include/extern.h b/include/extern.h index 448acc20f..f05f1eff1 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2496,7 +2496,6 @@ extern void flip_level_rnd(int, boolean); extern boolean check_room(xchar *, xchar *, xchar *, xchar *, boolean); extern boolean create_room(xchar, xchar, xchar, xchar, xchar, xchar, xchar, xchar); -extern void create_secret_door(struct mkroom *, xchar); extern boolean dig_corridor(coord *, coord *, boolean, schar, schar); extern void fill_special_room(struct mkroom *); extern void wallify_map(int, int, int, int); diff --git a/include/sp_lev.h b/include/sp_lev.h index 77c4dbd5c..1d9a95d79 100644 --- a/include/sp_lev.h +++ b/include/sp_lev.h @@ -6,6 +6,7 @@ #define SP_LEV_H /* wall directions */ +#define W_RANDOM -1 #define W_NORTH 1 #define W_SOUTH 2 #define W_EAST 4 diff --git a/src/nhlsel.c b/src/nhlsel.c index e2059cbcc..04d63c739 100644 --- a/src/nhlsel.c +++ b/src/nhlsel.c @@ -507,7 +507,7 @@ l_selection_grow(lua_State *L) { int argc = lua_gettop(L); const char *const growdirs[] = { "all", "random", "north", "west", "east", "south", NULL }; - const int growdirs2i[] = { W_ANY, -1, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 }; + const int growdirs2i[] = { W_ANY, W_RANDOM, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 }; struct selectionvar *sel = l_selection_check(L, 1); int dir = growdirs2i[luaL_checkoption(L, 2, "all", growdirs)]; diff --git a/src/sp_lev.c b/src/sp_lev.c index 4b96399b4..97f2ec936 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -99,6 +99,7 @@ static void get_table_xy_or_coord(lua_State *, int *, int *); static int get_table_region(lua_State *, const char *, int *, int *, int *, int *, boolean); static void set_wallprop_in_selection(lua_State *, int); +static xchar random_wdir(void); static int floodfillchk_match_under(int, int); static int floodfillchk_match_accessible(int, int); static boolean sel_flood_havepoint(int, int, xchar *, xchar *, int); @@ -1582,6 +1583,9 @@ create_door(room_door *dd, struct mkroom *broom) if (dd->secret == -1) dd->secret = rn2(2); + if (dd->wall == W_RANDOM) + dd->wall = W_ANY; /* speeds things up in the below loop */ + if (dd->mask == -1) { /* is it a locked door, closed, or a doorway? */ if (!dd->secret) { @@ -1608,13 +1612,7 @@ create_door(room_door *dd, struct mkroom *broom) } for (trycnt = 0; trycnt < 100; ++trycnt) { - int dwall, dpos; - - dwall = dd->wall; - if (dwall == -1) /* The wall is RANDOM */ - dwall = 1 << rn2(4); - - dpos = dd->pos; + int dwall = dd->wall, dpos = dd->pos; /* Convert wall and pos into an absolute coordinate! */ switch (rn2(4)) { @@ -1670,54 +1668,6 @@ create_door(room_door *dd, struct mkroom *broom) levl[x][y].doormask = dd->mask; } -/* - * Create a secret door in croom on any one of the specified walls. - */ -void -create_secret_door( - struct mkroom *croom, - xchar walls) /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */ -{ - xchar sx, sy; /* location of the secret door */ - int count; - - for (count = 0; count < 100; count++) { - sx = rn1(croom->hx - croom->lx + 1, croom->lx); - sy = rn1(croom->hy - croom->ly + 1, croom->ly); - - switch (rn2(4)) { - case 0: /* top */ - if (!(walls & W_NORTH)) - continue; - sy = croom->ly - 1; - break; - case 1: /* bottom */ - if (!(walls & W_SOUTH)) - continue; - sy = croom->hy + 1; - break; - case 2: /* left */ - if (!(walls & W_EAST)) - continue; - sx = croom->lx - 1; - break; - case 3: /* right */ - if (!(walls & W_WEST)) - continue; - sx = croom->hx + 1; - break; - } - - if (okdoor(sx, sy)) { - levl[sx][sy].typ = SDOOR; - levl[sx][sy].doormask = D_CLOSED; - return; - } - } - - impossible("couldn't create secret door on any walls 0x%x", walls); -} - /* * Create a trap in a room. */ @@ -2550,6 +2500,14 @@ create_corridor(corridor *c) return; } + /* Safety railings - if there's ever a case where des.corridor() needs to be + * called with src/destwall="random", that logic first needs to be + * implemented in search_door. */ + if (c->src.wall == W_ANY || c->src.wall == W_RANDOM + || c->dest.wall == W_ANY || c->dest.wall == W_RANDOM) { + impossible("create_corridor to/from a random wall"); + return; + } if (!search_door(&g.rooms[c->src.room], &org.x, &org.y, c->src.wall, c->src.door)) return; @@ -4208,7 +4166,7 @@ lspo_corridor(lua_State *L) "all", "random", "north", "west", "east", "south", NULL }; static const int walldirs2i[] = { - W_ANY, -1, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 + W_ANY, W_RANDOM, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 }; corridor tc; @@ -4398,6 +4356,14 @@ selection_rndcoord(struct selectionvar* ov, xchar *x, xchar *y, boolean removeit return 0; } +/* Choose a single random W_* direction. */ +static xchar +random_wdir(void) +{ + static const xchar wdirs[4] = { W_NORTH, W_SOUTH, W_EAST, W_WEST }; + return wdirs[rn2(4)]; +} + void selection_do_grow(struct selectionvar* ov, int dir) { @@ -4407,6 +4373,9 @@ selection_do_grow(struct selectionvar* ov, int dir) if (!ov || !tmp) return; + if (dir == W_RANDOM) + dir = random_wdir(); + for (x = 1; x < ov->wid; x++) for (y = 0; y < ov->hei; y++) { /* note: dir is a mask of multiple directions, but the only @@ -4909,6 +4878,8 @@ lspo_door(lua_State *L) static const char *const walldirs[] = { "all", "random", "north", "west", "east", "south", NULL }; + /* Note that "random" is also W_ANY, because create_door just wants a + * mask of acceptable walls */ static const int walldirs2i[] = { W_ANY, W_ANY, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 }; @@ -5723,7 +5694,7 @@ lspo_mazewalk(lua_State *L) static const char *const mwdirs[] = { "north", "south", "east", "west", "random", NULL }; - static const int mwdirs2i[] = { W_NORTH, W_SOUTH, W_EAST, W_WEST, -1, -2 }; + static const int mwdirs2i[] = { W_NORTH, W_SOUTH, W_EAST, W_WEST, W_RANDOM, -2 }; xchar x, y; int mx, my; xchar ftyp = ROOM; @@ -5759,8 +5730,8 @@ lspo_mazewalk(lua_State *L) ftyp = g.level.flags.corrmaze ? CORR : ROOM; } - if (dir == -1) - dir = mwdirs2i[rn2(4)]; + if (dir == W_RANDOM) + dir = random_wdir(); /* don't use move() - it doesn't use W_NORTH, etc. */ switch (dir) {