]> granicus.if.org Git - nethack/commitdiff
Xorns in stone outside Sokobon and other special levels
authorcohrs <cohrs>
Sat, 4 Feb 2006 23:51:26 +0000 (23:51 +0000)
committercohrs <cohrs>
Sat, 4 Feb 2006 23:51:26 +0000 (23:51 +0000)
First reported 12/13/2003, I think, but my archives contain more recent reports
too.  Special level specs like NON_PASSWALL and NON_DIGGABLE only apply
to the map sections for which they are specified.  So, on special levels of
Sokobon, the large surrounding area is stone, but have no special flags set.
So, it was possible to teleport a Xorn and have it appear in this outer area.

Addressed this by checking the perimeter of the map(s) and if all are
nondiggable and nonpassable, propagate this to the surrounding stone.
This appears to be the intent on such levels, so there is no need to
force the affected special levels to explicitly specify this.

doc/fixes34.4
src/sp_lev.c

index 26d7a723796c7f6a53a50c2a549c99bc60da9d1b..df1414a9cde2349eca09d766cae831794f7dd3ae 100644 (file)
@@ -188,6 +188,8 @@ make gender of quest leaders and nemeses consistent with data.base and
 Orion and Norn should be giant sized
 Orion, Norn, Cyclops and Lord Surtur should be able to tear webs
 typo in Gnome King cellar message
+ensure monsters cannot teleport to or be created outside nonpassable bounds
+       of special levels
 
 
 Platform- and/or Interface-Specific Fixes
index 34194b80e59141d8d2b5a1330553df52d2593789..6b5898f9615d6dff97168df3b6ba755fd2472f27 100644 (file)
@@ -2114,6 +2114,7 @@ dlb *fd;
     xchar   mustfill[(MAXNROFROOMS+1)*2];
     struct trap *badtrap;
     boolean has_bounds;
+    boolean bounds_nodigpass;
 
     (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map);
     load_common_data(fd, SP_LEV_MAZE);
@@ -2135,6 +2136,9 @@ dlb *fd;
            }
     }
 
+    /* if filling with stone, surrounding stone may all be nondig, nonpass */
+    bounds_nodigpass = (filling == STONE);
+
     /* Start reading the file */
     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
                                                /* Number of parts */
@@ -2184,6 +2188,7 @@ dlb *fd;
            ystart = 0;
            xsize = COLNO-1;
            ysize = ROWNO;
+           bounds_nodigpass = FALSE;
        } else {
            /* Load the map */
            for(y = ystart; y < ystart+ysize; y++)
@@ -2445,6 +2450,38 @@ dlb *fd;
                                  tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
        }
 
+       /* walk bounds, reset bounds_nodigpass diggable or passable */
+       if (bounds_nodigpass) {
+           for (x = xstart; x < xstart+xsize; x++) {
+               if (!IS_STWALL(levl[x][ystart].typ) ||
+                   (levl[x][ystart].wall_info &
+                    (W_NONDIGGABLE|W_NONPASSWALL)) !=
+                   (W_NONDIGGABLE|W_NONPASSWALL) ||
+                   !IS_STWALL(levl[x][ystart+ysize-1].typ) ||
+                   (levl[x][ystart+ysize-1].wall_info &
+                    (W_NONDIGGABLE|W_NONPASSWALL)) !=
+                   (W_NONDIGGABLE|W_NONPASSWALL)) {
+                   bounds_nodigpass = FALSE;
+                   break;
+               }
+           }
+       }
+       if (bounds_nodigpass) {
+           for(y = ystart; y < ystart+ysize; y++) {
+               if (!IS_STWALL(levl[xstart][y].typ) ||
+                   (levl[xstart][y].wall_info &
+                    (W_NONDIGGABLE|W_NONPASSWALL)) !=
+                   (W_NONDIGGABLE|W_NONPASSWALL) ||
+                   !IS_STWALL(levl[xstart+xsize-1][y].typ) ||
+                   (levl[xstart+xsize-1][y].wall_info &
+                    (W_NONDIGGABLE|W_NONPASSWALL)) !=
+                   (W_NONDIGGABLE|W_NONPASSWALL)) {
+                   bounds_nodigpass = FALSE;
+                   break;
+               }
+           }
+       }
+
        Fread((genericptr_t) &n, 1, sizeof(n), fd);
                                                /* Number of ladders */
        while(n--) {
@@ -2643,6 +2680,19 @@ dlb *fd;
                    (void) maketrap(mm.x, mm.y, trytrap);
            }
     }
+
+    /*
+     * If bounds_nodigpass, and no mazewalks, mark all locations outside
+     * the map are mapped as nodig and nopass as well.  This avoids passwall
+     * monsters like Xorns from appearing outside the accessible area.
+     */
+    if (bounds_nodigpass && !nwalk_sav) {
+       for(x = 1; x < COLNO; x++)
+           for(y = 0; y < ROWNO; y++)
+           if(!Map[x][y])
+               levl[x][y].wall_info |= W_NONDIGGABLE|W_NONPASSWALL;
+    }
+
     return TRUE;
 }