void
doaltarobj(obj) /* obj is an object dropped on an altar */
- register struct obj *obj;
+ register struct obj *obj;
{
- if (Blind)
- return;
+ if (Blind)
+ return;
- /* KMH, conduct */
- u.uconduct.gnostic++;
+ if (obj->oclass != COIN_CLASS) {
+ /* KMH, conduct */
+ u.uconduct.gnostic++;
+ } else {
+ /* coins don't have bless/curse status */
+ obj->blessed = obj->cursed = 0;
+ }
- if ((obj->blessed || obj->cursed) && obj->oclass != COIN_CLASS) {
+ if (obj->blessed || obj->cursed) {
- There("is %s flash as %s %s the altar.",
- an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
- doname(obj), otense(obj, "hit"));
- if (!Hallucination) obj->bknown = 1;
- } else {
- pline("%s %s on the altar.", Doname2(obj),
- otense(obj, "land"));
+ There("is %s flash as %s %s the altar.",
+ an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
+ doname(obj), otense(obj, "hit"));
+ if (!Hallucination) obj->bknown = 1;
+ } else {
+ pline("%s %s on the altar.", Doname2(obj),
+ otense(obj, "land"));
- obj->bknown = 1;
+ if (obj->oclass != COIN_CLASS) obj->bknown = 1;
- }
+ }
}
STATIC_OVL
d_level *newlevel;
boolean at_stairs, falling, portal;
{
- int fd, l_idx;
- xchar new_ledger;
- boolean cant_go_back,
- up = (depth(newlevel) < depth(&u.uz)),
- newdungeon = (u.uz.dnum != newlevel->dnum),
- was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
- familiar = FALSE;
- boolean new = FALSE; /* made a new level? */
- struct monst *mtmp;
- char whynot[BUFSZ];
-
- if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
- newlevel->dlevel = dunlevs_in_dungeon(newlevel);
- if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
- if (!u.uhave.amulet) return; /* must have the Amulet */
- if (!wizard) /* wizard ^V can bypass Earth level */
- assign_level(newlevel, &earth_level); /* (redundant) */
- }
- new_ledger = ledger_no(newlevel);
- if (new_ledger <= 0)
- done(ESCAPED); /* in fact < 0 is impossible */
+ int fd, l_idx;
+ xchar new_ledger;
+ boolean cant_go_back,
+ up = (depth(newlevel) < depth(&u.uz)),
+ newdungeon = (u.uz.dnum != newlevel->dnum),
+ was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
+ familiar = FALSE;
+ boolean new = FALSE; /* made a new level? */
+ struct monst *mtmp;
+ char whynot[BUFSZ];
+
+ if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
+ newlevel->dlevel = dunlevs_in_dungeon(newlevel);
+ if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
+ if (!u.uhave.amulet) return; /* must have the Amulet */
+ if (!wizard) /* wizard ^V can bypass Earth level */
+ assign_level(newlevel, &earth_level); /* (redundant) */
+ }
+ new_ledger = ledger_no(newlevel);
+ if (new_ledger <= 0)
+ done(ESCAPED); /* in fact < 0 is impossible */
- /* If you have the amulet and are trying to get out of Gehennom, going
- * up a set of stairs sometimes does some very strange things!
+ /* If you have the amulet and are trying to get out of Gehennom, going
+ * up a set of stairs sometimes does some very strange things!
- * Biased against law and towards chaos, but not nearly as strongly
- * as it used to be (prior to 3.2.0).
- * Odds: old new
- * "up" L N C "up" L N C
- * +1 75.0 75.0 75.0 +1 75.0 75.0 75.0
- * 0 0.0 12.5 25.0 0 6.25 8.33 12.5
- * -1 8.33 4.17 0.0 -1 6.25 8.33 12.5
- * -2 8.33 4.17 0.0 -2 6.25 8.33 0.0
- * -3 8.33 4.17 0.0 -3 6.25 0.0 0.0
+ * Biased against law and towards chaos. (The chance to be sent
+ * down multiple levels when attempting to go up are significantly
+ * less than the corresponding comment in older versions indicated
+ * due to overlooking the effect of the call to assign_rnd_lvl().)
+ *
+ * Odds for making it to the next level up, or of being sent down:
+ * "up" L N C
+ * +1 75.0 75.0 75.0
+ * 0 6.25 8.33 12.5
+ * -1 11.46 12.50 12.5
+ * -2 5.21 4.17 0.0
+ * -3 2.08 0.0 0.0
- */
- if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
- (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
- if (!rn2(4)) {
- int odds = 3 + (int)u.ualign.type, /* 2..4 */
- diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
-
- if (diff != 0) {
- assign_rnd_level(newlevel, &u.uz, diff);
- /* if inside the tower, stay inside */
- if (was_in_W_tower &&
- !On_W_tower_level(newlevel)) diff = 0;
- }
- if (diff == 0)
- assign_level(newlevel, &u.uz);
-
- new_ledger = ledger_no(newlevel);
-
- pline("A mysterious force momentarily surrounds you...");
- if (on_level(newlevel, &u.uz)) {
- (void) safe_teleds(FALSE);
- (void) next_to_u();
- return;
- } else
- at_stairs = at_ladder = FALSE;
- }
- }
+ */
+ if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
+ (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
+ if (!rn2(4)) {
+ int odds = 3 + (int)u.ualign.type, /* 2..4 */
+ diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
+
+ if (diff != 0) {
+ assign_rnd_level(newlevel, &u.uz, diff);
+ /* if inside the tower, stay inside */
+ if (was_in_W_tower &&
+ !On_W_tower_level(newlevel)) diff = 0;
+ }
+ if (diff == 0)
+ assign_level(newlevel, &u.uz);
+
+ new_ledger = ledger_no(newlevel);
+
+ pline("A mysterious force momentarily surrounds you...");
+ if (on_level(newlevel, &u.uz)) {
+ (void) safe_teleds(FALSE);
+ (void) next_to_u();
+ return;
+ } else
+ at_stairs = at_ladder = FALSE;
+ }
+ }
- /* Prevent the player from going past the first quest level unless
- * (s)he has been given the go-ahead by the leader.
- */
- if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
- pline("A mysterious force prevents you from descending.");
- return;
- }
+ /* Prevent the player from going past the first quest level unless
+ * (s)he has been given the go-ahead by the leader.
+ */
+ if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
+ pline("A mysterious force prevents you from descending.");
+ return;
+ }
- if (on_level(newlevel, &u.uz)) return; /* this can happen */
-
- /* tethered movement makes level change while trapped feasible */
- if (u.utrap && u.utraptype == TT_BURIEDBALL)
- buried_ball_to_punishment(); /* (before we save/leave old level) */
-
- fd = currentlevel_rewrite();
- if (fd < 0) return;
-
- if (falling) /* assuming this is only trap door or hole */
- impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
-
- check_special_room(TRUE); /* probably was a trap door */
- if (Punished) unplacebc();
- u.utrap = 0; /* needed in level_tele */
- fill_pit(u.ux, u.uy);
- u.ustuck = 0; /* idem */
- u.uinwater = 0;
- u.uundetected = 0; /* not hidden, even if means are available */
- keepdogs(FALSE);
- if (u.uswallow) /* idem */
- u.uswldtim = u.uswallow = 0;
- recalc_mapseen(); /* recalculate map overview before we leave the level */
- /*
- * We no longer see anything on the level. Make sure that this
- * follows u.uswallow set to null since uswallow overrides all
- * normal vision.
- */
- vision_recalc(2);
-
- /*
- * Save the level we're leaving. If we're entering the endgame,
- * we can get rid of all existing levels because they cannot be
- * reached any more. We still need to use savelev()'s cleanup
- * for the level being left, to recover dynamic memory in use and
- * to avoid dangling timers and light sources.
- */
- cant_go_back = (newdungeon && In_endgame(newlevel));
- if (!cant_go_back) {
- update_mlstmv(); /* current monsters are becoming inactive */
- bufon(fd); /* use buffered output */
- }
- savelev(fd, ledger_no(&u.uz),
- cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
- bclose(fd);
- if (cant_go_back) {
- /* discard unreachable levels; keep #0 */
- for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
- delete_levelfile(l_idx);
- /* mark #overview data for all dungeon branches as uninteresting */
- for (l_idx = 0; l_idx < n_dgns; ++l_idx)
- remdun_mapseen(l_idx);
- }
+ if (on_level(newlevel, &u.uz)) return; /* this can happen */
+
+ /* tethered movement makes level change while trapped feasible */
+ if (u.utrap && u.utraptype == TT_BURIEDBALL)
+ buried_ball_to_punishment(); /* (before we save/leave old level) */
+
+ fd = currentlevel_rewrite();
+ if (fd < 0) return;
+
+ if (falling) /* assuming this is only trap door or hole */
+ impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
+
+ check_special_room(TRUE); /* probably was a trap door */
+ if (Punished) unplacebc();
+ u.utrap = 0; /* needed in level_tele */
+ fill_pit(u.ux, u.uy);
+ u.ustuck = 0; /* idem */
+ u.uinwater = 0;
+ u.uundetected = 0; /* not hidden, even if means are available */
+ keepdogs(FALSE);
+ if (u.uswallow) /* idem */
+ u.uswldtim = u.uswallow = 0;
+ recalc_mapseen(); /* recalculate map overview before we leave the level */
+ /*
+ * We no longer see anything on the level. Make sure that this
+ * follows u.uswallow set to null since uswallow overrides all
+ * normal vision.
+ */
+ vision_recalc(2);
+
+ /*
+ * Save the level we're leaving. If we're entering the endgame,
+ * we can get rid of all existing levels because they cannot be
+ * reached any more. We still need to use savelev()'s cleanup
+ * for the level being left, to recover dynamic memory in use and
+ * to avoid dangling timers and light sources.
+ */
+ cant_go_back = (newdungeon && In_endgame(newlevel));
+ if (!cant_go_back) {
+ update_mlstmv(); /* current monsters are becoming inactive */
+ bufon(fd); /* use buffered output */
+ }
+ savelev(fd, ledger_no(&u.uz),
+ cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
+ bclose(fd);
+ if (cant_go_back) {
+ /* discard unreachable levels; keep #0 */
+ for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
+ delete_levelfile(l_idx);
+ /* mark #overview data for all dungeon branches as uninteresting */
+ for (l_idx = 0; l_idx < n_dgns; ++l_idx)
+ remdun_mapseen(l_idx);
+ }
- if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
- assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
+ if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
+ assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
#ifdef USE_TILES
- substitute_tiles(newlevel);
+ substitute_tiles(newlevel);
#endif
- /* record this level transition as a potential seen branch unless using
- * some non-standard means of transportation (level teleport).
- */
- if ((at_stairs || falling || portal) && (u.uz.dnum != newlevel->dnum))
- recbranch_mapseen(&u.uz, newlevel);
- assign_level(&u.uz0, &u.uz);
- assign_level(&u.uz, newlevel);
- assign_level(&u.utolev, newlevel);
- u.utotype = 0;
- if (dunlev_reached(&u.uz) < dunlev(&u.uz))
- dunlev_reached(&u.uz) = dunlev(&u.uz);
- reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
-
- /* set default level change destination areas */
- /* the special level code may override these */
- (void) memset((genericptr_t) &updest, 0, sizeof updest);
- (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
-
- if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
- /* entering this level for first time; make it now */
- if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
- impossible("goto_level: returning to discarded level?");
- level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
- }
- mklev();
- new = TRUE; /* made the level */
- } else {
- /* returning to previously visited level; reload it */
- fd = open_levelfile(new_ledger, whynot);
- if (fd < 0) {
- pline1(whynot);
- pline("Probably someone removed it.");
- Strcpy(killer.name, whynot);
- done(TRICKED);
- /* we'll reach here if running in wizard mode */
- error("Cannot continue this game.");
- }
- minit(); /* ZEROCOMP */
- getlev(fd, hackpid, new_ledger, FALSE);
- (void) close(fd);
- oinit(); /* reassign level dependent obj probabilities */
- }
- /* do this prior to level-change pline messages */
- vision_reset(); /* clear old level's line-of-sight */
- vision_full_recalc = 0; /* don't let that reenable vision yet */
- flush_screen(-1); /* ensure all map flushes are postponed */
-
- if (portal && !In_endgame(&u.uz)) {
- /* find the portal on the new level */
- register struct trap *ttrap;
-
- for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
- if (ttrap->ttyp == MAGIC_PORTAL) break;
-
- if (!ttrap) panic("goto_level: no corresponding portal!");
- seetrap(ttrap);
- u_on_newpos(ttrap->tx, ttrap->ty);
- } else if (at_stairs && !In_endgame(&u.uz)) {
- if (up) {
- if (at_ladder)
- u_on_newpos(xdnladder, ydnladder);
- else if (newdungeon)
- u_on_sstairs(1);
- else
- u_on_dnstairs();
- /* you climb up the {stairs|ladder};
- fly up the stairs; fly up along the ladder */
- pline("%s %s up%s the %s.",
- (Punished && !Levitation) ? "With great effort you" :
- "You",
- Flying ? "fly" : "climb",
- (Flying && at_ladder) ? " along" : "",
- at_ladder ? "ladder" : "stairs");
- } else { /* down */
- if (at_ladder)
- u_on_newpos(xupladder, yupladder);
- else if (newdungeon)
- u_on_sstairs(0);
- else
- u_on_upstairs();
- if (!u.dz) {
- ; /* stayed on same level? (no transit effects) */
- } else if (Flying) {
- if (flags.verbose)
- You("fly down %s.",
- at_ladder ? "along the ladder" : "the stairs");
- } else if (near_capacity() > UNENCUMBERED ||
- Punished || Fumbling) {
- You("fall down the %s.", at_ladder ? "ladder" : "stairs");
- if (Punished) {
- drag_down();
- if (carried(uball)) {
- if (uwep == uball)
- setuwep((struct obj *)0);
- if (uswapwep == uball)
- setuswapwep((struct obj *)0);
- if (uquiver == uball)
- setuqwep((struct obj *)0);
- freeinv(uball);
- }
- }
- /* falling off steed has its own losehp() call */
- if (u.usteed)
- dismount_steed(DISMOUNT_FELL);
- else
- losehp(Maybe_Half_Phys(rnd(3)),
- at_ladder ? "falling off a ladder" :
- "tumbling down a flight of stairs",
- KILLED_BY);
- selftouch("Falling, you");
- } else { /* ordinary descent */
- if (flags.verbose)
- You("%s.", at_ladder ? "climb down the ladder" :
- "descend the stairs");
- }
- }
- } else { /* trap door or level_tele or In_endgame */
- u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
- if (falling) {
- if (Punished) ballfall();
- selftouch("Falling, you");
- }
- }
+ /* record this level transition as a potential seen branch unless using
+ * some non-standard means of transportation (level teleport).
+ */
+ if ((at_stairs || falling || portal) && (u.uz.dnum != newlevel->dnum))
+ recbranch_mapseen(&u.uz, newlevel);
+ assign_level(&u.uz0, &u.uz);
+ assign_level(&u.uz, newlevel);
+ assign_level(&u.utolev, newlevel);
+ u.utotype = 0;
+ if (dunlev_reached(&u.uz) < dunlev(&u.uz))
+ dunlev_reached(&u.uz) = dunlev(&u.uz);
+ reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
+
+ /* set default level change destination areas */
+ /* the special level code may override these */
+ (void) memset((genericptr_t) &updest, 0, sizeof updest);
+ (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
+
+ if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
+ /* entering this level for first time; make it now */
+ if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
+ impossible("goto_level: returning to discarded level?");
+ level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
+ }
+ mklev();
+ new = TRUE; /* made the level */
+ } else {
+ /* returning to previously visited level; reload it */
+ fd = open_levelfile(new_ledger, whynot);
+ if (fd < 0) {
+ pline1(whynot);
+ pline("Probably someone removed it.");
+ Strcpy(killer.name, whynot);
+ done(TRICKED);
+ /* we'll reach here if running in wizard mode */
+ error("Cannot continue this game.");
+ }
+ minit(); /* ZEROCOMP */
+ getlev(fd, hackpid, new_ledger, FALSE);
+ (void) close(fd);
+ oinit(); /* reassign level dependent obj probabilities */
+ }
+ /* do this prior to level-change pline messages */
+ vision_reset(); /* clear old level's line-of-sight */
+ vision_full_recalc = 0; /* don't let that reenable vision yet */
+ flush_screen(-1); /* ensure all map flushes are postponed */
+
+ if (portal && !In_endgame(&u.uz)) {
+ /* find the portal on the new level */
+ register struct trap *ttrap;
+
+ for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
+ if (ttrap->ttyp == MAGIC_PORTAL) break;
+
+ if (!ttrap) panic("goto_level: no corresponding portal!");
+ seetrap(ttrap);
+ u_on_newpos(ttrap->tx, ttrap->ty);
+ } else if (at_stairs && !In_endgame(&u.uz)) {
+ if (up) {
+ if (at_ladder)
+ u_on_newpos(xdnladder, ydnladder);
+ else if (newdungeon)
+ u_on_sstairs(1);
+ else
+ u_on_dnstairs();
+ /* you climb up the {stairs|ladder};
+ fly up the stairs; fly up along the ladder */
+ pline("%s %s up%s the %s.",
+ (Punished && !Levitation) ? "With great effort you" :
+ "You",
+ Flying ? "fly" : "climb",
+ (Flying && at_ladder) ? " along" : "",
+ at_ladder ? "ladder" : "stairs");
+ } else { /* down */
+ if (at_ladder)
+ u_on_newpos(xupladder, yupladder);
+ else if (newdungeon)
+ u_on_sstairs(0);
+ else
+ u_on_upstairs();
+ if (!u.dz) {
+ ; /* stayed on same level? (no transit effects) */
+ } else if (Flying) {
+ if (flags.verbose)
+ You("fly down %s.",
+ at_ladder ? "along the ladder" : "the stairs");
+ } else if (near_capacity() > UNENCUMBERED ||
+ Punished || Fumbling) {
+ You("fall down the %s.", at_ladder ? "ladder" : "stairs");
+ if (Punished) {
+ drag_down();
+ if (carried(uball)) {
+ if (uwep == uball)
+ setuwep((struct obj *)0);
+ if (uswapwep == uball)
+ setuswapwep((struct obj *)0);
+ if (uquiver == uball)
+ setuqwep((struct obj *)0);
+ freeinv(uball);
+ }
+ }
+ /* falling off steed has its own losehp() call */
+ if (u.usteed)
+ dismount_steed(DISMOUNT_FELL);
+ else
+ losehp(Maybe_Half_Phys(rnd(3)),
+ at_ladder ? "falling off a ladder" :
+ "tumbling down a flight of stairs",
+ KILLED_BY);
+ selftouch("Falling, you");
+ } else { /* ordinary descent */
+ if (flags.verbose)
+ You("%s.", at_ladder ? "climb down the ladder" :
+ "descend the stairs");
+ }
+ }
+ } else { /* trap door or level_tele or In_endgame */
+ u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
+ if (falling) {
+ if (Punished) ballfall();
+ selftouch("Falling, you");
+ }
+ }
- if (Punished) placebc();
- obj_delivery(FALSE);
- losedogs();
- kill_genocided_monsters(); /* for those wiped out while in limbo */
- /*
- * Expire all timers that have gone off while away. Must be
- * after migrating monsters and objects are delivered
- * (losedogs and obj_delivery).
- */
- run_timers();
-
- initrack();
-
- if ((mtmp = m_at(u.ux, u.uy)) != 0 && mtmp != u.usteed) {
- /* There's a monster at your target destination; it might be one
- which accompanied you--see mon_arrive(dogmove.c)--or perhaps
- it was already here. Randomly move you to an adjacent spot
- or else the monster to any nearby location. Prior to 3.3.0
- the latter was done unconditionally. */
- coord cc;
-
- if (!rn2(2) &&
- enexto(&cc, u.ux, u.uy, youmonst.data) &&
- distu(cc.x, cc.y) <= 2)
- u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
- else
- mnexto(mtmp);
-
- if ((mtmp = m_at(u.ux, u.uy)) != 0) {
- /* there was an unconditional impossible("mnearto failed")
- here, but it's not impossible and we're prepared to cope
- with the situation, so only say something when debugging */
- if (wizard) pline("(monster in hero's way)");
- if (!rloc(mtmp, TRUE))
- /* no room to move it; send it away, to return later */
- migrate_to_level(mtmp, ledger_no(&u.uz),
- MIGR_RANDOM, (coord *)0);
- }
- }
+ if (Punished) placebc();
+ obj_delivery(FALSE);
+ losedogs();
+ kill_genocided_monsters(); /* for those wiped out while in limbo */
+ /*
+ * Expire all timers that have gone off while away. Must be
+ * after migrating monsters and objects are delivered
+ * (losedogs and obj_delivery).
+ */
+ run_timers();
+
+ initrack();
+
+ if ((mtmp = m_at(u.ux, u.uy)) != 0 && mtmp != u.usteed) {
+ /* There's a monster at your target destination; it might be one
+ which accompanied you--see mon_arrive(dogmove.c)--or perhaps
+ it was already here. Randomly move you to an adjacent spot
+ or else the monster to any nearby location. Prior to 3.3.0
+ the latter was done unconditionally. */
+ coord cc;
+
+ if (!rn2(2) &&
+ enexto(&cc, u.ux, u.uy, youmonst.data) &&
+ distu(cc.x, cc.y) <= 2)
+ u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
+ else
+ mnexto(mtmp);
+
+ if ((mtmp = m_at(u.ux, u.uy)) != 0) {
+ /* there was an unconditional impossible("mnearto failed")
+ here, but it's not impossible and we're prepared to cope
+ with the situation, so only say something when debugging */
+ if (wizard) pline("(monster in hero's way)");
+ if (!rloc(mtmp, TRUE))
+ /* no room to move it; send it away, to return later */
+ migrate_to_level(mtmp, ledger_no(&u.uz),
+ MIGR_RANDOM, (coord *)0);
+ }
+ }
- /* initial movement of bubbles just before vision_recalc */
- if (Is_waterlevel(&u.uz))
- movebubbles();
+ /* initial movement of bubbles just before vision_recalc */
+ if (Is_waterlevel(&u.uz))
+ movebubbles();
- if (level_info[new_ledger].flags & FORGOTTEN) {
- forget_map(ALL_MAP); /* forget the map */
- forget_traps(); /* forget all traps too */
- familiar = TRUE;
- level_info[new_ledger].flags &= ~FORGOTTEN;
- }
+ if (level_info[new_ledger].flags & FORGOTTEN) {
+ forget_map(ALL_MAP); /* forget the map */
+ forget_traps(); /* forget all traps too */
+ familiar = TRUE;
+ level_info[new_ledger].flags &= ~FORGOTTEN;
+ }
- /* Reset the screen. */
- vision_reset(); /* reset the blockages */
- docrt(); /* does a full vision recalc */
- flush_screen(-1);
+ /* Reset the screen. */
+ vision_reset(); /* reset the blockages */
+ docrt(); /* does a full vision recalc */
+ flush_screen(-1);
- /*
- * Move all plines beyond the screen reset.
- */
+ /*
+ * Move all plines beyond the screen reset.
+ */
- /* special levels can have a custom arrival message */
- deliver_splev_message();
+ /* special levels can have a custom arrival message */
+ deliver_splev_message();
- /* give room entrance message, if any */
- check_special_room(FALSE);
+ /* give room entrance message, if any */
+ check_special_room(FALSE);
- /* deliver objects traveling with player */
- obj_delivery(TRUE);
+ /* deliver objects traveling with player */
+ obj_delivery(TRUE);
- /* Check whether we just entered Gehennom. */
- if (!In_hell(&u.uz0) && Inhell) {
- if (Is_valley(&u.uz)) {
- You("arrive at the Valley of the Dead...");
- pline_The("odor of burnt flesh and decay pervades the air.");
+ /* Check whether we just entered Gehennom. */
+ if (!In_hell(&u.uz0) && Inhell) {
+ if (Is_valley(&u.uz)) {
+ You("arrive at the Valley of the Dead...");
+ pline_The("odor of burnt flesh and decay pervades the air.");
#ifdef MICRO
- display_nhwindow(WIN_MESSAGE, FALSE);
+ display_nhwindow(WIN_MESSAGE, FALSE);
#endif
- You_hear("groans and moans everywhere.");
- } else pline("It is hot here. You smell smoke...");
+ You_hear("groans and moans everywhere.");
+ } else pline("It is hot here. You smell smoke...");
+ u.uachieve.enter_gehennom = 1;
- }
- /* in case we've managed to bypass the Valley's stairway down */
- if (Inhell && !Is_valley(&u.uz)) u.uevent.gehennom_entered = 1;
-
- if (familiar) {
- static const char * const fam_msgs[4] = {
- "You have a sense of deja vu.",
- "You feel like you've been here before.",
- "This place %s familiar...",
- 0 /* no message */
- };
- static const char * const halu_fam_msgs[4] = {
- "Whoa! Everything %s different.",
- "You are surrounded by twisty little passages, all alike.",
- "Gee, this %s like uncle Conan's place...",
- 0 /* no message */
- };
- const char *mesg;
- char buf[BUFSZ];
- int which = rn2(4);
-
- if (Hallucination)
- mesg = halu_fam_msgs[which];
- else
- mesg = fam_msgs[which];
- if (mesg && index(mesg, '%')) {
- Sprintf(buf, mesg, !Blind ? "looks" : "seems");
- mesg = buf;
- }
- if (mesg) pline1(mesg);
- }
+ }
+ /* in case we've managed to bypass the Valley's stairway down */
+ if (Inhell && !Is_valley(&u.uz)) u.uevent.gehennom_entered = 1;
+
+ if (familiar) {
+ static const char * const fam_msgs[4] = {
+ "You have a sense of deja vu.",
+ "You feel like you've been here before.",
+ "This place %s familiar...",
+ 0 /* no message */
+ };
+ static const char * const halu_fam_msgs[4] = {
+ "Whoa! Everything %s different.",
+ "You are surrounded by twisty little passages, all alike.",
+ "Gee, this %s like uncle Conan's place...",
+ 0 /* no message */
+ };
+ const char *mesg;
+ char buf[BUFSZ];
+ int which = rn2(4);
+
+ if (Hallucination)
+ mesg = halu_fam_msgs[which];
+ else
+ mesg = fam_msgs[which];
+ if (mesg && index(mesg, '%')) {
+ Sprintf(buf, mesg, !Blind ? "looks" : "seems");
+ mesg = buf;
+ }
+ if (mesg) pline1(mesg);
+ }
- /* special location arrival messages/events */
- if (In_endgame(&u.uz)) {
- if (new && on_level(&u.uz, &astral_level))
- final_level(); /* guardian angel,&c */
- else if (newdungeon && u.uhave.amulet)
- resurrect(); /* force confrontation with Wizard */
- } else if (In_quest(&u.uz)) {
- onquest(); /* might be reaching locate|goal level */
- } else if (In_V_tower(&u.uz)) {
- if (newdungeon && In_hell(&u.uz0))
- pline_The("heat and smoke are gone.");
- } else if (Is_knox(&u.uz)) {
- /* alarm stops working once Croesus has died */
- if (new || !mvitals[PM_CROESUS].died) {
- You("have penetrated a high security area!");
- pline("An alarm sounds!");
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- mtmp->msleeping = 0;
- }
- }
- } else {
- if (new && Is_rogue_level(&u.uz))
- You("enter what seems to be an older, more primitive world.");
- /* main dungeon message from your quest leader */
- if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
- !(u.uevent.qcompleted || u.uevent.qexpelled ||
- quest_status.leader_is_dead)) {
- if (!u.uevent.qcalled) {
- u.uevent.qcalled = 1;
- com_pager(2); /* main "leader needs help" message */
- } else { /* reminder message */
- com_pager(Role_if(PM_ROGUE) ? 4 : 3);
- }
- }
- }
+ /* special location arrival messages/events */
+ if (In_endgame(&u.uz)) {
+ if (new && on_level(&u.uz, &astral_level))
+ final_level(); /* guardian angel,&c */
+ else if (newdungeon && u.uhave.amulet)
+ resurrect(); /* force confrontation with Wizard */
+ } else if (In_quest(&u.uz)) {
+ onquest(); /* might be reaching locate|goal level */
+ } else if (In_V_tower(&u.uz)) {
+ if (newdungeon && In_hell(&u.uz0))
+ pline_The("heat and smoke are gone.");
+ } else if (Is_knox(&u.uz)) {
+ /* alarm stops working once Croesus has died */
+ if (new || !mvitals[PM_CROESUS].died) {
+ You("have penetrated a high security area!");
+ pline("An alarm sounds!");
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ mtmp->msleeping = 0;
+ }
+ }
+ } else {
+ if (new && Is_rogue_level(&u.uz))
+ You("enter what seems to be an older, more primitive world.");
+ /* main dungeon message from your quest leader */
+ if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
+ !(u.uevent.qcompleted || u.uevent.qexpelled ||
+ quest_status.leader_is_dead)) {
+ if (!u.uevent.qcalled) {
+ u.uevent.qcalled = 1;
+ com_pager(2); /* main "leader needs help" message */
+ } else { /* reminder message */
+ com_pager(Role_if(PM_ROGUE) ? 4 : 3);
+ }
+ }
+ }
- assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
+ assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
#ifdef INSURANCE
- save_currentstate();
+ save_currentstate();
#endif
- /* assume this will always return TRUE when changing level */
- (void) in_out_region(u.ux, u.uy);
- (void) pickup(1);
+ /* assume this will always return TRUE when changing level */
+ (void) in_out_region(u.ux, u.uy);
+ (void) pickup(1);
}
STATIC_OVL void
}
#if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
- lastconfigfile[BUFSZ-1] = '\0';
+# if defined(WIN32) || defined(MSDOS)
+ /* user's home directory should be where we look first here, too */
+ envp = nh_getenv("USERPROFILE");
+# endif
++/*
++ * TODO: uncomment this when you figure out where to put it
+ (void) strncpy(lastconfigfile,
+ fqname(configfile, CONFIGPREFIX, 0), BUFSZ-1);
++ lastconfigfile[BUFSZ-1] = '\0';
+ if ((fp = fopenp(lastconfigfile, "r")) != (FILE *)0) {
++*/
+# ifdef WIN32
+ if (!envp) {
+ Strcpy(tmp_config, configfile);
+ } else {
+ Sprintf(tmp_config, "%s\\%s", envp, configfile);
+ }
+ /* try the home directory first, then the output of fqname() will
+ * pick up the current dir */
+ if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
+ return(fp);
+ if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *)0)
return(fp);
- }
+# else
+ if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *)0)
+ return(fp);
+# endif
# ifdef MSDOS
- (void) strncpy(lastconfigfile,
- fqname(backward_compat_configfile, CONFIGPREFIX, 0),
- BUFSZ-1);
- lastconfigfile[BUFSZ-1] = '\0';
- else if ((fp = fopenp(lastconfigfile, "r")) != (FILE *)0)
+ else {
+ if (!envp) {
+ Strcpy(tmp_config, backward_compat_configfile);
+ } else {
+ Sprintf(tmp_config, "%s\\%s", envp, backward_compat_configfile);
+ }
+ if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
return(fp);
+ if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *)0)
+ return(fp);
+ }
# endif
#else
/* constructed full path names don't need fqname() */
* Check for physical obstacles. First, the place we are going.
*/
if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
- if (Blind && mode == DO_MOVE) feel_location(x,y);
- if (Passes_walls && may_passwall(x,y)) {
- ; /* do nothing */
- } else if (tmpr->typ == IRONBARS) {
+ if (Blind && mode == DO_MOVE) feel_location(x,y);
+ if (Passes_walls && may_passwall(x,y)) {
+ ; /* do nothing */
+ } else if (tmpr->typ == IRONBARS) {
- if (!(Passes_walls || passes_bars(youmonst.data)))
+ if (!(Passes_walls || passes_bars(youmonst.data))) {
+ if (iflags.mention_walls)
+ You("cannot pass through the bars.");
- return FALSE;
+ return FALSE;
+ }
- } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
- /* Eat the rock. */
- if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
- } else if (flags.autodig && !context.run && !context.nopick &&
- uwep && is_pick(uwep)) {
- /* MRKR: Automatic digging when wielding the appropriate tool */
- if (mode == DO_MOVE)
- (void) use_pick_axe2(uwep);
- return FALSE;
- } else {
- if (mode == DO_MOVE) {
- if (Is_stronghold(&u.uz) && is_db_wall(x,y))
- pline_The("drawbridge is up!");
- /* sokoban restriction stays even after puzzle is solved */
+ } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
+ /* Eat the rock. */
+ if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
+ } else if (flags.autodig && !context.run && !context.nopick &&
+ uwep && is_pick(uwep)) {
+ /* MRKR: Automatic digging when wielding the appropriate tool */
+ if (mode == DO_MOVE)
+ (void) use_pick_axe2(uwep);
+ return FALSE;
+ } else {
+ if (mode == DO_MOVE) {
+ if (Is_stronghold(&u.uz) && is_db_wall(x,y))
+ pline_The("drawbridge is up!");
+ /* sokoban restriction stays even after puzzle is solved */
- if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
+ else if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
- pline_The("Sokoban walls resist your ability.");
+ pline_The("Sokoban walls resist your ability.");
+ else if (iflags.mention_walls)
+ pline("It's a wall.");
- }
- return FALSE;
- }
+ }
+ return FALSE;
+ }
} else if (IS_DOOR(tmpr->typ)) {
- if (closed_door(x,y)) {
- if (Blind && mode == DO_MOVE) feel_location(x,y);
- if (Passes_walls)
- ; /* do nothing */
- else if (can_ooze(&youmonst)) {
- if (mode == DO_MOVE) You("ooze under the door.");
- } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
- /* Eat the door. */
- if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
- } else {
- if (mode == DO_MOVE) {
- if (amorphous(youmonst.data))
- You("try to ooze under the door, but can't squeeze your possessions through.");
- else if (x == ux || y == uy) {
- if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
- if (u.usteed) {
- You_cant("lead %s through that closed door.",
- y_monnam(u.usteed));
- } else {
- pline("Ouch! You bump into a door.");
- exercise(A_DEX, FALSE);
- }
- } else pline("That door is closed.");
- }
- } else if (mode == TEST_TRAV) goto testdiag;
- return FALSE;
- }
- } else {
- testdiag:
- if (dx && dy && !Passes_walls
- && (!doorless_door(x, y) || block_door(x, y))) {
- /* Diagonal moves into a door are not allowed. */
- if (Blind && mode == DO_MOVE)
- feel_location(x,y);
- return FALSE;
- }
- }
+ if (closed_door(x,y)) {
+ if (Blind && mode == DO_MOVE) feel_location(x,y);
+ if (Passes_walls)
+ ; /* do nothing */
+ else if (can_ooze(&youmonst)) {
+ if (mode == DO_MOVE) You("ooze under the door.");
+ } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
+ /* Eat the door. */
+ if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
+ } else {
+ if (mode == DO_MOVE) {
+ if (amorphous(youmonst.data))
+ You("try to ooze under the door, but can't squeeze your possessions through.");
+ else if (x == ux || y == uy) {
+ if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
+ if (u.usteed) {
+ You_cant("lead %s through that closed door.",
+ y_monnam(u.usteed));
+ } else {
+ pline("Ouch! You bump into a door.");
+ exercise(A_DEX, FALSE);
+ }
+ } else pline("That door is closed.");
+ }
+ } else if (mode == TEST_TRAV) goto testdiag;
+ return FALSE;
+ }
+ } else {
+ testdiag:
+ if (dx && dy && !Passes_walls
+ && (!doorless_door(x, y) || block_door(x, y))) {
+ /* Diagonal moves into a door are not allowed. */
+ if (Blind && mode == DO_MOVE)
+ feel_location(x,y);
+ return FALSE;
+ }
+ }
}
if (dx && dy
- && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) {
- /* Move at a diagonal. */
- switch (cant_squeeze_thru(&youmonst)) {
- case 3:
- if (mode == DO_MOVE) You("cannot pass that way.");
- return FALSE;
- case 2:
- if (mode == DO_MOVE) You("are carrying too much to get through.");
- return FALSE;
- case 1:
- if (mode == DO_MOVE) Your("body is too large to fit through.");
- return FALSE;
- default:
- break; /* can squeeze through */
- }
+ && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) {
+ /* Move at a diagonal. */
+ switch (cant_squeeze_thru(&youmonst)) {
+ case 3:
+ if (mode == DO_MOVE) You("cannot pass that way.");
+ return FALSE;
+ case 2:
+ if (mode == DO_MOVE) You("are carrying too much to get through.");
+ return FALSE;
+ case 1:
+ if (mode == DO_MOVE) Your("body is too large to fit through.");
+ return FALSE;
+ default:
+ break; /* can squeeze through */
+ }
} else if (dx && dy && worm_cross(ux, uy, x, y)) {
- /* consecutive long worm segments are at <ux,y> and <x,uy> */
- if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y)));
- return FALSE;
+ /* consecutive long worm segments are at <ux,y> and <x,uy> */
+ if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y)));
+ return FALSE;
}
/* Pick travel path that does not require crossing a trap.
* Avoid water and lava using the usual running rules.
addinv_core1(obj)
struct obj *obj;
{
- if (obj->oclass == COIN_CLASS) {
- context.botl = 1;
- } else if (obj->otyp == AMULET_OF_YENDOR) {
- if (u.uhave.amulet) impossible("already have amulet?");
- u.uhave.amulet = 1;
+ if (obj->oclass == COIN_CLASS) {
+ context.botl = 1;
+ } else if (obj->otyp == AMULET_OF_YENDOR) {
+ if (u.uhave.amulet) impossible("already have amulet?");
+ u.uhave.amulet = 1;
+ u.uachieve.amulet = 1;
- } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
- if (u.uhave.menorah) impossible("already have candelabrum?");
- u.uhave.menorah = 1;
+ } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
+ if (u.uhave.menorah) impossible("already have candelabrum?");
+ u.uhave.menorah = 1;
+ u.uachieve.menorah = 1;
- } else if (obj->otyp == BELL_OF_OPENING) {
- if (u.uhave.bell) impossible("already have silver bell?");
- u.uhave.bell = 1;
+ } else if (obj->otyp == BELL_OF_OPENING) {
+ if (u.uhave.bell) impossible("already have silver bell?");
+ u.uhave.bell = 1;
+ u.uachieve.bell = 1;
- } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
- if (u.uhave.book) impossible("already have the book?");
- u.uhave.book = 1;
+ } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+ if (u.uhave.book) impossible("already have the book?");
+ u.uhave.book = 1;
+ u.uachieve.book = 1;
- } else if (obj->oartifact) {
- if (is_quest_artifact(obj)) {
- if (u.uhave.questart)
- impossible("already have quest artifact?");
- u.uhave.questart = 1;
- artitouch(obj);
- }
- set_artifact_intrinsic(obj, 1, W_ART);
- }
+ } else if (obj->oartifact) {
+ if (is_quest_artifact(obj)) {
+ if (u.uhave.questart)
+ impossible("already have quest artifact?");
+ u.uhave.questart = 1;
+ artitouch(obj);
+ }
+ set_artifact_intrinsic(obj, 1, W_ART);
+ }
+ if(obj->otyp == LUCKSTONE && obj->record_achieve_special) {
+ u.uachieve.mines_luckstone = 1;
+ obj->record_achieve_special = 0;
+ } else if((obj->otyp == AMULET_OF_REFLECTION ||
+ obj->otyp == BAG_OF_HOLDING) &&
+ obj->record_achieve_special) {
+ u.uachieve.finish_sokoban = 1;
+ obj->record_achieve_special = 0;
+ }
}
/*
getobj(let,word)
register const char *let,*word;
{
- register struct obj *otmp;
- register char ilet;
- char buf[BUFSZ], qbuf[QBUFSZ];
- char lets[BUFSZ], altlets[BUFSZ], *ap;
- register int foo = 0;
- register char *bp = buf;
- xchar allowcnt = 0; /* 0, 1 or 2 */
- struct obj *firstobj = invent;
- boolean usegold = FALSE; /* can't use gold because its illegal */
- boolean allowall = FALSE;
- boolean allownone = FALSE;
- boolean useboulder = FALSE;
- xchar foox = 0;
- long cnt, prevcnt;
- boolean prezero;
- long dummymask;
-
- if(*let == ALLOW_COUNT) let++, allowcnt = 1;
- if(*let == COIN_CLASS) let++, usegold = TRUE;
-
- /* Equivalent of an "ugly check" for gold */
- if (usegold && !strcmp(word, "eat") &&
- (!metallivorous(youmonst.data)
- || youmonst.data == &mons[PM_RUST_MONSTER]))
- usegold = FALSE;
-
- if(*let == ALL_CLASSES) let++, allowall = TRUE;
- if(*let == ALLOW_NONE) let++, allownone = TRUE;
- /* "ugly check" for reading fortune cookies, part 1 */
- /* The normal 'ugly check' keeps the object on the inventory list.
- * We don't want to do that for shirts/cookies, so the check for
- * them is handled a bit differently (and also requires that we set
- * allowall in the caller)
- */
- if(allowall && !strcmp(word, "read")) allowall = FALSE;
-
- /* another ugly check: show boulders (not statues) */
- if(*let == WEAPON_CLASS &&
- !strcmp(word, "throw") && throws_rocks(youmonst.data))
- useboulder = TRUE;
-
- if(allownone) *bp++ = '-';
- if(bp > buf && bp[-1] == '-') *bp++ = ' ';
- ap = altlets;
-
- if (!flags.invlet_constant) reassign();
-
- for (otmp = firstobj; otmp; otmp = otmp->nobj) {
- if (&bp[foo] == &buf[sizeof buf - 1] ||
- ap == &altlets[sizeof altlets - 1]) {
- /* we must have a huge number of NOINVSYM items somehow */
- impossible("getobj: inventory overflow");
- break;
- }
+ register struct obj *otmp;
+ register char ilet;
+ char buf[BUFSZ], qbuf[QBUFSZ];
+ char lets[BUFSZ], altlets[BUFSZ], *ap;
+ register int foo = 0;
+ register char *bp = buf;
+ xchar allowcnt = 0; /* 0, 1 or 2 */
+ struct obj *firstobj = invent;
+ boolean usegold = FALSE; /* can't use gold because its illegal */
+ boolean allowall = FALSE;
+ boolean allownone = FALSE;
+ boolean useboulder = FALSE;
+ xchar foox = 0;
+ long cnt, prevcnt;
+ boolean prezero;
+ long dummymask;
+
+ if(*let == ALLOW_COUNT) let++, allowcnt = 1;
+ if(*let == COIN_CLASS) let++, usegold = TRUE;
+
+ /* Equivalent of an "ugly check" for gold */
+ if (usegold && !strcmp(word, "eat") &&
+ (!metallivorous(youmonst.data)
+ || youmonst.data == &mons[PM_RUST_MONSTER]))
+ usegold = FALSE;
+
+ if(*let == ALL_CLASSES) let++, allowall = TRUE;
+ if(*let == ALLOW_NONE) let++, allownone = TRUE;
+ /* "ugly check" for reading fortune cookies, part 1 */
+ /* The normal 'ugly check' keeps the object on the inventory list.
+ * We don't want to do that for shirts/cookies, so the check for
+ * them is handled a bit differently (and also requires that we set
+ * allowall in the caller)
+ */
+ if(allowall && !strcmp(word, "read")) allowall = FALSE;
+
+ /* another ugly check: show boulders (not statues) */
+ if(*let == WEAPON_CLASS &&
+ !strcmp(word, "throw") && throws_rocks(youmonst.data))
+ useboulder = TRUE;
+
+ if(allownone) *bp++ = '-';
+ if(bp > buf && bp[-1] == '-') *bp++ = ' ';
+ ap = altlets;
+
+ if (!flags.invlet_constant) reassign();
- if (!*let || index(let, otmp->oclass)
- || (usegold && otmp->invlet == GOLD_SYM)
- || (useboulder && otmp->otyp == BOULDER)
- ) {
- register int otyp = otmp->otyp;
- bp[foo++] = otmp->invlet;
-
- /* ugly check: remove inappropriate things */
- if ((taking_off(word) &&
- !(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
- || (putting_on(word) &&
- (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
- /* already worn */
+ for (otmp = firstobj; otmp; otmp = otmp->nobj) {
+ if (&bp[foo] == &buf[sizeof buf - 1] ||
+ ap == &altlets[sizeof altlets - 1]) {
+ /* we must have a huge number of NOINVSYM items somehow */
+ impossible("getobj: inventory overflow");
+ break;
+ }
+
+ if (!*let || index(let, otmp->oclass)
+ || (usegold && otmp->invlet == GOLD_SYM)
+ || (useboulder && otmp->otyp == BOULDER)
+ ) {
+ register int otyp = otmp->otyp;
+ bp[foo++] = otmp->invlet;
+
+ /* ugly check: remove inappropriate things */
+ if ((taking_off(word) &&
+ !(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
+ || (putting_on(word) &&
+ (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
+ /* already worn */
#if 0 /* 3.4.1 -- include currently wielded weapon among the choices */
- || (!strcmp(word, "wield") &&
- (otmp->owornmask & W_WEP))
+ || (!strcmp(word, "wield") &&
+ (otmp->owornmask & W_WEP))
#endif
- || (!strcmp(word, "ready") &&
- (otmp == uwep || (otmp == uswapwep && u.twoweap)))
- || ((!strcmp(word, "dip") || !strcmp(word, "grease")) &&
- inaccessible_equipment(otmp, (const char *)0 , FALSE))
- ) {
- foo--;
- foox++;
- }
-
- /* Second ugly check; unlike the first it won't trigger an
- * "else" in "you don't have anything else to ___".
- */
- else if ((putting_on(word) &&
- ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
- (otmp->oclass == TOOL_CLASS &&
- otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
- || (!strcmp(word, "wield") &&
- (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
- || (!strcmp(word, "eat") && !is_edible(otmp))
- || (!strcmp(word, "sacrifice") &&
- (otyp != CORPSE &&
- otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
- || (!strcmp(word, "write with") &&
- (otmp->oclass == TOOL_CLASS &&
- otyp != MAGIC_MARKER && otyp != TOWEL))
- || (!strcmp(word, "tin") &&
- (otyp != CORPSE || !tinnable(otmp)))
- || (!strcmp(word, "rub") &&
- ((otmp->oclass == TOOL_CLASS &&
- otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
- otyp != BRASS_LANTERN) ||
- (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
- || ((!strcmp(word, "use or apply") ||
- !strcmp(word, "untrap with")) &&
- /* Picks, axes, pole-weapons, bullwhips */
- ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
- !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
- (otmp->oclass == POTION_CLASS &&
- /* only applicable potion is oil, and it will only
- be offered as a choice when already discovered */
- (otyp != POT_OIL || !otmp->dknown ||
- !objects[POT_OIL].oc_name_known)) ||
- (otmp->oclass == FOOD_CLASS &&
- otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
- (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
- || (!strcmp(word, "invoke") &&
- (!otmp->oartifact && !objects[otyp].oc_unique &&
- (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
- otyp != CRYSTAL_BALL && /* #invoke synonym for apply */
- /* note: presenting the possibility of invoking non-artifact
- mirrors and/or lamps is a simply a cruel deception... */
- otyp != MIRROR && otyp != MAGIC_LAMP &&
- (otyp != OIL_LAMP || /* don't list known oil lamp */
- (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
- || (!strcmp(word, "untrap with") &&
- (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
- || (!strcmp(word, "tip") && !Is_container(otmp) &&
- /* include horn of plenty if sufficiently discovered */
- (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown ||
- !objects[HORN_OF_PLENTY].oc_name_known))
- || (!strcmp(word, "charge") && !is_chargeable(otmp))
- || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
- )
- foo--;
- /* ugly check for unworn armor that can't be worn */
- else if ((putting_on(word) && *let == ARMOR_CLASS &&
- !canwearobj(otmp, &dummymask, FALSE))
- /* or unsuitable items rubbed on known touchstone */
- || (!strncmp(word, "rub on the stone", 16) &&
- *let == GEM_CLASS &&
- otmp->dknown && objects[otyp].oc_name_known)
- /* suppress corpses on astral, amulets elsewhere */
- || (!strcmp(word, "sacrifice") &&
- /* (!astral && amulet) || (astral && !amulet) */
- (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
- /* suppress container being stashed into */
- || (!strcmp(word, "stash") && !ck_bag(otmp))
- /* worn armor or accessory covered by cursed worn armor */
- || (taking_off(word) &&
- inaccessible_equipment(otmp, (const char *)0, TRUE))
- ) {
- /* acceptable but not listed as likely candidate */
- foo--;
- allowall = TRUE;
- *ap++ = otmp->invlet;
- }
- } else {
-
- /* "ugly check" for reading fortune cookies, part 2 */
- if ((!strcmp(word, "read")
+ || (!strcmp(word, "ready") &&
+ (otmp == uwep || (otmp == uswapwep && u.twoweap)))
+ || ((!strcmp(word, "dip") || !strcmp(word, "grease")) &&
+ inaccessible_equipment(otmp, (const char *)0 , FALSE))
+ ) {
+ foo--;
+ foox++;
+ }
+
+ /* Second ugly check; unlike the first it won't trigger an
+ * "else" in "you don't have anything else to ___".
+ */
+ else if ((putting_on(word) &&
+ ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
+ (otmp->oclass == TOOL_CLASS &&
+ otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
+ || (!strcmp(word, "wield") &&
+ (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
+ || (!strcmp(word, "eat") && !is_edible(otmp))
+ || (!strcmp(word, "sacrifice") &&
+ (otyp != CORPSE &&
+ otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
+ || (!strcmp(word, "write with") &&
+ (otmp->oclass == TOOL_CLASS &&
+ otyp != MAGIC_MARKER && otyp != TOWEL))
+ || (!strcmp(word, "tin") &&
+ (otyp != CORPSE || !tinnable(otmp)))
+ || (!strcmp(word, "rub") &&
+ ((otmp->oclass == TOOL_CLASS &&
+ otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
+ otyp != BRASS_LANTERN) ||
+ (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
+ || ((!strcmp(word, "use or apply") ||
+ !strcmp(word, "untrap with")) &&
+ /* Picks, axes, pole-weapons, bullwhips */
+ ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
+ !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
+ (otmp->oclass == POTION_CLASS &&
+ /* only applicable potion is oil, and it will only
+ be offered as a choice when already discovered */
+ (otyp != POT_OIL || !otmp->dknown ||
+ !objects[POT_OIL].oc_name_known)) ||
+ (otmp->oclass == FOOD_CLASS &&
+ otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
+ (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
+ || (!strcmp(word, "invoke") &&
+ (!otmp->oartifact && !objects[otyp].oc_unique &&
+ (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
+ otyp != CRYSTAL_BALL && /* #invoke synonym for apply */
+ /* note: presenting the possibility of invoking non-artifact
+ mirrors and/or lamps is a simply a cruel deception... */
+ otyp != MIRROR && otyp != MAGIC_LAMP &&
+ (otyp != OIL_LAMP || /* don't list known oil lamp */
+ (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
+ || (!strcmp(word, "untrap with") &&
+ (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
+ || (!strcmp(word, "tip") && !Is_container(otmp) &&
+ /* include horn of plenty if sufficiently discovered */
+ (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown ||
+ !objects[HORN_OF_PLENTY].oc_name_known))
+ || (!strcmp(word, "charge") && !is_chargeable(otmp))
+ || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
+ )
+ foo--;
+ /* ugly check for unworn armor that can't be worn */
+ else if ((putting_on(word) && *let == ARMOR_CLASS &&
+ !canwearobj(otmp, &dummymask, FALSE))
+ /* or unsuitable items rubbed on known touchstone */
+ || (!strncmp(word, "rub on the stone", 16) &&
+ *let == GEM_CLASS &&
+ otmp->dknown && objects[otyp].oc_name_known)
+ /* suppress corpses on astral, amulets elsewhere */
+ || (!strcmp(word, "sacrifice") &&
+ /* (!astral && amulet) || (astral && !amulet) */
+ (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
+ /* suppress container being stashed into */
+ || (!strcmp(word, "stash") && !ck_bag(otmp))
+ /* worn armor or accessory covered by cursed worn armor */
+ || (taking_off(word) &&
+ inaccessible_equipment(otmp, (const char *)0, TRUE))
+ ) {
+ /* acceptable but not listed as likely candidate */
+ foo--;
+ allowall = TRUE;
+ *ap++ = otmp->invlet;
+ }
+ } else {
+
+ /* "ugly check" for reading fortune cookies, part 2 */
+ if ((!strcmp(word, "read")
&& (otmp->otyp == FORTUNE_COOKIE || otmp->otyp == T_SHIRT)))
- allowall = TRUE;
- }
- }
- bp[foo] = 0;
- if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
- Strcpy(lets, bp); /* necessary since we destroy buf */
- if(foo > 5) /* compactify string */
- compactify(bp);
- *ap = '\0';
-
- if(!foo && !allowall && !allownone) {
- You("don't have anything %sto %s.",
- foox ? "else " : "", word);
- return((struct obj *)0);
- }
- for(;;) {
- cnt = 0;
- if (allowcnt == 2) allowcnt = 1; /* abort previous count */
- prezero = FALSE;
- if(!buf[0]) {
- Sprintf(qbuf, "What do you want to %s? [*]", word);
- } else {
- Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
- word, buf);
- }
- if (in_doagain)
- ilet = readchar();
- else
- ilet = yn_function(qbuf, (char *)0, '\0');
- if (digit(ilet) && !allowcnt) {
- pline("No count allowed with this command.");
- continue;
- }
- if (ilet == '0') prezero = TRUE;
- while (digit(ilet)) {
- if (ilet != '?' && ilet != '*') savech(ilet);
- /* accumulate unless cnt has overflowed */
- if (allowcnt < 3) {
- prevcnt = cnt;
- cnt = 10L * cnt + (long)(ilet - '0');
- /* signal presence of cnt */
- allowcnt = (cnt >= prevcnt) ? 2 : 3;
- }
- ilet = readchar();
- }
- if (allowcnt == 3) {
- /* overflow detected; force cnt to be invalid */
- cnt = -1L;
- allowcnt = 2;
- }
- if(index(quitchars,ilet)) {
- if(flags.verbose)
- pline1(Never_mind);
- return((struct obj *)0);
- }
- if(ilet == '-') {
+ allowall = TRUE;
+ }
+ }
+ bp[foo] = 0;
+ if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
+ Strcpy(lets, bp); /* necessary since we destroy buf */
+ if(foo > 5) /* compactify string */
+ compactify(bp);
+ *ap = '\0';
+
+ if(!foo && !allowall && !allownone) {
+ You("don't have anything %sto %s.",
+ foox ? "else " : "", word);
+ return((struct obj *)0);
+ }
+ for(;;) {
+ cnt = 0;
+ if (allowcnt == 2) allowcnt = 1; /* abort previous count */
+ prezero = FALSE;
+ if(!buf[0]) {
+ Sprintf(qbuf, "What do you want to %s? [*]", word);
+ } else {
+ Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
+ word, buf);
+ }
+ if (in_doagain)
+ ilet = readchar();
+ else
+ ilet = yn_function(qbuf, (char *)0, '\0');
+ if (digit(ilet) && !allowcnt) {
+ pline("No count allowed with this command.");
+ continue;
+ }
+ if (ilet == '0') prezero = TRUE;
+ while (digit(ilet)) {
+ if (ilet != '?' && ilet != '*') savech(ilet);
+ /* accumulate unless cnt has overflowed */
+ if (allowcnt < 3) {
+ prevcnt = cnt;
+ cnt = 10L * cnt + (long)(ilet - '0');
+ /* signal presence of cnt */
+ allowcnt = (cnt >= prevcnt) ? 2 : 3;
+ }
+ ilet = readchar();
+ }
+ if (allowcnt == 3) {
+ /* overflow detected; force cnt to be invalid */
+ cnt = -1L;
+ allowcnt = 2;
+ }
+ if(index(quitchars,ilet)) {
+ if(flags.verbose)
+ pline1(Never_mind);
+ return((struct obj *)0);
+ }
+ if(ilet == '-') {
- return(allownone ? &zeroobj : (struct obj *) 0);
+ if (!allownone) {
+ char *suf = NULL;
+ strcpy(buf, word);
+ if ((bp = strstr(buf, " on the ")) != NULL) { /* rub on the stone[s] */
+ *bp = '\0';
+ suf = (bp + 1);
+ }
+ if ((bp = strstr(buf, " or ")) != NULL) {
+ *bp = '\0';
+ bp = (rn2(2) ? buf : (bp + 4));
+ } else bp = buf;
+ You("mime %s something%s%s.", ing_suffix(bp),
+ suf ? " " : "", suf ? suf : "");
+ }
+ return(allownone ? &zeroobj : (struct obj *) 0);
- }
- if(ilet == def_oc_syms[COIN_CLASS].sym) {
- if (!usegold) {
- You("cannot %s gold.", word);
- return(struct obj *)0;
- }
- /* Historic note: early Nethack had a bug which was
- * first reported for Larn, where trying to drop 2^32-n
- * gold pieces was allowed, and did interesting things
- * to your money supply. The LRS is the tax bureau
- * from Larn.
- */
- if (allowcnt == 2 && cnt <= 0) {
- if (cnt < 0 || !prezero)
- pline_The(
- "LRS would be very interested to know you have that much.");
- return (struct obj *)0;
- }
+ }
+ if(ilet == def_oc_syms[COIN_CLASS].sym) {
+ if (!usegold) {
+ You("cannot %s gold.", word);
+ return(struct obj *)0;
+ }
+ /* Historic note: early Nethack had a bug which was
+ * first reported for Larn, where trying to drop 2^32-n
+ * gold pieces was allowed, and did interesting things
+ * to your money supply. The LRS is the tax bureau
+ * from Larn.
+ */
+ if (allowcnt == 2 && cnt <= 0) {
+ if (cnt < 0 || !prezero)
+ pline_The(
+ "LRS would be very interested to know you have that much.");
+ return (struct obj *)0;
+ }
- }
- if(ilet == '?' || ilet == '*') {
- char *allowed_choices = (ilet == '?') ? lets : (char *)0;
- long ctmp = 0;
-
- if (ilet == '?' && !*lets && *altlets)
- allowed_choices = altlets;
- ilet = display_pickinv(allowed_choices, TRUE,
- allowcnt ? &ctmp : (long *)0);
- if(!ilet) continue;
- if (allowcnt && ctmp >= 0) {
- cnt = ctmp;
- if (!cnt) prezero = TRUE;
- allowcnt = 2;
- }
- if(ilet == '\033') {
- if(flags.verbose)
- pline1(Never_mind);
- return((struct obj *)0);
- }
- /* they typed a letter (not a space) at the prompt */
- }
- if(allowcnt == 2 && !strcmp(word,"throw")) {
- /* permit counts for throwing gold, but don't accept
- * counts for other things since the throw code will
- * split off a single item anyway */
- if (ilet != def_oc_syms[COIN_CLASS].sym)
- allowcnt = 1;
- if(cnt == 0 && prezero) return((struct obj *)0);
- if(cnt > 1) {
- You("can only throw one item at a time.");
- continue;
- }
- }
- context.botl = 1; /* May have changed the amount of money */
- savech(ilet);
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp->invlet == ilet) break;
- if(!otmp) {
- You("don't have that object.");
- if (in_doagain) return((struct obj *) 0);
- continue;
- } else if (cnt < 0 || otmp->quan < cnt) {
- You("don't have that many! You have only %ld.",
- otmp->quan);
- if (in_doagain) return((struct obj *) 0);
- continue;
- }
- break;
- }
- if(!allowall && let && !index(let,otmp->oclass)
- && !(usegold && otmp->oclass == COIN_CLASS)
- ) {
- silly_thing(word, otmp);
- return((struct obj *)0);
- }
- if(allowcnt == 2) { /* cnt given */
- if(cnt == 0) return (struct obj *)0;
- if(cnt != otmp->quan) {
- /* don't split a stack of cursed loadstones */
- if (splittable(otmp))
- otmp = splitobj(otmp, cnt);
- else if (otmp->otyp == LOADSTONE && otmp->cursed)
- /* kludge for canletgo()'s can't-drop-this message */
- otmp->corpsenm = (int) cnt;
- }
- }
- return(otmp);
+ }
+ if(ilet == '?' || ilet == '*') {
+ char *allowed_choices = (ilet == '?') ? lets : (char *)0;
+ long ctmp = 0;
+
+ if (ilet == '?' && !*lets && *altlets)
+ allowed_choices = altlets;
+ ilet = display_pickinv(allowed_choices, TRUE,
+ allowcnt ? &ctmp : (long *)0);
+ if(!ilet) continue;
+ if (allowcnt && ctmp >= 0) {
+ cnt = ctmp;
+ if (!cnt) prezero = TRUE;
+ allowcnt = 2;
+ }
+ if(ilet == '\033') {
+ if(flags.verbose)
+ pline1(Never_mind);
+ return((struct obj *)0);
+ }
+ /* they typed a letter (not a space) at the prompt */
+ }
+ if(allowcnt == 2 && !strcmp(word,"throw")) {
+ /* permit counts for throwing gold, but don't accept
+ * counts for other things since the throw code will
+ * split off a single item anyway */
+ if (ilet != def_oc_syms[COIN_CLASS].sym)
+ allowcnt = 1;
+ if(cnt == 0 && prezero) return((struct obj *)0);
+ if(cnt > 1) {
+ You("can only throw one item at a time.");
+ continue;
+ }
+ }
+ context.botl = 1; /* May have changed the amount of money */
+ savech(ilet);
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (otmp->invlet == ilet) break;
+ if(!otmp) {
+ You("don't have that object.");
+ if (in_doagain) return((struct obj *) 0);
+ continue;
+ } else if (cnt < 0 || otmp->quan < cnt) {
+ You("don't have that many! You have only %ld.",
+ otmp->quan);
+ if (in_doagain) return((struct obj *) 0);
+ continue;
+ }
+ break;
+ }
+ if(!allowall && let && !index(let,otmp->oclass)
+ && !(usegold && otmp->oclass == COIN_CLASS)
+ ) {
+ silly_thing(word, otmp);
+ return((struct obj *)0);
+ }
+ if(allowcnt == 2) { /* cnt given */
+ if(cnt == 0) return (struct obj *)0;
+ if(cnt != otmp->quan) {
+ /* don't split a stack of cursed loadstones */
+ if (splittable(otmp))
+ otmp = splitobj(otmp, cnt);
+ else if (otmp->otyp == LOADSTONE && otmp->cursed)
+ /* kludge for canletgo()'s can't-drop-this message */
+ otmp->corpsenm = (int) cnt;
+ }
+ }
+ return(otmp);
}
void
boolean want_reply;
long* out_cnt;
{
- struct obj *otmp;
- char ilet, ret;
- char *invlet = flags.inv_order;
- int n, classcount;
- winid win; /* windows being used */
- static winid local_win = WIN_ERR; /* window for partial menus */
- anything any;
- menu_item *selected;
-
- /* overriden by global flag */
- if (flags.perm_invent) {
- win = (lets && *lets) ? local_win : WIN_INVEN;
- /* create the first time used */
- if (win == WIN_ERR)
- win = local_win = create_nhwindow(NHW_MENU);
- } else
- win = WIN_INVEN;
-
- /*
- Exit early if no inventory -- but keep going if we are doing
- a permanent inventory update. We need to keep going so the
- permanent inventory window updates itself to remove the last
- item(s) dropped. One down side: the addition of the exception
- for permanent inventory window updates _can_ pop the window
- up when it's not displayed -- even if it's empty -- because we
- don't know at this level if its up or not. This may not be
- an issue if empty checks are done before hand and the call
- to here is short circuited away.
- */
- if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
- pline("Not carrying anything.");
- return 0;
- }
+ struct obj *otmp;
+ char ilet, ret;
+ char *invlet = flags.inv_order;
+ int n, classcount;
+ winid win; /* windows being used */
+ static winid local_win = WIN_ERR; /* window for partial menus */
+ anything any;
+ menu_item *selected;
+
+ /* overriden by global flag */
+ if (flags.perm_invent) {
+ win = (lets && *lets) ? local_win : WIN_INVEN;
+ /* create the first time used */
+ if (win == WIN_ERR)
+ win = local_win = create_nhwindow(NHW_MENU);
+ } else
+ win = WIN_INVEN;
- /* oxymoron? temporarily assign permanent inventory letters */
- if (!flags.invlet_constant) reassign();
-
- if (lets && strlen(lets) == 1 && !iflags.override_ID) {
- /* when only one item of interest, use pline instead of menus;
- we actually use a fake message-line menu in order to allow
- the user to perform selection at the --More-- prompt for tty */
- ret = '\0';
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (otmp->invlet == lets[0]) {
- ret = message_menu(lets[0],
- want_reply ? PICK_ONE : PICK_NONE,
- xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
- if (out_cnt) *out_cnt = -1L; /* select all */
- break;
- }
- }
- return ret;
- }
+ /*
+ Exit early if no inventory -- but keep going if we are doing
+ a permanent inventory update. We need to keep going so the
+ permanent inventory window updates itself to remove the last
+ item(s) dropped. One down side: the addition of the exception
+ for permanent inventory window updates _can_ pop the window
+ up when it's not displayed -- even if it's empty -- because we
+ don't know at this level if its up or not. This may not be
+ an issue if empty checks are done before hand and the call
+ to here is short circuited away.
+ */
+ if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
+ pline("Not carrying anything.");
+ return 0;
+ }
- start_menu(win);
- if (wizard && iflags.override_ID) {
- char prompt[BUFSZ];
- any.a_char = -1;
- /* wiz_identify stuffed the wiz_identify cmd character
- into iflags.override_ID */
- Sprintf(prompt, "Debug Identify (%s to permanently identify)",
- visctrl(iflags.override_ID));
- add_menu(win, NO_GLYPH, &any,' ', iflags.override_ID, ATR_NONE,
- prompt, MENU_UNSELECTED);
- }
+ /* oxymoron? temporarily assign permanent inventory letters */
+ if (!flags.invlet_constant) reassign();
+
+ if (lets && strlen(lets) == 1 && !iflags.override_ID) {
+ /* when only one item of interest, use pline instead of menus;
+ we actually use a fake message-line menu in order to allow
+ the user to perform selection at the --More-- prompt for tty */
+ ret = '\0';
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ if (otmp->invlet == lets[0]) {
+ ret = message_menu(lets[0],
+ want_reply ? PICK_ONE : PICK_NONE,
+ xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
+ if (out_cnt) *out_cnt = -1L; /* select all */
+ break;
+ }
+ }
+ return ret;
+ }
+
+ start_menu(win);
+ if (wizard && iflags.override_ID) {
+ char prompt[BUFSZ];
+ any.a_char = -1;
+ /* wiz_identify stuffed the wiz_identify cmd character
+ into iflags.override_ID */
+ Sprintf(prompt, "Debug Identify (%s to permanently identify)",
+ visctrl(iflags.override_ID));
+ add_menu(win, NO_GLYPH, &any,' ', iflags.override_ID, ATR_NONE,
+ prompt, MENU_UNSELECTED);
+ }
nextclass:
- classcount = 0;
- any = zeroany; /* set all bits to zero */
- for(otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if(!lets || !*lets || index(lets, ilet)) {
- any = zeroany; /* zero */
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ classcount = 0;
+ any = zeroany; /* set all bits to zero */
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if(!lets || !*lets || index(lets, ilet)) {
+ any = zeroany; /* zero */
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
- let_to_name(*invlet, FALSE), MENU_UNSELECTED);
+ let_to_name(*invlet, FALSE, (want_reply && iflags.menu_head_objsym)), MENU_UNSELECTED);
- classcount++;
- }
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp),
- &any, ilet, 0, ATR_NONE, doname(otmp),
- MENU_UNSELECTED);
- }
- }
- }
- if (flags.sortpack) {
- if (*++invlet) goto nextclass;
- if (--invlet != venom_inv) {
- invlet = venom_inv;
- goto nextclass;
- }
- }
- end_menu(win, (char *) 0);
+ classcount++;
+ }
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp),
+ &any, ilet, 0, ATR_NONE, doname(otmp),
+ MENU_UNSELECTED);
+ }
+ }
+ }
+ if (flags.sortpack) {
+ if (*++invlet) goto nextclass;
+ if (--invlet != venom_inv) {
+ invlet = venom_inv;
+ goto nextclass;
+ }
+ }
+ end_menu(win, (char *) 0);
- n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
- if (n > 0) {
- ret = selected[0].item.a_char;
- if (out_cnt) *out_cnt = selected[0].count;
- free((genericptr_t)selected);
- } else
- ret = !n ? '\0' : '\033'; /* cancelled */
+ n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
+ if (n > 0) {
+ ret = selected[0].item.a_char;
+ if (out_cnt) *out_cnt = selected[0].count;
+ free((genericptr_t)selected);
+ } else
+ ret = !n ? '\0' : '\033'; /* cancelled */
- return ret;
+ return ret;
}
/*
display_used_invlets(avoidlet)
char avoidlet;
{
- struct obj *otmp;
- char ilet, ret = 0;
- char *invlet = flags.inv_order;
- int n, classcount, invdone = 0;
- winid win;
- anything any;
- menu_item *selected;
-
- if (invent) {
- win = create_nhwindow(NHW_MENU);
- start_menu(win);
- while (!invdone) {
- any = zeroany; /* set all bits to zero */
- classcount = 0;
- for(otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if (ilet == avoidlet) continue;
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- any = zeroany; /* zero */
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ struct obj *otmp;
+ char ilet, ret = 0;
+ char *invlet = flags.inv_order;
+ int n, classcount, invdone = 0;
+ winid win;
+ anything any;
+ menu_item *selected;
+
+ if (invent) {
+ win = create_nhwindow(NHW_MENU);
+ start_menu(win);
+ while (!invdone) {
+ any = zeroany; /* set all bits to zero */
+ classcount = 0;
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if (ilet == avoidlet) continue;
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ any = zeroany; /* zero */
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
- let_to_name(*invlet, FALSE), MENU_UNSELECTED);
+ let_to_name(*invlet, FALSE, FALSE), MENU_UNSELECTED);
- classcount++;
- }
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp),
- &any, ilet, 0, ATR_NONE, doname(otmp),
- MENU_UNSELECTED);
- }
- }
- if (flags.sortpack && *++invlet) continue;
- invdone = 1;
- }
- end_menu(win, "Inventory letters used:");
-
- n = select_menu(win, PICK_NONE, &selected);
- if (n > 0) {
- ret = selected[0].item.a_char;
- free((genericptr_t)selected);
- } else
- ret = !n ? '\0' : '\033'; /* cancelled */
- }
- return ret;
+ classcount++;
+ }
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp),
+ &any, ilet, 0, ATR_NONE, doname(otmp),
+ MENU_UNSELECTED);
+ }
+ }
+ if (flags.sortpack && *++invlet) continue;
+ invdone = 1;
+ }
+ end_menu(win, "Inventory letters used:");
+
+ n = select_menu(win, PICK_NONE, &selected);
+ if (n > 0) {
+ ret = selected[0].item.a_char;
+ free((genericptr_t)selected);
+ } else
+ ret = !n ? '\0' : '\033'; /* cancelled */
+ }
+ return ret;
}
/*
if (!flags.invlet_constant) reassign();
do {
- classcount = 0;
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if (otmp->unpaid) {
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
+ classcount = 0;
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if (otmp->unpaid) {
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
- putstr(win, 0, let_to_name(*invlet, TRUE));
+ putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
- classcount++;
- }
-
- totcost += cost = unpaid_cost(otmp, FALSE);
- iflags.suppress_price++; /* suppress "(unpaid)" suffix */
- putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
- ilet, TRUE, cost, 0L));
- iflags.suppress_price--;
- num_so_far++;
- }
- }
- }
+ classcount++;
+ }
+
+ totcost += cost = unpaid_cost(otmp, FALSE);
+ iflags.suppress_price++; /* suppress "(unpaid)" suffix */
+ putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
+ ilet, TRUE, cost, 0L));
+ iflags.suppress_price--;
+ num_so_far++;
+ }
+ }
+ }
} while (flags.sortpack && (*++invlet));
if (count > num_so_far) {
- /* something unpaid is contained */
- if (flags.sortpack)
+ /* something unpaid is contained */
+ if (flags.sortpack)
- putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
+ putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
- /*
- * Search through the container objects in the inventory for
- * unpaid items. The top level inventory items have already
- * been listed.
- */
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (Has_contents(otmp)) {
- long contcost = 0L;
-
- marker = (struct obj *) 0; /* haven't found any */
- while (find_unpaid(otmp->cobj, &marker)) {
- totcost += cost = unpaid_cost(marker, FALSE);
- contcost += cost;
- if (otmp->cknown) {
- iflags.suppress_price++; /* suppress "(unpaid)" sfx */
- putstr(win, 0,
- xprname(marker, distant_name(marker, doname),
- CONTAINED_SYM, TRUE, cost, 0L));
- iflags.suppress_price--;
- }
- }
- if (!otmp->cknown) {
- char contbuf[BUFSZ];
-
- /* Shopkeeper knows what to charge for contents */
- Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
- putstr(win, 0,
- xprname((struct obj *)0, contbuf,
- CONTAINED_SYM, TRUE, contcost, 0L));
- }
- }
- }
+ /*
+ * Search through the container objects in the inventory for
+ * unpaid items. The top level inventory items have already
+ * been listed.
+ */
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ if (Has_contents(otmp)) {
+ long contcost = 0L;
+
+ marker = (struct obj *) 0; /* haven't found any */
+ while (find_unpaid(otmp->cobj, &marker)) {
+ totcost += cost = unpaid_cost(marker, FALSE);
+ contcost += cost;
+ if (otmp->cknown) {
+ iflags.suppress_price++; /* suppress "(unpaid)" sfx */
+ putstr(win, 0,
+ xprname(marker, distant_name(marker, doname),
+ CONTAINED_SYM, TRUE, cost, 0L));
+ iflags.suppress_price--;
+ }
+ }
+ if (!otmp->cknown) {
+ char contbuf[BUFSZ];
+
+ /* Shopkeeper knows what to charge for contents */
+ Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
+ putstr(win, 0,
+ xprname((struct obj *)0, contbuf,
+ CONTAINED_SYM, TRUE, contcost, 0L));
+ }
+ }
+ }
}
putstr(win, 0, "");
static NEARDATA unsigned invbufsiz = 0;
char *
- let_to_name(let,unpaid)
+ let_to_name(let,unpaid,showsym)
char let;
- boolean unpaid;
+ boolean unpaid,showsym;
{
- const char *class_name;
- const char *pos;
- int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
- unsigned len;
-
- if (oclass)
- class_name = names[oclass];
- else if ((pos = index(oth_symbols, let)) != 0)
- class_name = oth_names[pos - oth_symbols];
- else
- class_name = names[0];
+ const char *ocsymfmt = " ('%c')";
+ const int invbuf_sympadding = 8; /* arbitrary */
+ const char *class_name;
+ const char *pos;
+ int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
+ unsigned len;
+
+ if (oclass)
+ class_name = names[oclass];
+ else if ((pos = index(oth_symbols, let)) != 0)
+ class_name = oth_names[pos - oth_symbols];
+ else
+ class_name = names[0];
- len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
+ len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "") +
+ (oclass ? (strlen(ocsymfmt)+invbuf_sympadding) : 0);
- if (len > invbufsiz) {
- if (invbuf) free((genericptr_t)invbuf);
- invbufsiz = len + 10; /* add slop to reduce incremental realloc */
- invbuf = (char *) alloc(invbufsiz);
- }
- if (unpaid)
- Strcat(strcpy(invbuf, "Unpaid "), class_name);
- else
- Strcpy(invbuf, class_name);
+ if (len > invbufsiz) {
+ if (invbuf) free((genericptr_t)invbuf);
+ invbufsiz = len + 10; /* add slop to reduce incremental realloc */
+ invbuf = (char *) alloc(invbufsiz);
+ }
+ if (unpaid)
+ Strcat(strcpy(invbuf, "Unpaid "), class_name);
+ else
+ Strcpy(invbuf, class_name);
+ if ((oclass != 0) && showsym) {
+ char *bp = eos(invbuf);
+ int mlen = invbuf_sympadding - strlen(class_name);
+ while (--mlen > 0) {
+ *bp = ' '; bp++;
+ }
+ *bp = '\0';
+ Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
+ }
- return invbuf;
+ return invbuf;
}
/* release the static buffer used by let_to_name() */
long age, retval = otmp->age;
if (otmp->otyp == CORPSE && otmp->on_ice) {
- /* Adjust the age; must be same as obj_timer_checks() for off ice*/
- age = monstermoves - otmp->age;
- retval += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
+ /* Adjust the age; must be same as obj_timer_checks() for off ice*/
+ age = monstermoves - otmp->age;
+ retval += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
- debugpline("The %s age has ice modifications:otmp->age = %ld, returning %ld.",
- s_suffix(doname(otmp)),otmp->age, retval);
- debugpline("Effective age of corpse: %ld.",
- monstermoves - retval);
+ debugpline3("The %s age has ice modifications: otmp->age = %ld, returning %ld.",
+ s_suffix(doname(otmp)), otmp->age, retval);
+ debugpline1("Effective age of corpse: %ld.", monstermoves - retval);
}
return retval;
}
/* Check for corpses just placed on or in ice */
if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x,y)) {
- tleft = stop_timer(action, obj_to_any(otmp));
- if (tleft == 0L) {
- action = REVIVE_MON;
- tleft = stop_timer(action, obj_to_any(otmp));
- }
- if (tleft != 0L) {
- long age;
-
- /* mark the corpse as being on ice */
- otmp->on_ice = 1;
+ tleft = stop_timer(action, obj_to_any(otmp));
+ if (tleft == 0L) {
+ action = REVIVE_MON;
+ tleft = stop_timer(action, obj_to_any(otmp));
+ }
+ if (tleft != 0L) {
+ long age;
+
+ /* mark the corpse as being on ice */
+ otmp->on_ice = 1;
- debugpline("%s is now on ice at %d,%d.", The(xname(otmp)),x,y);
+ debugpline3("%s is now on ice at <%d,%d>.",
+ The(xname(otmp)), x, y);
- /* Adjust the time remaining */
- tleft *= ROT_ICE_ADJUSTMENT;
- restart_timer = TRUE;
- /* Adjust the age; time spent off ice needs to be multiplied
- by the ice adjustment and subtracted from the age so that
- later calculations behave as if it had been on ice during
- that time (longwinded way of saying this is the inverse
- of removing it from the ice and of peeking at its age). */
- age = monstermoves - otmp->age;
- otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
- }
+ /* Adjust the time remaining */
+ tleft *= ROT_ICE_ADJUSTMENT;
+ restart_timer = TRUE;
+ /* Adjust the age; time spent off ice needs to be multiplied
+ by the ice adjustment and subtracted from the age so that
+ later calculations behave as if it had been on ice during
+ that time (longwinded way of saying this is the inverse
+ of removing it from the ice and of peeking at its age). */
+ age = monstermoves - otmp->age;
+ otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
+ }
}
/* Check for corpses coming off ice */
else if ((force < 0) ||
- (otmp->otyp == CORPSE && otmp->on_ice &&
- !((on_floor || buried) && is_ice(x,y)))) {
- tleft = stop_timer(action, obj_to_any(otmp));
- if (tleft == 0L) {
- action = REVIVE_MON;
- tleft = stop_timer(action, obj_to_any(otmp));
- }
- if (tleft != 0L) {
- long age;
-
- otmp->on_ice = 0;
+ (otmp->otyp == CORPSE && otmp->on_ice &&
+ !((on_floor || buried) && is_ice(x,y)))) {
+ tleft = stop_timer(action, obj_to_any(otmp));
+ if (tleft == 0L) {
+ action = REVIVE_MON;
+ tleft = stop_timer(action, obj_to_any(otmp));
+ }
+ if (tleft != 0L) {
+ long age;
+
+ otmp->on_ice = 0;
- debugpline("%s is no longer on ice at %d,%d.", The(xname(otmp)),x,y);
+ debugpline3("%s is no longer on ice at <%d,%d>.",
+ The(xname(otmp)), x, y);
- /* Adjust the remaining time */
- tleft /= ROT_ICE_ADJUSTMENT;
- restart_timer = TRUE;
- /* Adjust the age */
- age = monstermoves - otmp->age;
- otmp->age += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
- }
+ /* Adjust the remaining time */
+ tleft /= ROT_ICE_ADJUSTMENT;
+ restart_timer = TRUE;
+ /* Adjust the age */
+ age = monstermoves - otmp->age;
+ otmp->age += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
+ }
}
/* now re-start the timer with the appropriate modifications */
if (restart_timer)
/* transfer the monster's inventory */
for (otmp = mtmp2->minvent; otmp; otmp = otmp->nobj) {
- if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
+ if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
- debugpline("replmon: minvent inconsistency");
+ debugpline0("replmon: minvent inconsistency");
- otmp->ocarry = mtmp2;
+ otmp->ocarry = mtmp2;
}
mtmp->minvent = 0;
mondead(mtmp)
register struct monst *mtmp;
{
- struct permonst *mptr;
- int tmp;
-
- lifesaved_monster(mtmp);
- if (mtmp->mhp > 0) return;
-
- if (is_vampshifter(mtmp)) {
- int mndx = mtmp->cham;
- int x = mtmp->mx, y = mtmp->my;
- /* this only happens if shapeshifted */
- if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
- char buf[BUFSZ];
- boolean in_door = amorphous(mtmp->data) &&
- closed_door(mtmp->mx,mtmp->my);
- Sprintf(buf,
- "The %s%s suddenly %s and rises as %%s!",
- (nonliving(mtmp->data) ||
- noncorporeal(mtmp->data) ||
- amorphous(mtmp->data)) ? "" : "seemingly dead ",
- x_monnam(mtmp, ARTICLE_NONE, (char *)0,
- SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION |
- SUPPRESS_INVISIBLE | SUPPRESS_IT, FALSE),
- (nonliving(mtmp->data) ||
- noncorporeal(mtmp->data) ||
- amorphous(mtmp->data)) ?
- "reconstitutes" : "transforms");
- mtmp->mcanmove = 1;
- mtmp->mfrozen = 0;
- if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
- mtmp->mhp = mtmp->mhpmax;
- /* this can happen if previously a fog cloud */
- if (u.uswallow && (mtmp == u.ustuck))
- expels(mtmp, mtmp->data, FALSE);
- if (in_door) {
- coord new_xy;
- if (enexto(&new_xy,
- mtmp->mx, mtmp->my, &mons[mndx])) {
- rloc_to(mtmp, new_xy.x, new_xy.y);
- }
- }
- newcham(mtmp, &mons[mndx], FALSE, FALSE);
- if (mtmp->data == &mons[mndx])
- mtmp->cham = NON_PM;
- else
- mtmp->cham = mndx;
- if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
- pline(buf, a_monnam(mtmp));
- newsym(x,y);
- return;
- }
- }
-
- /* dead vault guard is actually kept at coordinate <0,0> until
- his temporary corridor to/from the vault has been removed;
- need to do this after life-saving and before m_detach() */
- if (mtmp->isgd && !grddead(mtmp)) return;
-
- /* Player is thrown from his steed when it dies */
- if (mtmp == u.usteed)
- dismount_steed(DISMOUNT_GENERIC);
-
- mptr = mtmp->data; /* save this for m_detach() */
- /* restore chameleon, lycanthropes to true form at death */
- if (mtmp->cham >= LOW_PM) {
- set_mon_data(mtmp, &mons[mtmp->cham], -1);
- mtmp->cham = NON_PM;
- }
- else if (mtmp->data == &mons[PM_WEREJACKAL])
- set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
- else if (mtmp->data == &mons[PM_WEREWOLF])
- set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
- else if (mtmp->data == &mons[PM_WERERAT])
- set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
-
- /* if MAXMONNO monsters of a given type have died, and it
- * can be done, extinguish that monster.
- *
- * mvitals[].died does double duty as total number of dead monsters
- * and as experience factor for the player killing more monsters.
- * this means that a dragon dying by other means reduces the
- * experience the player gets for killing a dragon directly; this
- * is probably not too bad, since the player likely finagled the
- * first dead dragon via ring of conflict or pets, and extinguishing
- * based on only player kills probably opens more avenues of abuse
- * for rings of conflict and such.
- */
- tmp = monsndx(mtmp->data);
- if (mvitals[tmp].died < 255) mvitals[tmp].died++;
-
- /* if it's a (possibly polymorphed) quest leader, mark him as dead */
- if (mtmp->m_id == quest_status.leader_m_id)
- quest_status.leader_is_dead = TRUE;
+ struct permonst *mptr;
+ int tmp;
+
+ lifesaved_monster(mtmp);
+ if (mtmp->mhp > 0) return;
+
+ if (is_vampshifter(mtmp)) {
+ int mndx = mtmp->cham;
+ int x = mtmp->mx, y = mtmp->my;
+ /* this only happens if shapeshifted */
+ if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
+ char buf[BUFSZ];
+ boolean in_door = amorphous(mtmp->data) &&
+ closed_door(mtmp->mx,mtmp->my);
+ Sprintf(buf,
+ "The %s%s suddenly %s and rises as %%s!",
+ (nonliving(mtmp->data) ||
+ noncorporeal(mtmp->data) ||
+ amorphous(mtmp->data)) ? "" : "seemingly dead ",
+ x_monnam(mtmp, ARTICLE_NONE, (char *)0,
+ SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION |
+ SUPPRESS_INVISIBLE | SUPPRESS_IT, FALSE),
+ (nonliving(mtmp->data) ||
+ noncorporeal(mtmp->data) ||
+ amorphous(mtmp->data)) ?
+ "reconstitutes" : "transforms");
+ mtmp->mcanmove = 1;
+ mtmp->mfrozen = 0;
+ if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
+ mtmp->mhp = mtmp->mhpmax;
+ /* this can happen if previously a fog cloud */
+ if (u.uswallow && (mtmp == u.ustuck))
+ expels(mtmp, mtmp->data, FALSE);
+ if (in_door) {
+ coord new_xy;
+ if (enexto(&new_xy,
+ mtmp->mx, mtmp->my, &mons[mndx])) {
+ rloc_to(mtmp, new_xy.x, new_xy.y);
+ }
+ }
+ newcham(mtmp, &mons[mndx], FALSE, FALSE);
+ if (mtmp->data == &mons[mndx])
+ mtmp->cham = NON_PM;
+ else
+ mtmp->cham = mndx;
+ if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
+ pline(buf, a_monnam(mtmp));
+ newsym(x,y);
+ return;
+ }
+ }
+
+ /* dead vault guard is actually kept at coordinate <0,0> until
+ his temporary corridor to/from the vault has been removed;
+ need to do this after life-saving and before m_detach() */
+ if (mtmp->isgd && !grddead(mtmp)) return;
+
+ /* Player is thrown from his steed when it dies */
+ if (mtmp == u.usteed)
+ dismount_steed(DISMOUNT_GENERIC);
+
+ mptr = mtmp->data; /* save this for m_detach() */
+ /* restore chameleon, lycanthropes to true form at death */
+ if (mtmp->cham >= LOW_PM) {
+ set_mon_data(mtmp, &mons[mtmp->cham], -1);
+ mtmp->cham = NON_PM;
+ }
+ else if (mtmp->data == &mons[PM_WEREJACKAL])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
+ else if (mtmp->data == &mons[PM_WEREWOLF])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
+ else if (mtmp->data == &mons[PM_WERERAT])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
+
+ /* if MAXMONNO monsters of a given type have died, and it
+ * can be done, extinguish that monster.
+ *
+ * mvitals[].died does double duty as total number of dead monsters
+ * and as experience factor for the player killing more monsters.
+ * this means that a dragon dying by other means reduces the
+ * experience the player gets for killing a dragon directly; this
+ * is probably not too bad, since the player likely finagled the
+ * first dead dragon via ring of conflict or pets, and extinguishing
+ * based on only player kills probably opens more avenues of abuse
+ * for rings of conflict and such.
+ */
+ tmp = monsndx(mtmp->data);
+ if (mvitals[tmp].died < 255) mvitals[tmp].died++;
+
+ /* if it's a (possibly polymorphed) quest leader, mark him as dead */
+ if (mtmp->m_id == quest_status.leader_m_id)
+ quest_status.leader_is_dead = TRUE;
#ifdef MAIL
- /* if the mail daemon dies, no more mail delivery. -3. */
- if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
+ /* if the mail daemon dies, no more mail delivery. -3. */
+ if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
#endif
- if (mtmp->data->mlet == S_KOP) {
- /* Dead Kops may come back. */
- switch(rnd(5)) {
- case 1: /* returns near the stairs */
- (void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
- break;
- case 2: /* randomly */
- (void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
- break;
- default:
- break;
- }
- }
- if(mtmp->iswiz) wizdead();
- if(mtmp->data->msound == MS_NEMESIS) nemdead();
+ if (mtmp->data->mlet == S_KOP) {
+ /* Dead Kops may come back. */
+ switch(rnd(5)) {
+ case 1: /* returns near the stairs */
+ (void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
+ break;
+ case 2: /* randomly */
+ (void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
+ break;
+ default:
+ break;
+ }
+ }
+ if(mtmp->iswiz) wizdead();
+ if(mtmp->data->msound == MS_NEMESIS) nemdead();
+ if(mtmp->data == &mons[PM_MEDUSA])
+ u.uachieve.killed_medusa = 1;
- if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
- unmap_object(mtmp->mx, mtmp->my);
- m_detach(mtmp, mptr);
+ if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
+ unmap_object(mtmp->mx, mtmp->my);
+ m_detach(mtmp, mptr);
}
/* TRUE if corpse might be dropped, magr may die if mon was swallowed */
};
static const char *const as_is[] = {
- /* makesingular() leaves these plural due to how they're used */
- "boots", "shoes",
+ /* makesingular() leaves these plural due to how they're used */
+ "boots", "shoes",
- "gloves", "lenses", "scales",
+ "gloves", "lenses", "scales", "eyes",
- "gauntlets",
- "iron bars",
- /* both singular and plural are spelled the same */
- "deer", "fish", "tuna", "yaki", "-hai",
- "krill", "manes", "ninja", "sheep", "ronin", "roshi", "shito", "tengu",
- "ki-rin", "Nazgul",
- "gunyoki", "piranha", "samurai",
- "shuriken",
- 0,
- /* Note: "fish" and "piranha" are collective plurals, suitable
- for "wiped out all <foo>". For "3 <foo>", they should be
- "fishes" and "piranhas" instead. We settle for collective
- variant instead of attempting to support both. */
+ "gauntlets",
+ "iron bars",
+ /* both singular and plural are spelled the same */
+ "deer", "fish", "tuna", "yaki", "-hai",
+ "krill", "manes", "ninja", "sheep", "ronin", "roshi", "shito", "tengu",
+ "ki-rin", "Nazgul",
+ "gunyoki", "piranha", "samurai",
+ "shuriken",
+ 0,
+ /* Note: "fish" and "piranha" are collective plurals, suitable
+ for "wiped out all <foo>". For "3 <foo>", they should be
+ "fishes" and "piranhas" instead. We settle for collective
+ variant instead of attempting to support both. */
};
/* singularize/pluralize decisiions common to both makesingular & makeplural */