From: nhmall Date: Sun, 12 Apr 2015 14:02:17 +0000 (-0400) Subject: Merge branch 'master' into nhmall-booktribute X-Git-Tag: NetHack-3.6.0_RC01~480^2~17 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11560933ccffced9a1de3d06d989de8a7da39dd2;p=nethack Merge branch 'master' into nhmall-booktribute Conflicts: doc/fixes35.0 include/extern.h src/mkobj.c src/mon.c src/objnam.c win/share/objects.txt --- 11560933ccffced9a1de3d06d989de8a7da39dd2 diff --cc doc/fixes35.0 index 0993ac707,4c4754c6b..5f5abf250 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@@ -1112,7 -1115,7 +1115,8 @@@ show more explicit reason why player wa added new hallucinatory-only gods options to create the character blind or nudist moving clouds on the plane of air + disclose extinct species alongside genocided ones +tribute to Terry Pratchett Platform- and/or Interface-Specific New Features diff --cc src/mkobj.c index 0f67aed13,0fd6ab589..a9d0ebfe8 --- a/src/mkobj.c +++ b/src/mkobj.c @@@ -585,296 -585,298 +585,305 @@@ int otyp boolean init; boolean artif; { - int mndx, tryct; - struct obj *otmp; - char let = objects[otyp].oc_class; - - otmp = newobj(); - *otmp = zeroobj; - otmp->age = monstermoves; - otmp->o_id = context.ident++; - if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */ - otmp->quan = 1L; - otmp->oclass = let; - otmp->otyp = otyp; - otmp->where = OBJ_FREE; - otmp->dknown = index(dknowns, let) ? 0 : 1; - if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) || - otmp->otyp == SHIELD_OF_REFLECTION) - otmp->dknown = 0; - if (!objects[otmp->otyp].oc_uses_known) - otmp->known = 1; - otmp->lknown = 0; - otmp->cknown = 0; - otmp->corpsenm = NON_PM; - - if (init) switch (let) { - case WEAPON_CLASS: - otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L; - if(!rn2(11)) { - otmp->spe = rne(3); - otmp->blessed = rn2(2); - } else if(!rn2(10)) { - curse(otmp); - otmp->spe = -rne(3); - } else blessorcurse(otmp, 10); - if (is_poisonable(otmp) && !rn2(100)) - otmp->opoisoned = 1; - - if (artif && !rn2(20)) - otmp = mk_artifact(otmp, (aligntyp)A_NONE); - break; - case FOOD_CLASS: - otmp->oeaten = 0; - switch(otmp->otyp) { - case CORPSE: - /* possibly overridden by mkcorpstat() */ - tryct = 50; - do otmp->corpsenm = undead_to_corpse(rndmonnum()); - while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0)); - if (tryct == 0) { - /* perhaps rndmonnum() only wants to make G_NOCORPSE monsters on - this level; let's create an adventurer's corpse instead, then */ - otmp->corpsenm = PM_HUMAN; - } - /* timer set below */ - break; - case EGG: - otmp->corpsenm = NON_PM; /* generic egg */ - if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) { - mndx = can_be_hatched(rndmonnum()); - if (mndx != NON_PM && !dead_species(mndx, TRUE)) { - otmp->corpsenm = mndx; /* typed egg */ - break; - } - } - /* timer set below */ - break; - case TIN: - otmp->corpsenm = NON_PM; /* empty (so far) */ - if (!rn2(6)) - set_tin_variety(otmp, SPINACH_TIN); - else for (tryct = 200; tryct > 0; --tryct) { - mndx = undead_to_corpse(rndmonnum()); - if (mons[mndx].cnutrit && - !(mvitals[mndx].mvflags & G_NOCORPSE)) { - otmp->corpsenm = mndx; - set_tin_variety(otmp, RANDOM_TIN); - break; - } - } - blessorcurse(otmp, 10); - break; - case SLIME_MOLD: - otmp->spe = context.current_fruit; - flags.made_fruit = TRUE; - break; - case KELP_FROND: - otmp->quan = (long) rnd(2); - break; - } - if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING && - otmp->otyp != KELP_FROND && !rn2(6)) - otmp->quan = 2L; - break; - case GEM_CLASS: - otmp->corpsenm = 0; /* LOADSTONE hack */ - if (otmp->otyp == LOADSTONE) curse(otmp); - else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6); - else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L; - else otmp->quan = 1L; - break; - case TOOL_CLASS: - switch(otmp->otyp) { - case TALLOW_CANDLE: - case WAX_CANDLE: otmp->spe = 1; - otmp->age = 20L * /* 400 or 200 */ - (long)objects[otmp->otyp].oc_cost; - otmp->lamplit = 0; - otmp->quan = 1L + - (long)(rn2(2) ? rn2(7) : 0); - blessorcurse(otmp, 5); - break; - case BRASS_LANTERN: - case OIL_LAMP: otmp->spe = 1; - otmp->age = (long) rn1(500,1000); - otmp->lamplit = 0; - blessorcurse(otmp, 5); - break; - case MAGIC_LAMP: otmp->spe = 1; - otmp->lamplit = 0; - blessorcurse(otmp, 2); - break; - case CHEST: - case LARGE_BOX: otmp->olocked = !!(rn2(5)); - otmp->otrapped = !(rn2(10)); - case ICE_BOX: - case SACK: - case OILSKIN_SACK: - case BAG_OF_HOLDING: mkbox_cnts(otmp); - break; - case LEASH: otmp->leashmon = 0; - break; - case EXPENSIVE_CAMERA: - case TINNING_KIT: - case MAGIC_MARKER: otmp->spe = rn1(70,30); - break; - case CAN_OF_GREASE: otmp->spe = rnd(25); - blessorcurse(otmp, 10); - break; - case CRYSTAL_BALL: otmp->spe = rnd(5); - blessorcurse(otmp, 2); - break; - case HORN_OF_PLENTY: - case BAG_OF_TRICKS: otmp->spe = rnd(20); - break; - case FIGURINE: { int tryct2 = 0; - do - otmp->corpsenm = rndmonnum(); - while(is_human(&mons[otmp->corpsenm]) - && tryct2++ < 30); - blessorcurse(otmp, 4); - break; - } - case BELL_OF_OPENING: otmp->spe = 3; - break; - case MAGIC_FLUTE: - case MAGIC_HARP: - case FROST_HORN: - case FIRE_HORN: - case DRUM_OF_EARTHQUAKE: - otmp->spe = rn1(5,4); - break; - } - break; - case AMULET_CLASS: - if (otmp->otyp == AMULET_OF_YENDOR) context.made_amulet = TRUE; - if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION || - otmp->otyp == AMULET_OF_CHANGE || - otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) { - curse(otmp); - } else blessorcurse(otmp, 10); - case VENOM_CLASS: - case CHAIN_CLASS: - case BALL_CLASS: - break; - case POTION_CLASS: - otmp->fromsink = 0; - if (otmp->otyp == POT_OIL) - otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */ - /* fall through */ - case SCROLL_CLASS: + int mndx, tryct; + struct obj *otmp; + char let = objects[otyp].oc_class; + + otmp = newobj(); + *otmp = zeroobj; + otmp->age = monstermoves; + otmp->o_id = context.ident++; + if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */ + otmp->quan = 1L; + otmp->oclass = let; + otmp->otyp = otyp; + otmp->where = OBJ_FREE; + otmp->dknown = index(dknowns, let) ? 0 : 1; + if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) || + otmp->otyp == SHIELD_OF_REFLECTION) + otmp->dknown = 0; + if (!objects[otmp->otyp].oc_uses_known) + otmp->known = 1; + otmp->lknown = 0; + otmp->cknown = 0; + otmp->corpsenm = NON_PM; + + if (init) switch (let) { + case WEAPON_CLASS: + otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L; + if(!rn2(11)) { + otmp->spe = rne(3); + otmp->blessed = rn2(2); + } else if(!rn2(10)) { + curse(otmp); + otmp->spe = -rne(3); + } else blessorcurse(otmp, 10); + if (is_poisonable(otmp) && !rn2(100)) + otmp->opoisoned = 1; + + if (artif && !rn2(20)) + otmp = mk_artifact(otmp, (aligntyp)A_NONE); + break; + case FOOD_CLASS: + otmp->oeaten = 0; + switch(otmp->otyp) { + case CORPSE: + /* possibly overridden by mkcorpstat() */ + tryct = 50; + do otmp->corpsenm = undead_to_corpse(rndmonnum()); + while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0)); + if (tryct == 0) { + /* perhaps rndmonnum() only wants to make G_NOCORPSE monsters on + this level; let's create an adventurer's corpse instead, then */ + otmp->corpsenm = PM_HUMAN; + } + /* timer set below */ + break; + case EGG: + otmp->corpsenm = NON_PM; /* generic egg */ + if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) { + mndx = can_be_hatched(rndmonnum()); + if (mndx != NON_PM && !dead_species(mndx, TRUE)) { + otmp->corpsenm = mndx; /* typed egg */ + break; + } + } + /* timer set below */ + break; + case TIN: + otmp->corpsenm = NON_PM; /* empty (so far) */ + if (!rn2(6)) + set_tin_variety(otmp, SPINACH_TIN); + else for (tryct = 200; tryct > 0; --tryct) { + mndx = undead_to_corpse(rndmonnum()); + if (mons[mndx].cnutrit && + !(mvitals[mndx].mvflags & G_NOCORPSE)) { + otmp->corpsenm = mndx; + set_tin_variety(otmp, RANDOM_TIN); + break; + } + } + blessorcurse(otmp, 10); + break; + case SLIME_MOLD: + otmp->spe = context.current_fruit; + flags.made_fruit = TRUE; + break; + case KELP_FROND: + otmp->quan = (long) rnd(2); + break; + } + if (Is_pudding(otmp)) { + otmp->globby = 1; + otmp->known = otmp->bknown = otmp->rknown = otmp->dknown = 1; + otmp->corpsenm = PM_GRAY_OOZE + (otmp->otyp - GLOB_OF_GRAY_OOZE); + /* this ensures that they don't fail merging because of + * BUC status or other irrelevancies */ + } else { + if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING + && otmp->otyp != KELP_FROND && !rn2(6)) { + otmp->quan = 2L; + } + } + break; + case GEM_CLASS: + otmp->corpsenm = 0; /* LOADSTONE hack */ + if (otmp->otyp == LOADSTONE) curse(otmp); + else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6); + else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L; + else otmp->quan = 1L; + break; + case TOOL_CLASS: + switch(otmp->otyp) { + case TALLOW_CANDLE: + case WAX_CANDLE: otmp->spe = 1; + otmp->age = 20L * /* 400 or 200 */ + (long)objects[otmp->otyp].oc_cost; + otmp->lamplit = 0; + otmp->quan = 1L + + (long)(rn2(2) ? rn2(7) : 0); + blessorcurse(otmp, 5); + break; + case BRASS_LANTERN: + case OIL_LAMP: otmp->spe = 1; + otmp->age = (long) rn1(500,1000); + otmp->lamplit = 0; + blessorcurse(otmp, 5); + break; + case MAGIC_LAMP: otmp->spe = 1; + otmp->lamplit = 0; + blessorcurse(otmp, 2); + break; + case CHEST: + case LARGE_BOX: otmp->olocked = !!(rn2(5)); + otmp->otrapped = !(rn2(10)); + case ICE_BOX: + case SACK: + case OILSKIN_SACK: + case BAG_OF_HOLDING: mkbox_cnts(otmp); + break; + case LEASH: otmp->leashmon = 0; + break; + case EXPENSIVE_CAMERA: + case TINNING_KIT: + case MAGIC_MARKER: otmp->spe = rn1(70,30); + break; + case CAN_OF_GREASE: otmp->spe = rnd(25); + blessorcurse(otmp, 10); + break; + case CRYSTAL_BALL: otmp->spe = rnd(5); + blessorcurse(otmp, 2); + break; + case HORN_OF_PLENTY: + case BAG_OF_TRICKS: otmp->spe = rnd(20); + break; + case FIGURINE: { int tryct2 = 0; + do + otmp->corpsenm = rndmonnum(); + while(is_human(&mons[otmp->corpsenm]) + && tryct2++ < 30); + blessorcurse(otmp, 4); + break; + } + case BELL_OF_OPENING: otmp->spe = 3; + break; + case MAGIC_FLUTE: + case MAGIC_HARP: + case FROST_HORN: + case FIRE_HORN: + case DRUM_OF_EARTHQUAKE: + otmp->spe = rn1(5,4); + break; + } + break; + case AMULET_CLASS: + if (otmp->otyp == AMULET_OF_YENDOR) context.made_amulet = TRUE; + if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION || + otmp->otyp == AMULET_OF_CHANGE || + otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) { + curse(otmp); + } else blessorcurse(otmp, 10); + case VENOM_CLASS: + case CHAIN_CLASS: + case BALL_CLASS: + break; + case POTION_CLASS: + otmp->fromsink = 0; + if (otmp->otyp == POT_OIL) + otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */ + /* fall through */ + case SCROLL_CLASS: #ifdef MAIL - if (otmp->otyp != SCR_MAIL) + if (otmp->otyp != SCR_MAIL) #endif - blessorcurse(otmp, 4); - break; - case SPBOOK_CLASS: - otmp->spestudied = 0; - blessorcurse(otmp, 17); - break; - case ARMOR_CLASS: - if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS || - otmp->otyp == LEVITATION_BOOTS || - otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT || - otmp->otyp == GAUNTLETS_OF_FUMBLING || - !rn2(11))) { - curse(otmp); - otmp->spe = -rne(3); - } else if(!rn2(10)) { - otmp->blessed = rn2(2); - otmp->spe = rne(3); - } else blessorcurse(otmp, 10); - if (artif && !rn2(40)) - otmp = mk_artifact(otmp, (aligntyp)A_NONE); - /* simulate lacquered armor for samurai */ - if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL && - (moves <= 1 || In_quest(&u.uz))) { + blessorcurse(otmp, 4); + break; + case SPBOOK_CLASS: + otmp->spestudied = 0; + blessorcurse(otmp, 17); + break; + case ARMOR_CLASS: + if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS || + otmp->otyp == LEVITATION_BOOTS || + otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT || + otmp->otyp == GAUNTLETS_OF_FUMBLING || + !rn2(11))) { + curse(otmp); + otmp->spe = -rne(3); + } else if(!rn2(10)) { + otmp->blessed = rn2(2); + otmp->spe = rne(3); + } else blessorcurse(otmp, 10); + if (artif && !rn2(40)) + otmp = mk_artifact(otmp, (aligntyp)A_NONE); + /* simulate lacquered armor for samurai */ + if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL && + (moves <= 1 || In_quest(&u.uz))) { #ifdef UNIXPC - /* optimizer bitfield bug */ - otmp->oerodeproof = 1; - otmp->rknown = 1; + /* optimizer bitfield bug */ + otmp->oerodeproof = 1; + otmp->rknown = 1; #else - otmp->oerodeproof = otmp->rknown = 1; + otmp->oerodeproof = otmp->rknown = 1; #endif - } - break; - case WAND_CLASS: - if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else - otmp->spe = rn1(5, - (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4); - blessorcurse(otmp, 17); - otmp->recharged = 0; /* used to control recharging */ - break; - case RING_CLASS: - if(objects[otmp->otyp].oc_charged) { - blessorcurse(otmp, 3); - if(rn2(10)) { - if(rn2(10) && bcsign(otmp)) - otmp->spe = bcsign(otmp) * rne(3); - else otmp->spe = rn2(2) ? rne(3) : -rne(3); - } - /* make useless +0 rings much less common */ - if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3); - /* negative rings are usually cursed */ - if (otmp->spe < 0 && rn2(5)) curse(otmp); - } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION || - otmp->otyp == RIN_POLYMORPH || - otmp->otyp == RIN_AGGRAVATE_MONSTER || - otmp->otyp == RIN_HUNGER || !rn2(9))) { - curse(otmp); - } - break; - case ROCK_CLASS: - switch (otmp->otyp) { - case STATUE: - /* possibly overridden by mkcorpstat() */ - otmp->corpsenm = rndmonnum(); - if (!verysmall(&mons[otmp->corpsenm]) && - rn2(level_difficulty()/2 + 10) > 10) - (void) add_to_container(otmp, - mkobj(SPBOOK_CLASS,FALSE)); - } - break; - case COIN_CLASS: - break; /* do nothing */ - default: - impossible("impossible mkobj %d, sym '%c'.", otmp->otyp, - objects[otmp->otyp].oc_class); - return (struct obj *)0; - } - - /* some things must get done (corpsenm, timers) even if init = 0 */ - switch (otmp->otyp) { - case CORPSE: - if (otmp->corpsenm == NON_PM) { - otmp->corpsenm = undead_to_corpse(rndmonnum()); - if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE|G_GONE)) - otmp->corpsenm = urole.malenum; - } - /*FALLTHRU*/ - case STATUE: - case FIGURINE: - if (otmp->corpsenm == NON_PM) otmp->corpsenm = rndmonnum(); - /*FALLTHRU*/ - case EGG: - /* case TIN: */ - set_corpsenm(otmp, otmp->corpsenm); - break; + } + break; + case WAND_CLASS: + if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else + otmp->spe = rn1(5, + (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4); + blessorcurse(otmp, 17); + otmp->recharged = 0; /* used to control recharging */ + break; + case RING_CLASS: + if(objects[otmp->otyp].oc_charged) { + blessorcurse(otmp, 3); + if(rn2(10)) { + if(rn2(10) && bcsign(otmp)) + otmp->spe = bcsign(otmp) * rne(3); + else otmp->spe = rn2(2) ? rne(3) : -rne(3); + } + /* make useless +0 rings much less common */ + if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3); + /* negative rings are usually cursed */ + if (otmp->spe < 0 && rn2(5)) curse(otmp); + } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION || + otmp->otyp == RIN_POLYMORPH || + otmp->otyp == RIN_AGGRAVATE_MONSTER || + otmp->otyp == RIN_HUNGER || !rn2(9))) { + curse(otmp); + } + break; + case ROCK_CLASS: + switch (otmp->otyp) { + case STATUE: + /* possibly overridden by mkcorpstat() */ + otmp->corpsenm = rndmonnum(); + if (!verysmall(&mons[otmp->corpsenm]) && + rn2(level_difficulty()/2 + 10) > 10) + (void) add_to_container(otmp, + mkobj(SPBOOK_CLASS,FALSE)); + } + break; + case COIN_CLASS: + break; /* do nothing */ + default: + impossible("impossible mkobj %d, sym '%c'.", otmp->otyp, + objects[otmp->otyp].oc_class); + return (struct obj *)0; + } + + /* some things must get done (corpsenm, timers) even if init = 0 */ + switch (otmp->otyp) { + case CORPSE: + if (otmp->corpsenm == NON_PM) { + otmp->corpsenm = undead_to_corpse(rndmonnum()); + if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE|G_GONE)) + otmp->corpsenm = urole.malenum; + } + /*FALLTHRU*/ + case STATUE: + case FIGURINE: + if (otmp->corpsenm == NON_PM) otmp->corpsenm = rndmonnum(); + /*FALLTHRU*/ + case EGG: + /* case TIN: */ + set_corpsenm(otmp, otmp->corpsenm); + break; + case SPE_NOVEL: + { + int novidx = -1; + otmp = oname(otmp, noveltitle(&novidx)); + otmp->novelidx = novidx; + } + break; - } + } - /* unique objects may have an associated artifact entry */ - if (objects[otyp].oc_unique && !otmp->oartifact) - otmp = mk_artifact(otmp, (aligntyp)A_NONE); - otmp->owt = weight(otmp); - return(otmp); + /* unique objects may have an associated artifact entry */ + if (objects[otyp].oc_unique && !otmp->oartifact) + otmp = mk_artifact(otmp, (aligntyp)A_NONE); + otmp->owt = weight(otmp); + return(otmp); } /* diff --cc src/mon.c index 5427f8da4,93fef1b0c..856b97b99 --- a/src/mon.c +++ b/src/mon.c @@@ -1496,121 -1515,123 +1515,121 @@@ 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(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) - unmap_object(mtmp->mx, mtmp->my); - m_detach(mtmp, mptr); + 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); } /* TRUE if corpse might be dropped, magr may die if mon was swallowed */ diff --cc src/objnam.c index 1f9930803,a0db8c681..3c5580c0d --- a/src/objnam.c +++ b/src/objnam.c @@@ -249,267 -248,263 +248,274 @@@ xname_flags(obj, cxn_flags register struct obj *obj; unsigned cxn_flags; /* bitmask of CXN_xxx values */ { - register char *buf; - register int typ = obj->otyp; - register struct objclass *ocl = &objects[typ]; - int nn = ocl->oc_name_known, omndx = obj->corpsenm; - const char *actualn = OBJ_NAME(*ocl); - const char *dn = OBJ_DESCR(*ocl); - const char *un = ocl->oc_uname; + register char *buf; + register int typ = obj->otyp; + register struct objclass *ocl = &objects[typ]; + int nn = ocl->oc_name_known, omndx = obj->corpsenm; + const char *actualn = OBJ_NAME(*ocl); + const char *dn = OBJ_DESCR(*ocl); + const char *un = ocl->oc_uname; boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR); - boolean known, dknown, bknown; - - buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */ - if (Role_if(PM_SAMURAI) && Japanese_item_name(typ)) - actualn = Japanese_item_name(typ); - - buf[0] = '\0'; - /* - * clean up known when it's tied to oc_name_known, eg after AD_DRIN - * This is only required for unique objects since the article - * printed for the object is tied to the combination of the two - * and printing the wrong article gives away information. - */ - if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0; - if (!Blind) obj->dknown = TRUE; - if (Role_if(PM_PRIEST)) obj->bknown = TRUE; + boolean known, dknown, bknown; - if (iflags.override_ID) { - known = dknown = bknown = TRUE; - nn = 1; - } else { - known = obj->known; - dknown = obj->dknown; - bknown = obj->bknown; - } + buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */ + if (Role_if(PM_SAMURAI) && Japanese_item_name(typ)) + actualn = Japanese_item_name(typ); - if (obj_is_pname(obj)) - goto nameit; - switch (obj->oclass) { - case AMULET_CLASS: - if (!dknown) - Strcpy(buf, "amulet"); - else if (typ == AMULET_OF_YENDOR || - typ == FAKE_AMULET_OF_YENDOR) - /* each must be identified individually */ - Strcpy(buf, known ? actualn : dn); - else if (nn) - Strcpy(buf, actualn); - else if (un) - Sprintf(buf,"amulet called %s", un); - else - Sprintf(buf,"%s amulet", dn); - break; - case WEAPON_CLASS: - if (is_poisonable(obj) && obj->opoisoned) - Strcpy(buf, "poisoned "); - case VENOM_CLASS: - case TOOL_CLASS: - if (typ == LENSES) - Strcpy(buf, "pair of "); - - if (!dknown) - Strcat(buf, dn ? dn : actualn); - else if (nn) - Strcat(buf, actualn); - else if (un) { - Strcat(buf, dn ? dn : actualn); - Strcat(buf, " called "); - Strcat(buf, un); - } else - Strcat(buf, dn ? dn : actualn); - /* If we use an() here we'd have to remember never to use */ - /* it whenever calling doname() or xname(). */ - if (typ == FIGURINE && omndx != NON_PM) - Sprintf(eos(buf), " of a%s %s", - index(vowels, *mons[omndx].mname) ? "n" : "", - mons[omndx].mname); - break; - case ARMOR_CLASS: - /* depends on order of the dragon scales objects */ - if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) { - Sprintf(buf, "set of %s", actualn); - break; - } - if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of "); - - if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD - && !dknown) { - Strcpy(buf, "shield"); - break; - } - if(obj->otyp == SHIELD_OF_REFLECTION && !dknown) { - Strcpy(buf, "smooth shield"); - break; - } + buf[0] = '\0'; + /* + * clean up known when it's tied to oc_name_known, eg after AD_DRIN + * This is only required for unique objects since the article + * printed for the object is tied to the combination of the two + * and printing the wrong article gives away information. + */ + if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0; + if (!Blind) obj->dknown = TRUE; + if (Role_if(PM_PRIEST)) obj->bknown = TRUE; - if(nn) Strcat(buf, actualn); - else if(un) { - if(is_boots(obj)) - Strcat(buf,"boots"); - else if(is_gloves(obj)) - Strcat(buf,"gloves"); - else if(is_cloak(obj)) - Strcpy(buf,"cloak"); - else if(is_helmet(obj)) - Strcpy(buf,"helmet"); - else if(is_shield(obj)) - Strcpy(buf,"shield"); - else - Strcpy(buf,"armor"); - Strcat(buf, " called "); - Strcat(buf, un); - } else Strcat(buf, dn); - break; - case FOOD_CLASS: - if (typ == SLIME_MOLD) { - register struct fruit *f; - - for(f=ffruit; f; f = f->nextf) { - if(f->fid == obj->spe) { - Strcpy(buf, f->fname); - break; - } - } - if (!f) { - impossible("Bad fruit #%d?", obj->spe); - Strcpy(buf, "fruit"); - } else if (pluralize) { - /* ick; already pluralized fruit names - are allowed--we want to try to avoid - adding a redundant plural suffix */ - Strcpy(buf, makeplural(makesingular(buf))); - pluralize = FALSE; - } - break; - } + if (iflags.override_ID) { + known = dknown = bknown = TRUE; + nn = 1; + } else { + known = obj->known; + dknown = obj->dknown; + bknown = obj->bknown; + } - Strcpy(buf, actualn); - if (typ == TIN && known) - tin_details(obj, omndx, buf); - break; - case COIN_CLASS: - case CHAIN_CLASS: - Strcpy(buf, actualn); - break; - case ROCK_CLASS: - if (typ == STATUE && omndx != NON_PM) - Sprintf(buf, "%s%s of %s%s", - (Role_if(PM_ARCHEOLOGIST) && - (obj->spe & STATUE_HISTORIC)) ? "historic " : "", - actualn, - type_is_pname(&mons[omndx]) ? "" : - the_unique_pm(&mons[omndx]) ? "the " : - index(vowels, *mons[omndx].mname) ? "an " : "a ", - mons[omndx].mname); - else Strcpy(buf, actualn); - break; - case BALL_CLASS: - Sprintf(buf, "%sheavy iron ball", - (obj->owt > ocl->oc_weight) ? "very " : ""); - break; - case POTION_CLASS: - if (dknown && obj->odiluted) - Strcpy(buf, "diluted "); - if(nn || un || !dknown) { - Strcat(buf, "potion"); - if(!dknown) break; - if(nn) { - Strcat(buf, " of "); - if (typ == POT_WATER && - bknown && (obj->blessed || obj->cursed)) { - Strcat(buf, obj->blessed ? "holy " : "unholy "); - } - Strcat(buf, actualn); - } else { - Strcat(buf, " called "); - Strcat(buf, un); - } - } else { - Strcat(buf, dn); - Strcat(buf, " potion"); - } - break; - case SCROLL_CLASS: - Strcpy(buf, "scroll"); - if(!dknown) break; - if(nn) { - Strcat(buf, " of "); - Strcat(buf, actualn); - } else if(un) { - Strcat(buf, " called "); - Strcat(buf, un); - } else if (ocl->oc_magic) { - Strcat(buf, " labeled "); - Strcat(buf, dn); - } else { - Strcpy(buf, dn); - Strcat(buf, " scroll"); - } - break; - case WAND_CLASS: - if(!dknown) - Strcpy(buf, "wand"); - else if(nn) - Sprintf(buf, "wand of %s", actualn); - else if(un) - Sprintf(buf, "wand called %s", un); - else - Sprintf(buf, "%s wand", dn); - break; - case SPBOOK_CLASS: - if (typ == SPE_NOVEL) { /* 3.6 tribute */ - if (!dknown) { - Strcpy(buf, "book"); - } else if (nn) { - Strcpy(buf, actualn); - } else if (un) { - Sprintf(buf, "novel called %s", un); - } else - Sprintf(buf, "%s book", dn); - break; - } else - /* end of tribute */ - if (!dknown) { - Strcpy(buf, "spellbook"); - } else if (nn) { - if (typ != SPE_BOOK_OF_THE_DEAD) - Strcpy(buf, "spellbook of "); - Strcat(buf, actualn); - } else if (un) { - Sprintf(buf, "spellbook called %s", un); - } else - Sprintf(buf, "%s spellbook", dn); - break; - case RING_CLASS: - if(!dknown) - Strcpy(buf, "ring"); - else if(nn) - Sprintf(buf, "ring of %s", actualn); - else if(un) - Sprintf(buf, "ring called %s", un); - else - Sprintf(buf, "%s ring", dn); - break; - case GEM_CLASS: - { - const char *rock = - (ocl->oc_material == MINERAL) ? "stone" : "gem"; - if (!dknown) { - Strcpy(buf, rock); - } else if (!nn) { - if (un) Sprintf(buf,"%s called %s", rock, un); - else Sprintf(buf, "%s %s", dn, rock); - } else { - Strcpy(buf, actualn); - if (GemStone(typ)) Strcat(buf, " stone"); - } - break; - } - default: - Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe); - } - if (pluralize) Strcpy(buf, makeplural(buf)); + if (obj_is_pname(obj)) + goto nameit; + switch (obj->oclass) { + case AMULET_CLASS: + if (!dknown) + Strcpy(buf, "amulet"); + else if (typ == AMULET_OF_YENDOR || + typ == FAKE_AMULET_OF_YENDOR) + /* each must be identified individually */ + Strcpy(buf, known ? actualn : dn); + else if (nn) + Strcpy(buf, actualn); + else if (un) + Sprintf(buf,"amulet called %s", un); + else + Sprintf(buf,"%s amulet", dn); + break; + case WEAPON_CLASS: + if (is_poisonable(obj) && obj->opoisoned) + Strcpy(buf, "poisoned "); + case VENOM_CLASS: + case TOOL_CLASS: + if (typ == LENSES) + Strcpy(buf, "pair of "); + + if (!dknown) + Strcat(buf, dn ? dn : actualn); + else if (nn) + Strcat(buf, actualn); + else if (un) { + Strcat(buf, dn ? dn : actualn); + Strcat(buf, " called "); + Strcat(buf, un); + } else + Strcat(buf, dn ? dn : actualn); + /* If we use an() here we'd have to remember never to use */ + /* it whenever calling doname() or xname(). */ + if (typ == FIGURINE && omndx != NON_PM) + Sprintf(eos(buf), " of a%s %s", + index(vowels, *mons[omndx].mname) ? "n" : "", + mons[omndx].mname); + break; + case ARMOR_CLASS: + /* depends on order of the dragon scales objects */ + if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) { + Sprintf(buf, "set of %s", actualn); + break; + } + if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of "); + + if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD + && !dknown) { + Strcpy(buf, "shield"); + break; + } + if(obj->otyp == SHIELD_OF_REFLECTION && !dknown) { + Strcpy(buf, "smooth shield"); + break; + } + + if(nn) Strcat(buf, actualn); + else if(un) { + if(is_boots(obj)) + Strcat(buf,"boots"); + else if(is_gloves(obj)) + Strcat(buf,"gloves"); + else if(is_cloak(obj)) + Strcpy(buf,"cloak"); + else if(is_helmet(obj)) + Strcpy(buf,"helmet"); + else if(is_shield(obj)) + Strcpy(buf,"shield"); + else + Strcpy(buf,"armor"); + Strcat(buf, " called "); + Strcat(buf, un); + } else Strcat(buf, dn); + break; + case FOOD_CLASS: + if (typ == SLIME_MOLD) { + register struct fruit *f; + + for(f=ffruit; f; f = f->nextf) { + if(f->fid == obj->spe) { + Strcpy(buf, f->fname); + break; + } + } + if (!f) { + impossible("Bad fruit #%d?", obj->spe); + Strcpy(buf, "fruit"); + } else if (pluralize) { + /* ick; already pluralized fruit names + are allowed--we want to try to avoid + adding a redundant plural suffix */ + Strcpy(buf, makeplural(makesingular(buf))); + pluralize = FALSE; + } + break; + } + if (Is_pudding(obj)) { + Sprintf(buf, "%s%s", + obj->owt < 100 ? "small " + : obj->owt > 500 ? "very large " + : obj->owt > 300 ? "large " + : "", actualn); + break; + } + + Strcpy(buf, actualn); + if (typ == TIN && known) + tin_details(obj, omndx, buf); + break; + case COIN_CLASS: + case CHAIN_CLASS: + Strcpy(buf, actualn); + break; + case ROCK_CLASS: + if (typ == STATUE && omndx != NON_PM) + Sprintf(buf, "%s%s of %s%s", + (Role_if(PM_ARCHEOLOGIST) && + (obj->spe & STATUE_HISTORIC)) ? "historic " : "", + actualn, + type_is_pname(&mons[omndx]) ? "" : + the_unique_pm(&mons[omndx]) ? "the " : + index(vowels, *mons[omndx].mname) ? "an " : "a ", + mons[omndx].mname); + else Strcpy(buf, actualn); + break; + case BALL_CLASS: + Sprintf(buf, "%sheavy iron ball", + (obj->owt > ocl->oc_weight) ? "very " : ""); + break; + case POTION_CLASS: + if (dknown && obj->odiluted) + Strcpy(buf, "diluted "); + if(nn || un || !dknown) { + Strcat(buf, "potion"); + if(!dknown) break; + if(nn) { + Strcat(buf, " of "); + if (typ == POT_WATER && + bknown && (obj->blessed || obj->cursed)) { + Strcat(buf, obj->blessed ? "holy " : "unholy "); + } + Strcat(buf, actualn); + } else { + Strcat(buf, " called "); + Strcat(buf, un); + } + } else { + Strcat(buf, dn); + Strcat(buf, " potion"); + } + break; + case SCROLL_CLASS: + Strcpy(buf, "scroll"); + if(!dknown) break; + if(nn) { + Strcat(buf, " of "); + Strcat(buf, actualn); + } else if(un) { + Strcat(buf, " called "); + Strcat(buf, un); + } else if (ocl->oc_magic) { + Strcat(buf, " labeled "); + Strcat(buf, dn); + } else { + Strcpy(buf, dn); + Strcat(buf, " scroll"); + } + break; + case WAND_CLASS: + if(!dknown) + Strcpy(buf, "wand"); + else if(nn) + Sprintf(buf, "wand of %s", actualn); + else if(un) + Sprintf(buf, "wand called %s", un); + else + Sprintf(buf, "%s wand", dn); + break; + case SPBOOK_CLASS: - if (!dknown) { ++ if (typ == SPE_NOVEL) { /* 3.6 tribute */ ++ if (!dknown) ++ Strcpy(buf, "book"); ++ else if (nn) ++ Strcpy(buf, actualn); ++ else if (un) ++ Sprintf(buf, "novel called %s", un); ++ else ++ Sprintf(buf, "%s book", dn); ++ break; ++ /* end of tribute */ ++ } else if (!dknown) { + Strcpy(buf, "spellbook"); + } else if (nn) { + if (typ != SPE_BOOK_OF_THE_DEAD) + Strcpy(buf, "spellbook of "); + Strcat(buf, actualn); + } else if (un) { + Sprintf(buf, "spellbook called %s", un); + } else + Sprintf(buf, "%s spellbook", dn); + break; + case RING_CLASS: + if(!dknown) + Strcpy(buf, "ring"); + else if(nn) + Sprintf(buf, "ring of %s", actualn); + else if(un) + Sprintf(buf, "ring called %s", un); + else + Sprintf(buf, "%s ring", dn); + break; + case GEM_CLASS: + { + const char *rock = + (ocl->oc_material == MINERAL) ? "stone" : "gem"; + if (!dknown) { + Strcpy(buf, rock); + } else if (!nn) { + if (un) Sprintf(buf,"%s called %s", rock, un); + else Sprintf(buf, "%s %s", dn, rock); + } else { + Strcpy(buf, actualn); + if (GemStone(typ)) Strcat(buf, " stone"); + } + break; + } + default: + Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe); + } + if (pluralize) Strcpy(buf, makeplural(buf)); if (obj->otyp == T_SHIRT && program_state.gameover) { char tmpbuf[BUFSZ]; @@@ -2447,831 -2448,825 +2459,846 @@@ struct obj *no_wish also, spe should always be positive -- some cheaters may try to confuse atoi() */ - if (spe < 0) { - spesgn = -1; /* cheaters get what they deserve */ - spe = abs(spe); - } - if (spe > SCHAR_LIM) - spe = SCHAR_LIM; - if (rechrg < 0 || rechrg > 7) rechrg = 7; /* recharge_limit */ - - /* now we have the actual name, as delivered by xname, say - green potions called whisky - scrolls labeled "QWERTY" - egg - fortune cookies - very heavy iron ball named hoei - wand of wishing - elven cloak - */ - if ((p = strstri(bp, " named ")) != 0) { - *p = 0; - name = p+7; - } - if ((p = strstri(bp, " called ")) != 0) { - *p = 0; - un = p+8; - /* "helmet called telepathy" is not "helmet" (a specific type) - * "shield called reflection" is not "shield" (a general type) - */ - for(i = 0; i < SIZE(o_ranges); i++) - if(!strcmpi(bp, o_ranges[i].name)) { - oclass = o_ranges[i].oclass; - goto srch; - } - } - if ((p = strstri(bp, " labeled ")) != 0) { - *p = 0; - dn = p+9; - } else if ((p = strstri(bp, " labelled ")) != 0) { - *p = 0; - dn = p+10; - } - if ((p = strstri(bp, " of spinach")) != 0) { - *p = 0; - contents = SPINACH; - } + if (spe < 0) { + spesgn = -1; /* cheaters get what they deserve */ + spe = abs(spe); + } + if (spe > SCHAR_LIM) + spe = SCHAR_LIM; + if (rechrg < 0 || rechrg > 7) rechrg = 7; /* recharge_limit */ + + /* now we have the actual name, as delivered by xname, say + green potions called whisky + scrolls labeled "QWERTY" + egg + fortune cookies + very heavy iron ball named hoei + wand of wishing + elven cloak + */ + if ((p = strstri(bp, " named ")) != 0) { + *p = 0; + name = p+7; + } + if ((p = strstri(bp, " called ")) != 0) { + *p = 0; + un = p+8; + /* "helmet called telepathy" is not "helmet" (a specific type) + * "shield called reflection" is not "shield" (a general type) + */ + for(i = 0; i < SIZE(o_ranges); i++) + if(!strcmpi(bp, o_ranges[i].name)) { + oclass = o_ranges[i].oclass; + goto srch; + } + } + if ((p = strstri(bp, " labeled ")) != 0) { + *p = 0; + dn = p+9; + } else if ((p = strstri(bp, " labelled ")) != 0) { + *p = 0; + dn = p+10; + } + if ((p = strstri(bp, " of spinach")) != 0) { + *p = 0; + contents = SPINACH; + } - /* - Skip over "pair of ", "pairs of", "set of" and "sets of". - - Accept "3 pair of boots" as well as "3 pairs of boots". It is valid - English either way. See makeplural() for more on pair/pairs. - - We should only double count if the object in question is not - refered to as a "pair of". E.g. We should double if the player - types "pair of spears", but not if the player types "pair of - lenses". Luckily (?) all objects that are refered to as pairs - -- boots, gloves, and lenses -- are also not mergable, so cnt is - ignored anyway. - */ - if(!strncmpi(bp, "pair of ",8)) { - bp += 8; - cnt *= 2; - } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) { - bp += 9; - cnt *= 2; - } else if (!strncmpi(bp, "set of ",7)) { - bp += 7; - } else if (!strncmpi(bp, "sets of ",8)) { - bp += 8; - } + /* + Skip over "pair of ", "pairs of", "set of" and "sets of". + + Accept "3 pair of boots" as well as "3 pairs of boots". It is valid + English either way. See makeplural() for more on pair/pairs. + + We should only double count if the object in question is not + refered to as a "pair of". E.g. We should double if the player + types "pair of spears", but not if the player types "pair of + lenses". Luckily (?) all objects that are refered to as pairs + -- boots, gloves, and lenses -- are also not mergable, so cnt is + ignored anyway. + */ + if(!strncmpi(bp, "pair of ",8)) { + bp += 8; + cnt *= 2; + } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) { + bp += 9; + cnt *= 2; + } else if (!strncmpi(bp, "set of ",7)) { + bp += 7; + } else if (!strncmpi(bp, "sets of ",8)) { + bp += 8; + } - /* - * Find corpse type using "of" (figurine of an orc, tin of orc meat) - * Don't check if it's a wand or spellbook. - * (avoid "wand/finger of death" confusion). - */ - if (!strstri(bp, "wand ") - && !strstri(bp, "spellbook ") - && !strstri(bp, "finger ")) { - if (((p = strstri(bp, "tin of ")) != 0) && - (tmp = tin_variety_txt(p+7, &tinv)) && - (mntmp = name_to_mon(p+7+tmp)) >= LOW_PM) { - *(p+3) = 0; - tvariety = tinv; - } else if ((p = strstri(bp, " of ")) != 0 - && (mntmp = name_to_mon(p+4)) >= LOW_PM) - *p = 0; - } - /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */ - if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */ - if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */ - if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */ - if (strncmpi(bp, "master key", 10)) /* not the "master" rank */ - if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */ - if (mntmp < LOW_PM && strlen(bp) > 2 && - (mntmp = name_to_mon(bp)) >= LOW_PM) { - int mntmptoo, mntmplen; /* double check for rank title */ - char *obp = bp; - mntmptoo = title_to_mon(bp, (int *)0, &mntmplen); - bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen; - if (*bp == ' ') bp++; - else if (!strncmpi(bp, "s ", 2)) bp += 2; - else if (!strncmpi(bp, "es ", 3)) bp += 3; - else if (!*bp && !actualn && !dn && !un && !oclass) { - /* no referent; they don't really mean a monster type */ - bp = obp; - mntmp = NON_PM; - } - } + /* intercept pudding globs here; they're a valid wish target, + * but we need them to not get treated like a corpse. + * + * also don't let player wish for multiple globs. + */ + if ((p = strstri(bp, "glob of ")) != 0 + || (p = strstri(bp, "globs of ")) != 0) { + int globoffset = (*(p+4) == 's') ? 9 : 8; + if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE + && mntmp <= PM_BLACK_PUDDING) { + mntmp = NON_PM; /* lie to ourselves */ + cnt = 0; /* force only one */ + } + } else { + /* + * Find corpse type using "of" (figurine of an orc, tin of orc meat) + * Don't check if it's a wand or spellbook. + * (avoid "wand/finger of death" confusion). + */ + if (!strstri(bp, "wand ") + && !strstri(bp, "spellbook ") + && !strstri(bp, "finger ")) { + if (((p = strstri(bp, "tin of ")) != 0) && + (tmp = tin_variety_txt(p + 7, &tinv)) && + (mntmp = name_to_mon(p + 7 + tmp)) >= LOW_PM) { + *(p + 3) = 0; + tvariety = tinv; + } else if ((p = strstri(bp, " of ")) != 0 + && (mntmp = name_to_mon(p + 4)) >= LOW_PM) + *p = 0; + } + } + /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */ + if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */ + if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */ + if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */ + if (strncmpi(bp, "master key", 10)) /* not the "master" rank */ + if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */ + if (mntmp < LOW_PM && strlen(bp) > 2 && + (mntmp = name_to_mon(bp)) >= LOW_PM) { + int mntmptoo, mntmplen; /* double check for rank title */ + char *obp = bp; + mntmptoo = title_to_mon(bp, (int *)0, &mntmplen); + bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen; + if (*bp == ' ') bp++; + else if (!strncmpi(bp, "s ", 2)) bp += 2; + else if (!strncmpi(bp, "es ", 3)) bp += 3; + else if (!*bp && !actualn && !dn && !un && !oclass) { + /* no referent; they don't really mean a monster type */ + bp = obp; + mntmp = NON_PM; + } + } - /* first change to singular if necessary */ - if (*bp) { - char *sng = makesingular(bp); - if (strcmp(bp, sng)) { - if (cnt == 1) cnt = 2; - Strcpy(bp, sng); - } - } + /* first change to singular if necessary */ + if (*bp) { + char *sng = makesingular(bp); + if (strcmp(bp, sng)) { + if (cnt == 1) cnt = 2; + Strcpy(bp, sng); + } + } - /* Alternate spellings (pick-ax, silver sabre, &c) */ + /* Alternate spellings (pick-ax, silver sabre, &c) */ { - struct alt_spellings *as = spellings; - - while (as->sp) { - if (fuzzymatch(bp, as->sp, " -", TRUE)) { - typ = as->ob; - goto typfnd; - } - as++; - } - /* can't use spellings list for this one due to shuffling */ - if (!strncmpi(bp, "grey spell", 10)) - *(bp + 2) = 'a'; - - if ((p = strstri(bp, "armour")) != 0) { - /* skip past "armo", then copy remainer beyond "u" */ - p += 4; - while ((*p = *(p + 1)) != '\0') ++p; /* self terminating */ - } + struct alt_spellings *as = spellings; + + while (as->sp) { + if (fuzzymatch(bp, as->sp, " -", TRUE)) { + typ = as->ob; + goto typfnd; + } + as++; + } + /* can't use spellings list for this one due to shuffling */ + if (!strncmpi(bp, "grey spell", 10)) + *(bp + 2) = 'a'; + + if ((p = strstri(bp, "armour")) != 0) { + /* skip past "armo", then copy remainer beyond "u" */ + p += 4; + while ((*p = *(p + 1)) != '\0') ++p; /* self terminating */ + } } - /* dragon scales - assumes order of dragons */ - if(!strcmpi(bp, "scales") && - mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) { - typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON; - mntmp = NON_PM; /* no monster */ - goto typfnd; - } + /* dragon scales - assumes order of dragons */ + if(!strcmpi(bp, "scales") && + mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) { + typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON; + mntmp = NON_PM; /* no monster */ + goto typfnd; + } - p = eos(bp); - if(!BSTRCMPI(bp, p-10, "holy water")) { - typ = POT_WATER; - if ((p-bp) >= 12 && *(p-12) == 'u') - iscursed = 1; /* unholy water */ - else blessed = 1; - goto typfnd; - } - if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) { - typ = SCR_BLANK_PAPER; - goto typfnd; - } - if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) { - typ = SPE_BLANK_PAPER; - goto typfnd; - } - /* - * NOTE: Gold pieces are handled as objects nowadays, and therefore - * this section should probably be reconsidered as well as the entire - * gold/money concept. Maybe we want to add other monetary units as - * well in the future. (TH) - */ - if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") || - !strcmpi(bp, "gold") || !strcmpi(bp, "money") || - !strcmpi(bp, "coin") || *bp == GOLD_SYM) { - if (cnt > 5000 && !wizard) cnt = 5000; - else if (cnt < 1) cnt = 1; - otmp = mksobj(GOLD_PIECE, FALSE, FALSE); - otmp->quan = (long) cnt; - otmp->owt = weight(otmp); - context.botl = 1; - return otmp; - } + p = eos(bp); + if(!BSTRCMPI(bp, p-10, "holy water")) { + typ = POT_WATER; + if ((p-bp) >= 12 && *(p-12) == 'u') + iscursed = 1; /* unholy water */ + else blessed = 1; + goto typfnd; + } + if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) { + typ = SCR_BLANK_PAPER; + goto typfnd; + } + if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) { + typ = SPE_BLANK_PAPER; + goto typfnd; + } + /* + * NOTE: Gold pieces are handled as objects nowadays, and therefore + * this section should probably be reconsidered as well as the entire + * gold/money concept. Maybe we want to add other monetary units as + * well in the future. (TH) + */ + if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") || + !strcmpi(bp, "gold") || !strcmpi(bp, "money") || + !strcmpi(bp, "coin") || *bp == GOLD_SYM) { + if (cnt > 5000 && !wizard) cnt = 5000; + else if (cnt < 1) cnt = 1; + otmp = mksobj(GOLD_PIECE, FALSE, FALSE); + otmp->quan = (long) cnt; + otmp->owt = weight(otmp); + context.botl = 1; + return otmp; + } - /* check for single character object class code ("/" for wand, &c) */ - if (strlen(bp) == 1 && - (i = def_char_to_objclass(*bp)) < MAXOCLASSES && - i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) { - oclass = i; - goto any; - } + /* check for single character object class code ("/" for wand, &c) */ + if (strlen(bp) == 1 && + (i = def_char_to_objclass(*bp)) < MAXOCLASSES && + i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) { + oclass = i; + goto any; + } - /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */ - /* false hits on, e.g., rings for "ring mail". */ - if(strncmpi(bp, "enchant ", 8) && - strncmpi(bp, "destroy ", 8) && - strncmpi(bp, "detect food", 11) && - strncmpi(bp, "food detection", 14) && - strncmpi(bp, "ring mail", 9) && - strncmpi(bp, "studded leather armor", 21) && - strncmpi(bp, "leather armor", 13) && - strncmpi(bp, "tooled horn", 11) && - strncmpi(bp, "food ration", 11) && - strncmpi(bp, "meat ring", 9) - ) - for (i = 0; i < (int)(sizeof wrpsym); i++) { - register int j = strlen(wrp[i]); - if(!strncmpi(bp, wrp[i], j)){ - oclass = wrpsym[i]; - if(oclass != AMULET_CLASS) { - bp += j; - if(!strncmpi(bp, " of ", 4)) actualn = bp+4; - /* else if(*bp) ?? */ - } else - actualn = bp; - goto srch; - } - if(!BSTRCMPI(bp, p-j, wrp[i])){ - oclass = wrpsym[i]; - p -= j; - *p = 0; - if(p > bp && p[-1] == ' ') p[-1] = 0; - actualn = dn = bp; - goto srch; - } - } + /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */ + /* false hits on, e.g., rings for "ring mail". */ + if(strncmpi(bp, "enchant ", 8) && + strncmpi(bp, "destroy ", 8) && + strncmpi(bp, "detect food", 11) && + strncmpi(bp, "food detection", 14) && + strncmpi(bp, "ring mail", 9) && + strncmpi(bp, "studded leather armor", 21) && + strncmpi(bp, "leather armor", 13) && + strncmpi(bp, "tooled horn", 11) && + strncmpi(bp, "food ration", 11) && + strncmpi(bp, "meat ring", 9) + ) + for (i = 0; i < (int)(sizeof wrpsym); i++) { + register int j = strlen(wrp[i]); + if(!strncmpi(bp, wrp[i], j)){ + oclass = wrpsym[i]; + if(oclass != AMULET_CLASS) { + bp += j; + if(!strncmpi(bp, " of ", 4)) actualn = bp+4; + /* else if(*bp) ?? */ + } else + actualn = bp; + goto srch; + } + if(!BSTRCMPI(bp, p-j, wrp[i])){ + oclass = wrpsym[i]; + p -= j; + *p = 0; + if(p > bp && p[-1] == ' ') p[-1] = 0; + actualn = dn = bp; + goto srch; + } + } - /* Wishing in wizard mode can create traps and furniture. - * Part I: distinguish between trap and object for the two - * types of traps which have corresponding objects: bear trap - * and land mine. "beartrap" (object) and "bear trap" (trap) - * have a difference in spelling which we used to exploit by - * adding a special case in wishymatch(), but "land mine" is - * spelled the same either way so needs different handing. - * Since we need something else for land mine, we've dropped - * the bear trap hack so that both are handled exactly the - * same. To get an armed trap instead of a disarmed object, - * the player can prefix either the object name or the trap - * name with "trapped " (which ordinarily applies to chests - * and tins), or append something--anything at all except for - * " object", but " trap" is suggested--to either the trap - * name or the object name. - */ - if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) { - boolean beartrap = (lowc(*bp) == 'b'); - char *zp = bp + 4; /* skip "bear"/"land" */ - - if (*zp == ' ') ++zp; /* embedded space is optional */ - if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) { - zp += 4; - if (trapped == 2 || !strcmpi(zp, " object")) { - /* "untrapped " or " object" */ - typ = beartrap ? BEARTRAP : LAND_MINE; - goto typfnd; - } else if (trapped == 1 || *zp != '\0') { - /* "trapped " or " trap" (actually "*") */ - int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE); - - /* use canonical trap spelling, skip object matching */ - Strcpy(bp, defsyms[idx].explanation); - goto wiztrap; - } - /* [no prefix or suffix; we're going to end up matching - the object name and getting a disarmed trap object] */ - } - } + /* Wishing in wizard mode can create traps and furniture. + * Part I: distinguish between trap and object for the two + * types of traps which have corresponding objects: bear trap + * and land mine. "beartrap" (object) and "bear trap" (trap) + * have a difference in spelling which we used to exploit by + * adding a special case in wishymatch(), but "land mine" is + * spelled the same either way so needs different handing. + * Since we need something else for land mine, we've dropped + * the bear trap hack so that both are handled exactly the + * same. To get an armed trap instead of a disarmed object, + * the player can prefix either the object name or the trap + * name with "trapped " (which ordinarily applies to chests + * and tins), or append something--anything at all except for + * " object", but " trap" is suggested--to either the trap + * name or the object name. + */ + if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) { + boolean beartrap = (lowc(*bp) == 'b'); + char *zp = bp + 4; /* skip "bear"/"land" */ + + if (*zp == ' ') ++zp; /* embedded space is optional */ + if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) { + zp += 4; + if (trapped == 2 || !strcmpi(zp, " object")) { + /* "untrapped " or " object" */ + typ = beartrap ? BEARTRAP : LAND_MINE; + goto typfnd; + } else if (trapped == 1 || *zp != '\0') { + /* "trapped " or " trap" (actually "*") */ + int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE); + + /* use canonical trap spelling, skip object matching */ + Strcpy(bp, defsyms[idx].explanation); + goto wiztrap; + } + /* [no prefix or suffix; we're going to end up matching + the object name and getting a disarmed trap object] */ + } + } retry: - /* "grey stone" check must be before general "stone" */ - for (i = 0; i < SIZE(o_ranges); i++) - if(!strcmpi(bp, o_ranges[i].name)) { - typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range); - goto typfnd; - } - - if (!BSTRCMPI(bp, p-6, " stone")) { - p[-6] = 0; - oclass = GEM_CLASS; - dn = actualn = bp; - goto srch; - } else if (!strcmpi(bp, "looking glass")) { - ; /* avoid false hit on "* glass" */ - } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) { - register char *g = bp; - if (strstri(g, "broken")) return (struct obj *)0; - if (!strncmpi(g, "worthless ", 10)) g += 10; - if (!strncmpi(g, "piece of ", 9)) g += 9; - if (!strncmpi(g, "colored ", 8)) g += 8; - else if (!strncmpi(g, "coloured ", 9)) g += 9; - if (!strcmpi(g, "glass")) { /* choose random color */ - /* 9 different kinds */ - typ = LAST_GEM + rnd(9); - if (objects[typ].oc_class == GEM_CLASS) goto typfnd; - else typ = 0; /* somebody changed objects[]? punt */ - } else { /* try to construct canonical form */ - char tbuf[BUFSZ]; - Strcpy(tbuf, "worthless piece of "); - Strcat(tbuf, g); /* assume it starts with the color */ - Strcpy(bp, tbuf); - } - } + /* "grey stone" check must be before general "stone" */ + for (i = 0; i < SIZE(o_ranges); i++) + if(!strcmpi(bp, o_ranges[i].name)) { + typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range); + goto typfnd; + } + + if (!BSTRCMPI(bp, p-6, " stone")) { + p[-6] = 0; + oclass = GEM_CLASS; + dn = actualn = bp; + goto srch; + } else if (!strcmpi(bp, "looking glass")) { + ; /* avoid false hit on "* glass" */ + } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) { + register char *g = bp; + if (strstri(g, "broken")) return (struct obj *)0; + if (!strncmpi(g, "worthless ", 10)) g += 10; + if (!strncmpi(g, "piece of ", 9)) g += 9; + if (!strncmpi(g, "colored ", 8)) g += 8; + else if (!strncmpi(g, "coloured ", 9)) g += 9; + if (!strcmpi(g, "glass")) { /* choose random color */ + /* 9 different kinds */ + typ = LAST_GEM + rnd(9); + if (objects[typ].oc_class == GEM_CLASS) goto typfnd; + else typ = 0; /* somebody changed objects[]? punt */ + } else { /* try to construct canonical form */ + char tbuf[BUFSZ]; + Strcpy(tbuf, "worthless piece of "); + Strcat(tbuf, g); /* assume it starts with the color */ + Strcpy(bp, tbuf); + } + } - actualn = bp; - if (!dn) dn = actualn; /* ex. "skull cap" */ + actualn = bp; + if (!dn) dn = actualn; /* ex. "skull cap" */ srch: - /* check real names of gems first */ - if(!oclass && actualn) { - for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) { - register const char *zn; - - if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) { - typ = i; - goto typfnd; - } - } - } - i = oclass ? bases[(int)oclass] : 1; - while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){ - register const char *zn; - - if (actualn && (zn = OBJ_NAME(objects[i])) != 0 && - wishymatch(actualn, zn, TRUE)) { - typ = i; - goto typfnd; - } - if (dn && (zn = OBJ_DESCR(objects[i])) != 0 && - wishymatch(dn, zn, FALSE)) { - /* don't match extra descriptions (w/o real name) */ - if (!OBJ_NAME(objects[i])) return (struct obj *)0; - typ = i; - goto typfnd; - } - if (un && (zn = objects[i].oc_uname) != 0 && - wishymatch(un, zn, FALSE)) { - typ = i; - goto typfnd; - } - i++; - } - if (actualn) { - struct Jitem *j = Japanese_items; - while(j->item) { - if (actualn && !strcmpi(actualn, j->name)) { - typ = j->item; - goto typfnd; - } - j++; - } - } - /* if we've stripped off "armor" and failed to match anything - in objects[], append "mail" and try again to catch misnamed - requests like "plate armor" and "yellow dragon scale armor" */ - if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) { - /* modifying bp's string is ok; we're about to resort - to random armor if this also fails to match anything */ - Strcat(bp, " mail"); - goto retry; - } - if (!strcmpi(bp, "spinach")) { - contents = SPINACH; - typ = TIN; - goto typfnd; - } - /* Note: not strcmpi. 2 fruits, one capital, one not, are possible. - Also not strncmp. We used to ignore trailing text with it, but - that resulted in "grapefruit" matching "grape" if the latter came - earlier than the former in the fruit list. */ - { - char *fp; - int l, cntf; - int blessedf, iscursedf, uncursedf, halfeatenf; - - blessedf = iscursedf = uncursedf = halfeatenf = 0; - cntf = 0; - - fp = fruitbuf; - for(;;) { - if (!fp || !*fp) break; - if (!strncmpi(fp, "an ", l=3) || - !strncmpi(fp, "a ", l=2)) { - cntf = 1; - } else if (!cntf && digit(*fp)) { - cntf = atoi(fp); - while(digit(*fp)) fp++; - while(*fp == ' ') fp++; - l = 0; - } else if (!strncmpi(fp, "blessed ", l=8)) { - blessedf = 1; - } else if (!strncmpi(fp, "cursed ", l=7)) { - iscursedf = 1; - } else if (!strncmpi(fp, "uncursed ", l=9)) { - uncursedf = 1; - } else if (!strncmpi(fp, "partly eaten ", l=13) || - !strncmpi(fp, "partially eaten ", l=16)) { - halfeatenf = 1; - } else break; - fp += l; - } - - for(f=ffruit; f; f = f->nextf) { - /* match type: 0=none, 1=exact, 2=singular, 3=plural */ - int ftyp = 0; - - if (!strcmp(fp, f->fname)) ftyp = 1; - else if (!strcmp(fp, makesingular(f->fname))) ftyp = 2; - else if (!strcmp(fp, makeplural(f->fname))) ftyp = 3; - if (ftyp) { - typ = SLIME_MOLD; - blessed = blessedf; - iscursed = iscursedf; - uncursed = uncursedf; - halfeaten = halfeatenf; - /* adjust count if user explicitly asked for - singular amount (can't happen unless fruit - has been given an already pluralized name) - or for plural amount */ - if (ftyp == 2 && !cntf) cntf = 1; - else if (ftyp == 3 && !cntf) cntf = 2; - cnt = cntf; - ftype = f->fid; - goto typfnd; - } - } - } + /* check real names of gems first */ + if(!oclass && actualn) { + for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) { + register const char *zn; + + if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) { + typ = i; + goto typfnd; + } + } + } + i = oclass ? bases[(int)oclass] : 1; + while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){ + register const char *zn; + + if (actualn && (zn = OBJ_NAME(objects[i])) != 0 && + wishymatch(actualn, zn, TRUE)) { + typ = i; + goto typfnd; + } + if (dn && (zn = OBJ_DESCR(objects[i])) != 0 && + wishymatch(dn, zn, FALSE)) { + /* don't match extra descriptions (w/o real name) */ + if (!OBJ_NAME(objects[i])) return (struct obj *)0; + typ = i; + goto typfnd; + } + if (un && (zn = objects[i].oc_uname) != 0 && + wishymatch(un, zn, FALSE)) { + typ = i; + goto typfnd; + } + i++; + } + if (actualn) { + struct Jitem *j = Japanese_items; + while(j->item) { + if (actualn && !strcmpi(actualn, j->name)) { + typ = j->item; + goto typfnd; + } + j++; + } + } + /* if we've stripped off "armor" and failed to match anything + in objects[], append "mail" and try again to catch misnamed + requests like "plate armor" and "yellow dragon scale armor" */ + if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) { + /* modifying bp's string is ok; we're about to resort + to random armor if this also fails to match anything */ + Strcat(bp, " mail"); + goto retry; + } + if (!strcmpi(bp, "spinach")) { + contents = SPINACH; + typ = TIN; + goto typfnd; + } + /* Note: not strcmpi. 2 fruits, one capital, one not, are possible. + Also not strncmp. We used to ignore trailing text with it, but + that resulted in "grapefruit" matching "grape" if the latter came + earlier than the former in the fruit list. */ + { + char *fp; + int l, cntf; + int blessedf, iscursedf, uncursedf, halfeatenf; + + blessedf = iscursedf = uncursedf = halfeatenf = 0; + cntf = 0; + + fp = fruitbuf; + for(;;) { + if (!fp || !*fp) break; + if (!strncmpi(fp, "an ", l=3) || + !strncmpi(fp, "a ", l=2)) { + cntf = 1; + } else if (!cntf && digit(*fp)) { + cntf = atoi(fp); + while(digit(*fp)) fp++; + while(*fp == ' ') fp++; + l = 0; + } else if (!strncmpi(fp, "blessed ", l=8)) { + blessedf = 1; + } else if (!strncmpi(fp, "cursed ", l=7)) { + iscursedf = 1; + } else if (!strncmpi(fp, "uncursed ", l=9)) { + uncursedf = 1; + } else if (!strncmpi(fp, "partly eaten ", l=13) || + !strncmpi(fp, "partially eaten ", l=16)) { + halfeatenf = 1; + } else break; + fp += l; + } + + for(f=ffruit; f; f = f->nextf) { + /* match type: 0=none, 1=exact, 2=singular, 3=plural */ + int ftyp = 0; + + if (!strcmp(fp, f->fname)) ftyp = 1; + else if (!strcmp(fp, makesingular(f->fname))) ftyp = 2; + else if (!strcmp(fp, makeplural(f->fname))) ftyp = 3; + if (ftyp) { + typ = SLIME_MOLD; + blessed = blessedf; + iscursed = iscursedf; + uncursed = uncursedf; + halfeaten = halfeatenf; + /* adjust count if user explicitly asked for + singular amount (can't happen unless fruit + has been given an already pluralized name) + or for plural amount */ + if (ftyp == 2 && !cntf) cntf = 1; + else if (ftyp == 3 && !cntf) cntf = 2; + cnt = cntf; + ftype = f->fid; + goto typfnd; + } + } + } - if(!oclass && actualn) { - short objtyp; + if(!oclass && actualn) { + short objtyp; - /* Perhaps it's an artifact specified by name, not type */ - name = artifact_name(actualn, &objtyp); - if(name) { - typ = objtyp; - goto typfnd; - } - } - /* Let wizards wish for traps and furniture. - * Must come after objects check so wizards can still wish for - * trap objects like beartraps. - * Disallow such topology tweaks for WIZKIT startup wishes. - */ + /* Perhaps it's an artifact specified by name, not type */ + name = artifact_name(actualn, &objtyp); + if(name) { + typ = objtyp; + goto typfnd; + } + } + /* Let wizards wish for traps and furniture. + * Must come after objects check so wizards can still wish for + * trap objects like beartraps. + * Disallow such topology tweaks for WIZKIT startup wishes. + */ wiztrap: - if (wizard && !program_state.wizkit_wishing) { - struct rm *lev; - int trap, x = u.ux, y = u.uy; - - for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) { - struct trap *t; - const char *tname; - - tname = defsyms[trap_to_defsym(trap)].explanation; - if (strncmpi(tname, bp, strlen(tname))) continue; - /* found it; avoid stupid mistakes */ - if ((trap == TRAPDOOR || trap == HOLE) && - !Can_fall_thru(&u.uz)) trap = ROCKTRAP; - if ((t = maketrap(x, y, trap)) != 0) { - trap = t->ttyp; - tname = defsyms[trap_to_defsym(trap)].explanation; - pline("%s%s.", An(tname), - (trap != MAGIC_PORTAL) ? "" : " to nowhere"); - } else - pline("Creation of %s failed.", an(tname)); - return(&zeroobj); - } - - /* furniture and terrain */ - lev = &levl[x][y]; - p = eos(bp); - if (!BSTRCMPI(bp, p-8, "fountain")) { - lev->typ = FOUNTAIN; - level.flags.nfountains++; - if(!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1; - pline("A %sfountain.", lev->blessedftn ? "magic " : ""); - newsym(x, y); - return(&zeroobj); - } - if (!BSTRCMPI(bp, p-6, "throne")) { - lev->typ = THRONE; - pline("A throne."); - newsym(x, y); - return(&zeroobj); - } - if (!BSTRCMPI(bp, p-4, "sink")) { - lev->typ = SINK; - level.flags.nsinks++; - pline("A sink."); - newsym(x, y); - return &zeroobj; - } - /* ("water" matches "potion of water" rather than terrain) */ - if (!BSTRCMPI(bp, p-4, "pool") || !BSTRCMPI(bp, p-4, "moat")) { - lev->typ = !BSTRCMPI(bp, p-4, "pool") ? POOL : MOAT; - del_engr_at(x, y); - pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); - /* Must manually make kelp! */ - water_damage_chain(level.objects[x][y], TRUE); - newsym(x, y); - return &zeroobj; - } - if (!BSTRCMPI(bp, p-4, "lava")) { /* also matches "molten lava" */ - lev->typ = LAVAPOOL; - del_engr_at(x, y); - pline("A pool of molten lava."); - if (!(Levitation || Flying)) (void) lava_effects(); - newsym(x, y); - return &zeroobj; - } - - if (!BSTRCMPI(bp, p-5, "altar")) { - aligntyp al; - - lev->typ = ALTAR; - if(!strncmpi(bp, "chaotic ", 8)) - al = A_CHAOTIC; - else if(!strncmpi(bp, "neutral ", 8)) - al = A_NEUTRAL; - else if(!strncmpi(bp, "lawful ", 7)) - al = A_LAWFUL; - else if(!strncmpi(bp, "unaligned ", 10)) - al = A_NONE; - else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */ - al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1; - lev->altarmask = Align2amask(al); - pline("%s altar.", An(align_str(al))); - newsym(x, y); - return(&zeroobj); - } - - if (!BSTRCMPI(bp, p-5, "grave") || - !BSTRCMPI(bp, p-9, "headstone")) { - make_grave(x, y, (char *)0); - pline("%s.", IS_GRAVE(lev->typ) ? "A grave" : - "Can't place a grave here"); - newsym(x, y); - return(&zeroobj); - } - - if (!BSTRCMPI(bp, p-4, "tree")) { - lev->typ = TREE; - pline("A tree."); - newsym(x, y); - block_point(x, y); - return &zeroobj; - } - - if (!BSTRCMPI(bp, p-4, "bars")) { - lev->typ = IRONBARS; - pline("Iron bars."); - newsym(x, y); - return &zeroobj; - } - } + if (wizard && !program_state.wizkit_wishing) { + struct rm *lev; + int trap, x = u.ux, y = u.uy; + + for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) { + struct trap *t; + const char *tname; + + tname = defsyms[trap_to_defsym(trap)].explanation; + if (strncmpi(tname, bp, strlen(tname))) continue; + /* found it; avoid stupid mistakes */ + if ((trap == TRAPDOOR || trap == HOLE) && + !Can_fall_thru(&u.uz)) trap = ROCKTRAP; + if ((t = maketrap(x, y, trap)) != 0) { + trap = t->ttyp; + tname = defsyms[trap_to_defsym(trap)].explanation; + pline("%s%s.", An(tname), + (trap != MAGIC_PORTAL) ? "" : " to nowhere"); + } else + pline("Creation of %s failed.", an(tname)); + return(&zeroobj); + } + + /* furniture and terrain */ + lev = &levl[x][y]; + p = eos(bp); + if (!BSTRCMPI(bp, p-8, "fountain")) { + lev->typ = FOUNTAIN; + level.flags.nfountains++; + if(!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1; + pline("A %sfountain.", lev->blessedftn ? "magic " : ""); + newsym(x, y); + return(&zeroobj); + } + if (!BSTRCMPI(bp, p-6, "throne")) { + lev->typ = THRONE; + pline("A throne."); + newsym(x, y); + return(&zeroobj); + } + if (!BSTRCMPI(bp, p-4, "sink")) { + lev->typ = SINK; + level.flags.nsinks++; + pline("A sink."); + newsym(x, y); + return &zeroobj; + } + /* ("water" matches "potion of water" rather than terrain) */ + if (!BSTRCMPI(bp, p-4, "pool") || !BSTRCMPI(bp, p-4, "moat")) { + lev->typ = !BSTRCMPI(bp, p-4, "pool") ? POOL : MOAT; + del_engr_at(x, y); + pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); + /* Must manually make kelp! */ + water_damage_chain(level.objects[x][y], TRUE); + newsym(x, y); + return &zeroobj; + } + if (!BSTRCMPI(bp, p-4, "lava")) { /* also matches "molten lava" */ + lev->typ = LAVAPOOL; + del_engr_at(x, y); + pline("A pool of molten lava."); + if (!(Levitation || Flying)) (void) lava_effects(); + newsym(x, y); + return &zeroobj; + } + + if (!BSTRCMPI(bp, p-5, "altar")) { + aligntyp al; + + lev->typ = ALTAR; + if(!strncmpi(bp, "chaotic ", 8)) + al = A_CHAOTIC; + else if(!strncmpi(bp, "neutral ", 8)) + al = A_NEUTRAL; + else if(!strncmpi(bp, "lawful ", 7)) + al = A_LAWFUL; + else if(!strncmpi(bp, "unaligned ", 10)) + al = A_NONE; + else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */ + al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1; + lev->altarmask = Align2amask(al); + pline("%s altar.", An(align_str(al))); + newsym(x, y); + return(&zeroobj); + } + + if (!BSTRCMPI(bp, p-5, "grave") || + !BSTRCMPI(bp, p-9, "headstone")) { + make_grave(x, y, (char *)0); + pline("%s.", IS_GRAVE(lev->typ) ? "A grave" : + "Can't place a grave here"); + newsym(x, y); + return(&zeroobj); + } + + if (!BSTRCMPI(bp, p-4, "tree")) { + lev->typ = TREE; + pline("A tree."); + newsym(x, y); + block_point(x, y); + return &zeroobj; + } + + if (!BSTRCMPI(bp, p-4, "bars")) { + lev->typ = IRONBARS; + pline("Iron bars."); + newsym(x, y); + return &zeroobj; + } + } - if(!oclass) return((struct obj *)0); + if(!oclass) return((struct obj *)0); any: - if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))]; + if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))]; typfnd: - if (typ) oclass = objects[typ].oc_class; - - /* handle some objects that are only allowed in wizard mode */ - if (typ && !wizard) { - switch (typ) { - case AMULET_OF_YENDOR: - typ = FAKE_AMULET_OF_YENDOR; - break; - case CANDELABRUM_OF_INVOCATION: - typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE); - break; - case BELL_OF_OPENING: - typ = BELL; - break; - case SPE_BOOK_OF_THE_DEAD: - typ = SPE_BLANK_PAPER; - break; - case MAGIC_LAMP: - typ = OIL_LAMP; - break; - default: - /* catch any other non-wishable objects (venom) */ - if (objects[typ].oc_nowish) return ((struct obj *)0); - break; - } - } + if (typ) oclass = objects[typ].oc_class; + + /* handle some objects that are only allowed in wizard mode */ + if (typ && !wizard) { + switch (typ) { + case AMULET_OF_YENDOR: + typ = FAKE_AMULET_OF_YENDOR; + break; + case CANDELABRUM_OF_INVOCATION: + typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE); + break; + case BELL_OF_OPENING: + typ = BELL; + break; + case SPE_BOOK_OF_THE_DEAD: + typ = SPE_BLANK_PAPER; + break; + case MAGIC_LAMP: + typ = OIL_LAMP; + break; + default: + /* catch any other non-wishable objects (venom) */ + if (objects[typ].oc_nowish) return ((struct obj *)0); + break; + } + } + if (typ && wizard) { + if (typ == SPE_NOVEL) { + if (name && !lookup_novel(name, (int *)0)) { + pline("There's no novel by that name."); + return ((struct obj *)0); + } + } + } + - /* - * Create the object, then fine-tune it. - */ - otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE); - typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */ - - if (islit && - (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN || - Is_candle(otmp) || typ == POT_OIL)) { - place_object(otmp, u.ux, u.uy); /* make it viable light source */ - begin_burn(otmp, FALSE); - obj_extract_self(otmp); /* now release it for caller's use */ - } + /* + * Create the object, then fine-tune it. + */ + otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE); + typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */ + + if (islit && + (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN || + Is_candle(otmp) || typ == POT_OIL)) { + place_object(otmp, u.ux, u.uy); /* make it viable light source */ + begin_burn(otmp, FALSE); + obj_extract_self(otmp); /* now release it for caller's use */ + } - /* if player specified a reasonable count, maybe honor it */ - if (cnt > 0 && objects[typ].oc_merge && - (wizard || cnt < rnd(6) || - (cnt <= 7 && Is_candle(otmp)) || - (cnt <= 20 && - ((oclass == WEAPON_CLASS && is_ammo(otmp)) - || typ == ROCK || is_missile(otmp))))) - otmp->quan = (long) cnt; - - if (oclass == VENOM_CLASS) otmp->spe = 1; - - if (spesgn == 0) { - spe = otmp->spe; - } else if (wizard) { - ; /* no alteration to spe */ - } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS || - is_weptool(otmp) || - (oclass==RING_CLASS && objects[typ].oc_charged)) { - if(spe > rnd(5) && spe > otmp->spe) spe = 0; - if(spe > 2 && Luck < 0) spesgn = -1; - } else { - if (oclass == WAND_CLASS) { - if (spe > 1 && spesgn == -1) spe = 1; - } else { - if (spe > 0 && spesgn == -1) spe = 0; - } - if (spe > otmp->spe) spe = otmp->spe; - } + /* if player specified a reasonable count, maybe honor it */ + if (cnt > 0 && objects[typ].oc_merge && + (wizard || cnt < rnd(6) || + (cnt <= 7 && Is_candle(otmp)) || + (cnt <= 20 && + ((oclass == WEAPON_CLASS && is_ammo(otmp)) + || typ == ROCK || is_missile(otmp))))) + otmp->quan = (long) cnt; + + if (oclass == VENOM_CLASS) otmp->spe = 1; + + if (spesgn == 0) { + spe = otmp->spe; + } else if (wizard) { + ; /* no alteration to spe */ + } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS || + is_weptool(otmp) || + (oclass==RING_CLASS && objects[typ].oc_charged)) { + if(spe > rnd(5) && spe > otmp->spe) spe = 0; + if(spe > 2 && Luck < 0) spesgn = -1; + } else { + if (oclass == WAND_CLASS) { + if (spe > 1 && spesgn == -1) spe = 1; + } else { + if (spe > 0 && spesgn == -1) spe = 0; + } + if (spe > otmp->spe) spe = otmp->spe; + } - if (spesgn == -1) spe = -spe; - - /* set otmp->spe. This may, or may not, use spe... */ - switch (typ) { - case TIN: if (contents==EMPTY) { - otmp->corpsenm = NON_PM; - otmp->spe = 0; - } else if (contents==SPINACH) { - otmp->corpsenm = NON_PM; - otmp->spe = 1; - } - break; - case SLIME_MOLD: otmp->spe = ftype; - /* Fall through */ - case SKELETON_KEY: case CHEST: case LARGE_BOX: - case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE: - /* otmp->cobj already done in mksobj() */ - break; + if (spesgn == -1) spe = -spe; + + /* set otmp->spe. This may, or may not, use spe... */ + switch (typ) { + case TIN: if (contents==EMPTY) { + otmp->corpsenm = NON_PM; + otmp->spe = 0; + } else if (contents==SPINACH) { + otmp->corpsenm = NON_PM; + otmp->spe = 1; + } + break; + case SLIME_MOLD: otmp->spe = ftype; + /* Fall through */ + case SKELETON_KEY: case CHEST: case LARGE_BOX: + case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE: + /* otmp->cobj already done in mksobj() */ + break; #ifdef MAIL - case SCR_MAIL: otmp->spe = 1; break; + case SCR_MAIL: otmp->spe = 1; break; #endif - case WAN_WISHING: - if (!wizard) { - otmp->spe = (rn2(10) ? -1 : 0); - break; - } - /* fall through, if wizard */ - default: otmp->spe = spe; - } + case WAN_WISHING: + if (!wizard) { + otmp->spe = (rn2(10) ? -1 : 0); + break; + } + /* fall through, if wizard */ + default: otmp->spe = spe; + } - /* set otmp->corpsenm or dragon scale [mail] */ - if (mntmp >= LOW_PM) { - if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM; - - switch (typ) { - case TIN: - otmp->spe = 0; /* No spinach */ - if (dead_species(mntmp, FALSE)) { - otmp->corpsenm = NON_PM; /* it's empty */ - } else if (!(mons[mntmp].geno & G_UNIQ) && - !(mvitals[mntmp].mvflags & G_NOCORPSE) && - mons[mntmp].cnutrit != 0) { - otmp->corpsenm = mntmp; - } - break; - case CORPSE: - if (!(mons[mntmp].geno & G_UNIQ) && - !(mvitals[mntmp].mvflags & G_NOCORPSE)) { - if (mons[mntmp].msound == MS_GUARDIAN) - mntmp = genus(mntmp,1); - set_corpsenm(otmp, mntmp); - } - break; - case FIGURINE: - if (!(mons[mntmp].geno & G_UNIQ) - && !is_human(&mons[mntmp]) + /* set otmp->corpsenm or dragon scale [mail] */ + if (mntmp >= LOW_PM) { + if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM; + + switch (typ) { + case TIN: + otmp->spe = 0; /* No spinach */ + if (dead_species(mntmp, FALSE)) { + otmp->corpsenm = NON_PM; /* it's empty */ + } else if (!(mons[mntmp].geno & G_UNIQ) && + !(mvitals[mntmp].mvflags & G_NOCORPSE) && + mons[mntmp].cnutrit != 0) { + otmp->corpsenm = mntmp; + } + break; + case CORPSE: + if (!(mons[mntmp].geno & G_UNIQ) && + !(mvitals[mntmp].mvflags & G_NOCORPSE)) { + if (mons[mntmp].msound == MS_GUARDIAN) + mntmp = genus(mntmp,1); + set_corpsenm(otmp, mntmp); + } + break; + case FIGURINE: + if (!(mons[mntmp].geno & G_UNIQ) + && !is_human(&mons[mntmp]) #ifdef MAIL - && mntmp != PM_MAIL_DAEMON + && mntmp != PM_MAIL_DAEMON #endif - ) - otmp->corpsenm = mntmp; - break; - case EGG: - mntmp = can_be_hatched(mntmp); - /* this also sets hatch timer if appropriate */ - set_corpsenm(otmp, mntmp); - break; - case STATUE: otmp->corpsenm = mntmp; - if (Has_contents(otmp) && verysmall(&mons[mntmp])) - delete_contents(otmp); /* no spellbook */ - otmp->spe = ishistoric ? STATUE_HISTORIC : 0; - break; - case SCALE_MAIL: - /* Dragon mail - depends on the order of objects */ - /* & dragons. */ - if (mntmp >= PM_GRAY_DRAGON && - mntmp <= PM_YELLOW_DRAGON) - otmp->otyp = GRAY_DRAGON_SCALE_MAIL + - mntmp - PM_GRAY_DRAGON; - break; - } - } - - /* set blessed/cursed -- setting the fields directly is safe - * since weight() is called below and addinv() will take care - * of luck */ - if (iscursed) { - curse(otmp); - } else if (uncursed) { - otmp->blessed = 0; - otmp->cursed = (Luck < 0 && !wizard); - } else if (blessed) { - otmp->blessed = (Luck >= 0 || wizard); - otmp->cursed = (Luck < 0 && !wizard); - } else if (spesgn < 0) { - curse(otmp); - } + ) + otmp->corpsenm = mntmp; + break; + case EGG: + mntmp = can_be_hatched(mntmp); + /* this also sets hatch timer if appropriate */ + set_corpsenm(otmp, mntmp); + break; + case STATUE: otmp->corpsenm = mntmp; + if (Has_contents(otmp) && verysmall(&mons[mntmp])) + delete_contents(otmp); /* no spellbook */ + otmp->spe = ishistoric ? STATUE_HISTORIC : 0; + break; + case SCALE_MAIL: + /* Dragon mail - depends on the order of objects */ + /* & dragons. */ + if (mntmp >= PM_GRAY_DRAGON && + mntmp <= PM_YELLOW_DRAGON) + otmp->otyp = GRAY_DRAGON_SCALE_MAIL + + mntmp - PM_GRAY_DRAGON; + break; + } + } - /* set eroded */ - if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) { - if (eroded && (is_flammable(otmp) || is_rustprone(otmp))) - otmp->oeroded = eroded; - if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp))) - otmp->oeroded2 = eroded2; + /* set blessed/cursed -- setting the fields directly is safe + * since weight() is called below and addinv() will take care + * of luck */ + if (iscursed) { + curse(otmp); + } else if (uncursed) { + otmp->blessed = 0; + otmp->cursed = (Luck < 0 && !wizard); + } else if (blessed) { + otmp->blessed = (Luck >= 0 || wizard); + otmp->cursed = (Luck < 0 && !wizard); + } else if (spesgn < 0) { + curse(otmp); + } - /* set erodeproof */ - if (erodeproof && !eroded && !eroded2) - otmp->oerodeproof = (Luck >= 0 || wizard); - } + /* set eroded */ + if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) { + if (eroded && (is_flammable(otmp) || is_rustprone(otmp))) + otmp->oeroded = eroded; + if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp))) + otmp->oeroded2 = eroded2; - /* set otmp->recharged */ - if (oclass == WAND_CLASS) { - /* prevent wishing abuse */ - if (otmp->otyp == WAN_WISHING && !wizard) rechrg = 1; - otmp->recharged = (unsigned)rechrg; - } + /* set erodeproof */ + if (erodeproof && !eroded && !eroded2) + otmp->oerodeproof = (Luck >= 0 || wizard); + } - /* set poisoned */ - if (ispoisoned) { - if (is_poisonable(otmp)) - otmp->opoisoned = (Luck >= 0); - else if (oclass == FOOD_CLASS) - /* try to taint by making it as old as possible */ - otmp->age = 1L; - } - /* and [un]trapped */ - if (trapped) { - if (Is_box(otmp) || typ == TIN) - otmp->otrapped = (trapped == 1); - } + /* set otmp->recharged */ + if (oclass == WAND_CLASS) { + /* prevent wishing abuse */ + if (otmp->otyp == WAN_WISHING && !wizard) rechrg = 1; + otmp->recharged = (unsigned)rechrg; + } - if (isgreased) otmp->greased = 1; + /* set poisoned */ + if (ispoisoned) { + if (is_poisonable(otmp)) + otmp->opoisoned = (Luck >= 0); + else if (oclass == FOOD_CLASS) + /* try to taint by making it as old as possible */ + otmp->age = 1L; + } + /* and [un]trapped */ + if (trapped) { + if (Is_box(otmp) || typ == TIN) + otmp->otrapped = (trapped == 1); + } - if (isdiluted && otmp->oclass == POTION_CLASS && - otmp->otyp != POT_WATER) - otmp->odiluted = 1; + if (isgreased) otmp->greased = 1; - /* set tin variety */ - if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard)) - set_tin_variety(otmp, tvariety); + if (isdiluted && otmp->oclass == POTION_CLASS && + otmp->otyp != POT_WATER) + otmp->odiluted = 1; - if (name) { - const char *aname; - short objtyp; + /* set tin variety */ + if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard)) + set_tin_variety(otmp, tvariety); - /* an artifact name might need capitalization fixing */ - aname = artifact_name(name, &objtyp); - if (aname && objtyp == otmp->otyp) name = aname; + if (name) { + const char *aname; + short objtyp; - /* 3.6.0 tribute - fix up novel */ - if (otmp->otyp == SPE_NOVEL) { - int novidx = 0; - const char *novelname; + /* an artifact name might need capitalization fixing */ + aname = artifact_name(name, &objtyp); + if (aname && objtyp == otmp->otyp) name = aname; - novelname = lookup_novel(name, &novidx); - if (novelname) { - otmp->novelidx = novidx; - name = novelname; - } - } ++ /* 3.6.0 tribute - fix up novel */ ++ if (otmp->otyp == SPE_NOVEL) { ++ int novidx = 0; ++ const char *novelname; + - otmp = oname(otmp, name); - if (otmp->oartifact) { - otmp->quan = 1L; - u.uconduct.wisharti++; - } ++ novelname = lookup_novel(name, &novidx); ++ if (novelname) { ++ otmp->novelidx = novidx; ++ name = novelname; ++ } + } + - /* more wishing abuse: don't allow wishing for certain artifacts */ - /* and make them pay; charge them for the wish anyway! */ - if ((is_quest_artifact(otmp) || - (otmp->oartifact && rn2(nartifact_exist()) > 1)) && - !wizard) { - artifact_exists(otmp, safe_oname(otmp), FALSE); - obfree(otmp, (struct obj *) 0); - otmp = &zeroobj; - pline("For a moment, you feel %s in your %s, but it disappears!", - something, - makeplural(body_part(HAND))); - } + otmp = oname(otmp, name); + if (otmp->oartifact) { + otmp->quan = 1L; + u.uconduct.wisharti++; /* KMH, conduct */ + } + } - if (halfeaten && otmp->oclass == FOOD_CLASS) { - if (otmp->otyp == CORPSE) - otmp->oeaten = mons[otmp->corpsenm].cnutrit; - else otmp->oeaten = objects[otmp->otyp].oc_nutrition; - /* (do this adjustment before setting up object's weight) */ - consume_oeaten(otmp, 1); - } - otmp->owt = weight(otmp); - if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160; + /* more wishing abuse: don't allow wishing for certain artifacts */ + /* and make them pay; charge them for the wish anyway! */ + if ((is_quest_artifact(otmp) || + (otmp->oartifact && rn2(nartifact_exist()) > 1)) && + !wizard) { + artifact_exists(otmp, safe_oname(otmp), FALSE); + obfree(otmp, (struct obj *) 0); + otmp = &zeroobj; + pline("For a moment, you feel %s in your %s, but it disappears!", + something, + makeplural(body_part(HAND))); + } + + if (halfeaten && otmp->oclass == FOOD_CLASS) { + if (otmp->otyp == CORPSE) + otmp->oeaten = mons[otmp->corpsenm].cnutrit; + else otmp->oeaten = objects[otmp->otyp].oc_nutrition; + /* (do this adjustment before setting up object's weight) */ + consume_oeaten(otmp, 1); + } + otmp->owt = weight(otmp); + if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160; - return(otmp); + return(otmp); } int diff --cc win/share/objects.txt index 09f3747f3,5c9a69b73..257a277e6 --- a/win/share/objects.txt +++ b/win/share/objects.txt @@@ -6930,26 -7006,7 +7006,25 @@@ P = (108, 145, 182 MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 368 (papyrus / Book of the Dead) +# tile 363 (paperback / novel) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMEEEEMMMMMMMM + MMMMEEEEEEMMMMMM + MMMEEEEEEEEEEMMM + MMMEEEEEEEEEBMMM + MMEEEEEEEEEEOAMM + MMEEEEEEEEEBOAAM + MEEEEEEEEEEOEAMM + MEEEEEEEEEBOAAMM + MEOOEEEEEEOEAMMM + MMEEOOOEEBOAAMMM + MMMMEEEOOOEAMMMM + MMMMMMMEEEAAMMMM + MMMMMMMMMMMMMMMM +} - # tile 364 (papyrus / Book of the Dead) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM