1 /* SCCS Id: @(#)objnam.c 3.4 2003/12/04 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
8 #define PREFIX 80 /* (56) */
12 STATIC_DCL char *FDECL(strprepend,(char *,const char *));
14 static boolean FDECL(wishymatch, (const char *,const char *,BOOLEAN_P));
16 static char *NDECL(nextobuf);
17 static void FDECL(add_erosion_words, (struct obj *, char *));
24 /* true for gems/rocks that should have " stone" appended to their names */
25 #define GemStone(typ) (typ == FLINT || \
26 (objects[typ].oc_material == GEMSTONE && \
27 (typ != DILITHIUM_CRYSTAL && typ != RUBY && \
28 typ != DIAMOND && typ != SAPPHIRE && \
29 typ != BLACK_OPAL && \
30 typ != EMERALD && typ != OPAL)))
34 STATIC_DCL struct Jitem Japanese_items[];
38 STATIC_OVL struct Jitem Japanese_items[] = {
39 { SHORT_SWORD, "wakizashi" },
40 { BROADSWORD, "ninja-to" },
41 { FLAIL, "nunchaku" },
42 { GLAIVE, "naginata" },
43 { LOCK_PICK, "osaku" },
44 { WOODEN_HARP, "koto" },
46 { PLATE_MAIL, "tanko" },
48 { LEATHER_GLOVES, "yugake" },
49 { FOOD_RATION, "gunyoki" },
50 { POT_BOOZE, "sake" },
56 STATIC_DCL const char *FDECL(Japanese_item_name,(int i));
63 register const char *pref;
65 register int i = (int)strlen(pref);
68 impossible("PREFIX too short (for %d).", i);
72 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
79 /* manage a pool of BUFSZ buffers, so callers don't have to */
83 static char NEARDATA bufs[NUMOBUF][BUFSZ];
84 static int bufidx = 0;
86 bufidx = (bufidx + 1) % NUMOBUF;
94 char *buf = nextobuf();
95 register struct objclass *ocl = &objects[otyp];
96 register const char *actualn = OBJ_NAME(*ocl);
97 register const char *dn = OBJ_DESCR(*ocl);
98 register const char *un = ocl->oc_uname;
99 register int nn = ocl->oc_name_known;
101 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
102 actualn = Japanese_item_name(otyp);
103 switch(ocl->oc_class) {
108 Strcpy(buf, "potion");
111 Strcpy(buf, "scroll");
117 Strcpy(buf, "spellbook");
126 Strcpy(buf,"amulet");
128 Sprintf(eos(buf)," called %s",un);
130 Sprintf(eos(buf)," (%s)",dn);
134 Strcpy(buf, actualn);
136 Strcat(buf, " stone");
138 Sprintf(eos(buf), " called %s", un);
140 Sprintf(eos(buf), " (%s)", dn);
142 Strcpy(buf, dn ? dn : actualn);
143 if(ocl->oc_class == GEM_CLASS)
144 Strcat(buf, (ocl->oc_material == MINERAL) ?
147 Sprintf(eos(buf), " called %s", un);
151 /* here for ring/scroll/potion/wand */
154 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
156 Sprintf(eos(buf), " of %s", actualn);
159 Sprintf(eos(buf), " called %s", un);
161 Sprintf(eos(buf), " (%s)", dn);
165 /* less verbose result than obj_typename(); either the actual name
166 or the description (but not both); user-assigned name is ignored */
168 simple_typename(otyp)
171 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
173 objects[otyp].oc_uname = 0; /* suppress any name given by user */
174 bufp = obj_typename(otyp);
175 objects[otyp].oc_uname = save_uname;
176 if ((pp = strstri(bufp, " (")) != 0)
177 *pp = '\0'; /* strip the appended description */
183 register struct obj *obj;
185 return((boolean)(obj->dknown && obj->known && obj->onamelth &&
186 /* Since there aren't any objects which are both
187 artifacts and unique, the last check is redundant. */
188 obj->oartifact && !objects[obj->otyp].oc_unique));
191 /* Give the name of an object seen at a distance. Unlike xname/doname,
192 * we don't want to set dknown if it's not set already. The kludge used is
193 * to temporarily set Blind so that xname() skips the dknown setting. This
194 * assumes that we don't want to do this too often; if this function becomes
195 * frequently used, it'd probably be better to pass a parameter to xname()
196 * or doname() instead.
199 distant_name(obj, func)
200 register struct obj *obj;
201 char *FDECL((*func), (OBJ_P));
205 long save_Blinded = Blinded;
208 Blinded = save_Blinded;
212 /* convert player specified fruit name into corresponding fruit juice name
213 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
216 boolean juice; /* whether or not to append " juice" to the name */
218 char *buf = nextobuf();
219 const char *fruit_nam = strstri(pl_fruit, " of ");
222 fruit_nam += 4; /* skip past " of " */
224 fruit_nam = pl_fruit; /* use it as is */
226 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
235 register struct obj *obj;
238 register int typ = obj->otyp;
239 register struct objclass *ocl = &objects[typ];
240 register int nn = ocl->oc_name_known;
241 register const char *actualn = OBJ_NAME(*ocl);
242 register const char *dn = OBJ_DESCR(*ocl);
243 register const char *un = ocl->oc_uname;
245 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
246 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
247 actualn = Japanese_item_name(typ);
251 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
252 * This is only required for unique objects since the article
253 * printed for the object is tied to the combination of the two
254 * and printing the wrong article gives away information.
256 if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0;
257 if (!Blind) obj->dknown = TRUE;
258 if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
259 if (obj_is_pname(obj))
261 switch (obj->oclass) {
264 Strcpy(buf, "amulet");
265 else if (typ == AMULET_OF_YENDOR ||
266 typ == FAKE_AMULET_OF_YENDOR)
267 /* each must be identified individually */
268 Strcpy(buf, obj->known ? actualn : dn);
270 Strcpy(buf, actualn);
272 Sprintf(buf,"amulet called %s", un);
274 Sprintf(buf,"%s amulet", dn);
277 if (is_poisonable(obj) && obj->opoisoned)
278 Strcpy(buf, "poisoned ");
282 Strcpy(buf, "pair of ");
285 Strcat(buf, dn ? dn : actualn);
287 Strcat(buf, actualn);
289 Strcat(buf, dn ? dn : actualn);
290 Strcat(buf, " called ");
293 Strcat(buf, dn ? dn : actualn);
294 /* If we use an() here we'd have to remember never to use */
295 /* it whenever calling doname() or xname(). */
297 Sprintf(eos(buf), " of a%s %s",
298 index(vowels,*(mons[obj->corpsenm].mname)) ? "n" : "",
299 mons[obj->corpsenm].mname);
302 /* depends on order of the dragon scales objects */
303 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
304 Sprintf(buf, "set of %s", actualn);
307 if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
309 if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
311 Strcpy(buf, "shield");
314 if(obj->otyp == SHIELD_OF_REFLECTION && !obj->dknown) {
315 Strcpy(buf, "smooth shield");
319 if(nn) Strcat(buf, actualn);
323 else if(is_gloves(obj))
324 Strcat(buf,"gloves");
325 else if(is_cloak(obj))
327 else if(is_helmet(obj))
328 Strcpy(buf,"helmet");
329 else if(is_shield(obj))
330 Strcpy(buf,"shield");
333 Strcat(buf, " called ");
335 } else Strcat(buf, dn);
338 if (typ == SLIME_MOLD) {
339 register struct fruit *f;
341 for(f=ffruit; f; f = f->nextf) {
342 if(f->fid == obj->spe) {
343 Strcpy(buf, f->fname);
347 if (!f) impossible("Bad fruit #%d?", obj->spe);
351 Strcpy(buf, actualn);
352 if (typ == TIN && obj->known) {
354 Strcat(buf, " of spinach");
355 else if (obj->corpsenm == NON_PM)
356 Strcpy(buf, "empty tin");
357 else if (vegetarian(&mons[obj->corpsenm]))
358 Sprintf(eos(buf), " of %s", mons[obj->corpsenm].mname);
360 Sprintf(eos(buf), " of %s meat", mons[obj->corpsenm].mname);
365 Strcpy(buf, actualn);
369 Sprintf(buf, "%s%s of %s%s",
370 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) ? "historic " : "" ,
372 type_is_pname(&mons[obj->corpsenm]) ? "" :
373 (mons[obj->corpsenm].geno & G_UNIQ) ? "the " :
374 (index(vowels,*(mons[obj->corpsenm].mname)) ?
376 mons[obj->corpsenm].mname);
377 else Strcpy(buf, actualn);
380 Sprintf(buf, "%sheavy iron ball",
381 (obj->owt > ocl->oc_weight) ? "very " : "");
384 if (obj->dknown && obj->odiluted)
385 Strcpy(buf, "diluted ");
386 if(nn || un || !obj->dknown) {
387 Strcat(buf, "potion");
388 if(!obj->dknown) break;
391 if (typ == POT_WATER &&
392 obj->bknown && (obj->blessed || obj->cursed)) {
393 Strcat(buf, obj->blessed ? "holy " : "unholy ");
395 Strcat(buf, actualn);
397 Strcat(buf, " called ");
402 Strcat(buf, " potion");
406 Strcpy(buf, "scroll");
407 if(!obj->dknown) break;
410 Strcat(buf, actualn);
412 Strcat(buf, " called ");
414 } else if (ocl->oc_magic) {
415 Strcat(buf, " labeled ");
419 Strcat(buf, " scroll");
426 Sprintf(buf, "wand of %s", actualn);
428 Sprintf(buf, "wand called %s", un);
430 Sprintf(buf, "%s wand", dn);
434 Strcpy(buf, "spellbook");
436 if (typ != SPE_BOOK_OF_THE_DEAD)
437 Strcpy(buf, "spellbook of ");
438 Strcat(buf, actualn);
440 Sprintf(buf, "spellbook called %s", un);
442 Sprintf(buf, "%s spellbook", dn);
448 Sprintf(buf, "ring of %s", actualn);
450 Sprintf(buf, "ring called %s", un);
452 Sprintf(buf, "%s ring", dn);
457 (ocl->oc_material == MINERAL) ? "stone" : "gem";
461 if (un) Sprintf(buf,"%s called %s", rock, un);
462 else Sprintf(buf, "%s %s", dn, rock);
464 Strcpy(buf, actualn);
465 if (GemStone(typ)) Strcat(buf, " stone");
470 Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
472 if (obj->quan != 1L) Strcpy(buf, makeplural(buf));
474 if (obj->onamelth && obj->dknown) {
475 Strcat(buf, " named ");
477 Strcat(buf, ONAME(obj));
480 if (!strncmpi(buf, "the ", 4)) buf += 4;
484 /* xname() output augmented for multishot missile feedback */
490 char *onm = xname(obj);
492 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
493 /* copy xname's result so that we can reuse its return buffer */
495 /* "the Nth arrow"; value will eventually be passed to an() or
496 The(), both of which correctly handle this "the " prefix */
497 Sprintf(onm, "the %d%s %s", m_shot.i, ordin(m_shot.i), tmpbuf);
506 /* used for naming "the unique_item" instead of "a unique_item" */
509 register struct obj *obj;
513 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !obj->known)
514 return TRUE; /* lie */
516 return (boolean)(objects[obj->otyp].oc_unique &&
517 (obj->known || obj->otyp == AMULET_OF_YENDOR));
521 add_erosion_words(obj,prefix)
525 boolean iscrys = (obj->otyp == CRYSKNIFE);
528 if (!is_damageable(obj) && !iscrys) return;
530 /* The only cases where any of these bits do double duty are for
531 * rotted food and diluted potions, which are all not is_damageable().
533 if (obj->oeroded && !iscrys) {
534 switch (obj->oeroded) {
535 case 2: Strcat(prefix, "very "); break;
536 case 3: Strcat(prefix, "thoroughly "); break;
538 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
540 if (obj->oeroded2 && !iscrys) {
541 switch (obj->oeroded2) {
542 case 2: Strcat(prefix, "very "); break;
543 case 3: Strcat(prefix, "thoroughly "); break;
545 Strcat(prefix, is_corrodeable(obj) ? "corroded " :
548 if (obj->rknown && obj->oerodeproof)
551 is_rustprone(obj) ? "rustproof " :
552 is_corrodeable(obj) ? "corrodeproof " : /* "stainless"? */
553 is_flammable(obj) ? "fireproof " : "");
558 register struct obj *obj;
560 boolean ispoisoned = FALSE;
562 char tmpbuf[PREFIX+1];
563 /* when we have to add something at the start of prefix instead of the
564 * end (Strcat is used on the end)
566 register char *bp = xname(obj);
568 /* When using xname, we want "poisoned arrow", and when using
569 * doname, we want "poisoned +0 arrow". This kludge is about the only
570 * way to do it, at least until someone overhauls xname() and doname(),
571 * combining both into one function taking a parameter.
573 /* must check opoisoned--someone can have a weirdly-named fruit */
574 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
580 Sprintf(prefix, "%ld ", obj->quan);
581 else if (obj_is_pname(obj) || the_unique_obj(obj)) {
582 if (!strncmpi(bp, "the ", 4))
584 Strcpy(prefix, "the ");
586 Strcpy(prefix, "a ");
588 #ifdef INVISIBLE_OBJECTS
589 if (obj->oinvis) Strcat(prefix,"invisible ");
593 obj->oclass != COIN_CLASS &&
594 (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
595 || (!obj->cursed && !obj->blessed))) {
596 /* allow 'blessed clear potion' if we don't know it's holy water;
597 * always allow "uncursed potion of water"
600 Strcat(prefix, "cursed ");
601 else if (obj->blessed)
602 Strcat(prefix, "blessed ");
603 else if ((!obj->known || !objects[obj->otyp].oc_charged ||
604 (obj->oclass == ARMOR_CLASS ||
605 obj->oclass == RING_CLASS))
606 /* For most items with charges or +/-, if you know how many
607 * charges are left or what the +/- is, then you must have
608 * totally identified the item, so "uncursed" is unneccesary,
609 * because an identified object not described as "blessed" or
610 * "cursed" must be uncursed.
612 * If the charges or +/- is not known, "uncursed" must be
613 * printed to avoid ambiguity between an item whose curse
614 * status is unknown, and an item known to be uncursed.
617 && obj->otyp != SCR_MAIL
619 && obj->otyp != FAKE_AMULET_OF_YENDOR
620 && obj->otyp != AMULET_OF_YENDOR
621 && !Role_if(PM_PRIEST))
622 Strcat(prefix, "uncursed ");
625 if (obj->greased) Strcat(prefix, "greased ");
627 switch(obj->oclass) {
629 if(obj->owornmask & W_AMUL)
630 Strcat(bp, " (being worn)");
634 Strcat(prefix, "poisoned ");
636 add_erosion_words(obj, prefix);
638 Strcat(prefix, sitoa(obj->spe));
643 if(obj->owornmask & W_ARMOR)
644 Strcat(bp, (obj == uskin) ? " (embedded in your skin)" :
648 /* weptools already get this done when we go to the +n code */
649 if (!is_weptool(obj))
650 add_erosion_words(obj, prefix);
651 if(obj->owornmask & (W_TOOL /* blindfold */
656 Strcat(bp, " (being worn)");
659 if (obj->otyp == LEASH && obj->leashmon != 0) {
660 Strcat(bp, " (in use)");
665 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
667 Strcpy(tmpbuf, "no");
669 Sprintf(tmpbuf, "%d", obj->spe);
670 Sprintf(eos(bp), " (%s candle%s%s)",
671 tmpbuf, plur(obj->spe),
672 !obj->lamplit ? " attached" : ", lit");
674 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
675 obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
676 if (Is_candle(obj) &&
677 obj->age < 20L * (long)objects[obj->otyp].oc_cost)
678 Strcat(prefix, "partly used ");
680 Strcat(bp, " (lit)");
683 if(objects[obj->otyp].oc_charged)
687 add_erosion_words(obj, prefix);
690 Sprintf(eos(bp), " (%d:%d)", (int)obj->recharged, obj->spe);
693 if (obj->otyp == POT_OIL && obj->lamplit)
694 Strcat(bp, " (lit)");
697 add_erosion_words(obj, prefix);
699 if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
700 if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
701 if(obj->owornmask & W_RING) {
702 Strcat(bp, body_part(HAND));
705 if(obj->known && objects[obj->otyp].oc_charged) {
706 Strcat(prefix, sitoa(obj->spe));
712 Strcat(prefix, "partly eaten ");
713 if (obj->otyp == CORPSE) {
714 if (mons[obj->corpsenm].geno & G_UNIQ) {
715 Sprintf(prefix, "%s%s ",
716 (type_is_pname(&mons[obj->corpsenm]) ?
718 s_suffix(mons[obj->corpsenm].mname));
719 if (obj->oeaten) Strcat(prefix, "partly eaten ");
721 Strcat(prefix, mons[obj->corpsenm].mname);
724 } else if (obj->otyp == EGG) {
725 #if 0 /* corpses don't tell if they're stale either */
726 if (obj->known && stale_egg(obj))
727 Strcat(prefix, "stale ");
729 if (obj->corpsenm >= LOW_PM &&
731 mvitals[obj->corpsenm].mvflags & MV_KNOWS_EGG)) {
732 Strcat(prefix, mons[obj->corpsenm].mname);
735 Strcat(bp, " (laid by you)");
738 if (obj->otyp == MEAT_RING) goto ring;
742 add_erosion_words(obj, prefix);
743 if(obj->owornmask & W_BALL)
744 Strcat(bp, " (chained to you)");
748 if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
749 if (obj->quan != 1L) {
750 Strcat(bp, " (wielded)");
752 const char *hand_s = body_part(HAND);
754 if (bimanual(obj)) hand_s = makeplural(hand_s);
755 Sprintf(eos(bp), " (weapon in %s)", hand_s);
758 if(obj->owornmask & W_SWAPWEP) {
760 Sprintf(eos(bp), " (wielded in other %s)",
763 Strcat(bp, " (alternate weapon; not wielded)");
765 if(obj->owornmask & W_QUIVER) Strcat(bp, " (in quiver)");
768 long quotedprice = unpaid_cost(obj);
769 struct monst *shkp = (struct monst *)0;
771 if (Has_contents(obj) &&
772 get_obj_location(obj, &ox, &oy, BURIED_TOO|CONTAINED_TOO) &&
773 costly_spot(ox, oy) &&
774 (shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))))
775 quotedprice += contained_cost(obj, shkp, 0L, FALSE, TRUE);
776 Sprintf(eos(bp), " (unpaid, %ld %s)",
777 quotedprice, currency(quotedprice));
779 if (!strncmp(prefix, "a ", 2) &&
780 index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
781 && (*(prefix+2) || (strncmp(bp, "uranium", 7)
782 && strncmp(bp, "unicorn", 7)
783 && strncmp(bp, "eucalyptus", 10)))) {
784 Strcpy(tmpbuf, prefix);
785 Strcpy(prefix, "an ");
786 Strcpy(prefix+3, tmpbuf+2);
788 bp = strprepend(bp, prefix);
795 /* used from invent.c */
797 not_fully_identified(otmp)
798 register struct obj *otmp;
801 /* gold doesn't have any interesting attributes [yet?] */
802 if (otmp->oclass == COIN_CLASS) return FALSE; /* always fully ID'd */
804 /* check fundamental ID hallmarks first */
805 if (!otmp->known || !otmp->dknown ||
807 (!otmp->bknown && otmp->otyp != SCR_MAIL) ||
811 !objects[otmp->otyp].oc_name_known) /* ?redundant? */
813 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
815 /* otmp->rknown is the only item of interest if we reach here */
817 * Note: if a revision ever allows scrolls to become fireproof or
818 * rings to become shockproof, this checking will need to be revised.
819 * `rknown' ID only matters if xname() will provide the info about it.
821 if (otmp->rknown || (otmp->oclass != ARMOR_CLASS &&
822 otmp->oclass != WEAPON_CLASS &&
823 !is_weptool(otmp) && /* (redunant) */
824 otmp->oclass != BALL_CLASS)) /* (useless) */
826 else /* lack of `rknown' only matters for vulnerable objects */
827 return (boolean)(is_rustprone(otmp) ||
828 is_corrodeable(otmp) ||
833 corpse_xname(otmp, ignore_oquan)
835 boolean ignore_oquan; /* to force singular */
837 char *nambuf = nextobuf();
839 Sprintf(nambuf, "%s corpse", mons[otmp->corpsenm].mname);
841 if (ignore_oquan || otmp->quan < 2)
844 return makeplural(nambuf);
847 /* xname, unless it's a corpse, then corpse_xname(obj, FALSE) */
852 if (obj->otyp == CORPSE)
853 return corpse_xname(obj, FALSE);
857 /* treat an object as fully ID'd when it might be used as reason for death */
863 unsigned save_ocknown;
864 char *buf, *save_ocuname;
866 /* remember original settings for core of the object;
867 oname and oattached extensions don't matter here--since they
868 aren't modified they don't need to be saved and restored */
870 /* killer name should be more specific than general xname; however, exact
871 info like blessed/cursed and rustproof makes things be too verbose */
872 obj->known = obj->dknown = 1;
873 obj->bknown = obj->rknown = obj->greased = 0;
874 /* if character is a priest[ess], bknown will get toggled back on */
875 obj->blessed = obj->cursed = 0;
876 /* "killed by poisoned <obj>" would be misleading when poison is
877 not the cause of death and "poisoned by poisoned <obj>" would
878 be redundant when it is, so suppress "poisoned" prefix */
880 /* strip user-supplied name; artifacts keep theirs */
881 if (!obj->oartifact) obj->onamelth = 0;
882 /* temporarily identify the type of object */
883 save_ocknown = objects[obj->otyp].oc_name_known;
884 objects[obj->otyp].oc_name_known = 1;
885 save_ocuname = objects[obj->otyp].oc_uname;
886 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
889 if (obj->quan == 1L) buf = obj_is_pname(obj) ? the(buf) : an(buf);
891 objects[obj->otyp].oc_name_known = save_ocknown;
892 objects[obj->otyp].oc_uname = save_ocuname;
893 *obj = save_obj; /* restore object's core settings */
899 * Used if only one of a collection of objects is named (e.g. in eat.c).
903 register struct obj *otmp;
904 char *FDECL((*func), (OBJ_P));
909 /* Note: using xname for corpses will not give the monster type */
910 if (otmp->otyp == CORPSE && func == xname)
911 return corpse_xname(otmp, TRUE);
913 savequan = otmp->quan;
916 otmp->quan = savequan;
922 register const char *str;
924 char *buf = nextobuf();
928 if (strncmpi(str, "the ", 4) &&
929 strcmp(str, "molten lava") &&
930 strcmp(str, "iron bars") &&
931 strcmp(str, "ice")) {
932 if (index(vowels, *str) &&
933 strncmp(str, "one-", 4) &&
934 strncmp(str, "useful", 6) &&
935 strncmp(str, "unicorn", 7) &&
936 strncmp(str, "uranium", 7) &&
937 strncmp(str, "eucalyptus", 10))
951 register char *tmp = an(str);
957 * Prepend "the" if necessary; assumes str is a subject derived from xname.
958 * Use type_is_pname() for monster names, not the(). the() is idempotent.
964 char *buf = nextobuf();
965 boolean insert_the = FALSE;
967 if (!strncmpi(str, "the ", 4)) {
969 Strcpy(&buf[1], str+1);
971 } else if (*str < 'A' || *str > 'Z') {
972 /* not a proper name, needs an article */
975 /* Probably a proper name, might not need an article */
976 register char *tmp, *named, *called;
979 /* some objects have capitalized adjectives in their names */
980 if(((tmp = rindex(str, ' ')) || (tmp = rindex(str, '-'))) &&
981 (tmp[1] < 'A' || tmp[1] > 'Z'))
983 else if (tmp && index(str, ' ') < tmp) { /* has spaces */
984 /* it needs an article if the name contains "of" */
985 tmp = strstri(str, " of ");
986 named = strstri(str, " named ");
987 called = strstri(str, " called ");
988 if (called && (!named || called < named)) named = called;
990 if (tmp && (!named || tmp < named)) /* found an "of" */
992 /* stupid special case: lacks "of" but needs "the" */
993 else if (!named && (l = strlen(str)) >= 31 &&
994 !strcmp(&str[l - 31], "Platinum Yendorian Express Card"))
1011 register char *tmp = the(str);
1016 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
1019 register struct obj *otmp;
1020 register const char *verb;
1022 register char *bp = cxname(otmp);
1023 char prefix[PREFIX];
1025 if(otmp->quan != 1L) {
1026 Sprintf(prefix, "%ld ", otmp->quan);
1027 bp = strprepend(bp, prefix);
1032 Strcat(bp, otense(otmp, verb));
1037 /* like aobjnam, but prepend "The", not count, and use xname */
1040 register struct obj *otmp;
1041 register const char *verb;
1043 char *bp = The(xname(otmp));
1047 Strcat(bp, otense(otmp, verb));
1052 /* return form of the verb (input plural) if xname(otmp) were the subject */
1055 register struct obj *otmp;
1056 register const char *verb;
1061 * verb is given in plural (without trailing s). Return as input
1062 * if the result of xname(otmp) would be plural. Don't bother
1063 * recomputing xname(otmp) at this time.
1065 if (!is_plural(otmp))
1066 return vtense((char *)0, verb);
1073 /* various singular words that vtense would otherwise categorize as plural */
1074 static const char * const special_subjs[] = {
1076 "manes", /* this one is ambiguous */
1086 /* return form of the verb (input plural) for present tense 3rd person subj */
1089 register const char *subj;
1090 register const char *verb;
1092 char *buf = nextobuf();
1094 const char *sp, *spot;
1095 const char * const *spec;
1098 * verb is given in plural (without trailing s). Return as input
1099 * if subj appears to be plural. Add special cases as necessary.
1100 * Many hard cases can already be handled by using otense() instead.
1101 * If this gets much bigger, consider decomposing makeplural.
1102 * Note: monster names are not expected here (except before corpse).
1104 * special case: allow null sobj to get the singular 3rd person
1105 * present tense form so we don't duplicate this code elsewhere.
1108 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
1110 spot = (const char *)0;
1111 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
1112 if (!strncmp(sp, " of ", 4) ||
1113 !strncmp(sp, " from ", 6) ||
1114 !strncmp(sp, " called ", 8) ||
1115 !strncmp(sp, " named ", 7) ||
1116 !strncmp(sp, " labeled ", 9)) {
1117 if (sp != subj) spot = sp - 1;
1121 len = (int) strlen(subj);
1122 if (!spot) spot = subj + len - 1;
1125 * plural: anything that ends in 's', but not '*us' or '*ss'.
1126 * Guess at a few other special cases that makeplural creates.
1128 if ((*spot == 's' && spot != subj &&
1129 (*(spot-1) != 'u' && *(spot-1) != 's')) ||
1130 ((spot - subj) >= 4 && !strncmp(spot-3, "eeth", 4)) ||
1131 ((spot - subj) >= 3 && !strncmp(spot-3, "feet", 4)) ||
1132 ((spot - subj) >= 2 && !strncmp(spot-1, "ia", 2)) ||
1133 ((spot - subj) >= 2 && !strncmp(spot-1, "ae", 2))) {
1134 /* check for special cases to avoid false matches */
1135 len = (int)(spot - subj) + 1;
1136 for (spec = special_subjs; *spec; spec++) {
1137 ltmp = strlen(*spec);
1138 if (len == ltmp && !strncmpi(*spec, subj, len)) goto sing;
1139 /* also check for <prefix><space><special_subj>
1140 to catch things like "the invisible erinys" */
1141 if (len > ltmp && *(spot - ltmp) == ' ' &&
1142 !strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
1145 return strcpy(buf, verb);
1148 * 3rd person plural doesn't end in telltale 's';
1149 * 2nd person singular behaves as if plural.
1151 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
1152 return strcpy(buf, verb);
1157 spot = verb + len - 1;
1159 if (!strcmp(verb, "are"))
1161 else if (!strcmp(verb, "have"))
1163 else if (index("zxs", *spot) ||
1164 (len >= 2 && *spot=='h' && index("cs", *(spot-1))) ||
1165 (len == 2 && *spot == 'o')) {
1166 /* Ends in z, x, s, ch, sh; add an "es" */
1169 } else if (*spot == 'y' && (!index(vowels, *(spot-1)))) {
1170 /* like "y" case in makeplural */
1172 Strcpy(buf + len - 1, "ies");
1181 /* capitalized variant of doname() */
1184 register struct obj *obj;
1186 register char *s = doname(obj);
1192 /* returns "your xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
1197 char *outbuf = nextobuf();
1198 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
1199 int space_left = BUFSZ - strlen(s) - sizeof " ";
1201 return strncat(strcat(s, " "), cxname(obj), space_left);
1204 /* capitalized variant of yname() */
1209 char *s = yname(obj);
1215 /* returns "your simple_typename(obj->otyp)"
1216 * or "Foobar's simple_typename(obj->otyp)"
1217 * or "the simple_typename(obj-otyp)"
1223 char *outbuf = nextobuf();
1224 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
1225 int space_left = BUFSZ - strlen(s) - sizeof " ";
1227 return strncat(strcat(s, " "), simple_typename(obj->otyp), space_left);
1230 /* capitalized variant of ysimple_name() */
1235 char *s = ysimple_name(obj);
1241 static const char *wrp[] = {
1242 "wand", "ring", "potion", "scroll", "gem", "amulet",
1243 "spellbook", "spell book",
1244 /* for non-specific wishes */
1245 "weapon", "armor", "armour", "tool", "food", "comestible",
1247 static const char wrpsym[] = {
1248 WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, GEM_CLASS,
1249 AMULET_CLASS, SPBOOK_CLASS, SPBOOK_CLASS,
1250 WEAPON_CLASS, ARMOR_CLASS, ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
1257 /* Plural routine; chiefly used for user-defined fruits. We have to try to
1258 * account for everything reasonable the player has; something unreasonable
1259 * can still break the code. However, it's still a lot more accurate than
1260 * "just add an s at the end", which Rogue uses...
1262 * Also used for plural monster names ("Wiped out all homunculi.")
1265 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
1271 /* Note: cannot use strcmpi here -- it'd give MATZot, CAVEMeN,... */
1272 register char *spot;
1273 char *str = nextobuf();
1274 const char *excess = (char *)0;
1277 while (*oldstr==' ') oldstr++;
1278 if (!oldstr || !*oldstr) {
1279 impossible("plural of null?");
1283 Strcpy(str, oldstr);
1286 * Skip changing "pair of" to "pairs of". According to Webster, usual
1287 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
1288 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
1289 * refer to pairs of humans in this game so just skip to the bottom.
1291 if (!strncmp(str, "pair of ", 8))
1294 /* Search for common compounds, ex. lump of royal jelly */
1295 for(spot=str; *spot; spot++) {
1296 if (!strncmp(spot, " of ", 4)
1297 || !strncmp(spot, " labeled ", 9)
1298 || !strncmp(spot, " called ", 8)
1299 || !strncmp(spot, " named ", 7)
1300 || !strcmp(spot, " above") /* lurkers above */
1301 || !strncmp(spot, " versus ", 8)
1302 || !strncmp(spot, " from ", 6)
1303 || !strncmp(spot, " in ", 4)
1304 || !strncmp(spot, " on ", 4)
1305 || !strncmp(spot, " a la ", 6)
1306 || !strncmp(spot, " with", 5) /* " with "? */
1307 || !strncmp(spot, " de ", 4)
1308 || !strncmp(spot, " d'", 3)
1309 || !strncmp(spot, " du ", 4)) {
1310 excess = oldstr + (int) (spot - str);
1316 while (*spot==' ') spot--; /* Strip blanks from end */
1318 /* Now spot is the last character of the string */
1322 /* Single letters */
1323 if (len==1 || !letter(*spot)) {
1324 Strcpy(spot+1, "'s");
1328 /* Same singular and plural; mostly Japanese words except for "manes" */
1329 if ((len == 2 && !strcmp(str, "ya")) ||
1330 (len >= 2 && !strcmp(spot-1, "ai")) || /* samurai, Uruk-hai */
1331 (len >= 3 && !strcmp(spot-2, " ya")) ||
1333 (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") ||
1334 !strcmp(spot-3, "deer") || !strcmp(spot-3, "yaki"))) ||
1335 (len >= 5 && (!strcmp(spot-4, "sheep") ||
1336 !strcmp(spot-4, "ninja") ||
1337 !strcmp(spot-4, "ronin") ||
1338 !strcmp(spot-4, "shito") ||
1339 !strcmp(spot-7, "shuriken") ||
1340 !strcmp(spot-4, "tengu") ||
1341 !strcmp(spot-4, "manes"))) ||
1342 (len >= 6 && !strcmp(spot-5, "ki-rin")) ||
1343 (len >= 7 && !strcmp(spot-6, "gunyoki")))
1346 /* man/men ("Wiped out all cavemen.") */
1347 if (len >= 3 && !strcmp(spot-2, "man") &&
1348 (len<6 || strcmp(spot-5, "shaman")) &&
1349 (len<5 || strcmp(spot-4, "human"))) {
1355 if (len >= 5 && !strcmp(spot-4, "tooth")) {
1356 Strcpy(spot-3, "eeth");
1360 /* knife/knives, etc... */
1361 if (!strcmp(spot-1, "fe")) {
1362 Strcpy(spot-1, "ves");
1364 } else if (*spot == 'f') {
1365 if (index("lr", *(spot-1)) || index(vowels, *(spot-1))) {
1366 Strcpy(spot, "ves");
1368 } else if (len >= 5 && !strncmp(spot-4, "staf", 4)) {
1369 Strcpy(spot-1, "ves");
1374 /* foot/feet (body part) */
1375 if (len >= 4 && !strcmp(spot-3, "foot")) {
1376 Strcpy(spot-2, "eet");
1380 /* ium/ia (mycelia, baluchitheria) */
1381 if (len >= 3 && !strcmp(spot-2, "ium")) {
1382 *(spot--) = (char)0;
1387 /* algae, larvae, hyphae (another fungus part) */
1388 if ((len >= 4 && !strcmp(spot-3, "alga")) ||
1390 (!strcmp(spot-4, "hypha") || !strcmp(spot-4, "larva")))) {
1395 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
1396 if (len > 3 && !strcmp(spot-1, "us") &&
1397 (len < 5 || (strcmp(spot-4, "lotus") &&
1398 (len < 6 || strcmp(spot-5, "wumpus"))))) {
1399 *(spot--) = (char)0;
1404 /* vortex/vortices */
1405 if (len >= 6 && !strcmp(spot-3, "rtex")) {
1406 Strcpy(spot-1, "ices");
1410 /* djinni/djinn (note: also efreeti/efreet) */
1411 if (len >= 6 && !strcmp(spot-5, "djinni")) {
1417 if (len >= 5 && !strcmp(spot-4, "mumak")) {
1418 Strcpy(spot+1, "il");
1422 /* sis/ses (nemesis) */
1423 if (len >= 3 && !strcmp(spot-2, "sis")) {
1428 /* erinys/erinyes */
1429 if (len >= 6 && !strcmp(spot-5, "erinys")) {
1434 /* mouse/mice,louse/lice (not a monster, but possible in food names) */
1435 if (len >= 5 && !strcmp(spot-3, "ouse") && index("MmLl", *(spot-4))) {
1436 Strcpy(spot-3, "ice");
1440 /* matzoh/matzot, possible food name */
1441 if (len >= 6 && (!strcmp(spot-5, "matzoh")
1442 || !strcmp(spot-5, "matzah"))) {
1443 Strcpy(spot-1, "ot");
1446 if (len >= 5 && (!strcmp(spot-4, "matzo")
1447 || !strcmp(spot-5, "matza"))) {
1452 /* child/children (for wise guys who give their food funny names) */
1453 if (len >= 5 && !strcmp(spot-4, "child")) {
1454 Strcpy(spot, "dren");
1458 /* note: -eau/-eaux (gateau, bordeau...) */
1459 /* note: ox/oxen, VAX/VAXen, goose/geese */
1461 /* Ends in z, x, s, ch, sh; add an "es" */
1462 if (index("zxs", *spot)
1463 || (len >= 2 && *spot=='h' && index("cs", *(spot-1)))
1464 /* Kludge to get "tomatoes" and "potatoes" right */
1465 || (len >= 4 && !strcmp(spot-2, "ato"))) {
1466 Strcpy(spot+1, "es");
1470 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
1472 (!index(vowels, *(spot-1)))) {
1473 Strcpy(spot, "ies");
1477 /* Default: append an 's' */
1478 Strcpy(spot+1, "s");
1480 bottom: if (excess) Strcpy(eos(str), excess);
1487 const char *name, oclass;
1488 int f_o_range, l_o_range;
1493 STATIC_DCL const struct o_range o_ranges[];
1497 /* wishable subranges of objects */
1498 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
1499 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
1500 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
1501 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
1502 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
1503 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
1504 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
1505 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
1506 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
1507 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
1508 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
1509 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
1511 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
1514 ARMOR_CLASS, GRAY_DRAGON_SCALES, YELLOW_DRAGON_SCALES },
1515 { "dragon scale mail",
1516 ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL },
1517 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
1519 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
1521 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
1522 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
1525 #define BSTRCMP(base,ptr,string) ((ptr) < base || strcmp((ptr),string))
1526 #define BSTRCMPI(base,ptr,string) ((ptr) < base || strcmpi((ptr),string))
1527 #define BSTRNCMP(base,ptr,string,num) ((ptr)<base || strncmp((ptr),string,num))
1528 #define BSTRNCMPI(base,ptr,string,num) ((ptr)<base||strncmpi((ptr),string,num))
1531 * Singularize a string the user typed in; this helps reduce the complexity
1532 * of readobjnam, and is also used in pager.c to singularize the string
1533 * for which help is sought.
1536 makesingular(oldstr)
1539 register char *p, *bp;
1540 char *str = nextobuf();
1542 if (!oldstr || !*oldstr) {
1543 impossible("singular of null?");
1547 Strcpy(str, oldstr);
1550 while (*bp == ' ') bp++;
1551 /* find "cloves of garlic", "worthless pieces of blue glass" */
1552 if ((p = strstri(bp, "s of ")) != 0) {
1553 /* but don't singularize "gauntlets", "boots", "Eyes of the.." */
1554 if (BSTRNCMPI(bp, p-3, "Eye", 3) &&
1555 BSTRNCMP(bp, p-4, "boot", 4) &&
1556 BSTRNCMP(bp, p-8, "gauntlet", 8))
1557 while ((*p = *(p+1)) != 0) p++;
1561 /* remove -s or -es (boxes) or -ies (rubies) */
1563 if (p >= bp+1 && p[-1] == 's') {
1564 if (p >= bp+2 && p[-2] == 'e') {
1565 if (p >= bp+3 && p[-3] == 'i') {
1566 if(!BSTRCMP(bp, p-7, "cookies") ||
1567 !BSTRCMP(bp, p-4, "pies"))
1573 /* note: cloves / knives from clove / knife */
1574 if(!BSTRCMP(bp, p-6, "knives")) {
1578 if(!BSTRCMP(bp, p-6, "staves")) {
1582 if (!BSTRCMPI(bp, p-6, "leaves")) {
1586 if (!BSTRCMP(bp, p-8, "vortices")) {
1591 /* note: nurses, axes but boxes */
1592 if (!BSTRCMP(bp, p-5, "boxes") ||
1593 !BSTRCMP(bp, p-4, "ches")) {
1598 if (!BSTRCMP(bp, p-6, "gloves") ||
1599 !BSTRCMP(bp, p-6, "lenses") ||
1600 !BSTRCMP(bp, p-5, "shoes") ||
1601 !BSTRCMP(bp, p-6, "scales"))
1604 } else if (!BSTRCMP(bp, p-5, "boots") ||
1605 !BSTRCMP(bp, p-9, "gauntlets") ||
1606 !BSTRCMP(bp, p-6, "tricks") ||
1607 !BSTRCMP(bp, p-9, "paralysis") ||
1608 !BSTRCMP(bp, p-5, "glass") ||
1609 !BSTRCMP(bp, p-4, "ness") ||
1610 !BSTRCMP(bp, p-14, "shape changers") ||
1611 !BSTRCMP(bp, p-15, "detect monsters") ||
1612 !BSTRCMPI(bp, p-11, "Aesculapius") || /* staff */
1613 !BSTRCMP(bp, p-10, "eucalyptus") ||
1615 !BSTRCMP(bp, p-9, "iron bars") ||
1617 !BSTRCMP(bp, p-5, "aklys") ||
1618 !BSTRCMP(bp, p-6, "fungus"))
1625 if(!BSTRCMP(bp, p-5, "teeth")) {
1626 Strcpy(p-5, "tooth");
1630 if (!BSTRCMP(bp, p-5, "fungi")) {
1631 Strcpy(p-5, "fungus");
1635 /* here we cannot find the plural suffix */
1640 /* compare user string against object name string using fuzzy matching */
1642 wishymatch(u_str, o_str, retry_inverted)
1643 const char *u_str; /* from user, so might be variant spelling */
1644 const char *o_str; /* from objects[], so is in canonical form */
1645 boolean retry_inverted; /* optional extra "of" handling */
1647 /* special case: wizards can wish for traps. The object is "beartrap"
1648 * and the trap is "bear trap", so to let wizards wish for both we
1649 * must not fuzzymatch.
1652 if (wizard && !strcmp(o_str, "beartrap"))
1653 return !strncmpi(o_str, u_str, 8);
1656 /* ignore spaces & hyphens and upper/lower case when comparing */
1657 if (fuzzymatch(u_str, o_str, " -", TRUE)) return TRUE;
1659 if (retry_inverted) {
1660 const char *u_of, *o_of;
1661 char *p, buf[BUFSZ];
1663 /* when just one of the strings is in the form "foo of bar",
1664 convert it into "bar foo" and perform another comparison */
1665 u_of = strstri(u_str, " of ");
1666 o_of = strstri(o_str, " of ");
1667 if (u_of && !o_of) {
1668 Strcpy(buf, u_of + 4);
1669 p = eos(strcat(buf, " "));
1670 while (u_str < u_of) *p++ = *u_str++;
1672 return fuzzymatch(buf, o_str, " -", TRUE);
1673 } else if (o_of && !u_of) {
1674 Strcpy(buf, o_of + 4);
1675 p = eos(strcat(buf, " "));
1676 while (o_str < o_of) *p++ = *o_str++;
1678 return fuzzymatch(u_str, buf, " -", TRUE);
1682 /* [note: if something like "elven speed boots" ever gets added, these
1683 special cases should be changed to call wishymatch() recursively in
1684 order to get the "of" inversion handling] */
1685 if (!strncmp(o_str, "dwarvish ", 9)) {
1686 if (!strncmpi(u_str, "dwarven ", 8))
1687 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
1688 } else if (!strncmp(o_str, "elven ", 6)) {
1689 if (!strncmpi(u_str, "elvish ", 7))
1690 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
1691 else if (!strncmpi(u_str, "elfin ", 6))
1692 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
1693 } else if (!strcmp(o_str, "aluminum")) {
1694 /* this special case doesn't really fit anywhere else... */
1695 /* (note that " wand" will have been stripped off by now) */
1696 if (!strcmpi(u_str, "aluminium"))
1697 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
1703 /* alternate spellings; if the difference is only the presence or
1704 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
1705 vs "pick-axe") then there is no need for inclusion in this list;
1706 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
1707 struct alt_spellings {
1711 { "pickax", PICK_AXE },
1712 { "whip", BULLWHIP },
1713 { "saber", SILVER_SABER },
1714 { "silver sabre", SILVER_SABER },
1715 { "smooth shield", SHIELD_OF_REFLECTION },
1716 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
1717 { "grey dragon scales", GRAY_DRAGON_SCALES },
1718 { "enchant armour", SCR_ENCHANT_ARMOR },
1719 { "destroy armour", SCR_DESTROY_ARMOR },
1720 { "scroll of enchant armour", SCR_ENCHANT_ARMOR },
1721 { "scroll of destroy armour", SCR_DESTROY_ARMOR },
1722 { "leather armour", LEATHER_ARMOR },
1723 { "studded leather armour", STUDDED_LEATHER_ARMOR },
1724 { "iron ball", HEAVY_IRON_BALL },
1725 { "lantern", BRASS_LANTERN },
1726 { "mattock", DWARVISH_MATTOCK },
1727 { "amulet of poison resistance", AMULET_VERSUS_POISON },
1730 { "camera", EXPENSIVE_CAMERA },
1731 { "tee shirt", T_SHIRT },
1734 { "can opener", TIN_OPENER },
1735 { "kelp", KELP_FROND },
1736 { "eucalyptus", EUCALYPTUS_LEAF },
1737 { "grapple", GRAPPLING_HOOK },
1738 { (const char *)0, 0 },
1742 * Return something wished for. Specifying a null pointer for
1743 * the user request string results in a random object. Otherwise,
1744 * if asking explicitly for "nothing" (or "nil") return no_wish;
1745 * if not an object return &zeroobj; if an error (no matching object),
1747 * If from_user is false, we're reading from the wizkit, nothing was typed in.
1750 readobjnam(bp, no_wish, from_user)
1752 struct obj *no_wish;
1757 register struct obj *otmp;
1758 int cnt, spe, spesgn, typ, very, rechrg;
1759 int blessed, uncursed, iscursed, ispoisoned, isgreased;
1760 int eroded, eroded2, erodeproof;
1761 #ifdef INVISIBLE_OBJECTS
1764 int halfeaten, mntmp, contents;
1765 int islit, unlabeled, ishistoric, isdiluted;
1767 int ftype = current_fruit;
1768 char fruitbuf[BUFSZ];
1769 /* Fruits may not mess up the ability to wish for real objects (since
1770 * you can leave a fruit in a bones file and it will be added to
1771 * another person's game), so they must be checked for last, after
1772 * stripping all the possible prefixes and seeing if there's a real
1773 * name in there. So we have to save the full original name. However,
1774 * it's still possible to do things like "uncursed burnt Alaska",
1775 * or worse yet, "2 burned 5 course meals", so we need to loop to
1776 * strip off the prefixes again, this time stripping only the ones
1778 * We could get even more detailed so as to allow food names with
1779 * prefixes that _are_ possible on food, so you could wish for
1780 * "2 3 alarm chilis". Currently this isn't allowed; options.c
1781 * automatically sticks 'candied' in front of such names.
1785 char *un, *dn, *actualn;
1788 cnt = spe = spesgn = typ = very = rechrg =
1789 blessed = uncursed = iscursed =
1790 #ifdef INVISIBLE_OBJECTS
1793 ispoisoned = isgreased = eroded = eroded2 = erodeproof =
1794 halfeaten = islit = unlabeled = ishistoric = isdiluted = 0;
1799 contents = UNDEFINED;
1801 actualn = dn = un = 0;
1804 /* first, remove extra whitespace they may have typed */
1805 (void)mungspaces(bp);
1806 /* allow wishing for "nothing" to preserve wishless conduct...
1807 [now requires "wand of nothing" if that's what was really wanted] */
1808 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil") ||
1809 !strcmpi(bp, "none")) return no_wish;
1810 /* save the [nearly] unmodified choice string */
1811 Strcpy(fruitbuf, bp);
1816 if (!bp || !*bp) goto any;
1817 if (!strncmpi(bp, "an ", l=3) ||
1818 !strncmpi(bp, "a ", l=2)) {
1820 } else if (!strncmpi(bp, "the ", l=4)) {
1821 ; /* just increment `bp' by `l' below */
1822 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
1824 while(digit(*bp)) bp++;
1825 while(*bp == ' ') bp++;
1827 } else if (*bp == '+' || *bp == '-') {
1828 spesgn = (*bp++ == '+') ? 1 : -1;
1830 while(digit(*bp)) bp++;
1831 while(*bp == ' ') bp++;
1833 } else if (!strncmpi(bp, "blessed ", l=8) ||
1834 !strncmpi(bp, "holy ", l=5)) {
1836 } else if (!strncmpi(bp, "cursed ", l=7) ||
1837 !strncmpi(bp, "unholy ", l=7)) {
1839 } else if (!strncmpi(bp, "uncursed ", l=9)) {
1841 #ifdef INVISIBLE_OBJECTS
1842 } else if (!strncmpi(bp, "invisible ", l=10)) {
1845 } else if (!strncmpi(bp, "rustproof ", l=10) ||
1846 !strncmpi(bp, "erodeproof ", l=11) ||
1847 !strncmpi(bp, "corrodeproof ", l=13) ||
1848 !strncmpi(bp, "fixed ", l=6) ||
1849 !strncmpi(bp, "fireproof ", l=10) ||
1850 !strncmpi(bp, "rotproof ", l=9)) {
1852 } else if (!strncmpi(bp,"lit ", l=4) ||
1853 !strncmpi(bp,"burning ", l=8)) {
1855 } else if (!strncmpi(bp,"unlit ", l=6) ||
1856 !strncmpi(bp,"extinguished ", l=13)) {
1858 /* "unlabeled" and "blank" are synonymous */
1859 } else if (!strncmpi(bp,"unlabeled ", l=10) ||
1860 !strncmpi(bp,"unlabelled ", l=11) ||
1861 !strncmpi(bp,"blank ", l=6)) {
1863 } else if(!strncmpi(bp, "poisoned ",l=9)
1865 || (wizard && !strncmpi(bp, "trapped ",l=8))
1869 } else if(!strncmpi(bp, "greased ",l=8)) {
1871 } else if (!strncmpi(bp, "very ", l=5)) {
1872 /* very rusted very heavy iron ball */
1874 } else if (!strncmpi(bp, "thoroughly ", l=11)) {
1876 } else if (!strncmpi(bp, "rusty ", l=6) ||
1877 !strncmpi(bp, "rusted ", l=7) ||
1878 !strncmpi(bp, "burnt ", l=6) ||
1879 !strncmpi(bp, "burned ", l=7)) {
1882 } else if (!strncmpi(bp, "corroded ", l=9) ||
1883 !strncmpi(bp, "rotted ", l=7)) {
1886 } else if (!strncmpi(bp, "partly eaten ", l=13)) {
1888 } else if (!strncmpi(bp, "historic ", l=9)) {
1890 } else if (!strncmpi(bp, "diluted ", l=8)) {
1892 } else if(!strncmpi(bp, "empty ", l=6)) {
1897 if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */
1898 if (strlen(bp) > 1) {
1899 if ((p = rindex(bp, '(')) != 0) {
1900 if (p > bp && p[-1] == ' ') p[-1] = 0;
1903 if (!strcmpi(p, "lit)")) {
1907 while (digit(*p)) p++;
1912 while (digit(*p)) p++;
1919 if (*p) Strcat(bp, p);
1925 otmp->spe is type schar; so we don't want spe to be any bigger or smaller.
1926 also, spe should always be positive -- some cheaters may try to confuse
1930 spesgn = -1; /* cheaters get what they deserve */
1933 if (spe > SCHAR_LIM)
1935 if (rechrg < 0 || rechrg > 7) rechrg = 7; /* recharge_limit */
1937 /* now we have the actual name, as delivered by xname, say
1938 green potions called whisky
1939 scrolls labeled "QWERTY"
1942 very heavy iron ball named hoei
1946 if ((p = strstri(bp, " named ")) != 0) {
1950 if ((p = strstri(bp, " called ")) != 0) {
1953 /* "helmet called telepathy" is not "helmet" (a specific type)
1954 * "shield called reflection" is not "shield" (a general type)
1956 for(i = 0; i < SIZE(o_ranges); i++)
1957 if(!strcmpi(bp, o_ranges[i].name)) {
1958 oclass = o_ranges[i].oclass;
1962 if ((p = strstri(bp, " labeled ")) != 0) {
1965 } else if ((p = strstri(bp, " labelled ")) != 0) {
1969 if ((p = strstri(bp, " of spinach")) != 0) {
1975 Skip over "pair of ", "pairs of", "set of" and "sets of".
1977 Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
1978 English either way. See makeplural() for more on pair/pairs.
1980 We should only double count if the object in question is not
1981 refered to as a "pair of". E.g. We should double if the player
1982 types "pair of spears", but not if the player types "pair of
1983 lenses". Luckily (?) all objects that are refered to as pairs
1984 -- boots, gloves, and lenses -- are also not mergable, so cnt is
1987 if(!strncmpi(bp, "pair of ",8)) {
1990 } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) {
1993 } else if (!strncmpi(bp, "set of ",7)) {
1995 } else if (!strncmpi(bp, "sets of ",8)) {
2000 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
2001 * Don't check if it's a wand or spellbook.
2002 * (avoid "wand/finger of death" confusion).
2004 if (!strstri(bp, "wand ")
2005 && !strstri(bp, "spellbook ")
2006 && !strstri(bp, "finger ")) {
2007 if ((p = strstri(bp, " of ")) != 0
2008 && (mntmp = name_to_mon(p+4)) >= LOW_PM)
2011 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
2012 if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
2013 if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
2014 if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
2015 if (strncmpi(bp, "master key", 10)) /* not the "master" rank */
2016 if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
2017 if (mntmp < LOW_PM && strlen(bp) > 2 &&
2018 (mntmp = name_to_mon(bp)) >= LOW_PM) {
2019 int mntmptoo, mntmplen; /* double check for rank title */
2021 mntmptoo = title_to_mon(bp, (int *)0, &mntmplen);
2022 bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen;
2023 if (*bp == ' ') bp++;
2024 else if (!strncmpi(bp, "s ", 2)) bp += 2;
2025 else if (!strncmpi(bp, "es ", 3)) bp += 3;
2026 else if (!*bp && !actualn && !dn && !un && !oclass) {
2027 /* no referent; they don't really mean a monster type */
2033 /* first change to singular if necessary */
2035 char *sng = makesingular(bp);
2036 if (strcmp(bp, sng)) {
2037 if (cnt == 1) cnt = 2;
2042 /* Alternate spellings (pick-ax, silver sabre, &c) */
2044 struct alt_spellings *as = spellings;
2047 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
2053 /* can't use spellings list for this one due to shuffling */
2054 if (!strncmpi(bp, "grey spell", 10))
2058 /* dragon scales - assumes order of dragons */
2059 if(!strcmpi(bp, "scales") &&
2060 mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) {
2061 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
2062 mntmp = NON_PM; /* no monster */
2067 if(!BSTRCMPI(bp, p-10, "holy water")) {
2069 if ((p-bp) >= 12 && *(p-12) == 'u')
2070 iscursed = 1; /* unholy water */
2074 if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) {
2075 typ = SCR_BLANK_PAPER;
2078 if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) {
2079 typ = SPE_BLANK_PAPER;
2083 * NOTE: Gold pieces are handled as objects nowadays, and therefore
2084 * this section should probably be reconsidered as well as the entire
2085 * gold/money concept. Maybe we want to add other monetary units as
2086 * well in the future. (TH)
2088 if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
2089 !strcmpi(bp, "gold") || !strcmpi(bp, "money") ||
2090 !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
2099 pline("%d gold piece%s.", cnt, plur(cnt));
2104 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
2106 otmp->owt = weight(otmp);
2111 if (strlen(bp) == 1 &&
2112 (i = def_char_to_objclass(*bp)) < MAXOCLASSES && i > ILLOBJ_CLASS
2114 && (wizard || i != VENOM_CLASS)
2123 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
2124 /* false hits on, e.g., rings for "ring mail". */
2125 if(strncmpi(bp, "enchant ", 8) &&
2126 strncmpi(bp, "destroy ", 8) &&
2127 strncmpi(bp, "food detection", 14) &&
2128 strncmpi(bp, "ring mail", 9) &&
2129 strncmpi(bp, "studded leather arm", 19) &&
2130 strncmpi(bp, "leather arm", 11) &&
2131 strncmpi(bp, "tooled horn", 11) &&
2132 strncmpi(bp, "food ration", 11) &&
2133 strncmpi(bp, "meat ring", 9)
2135 for (i = 0; i < (int)(sizeof wrpsym); i++) {
2136 register int j = strlen(wrp[i]);
2137 if(!strncmpi(bp, wrp[i], j)){
2139 if(oclass != AMULET_CLASS) {
2141 if(!strncmpi(bp, " of ", 4)) actualn = bp+4;
2142 /* else if(*bp) ?? */
2147 if(!BSTRCMPI(bp, p-j, wrp[i])){
2151 if(p > bp && p[-1] == ' ') p[-1] = 0;
2157 /* "grey stone" check must be before general "stone" */
2158 for (i = 0; i < SIZE(o_ranges); i++)
2159 if(!strcmpi(bp, o_ranges[i].name)) {
2160 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
2164 if (!BSTRCMPI(bp, p-6, " stone")) {
2169 } else if (!strcmpi(bp, "looking glass")) {
2170 ; /* avoid false hit on "* glass" */
2171 } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) {
2172 register char *g = bp;
2173 if (strstri(g, "broken")) return (struct obj *)0;
2174 if (!strncmpi(g, "worthless ", 10)) g += 10;
2175 if (!strncmpi(g, "piece of ", 9)) g += 9;
2176 if (!strncmpi(g, "colored ", 8)) g += 8;
2177 else if (!strncmpi(g, "coloured ", 9)) g += 9;
2178 if (!strcmpi(g, "glass")) { /* choose random color */
2179 /* 9 different kinds */
2180 typ = LAST_GEM + rnd(9);
2181 if (objects[typ].oc_class == GEM_CLASS) goto typfnd;
2182 else typ = 0; /* somebody changed objects[]? punt */
2183 } else { /* try to construct canonical form */
2185 Strcpy(tbuf, "worthless piece of ");
2186 Strcat(tbuf, g); /* assume it starts with the color */
2192 if (!dn) dn = actualn; /* ex. "skull cap" */
2194 /* check real names of gems first */
2195 if(!oclass && actualn) {
2196 for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
2197 register const char *zn;
2199 if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
2205 i = oclass ? bases[(int)oclass] : 1;
2206 while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){
2207 register const char *zn;
2209 if (actualn && (zn = OBJ_NAME(objects[i])) != 0 &&
2210 wishymatch(actualn, zn, TRUE)) {
2214 if (dn && (zn = OBJ_DESCR(objects[i])) != 0 &&
2215 wishymatch(dn, zn, FALSE)) {
2216 /* don't match extra descriptions (w/o real name) */
2217 if (!OBJ_NAME(objects[i])) return (struct obj *)0;
2221 if (un && (zn = objects[i].oc_uname) != 0 &&
2222 wishymatch(un, zn, FALSE)) {
2229 struct Jitem *j = Japanese_items;
2231 if (actualn && !strcmpi(actualn, j->name)) {
2238 if (!strcmpi(bp, "spinach")) {
2243 /* Note: not strncmpi. 2 fruits, one capital, one not, are possible. */
2247 int blessedf, iscursedf, uncursedf, halfeatenf;
2249 blessedf = iscursedf = uncursedf = halfeatenf = 0;
2254 if (!fp || !*fp) break;
2255 if (!strncmpi(fp, "an ", l=3) ||
2256 !strncmpi(fp, "a ", l=2)) {
2258 } else if (!cntf && digit(*fp)) {
2260 while(digit(*fp)) fp++;
2261 while(*fp == ' ') fp++;
2263 } else if (!strncmpi(fp, "blessed ", l=8)) {
2265 } else if (!strncmpi(fp, "cursed ", l=7)) {
2267 } else if (!strncmpi(fp, "uncursed ", l=9)) {
2269 } else if (!strncmpi(fp, "partly eaten ", l=13)) {
2275 for(f=ffruit; f; f = f->nextf) {
2276 char *f1 = f->fname, *f2 = makeplural(f->fname);
2278 if(!strncmp(fp, f1, strlen(f1)) ||
2279 !strncmp(fp, f2, strlen(f2))) {
2282 iscursed = iscursedf;
2283 uncursed = uncursedf;
2284 halfeaten = halfeatenf;
2292 if(!oclass && actualn) {
2295 /* Perhaps it's an artifact specified by name, not type */
2296 name = artifact_name(actualn, &objtyp);
2303 /* Let wizards wish for traps --KAA */
2304 /* must come after objects check so wizards can still wish for
2305 * trap objects like beartraps
2307 if (wizard && from_user) {
2310 for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
2313 tname = defsyms[trap_to_defsym(trap)].explanation;
2314 if (!strncmpi(tname, bp, strlen(tname))) {
2315 /* avoid stupid mistakes */
2316 if((trap == TRAPDOOR || trap == HOLE)
2317 && !Can_fall_thru(&u.uz)) trap = ROCKTRAP;
2318 (void) maketrap(u.ux, u.uy, trap);
2319 pline("%s.", An(tname));
2323 /* or some other dungeon features -dlc */
2325 if(!BSTRCMP(bp, p-8, "fountain")) {
2326 levl[u.ux][u.uy].typ = FOUNTAIN;
2327 level.flags.nfountains++;
2328 if(!strncmpi(bp, "magic ", 6))
2329 levl[u.ux][u.uy].blessedftn = 1;
2330 pline("A %sfountain.",
2331 levl[u.ux][u.uy].blessedftn ? "magic " : "");
2335 if(!BSTRCMP(bp, p-6, "throne")) {
2336 levl[u.ux][u.uy].typ = THRONE;
2342 if(!BSTRCMP(bp, p-4, "sink")) {
2343 levl[u.ux][u.uy].typ = SINK;
2344 level.flags.nsinks++;
2350 if(!BSTRCMP(bp, p-4, "pool")) {
2351 levl[u.ux][u.uy].typ = POOL;
2352 del_engr_at(u.ux, u.uy);
2354 /* Must manually make kelp! */
2355 water_damage(level.objects[u.ux][u.uy], FALSE, TRUE);
2359 if (!BSTRCMP(bp, p-4, "lava")) { /* also matches "molten lava" */
2360 levl[u.ux][u.uy].typ = LAVAPOOL;
2361 del_engr_at(u.ux, u.uy);
2362 pline("A pool of molten lava.");
2363 if (!(Levitation || Flying)) (void) lava_effects();
2368 if(!BSTRCMP(bp, p-5, "altar")) {
2371 levl[u.ux][u.uy].typ = ALTAR;
2372 if(!strncmpi(bp, "chaotic ", 8))
2374 else if(!strncmpi(bp, "neutral ", 8))
2376 else if(!strncmpi(bp, "lawful ", 7))
2378 else if(!strncmpi(bp, "unaligned ", 10))
2380 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
2381 al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1;
2382 levl[u.ux][u.uy].altarmask = Align2amask( al );
2383 pline("%s altar.", An(align_str(al)));
2388 if(!BSTRCMP(bp, p-5, "grave") || !BSTRCMP(bp, p-9, "headstone")) {
2389 make_grave(u.ux, u.uy, (char *) 0);
2395 if(!BSTRCMP(bp, p-4, "tree")) {
2396 levl[u.ux][u.uy].typ = TREE;
2399 block_point(u.ux, u.uy);
2403 if(!BSTRCMP(bp, p-4, "bars")) {
2404 levl[u.ux][u.uy].typ = IRONBARS;
2405 pline("Iron bars.");
2411 if(!oclass) return((struct obj *)0);
2413 if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))];
2415 if (typ) oclass = objects[typ].oc_class;
2417 /* check for some objects that are not allowed */
2418 if (typ && objects[typ].oc_unique) {
2421 ; /* allow unique objects */
2425 case AMULET_OF_YENDOR:
2426 typ = FAKE_AMULET_OF_YENDOR;
2428 case CANDELABRUM_OF_INVOCATION:
2429 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
2431 case BELL_OF_OPENING:
2434 case SPE_BOOK_OF_THE_DEAD:
2435 typ = SPE_BLANK_PAPER;
2440 /* catch any other non-wishable objects */
2441 if (objects[typ].oc_nowish
2446 return((struct obj *)0);
2448 /* convert magic lamps to regular lamps before lighting them or setting
2450 if (typ == MAGIC_LAMP
2458 otmp = mksobj(typ, TRUE, FALSE);
2460 otmp = mkobj(oclass, FALSE);
2461 if (otmp) typ = otmp->otyp;
2465 (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN ||
2466 Is_candle(otmp) || typ == POT_OIL)) {
2467 place_object(otmp, u.ux, u.uy); /* make it viable light source */
2468 begin_burn(otmp, FALSE);
2469 obj_extract_self(otmp); /* now release it for caller's use */
2472 if(cnt > 0 && objects[typ].oc_merge && oclass != SPBOOK_CLASS &&
2477 (cnt <= 7 && Is_candle(otmp)) ||
2479 ((oclass == WEAPON_CLASS && is_ammo(otmp))
2480 || typ == ROCK || is_missile(otmp)))))
2481 otmp->quan = (long) cnt;
2484 if (oclass == VENOM_CLASS) otmp->spe = 1;
2487 if (spesgn == 0) spe = otmp->spe;
2489 else if (wizard) /* no alteration to spe */ ;
2491 else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS ||
2493 (oclass==RING_CLASS && objects[typ].oc_charged)) {
2494 if(spe > rnd(5) && spe > otmp->spe) spe = 0;
2495 if(spe > 2 && Luck < 0) spesgn = -1;
2497 if (oclass == WAND_CLASS) {
2498 if (spe > 1 && spesgn == -1) spe = 1;
2500 if (spe > 0 && spesgn == -1) spe = 0;
2502 if (spe > otmp->spe) spe = otmp->spe;
2505 if (spesgn == -1) spe = -spe;
2507 /* set otmp->spe. This may, or may not, use spe... */
2509 case TIN: if (contents==EMPTY) {
2510 otmp->corpsenm = NON_PM;
2512 } else if (contents==SPINACH) {
2513 otmp->corpsenm = NON_PM;
2517 case SLIME_MOLD: otmp->spe = ftype;
2519 case SKELETON_KEY: case CHEST: case LARGE_BOX:
2520 case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
2521 /* otmp->cobj already done in mksobj() */
2524 case SCR_MAIL: otmp->spe = 1; break;
2530 otmp->spe = (rn2(10) ? -1 : 0);
2534 /* fall through, if wizard */
2536 default: otmp->spe = spe;
2539 /* set otmp->corpsenm or dragon scale [mail] */
2540 if (mntmp >= LOW_PM) {
2541 if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM;
2545 otmp->spe = 0; /* No spinach */
2546 if (dead_species(mntmp, FALSE)) {
2547 otmp->corpsenm = NON_PM; /* it's empty */
2548 } else if (!(mons[mntmp].geno & G_UNIQ) &&
2549 !(mvitals[mntmp].mvflags & G_NOCORPSE) &&
2550 mons[mntmp].cnutrit != 0) {
2551 otmp->corpsenm = mntmp;
2555 if (!(mons[mntmp].geno & G_UNIQ) &&
2556 !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
2557 /* beware of random troll or lizard corpse,
2558 or of ordinary one being forced to such */
2559 if (otmp->timed) obj_stop_timers(otmp);
2560 if (mons[mntmp].msound == MS_GUARDIAN)
2561 otmp->corpsenm = genus(mntmp,1);
2563 otmp->corpsenm = mntmp;
2564 start_corpse_timeout(otmp);
2568 if (!(mons[mntmp].geno & G_UNIQ)
2569 && !is_human(&mons[mntmp])
2571 && mntmp != PM_MAIL_DAEMON
2574 otmp->corpsenm = mntmp;
2577 mntmp = can_be_hatched(mntmp);
2578 if (mntmp != NON_PM) {
2579 otmp->corpsenm = mntmp;
2580 if (!dead_species(mntmp, TRUE))
2581 attach_egg_hatch_timeout(otmp);
2586 case STATUE: otmp->corpsenm = mntmp;
2587 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
2588 delete_contents(otmp); /* no spellbook */
2589 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
2592 /* Dragon mail - depends on the order of objects */
2594 if (mntmp >= PM_GRAY_DRAGON &&
2595 mntmp <= PM_YELLOW_DRAGON)
2596 otmp->otyp = GRAY_DRAGON_SCALE_MAIL +
2597 mntmp - PM_GRAY_DRAGON;
2602 /* set blessed/cursed -- setting the fields directly is safe
2603 * since weight() is called below and addinv() will take care
2607 } else if (uncursed) {
2609 otmp->cursed = (Luck < 0
2614 } else if (blessed) {
2615 otmp->blessed = (Luck >= 0
2620 otmp->cursed = (Luck < 0
2625 } else if (spesgn < 0) {
2629 #ifdef INVISIBLE_OBJECTS
2630 if (isinvisible) otmp->oinvis = 1;
2634 if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
2635 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
2636 otmp->oeroded = eroded;
2637 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
2638 otmp->oeroded2 = eroded2;
2640 /* set erodeproof */
2641 if (erodeproof && !eroded && !eroded2)
2642 otmp->oerodeproof = (Luck >= 0
2649 /* set otmp->recharged */
2650 if (oclass == WAND_CLASS) {
2651 /* prevent wishing abuse */
2652 if (otmp->otyp == WAN_WISHING
2657 otmp->recharged = (unsigned)rechrg;
2662 if (is_poisonable(otmp))
2663 otmp->opoisoned = (Luck >= 0);
2664 else if (Is_box(otmp) || typ == TIN)
2666 else if (oclass == FOOD_CLASS)
2667 /* try to taint by making it as old as possible */
2671 if (isgreased) otmp->greased = 1;
2673 if (isdiluted && otmp->oclass == POTION_CLASS &&
2674 otmp->otyp != POT_WATER)
2681 /* an artifact name might need capitalization fixing */
2682 aname = artifact_name(name, &objtyp);
2683 if (aname && objtyp == otmp->otyp) name = aname;
2685 otmp = oname(otmp, name);
2686 if (otmp->oartifact) {
2688 u.uconduct.wisharti++; /* KMH, conduct */
2692 /* more wishing abuse: don't allow wishing for certain artifacts */
2693 /* and make them pay; charge them for the wish anyway! */
2694 if ((is_quest_artifact(otmp) ||
2695 (otmp->oartifact && rn2(nartifact_exist()) > 1))
2700 artifact_exists(otmp, ONAME(otmp), FALSE);
2701 obfree(otmp, (struct obj *) 0);
2703 pline("For a moment, you feel %s in your %s, but it disappears!",
2705 makeplural(body_part(HAND)));
2708 if (halfeaten && otmp->oclass == FOOD_CLASS) {
2709 if (otmp->otyp == CORPSE)
2710 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
2711 else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
2712 /* (do this adjustment before setting up object's weight) */
2713 consume_oeaten(otmp, 1);
2715 otmp->owt = weight(otmp);
2716 if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
2722 rnd_class(first,last)
2729 for(i=first; i<=last; i++)
2730 sum += objects[i].oc_prob;
2731 if (!sum) /* all zero */
2732 return first + rn2(last-first+1);
2734 for(i=first; i<=last; i++)
2735 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
2740 STATIC_OVL const char *
2741 Japanese_item_name(i)
2744 struct Jitem *j = Japanese_items;
2751 return (const char *)0;
2755 cloak_simple_name(cloak)
2759 switch (cloak->otyp) {
2762 case MUMMY_WRAPPING:
2765 return (objects[cloak->otyp].oc_name_known &&
2766 cloak->dknown) ? "smock" : "apron";
2775 mimic_obj_name(mtmp)
2778 if (mtmp->m_ap_type == M_AP_OBJECT && mtmp->mappearance != STRANGE_OBJECT) {
2779 int idx = objects[mtmp->mappearance].oc_descr_idx;
2780 if (mtmp->mappearance == GOLD_PIECE) return "gold";
2781 return obj_descr[idx].oc_name;
2783 return "whatcha-may-callit";