]> granicus.if.org Git - nethack/commitdiff
oracle bones (trunk only)
authornethack.rankin <nethack.rankin>
Wed, 15 Feb 2012 01:55:34 +0000 (01:55 +0000)
committernethack.rankin <nethack.rankin>
Wed, 15 Feb 2012 01:55:34 +0000 (01:55 +0000)
     Noticed while working on #overview/#annotate revisions, one of which
will key off the oracle's welcome message.  On a bones level, the oracle
could be outside her room, or the room's one time welcome message could be
used up, or both.  During bones creation, discard her if she's on the wrong
level (probably not possible, aside from wizard mode ^G), try to put her
back into her room if she's outside it on the right level, and restore the
room's type (if she's still in it, or has been successfully moved back into
it) so that next hero who loads the bones will get her welcome message the
first time that room is entered.

     Other special rooms could be fixed up too, provided that they're
sufficiently intact (stealthy hero might enter and get the one-time message
then run away and die elsewhere on the level; at present, next hero won't
get the room's entry message) but this doesn't attempt to deal with that.

include/mkroom.h
include/patchlevel.h
src/bones.c
src/mklev.c

index 031b08764ddfc1402b1a6d616a0f9a13985b351b..993f7028fda3792b8836cd4be33f3331ac3f7143 100644 (file)
@@ -1,5 +1,4 @@
 /* NetHack 3.5 mkroom.h        $Date$  $Revision$ */
-/*     SCCS Id: @(#)mkroom.h   3.5     2005/03/12      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -11,6 +10,7 @@
 struct mkroom {
        schar lx,hx,ly,hy;      /* usually xchar, but hx may be -1 */
        schar rtype;            /* type of room (zoo, throne, etc...) */
+       schar orig_rtype;       /* same as rtype, but not zeroed later */
        schar rlit;             /* is the room lit ? */
        schar doorct;           /* door count */
        schar fdoor;            /* index for the first door of the room */
index 4dc0598a3dc7c923e799c07373a8f3e636cd068d..2459c53edfe64302999875c7c13943256f623a10 100644 (file)
@@ -13,7 +13,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL      51
+#define EDITLEVEL      52
 
 #define COPYRIGHT_BANNER_A \
 "NetHack, Copyright 1985-2012"
index b762e5a00feaf2c9d5443fc8e8b04ac5f6b927b6..2c05124d34a315ee1b7df4aafddab932e845fbeb 100644 (file)
@@ -13,6 +13,7 @@ extern long bytes_counted;
 STATIC_DCL boolean FDECL(no_bones_level, (d_level *));
 STATIC_DCL void FDECL(goodfruit, (int));
 STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P));
+STATIC_DCL boolean FDECL(fixuporacle, (struct monst *));
 
 STATIC_OVL boolean
 no_bones_level(lev)
@@ -240,6 +241,55 @@ int x, y;
        if (cont) cont->owt = weight(cont);
 }
 
+/* possibly restore oracle's room and/or put her back inside it; returns
+   False if she's on the wrong level and should be removed, True otherwise */
+STATIC_OVL boolean
+fixuporacle(oracle)
+struct monst *oracle;
+{
+    coord cc;
+    int ridx, o_ridx;
+
+    /* oracle doesn't move, but knight's joust or monk's staggering blow
+       could push her onto a hole in the floor; at present, traps don't
+       activate in such situation hence she won't fall to another level;
+       however, that could change so be prepared to cope with such things */
+    if (!Is_oracle_level(&u.uz))
+       return FALSE;
+
+    oracle->mpeaceful = 1;
+    o_ridx = levl[oracle->mx][oracle->my].roomno - ROOMOFFSET;
+    if (o_ridx >= 0 && rooms[o_ridx].rtype == DELPHI)
+       return TRUE;            /* no fixup needed */
+
+    /*
+     * The Oracle isn't in DELPHI room.  Either hero entered her chamber
+     * and got the one-time welcome message, converting it into an
+     * ordinary room, or she got teleported out, or both.  Try to put
+     * her back inside her room, if necessary, and restore its type.
+     */
+
+    /* find original delphi chamber; should always succeed */
+    for (ridx = 0; ridx < SIZE(rooms); ++ridx)
+       if (rooms[ridx].orig_rtype == DELPHI) break;
+
+    if (o_ridx != ridx && ridx < SIZE(rooms)) {
+       /* room found and she's not not in it, so try to move her there */
+       cc.x = (rooms[ridx].lx + rooms[ridx].hx) / 2;
+       cc.y = (rooms[ridx].ly + rooms[ridx].hy) / 2;
+       if (enexto(&cc, cc.x, cc.y, oracle->data)) {
+           rloc_to(oracle, cc.x, cc.y);
+           o_ridx = levl[oracle->mx][oracle->my].roomno - ROOMOFFSET;
+       }
+       /* [if her room is already full, she might end up outside;
+          that's ok, next hero just won't get any welcome message,
+          same as used to happen before this fixup was introduced] */
+    }
+    if (ridx == o_ridx)                /* if she's in her room, mark it as such */
+       rooms[ridx].rtype = DELPHI;
+    return TRUE;               /* keep oracle in new bones file */
+}
+
 /* check whether bones are feasible */
 boolean
 can_make_bones()
@@ -317,7 +367,8 @@ struct obj *corpse;
            mptr = mtmp->data;
            if (mtmp->iswiz || mptr == &mons[PM_MEDUSA] ||
                    mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER ||
-                   mptr == &mons[PM_VLAD_THE_IMPALER])
+                   mptr == &mons[PM_VLAD_THE_IMPALER] ||
+                   (mptr == &mons[PM_ORACLE] && !fixuporacle(mtmp)))
                mongone(mtmp);
        }
 #ifdef STEED
@@ -403,7 +454,7 @@ struct obj *corpse;
        u.ux = u.uy = 0;
 
        /* Clear all memory from the level. */
-       for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) {
+       for (x = 1; x < COLNO; x++) for (y = 0; y<ROWNO; y++) {
            levl[x][y].seenv = 0;
            levl[x][y].waslit = 0;
            levl[x][y].glyph = cmap_to_glyph(S_stone);
index 2a98163cdf4401d01531fd2ebba4b4ae98f34421..e75216ef6fd0727988c06e9c0e1f55c0b2d2645e 100644 (file)
@@ -931,11 +931,13 @@ void
 mklev()
 {
        struct mkroom *croom;
+       int ridx;
 
 #ifdef DUNGEON_OVERVIEW
        init_mapseen(&u.uz);
 #endif
        if(getbones()) return;
+
        in_mklev = TRUE;
        makelevel();
        bound_digging();
@@ -955,6 +957,10 @@ mklev()
 #endif
        }
        set_wall_state();
+       /* for many room types, rooms[].rtype is zeroed once the room has been
+          entered; rooms[].orig_rtype always retains original rtype value */
+       for (ridx = 0; ridx < SIZE(rooms); ridx++)
+           rooms[ridx].orig_rtype = rooms[ridx].rtype;
 }
 
 void