From: Derek S. Ray Date: Wed, 25 Mar 2015 21:23:59 +0000 (-0400) Subject: Merge branch 'master' into derek-farming X-Git-Tag: NetHack-3.6.0_RC01~414^2~41^2~16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=335c7fc003be2d5f0963e8d0e46d6bd7a1969760;p=nethack Merge branch 'master' into derek-farming * master: (49 commits) Fix 'fetch' syntax, include sparkly 'git log' trick Show object symbols in menu headings Fix a memory leak on termination. ... Conflicts: include/obj.h src/do.c src/files.c src/hack.c src/invent.c src/mkobj.c src/mon.c src/objnam.c --- 335c7fc003be2d5f0963e8d0e46d6bd7a1969760 diff --cc src/do.c index 620afe862,b387752d6..1fe18d7c5 --- a/src/do.c +++ b/src/do.c @@@ -225,24 -217,29 +225,29 @@@ const char *verb 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 @@@ -993,414 -990,418 +998,418 @@@ goto_level(newlevel, at_stairs, falling 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 diff --cc src/files.c index 4ddeda27d,ace417e7d..86688beb2 --- a/src/files.c +++ b/src/files.c @@@ -1872,38 -1883,19 +1883,45 @@@ int src } #if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32) +# 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'; ++ 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() */ diff --cc src/hack.c index 12e7c4e2d,7f15af6ee..1eb9eac97 --- a/src/hack.c +++ b/src/hack.c @@@ -626,90 -626,95 +626,95 @@@ int mode * 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 and */ - if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y))); - return FALSE; + /* consecutive long worm segments are at and */ + 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. diff --cc src/invent.c index 37b1a1549,e5100ee5e..1a6e7673e --- a/src/invent.c +++ b/src/invent.c @@@ -235,29 -235,42 +235,42 @@@ voi 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; + } } /* @@@ -752,313 -753,327 +765,327 @@@ struct obj 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 @@@ -1699,109 -1714,109 +1726,109 @@@ register const char *lets 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; } /* @@@ -1827,49 -1842,49 +1854,49 @@@ STATIC_OVL cha 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; } /* @@@ -1970,63 -1985,63 +1997,63 @@@ dounpaid( 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, ""); @@@ -2686,33 -2701,45 +2713,45 @@@ static NEARDATA char *invbuf = (char *) 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 *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]; + 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() */ diff --cc src/mkobj.c index d9312a0f3,4092401cd..25e598746 --- a/src/mkobj.c +++ b/src/mkobj.c @@@ -1526,13 -1518,12 +1526,12 @@@ struct obj *otmp 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; } @@@ -1551,50 -1542,52 +1550,52 @@@ int force; /* 0 = no force so do checks /* 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) diff --cc src/mon.c index ce04cc382,d9bc63d6d..2da55e37f --- a/src/mon.c +++ b/src/mon.c @@@ -1278,9 -1259,9 +1278,9 @@@ register struct monst *mtmp, *mtmp2 /* 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; @@@ -1511,121 -1492,123 +1511,123 @@@ voi 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 */ diff --cc src/objnam.c index 8b418d769,898dfb60a..13a145043 --- a/src/objnam.c +++ b/src/objnam.c @@@ -1691,22 -1680,22 +1691,22 @@@ static struct sing_plur one_off[] = }; 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 ". For "3 ", 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 ". For "3 ", 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 */