diff --git a/include/mkroom.h b/include/mkroom.h index 031b08764..993f7028f 100644 --- a/include/mkroom.h +++ b/include/mkroom.h @@ -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 */ diff --git a/include/patchlevel.h b/include/patchlevel.h index 4dc0598a3..2459c53ed 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -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" diff --git a/src/bones.c b/src/bones.c index b762e5a00..2c05124d3 100644 --- a/src/bones.c +++ b/src/bones.c @@ -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