Source:NetHack 3.4.0/objnam.c

From NetHackWiki
(Redirected from NetHack 3.4.0/objnam.c)
Jump to navigation Jump to search

Below is the full text to objnam.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/objnam.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)objnam.c	3.4	2002/02/22	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
8.    #define PREFIX	80	/* (56) */
9.    #define SCHAR_LIM 127
10.   #define NUMOBUF 12
11.   
12.   STATIC_DCL char *FDECL(strprepend,(char *,const char *));
13.   #ifdef OVLB
14.   static boolean FDECL(wishymatch, (const char *,const char *,BOOLEAN_P));
15.   #endif
16.   static char *NDECL(nextobuf);
17.   static void FDECL(add_erosion_words, (struct obj *, char *));
18.   
19.   struct Jitem {
20.   	int item;
21.   	const char *name;
22.   };
23.   
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)))
31.   
32.   #ifndef OVLB
33.   
34.   STATIC_DCL struct Jitem Japanese_items[];
35.   
36.   #else /* OVLB */
37.   
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" },
45.   	{ KNIFE, "shito" },
46.   	{ PLATE_MAIL, "tanko" },
47.   	{ HELMET, "kabuto" },
48.   	{ LEATHER_GLOVES, "yugake" },
49.   	{ FOOD_RATION, "gunyoki" },
50.   	{ POT_BOOZE, "sake" },
51.   	{0, "" }
52.   };
53.   
54.   #endif /* OVLB */
55.   
56.   STATIC_DCL const char *FDECL(Japanese_item_name,(int i));
57.   
58.   #ifdef OVL1
59.   
60.   STATIC_OVL char *
61.   strprepend(s,pref)
62.   register char *s;
63.   register const char *pref;
64.   {
65.   	register int i = (int)strlen(pref);
66.   
67.   	if(i > PREFIX) {
68.   		impossible("PREFIX too short (for %d).", i);
69.   		return(s);
70.   	}
71.   	s -= i;
72.   	(void) strncpy(s, pref, i);	/* do not copy trailing 0 */
73.   	return(s);
74.   }
75.   
76.   #endif /* OVL1 */
77.   #ifdef OVLB
78.   
79.   /* manage a pool of BUFSZ buffers, so callers don't have to */
80.   static char *
81.   nextobuf()
82.   {
83.   	static char NEARDATA bufs[NUMOBUF][BUFSZ];
84.   	static int bufidx = 0;
85.   
86.   	bufidx = (bufidx + 1) % NUMOBUF;
87.   	return bufs[bufidx];
88.   }
89.   
90.   char *
91.   obj_typename(otyp)
92.   register int otyp;
93.   {
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;
100.  
101.  	if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
102.  		actualn = Japanese_item_name(otyp);
103.  	switch(ocl->oc_class) {
104.  	case GOLD_CLASS:
105.  		Strcpy(buf, "coin");
106.  		break;
107.  	case POTION_CLASS:
108.  		Strcpy(buf, "potion");
109.  		break;
110.  	case SCROLL_CLASS:
111.  		Strcpy(buf, "scroll");
112.  		break;
113.  	case WAND_CLASS:
114.  		Strcpy(buf, "wand");
115.  		break;
116.  	case SPBOOK_CLASS:
117.  		Strcpy(buf, "spellbook");
118.  		break;
119.  	case RING_CLASS:
120.  		Strcpy(buf, "ring");
121.  		break;
122.  	case AMULET_CLASS:
123.  		if(nn)
124.  			Strcpy(buf,actualn);
125.  		else
126.  			Strcpy(buf,"amulet");
127.  		if(un)
128.  			Sprintf(eos(buf)," called %s",un);
129.  		if(dn)
130.  			Sprintf(eos(buf)," (%s)",dn);
131.  		return(buf);
132.  	default:
133.  		if(nn) {
134.  			Strcpy(buf, actualn);
135.  			if (GemStone(otyp))
136.  				Strcat(buf, " stone");
137.  			if(un)
138.  				Sprintf(eos(buf), " called %s", un);
139.  			if(dn)
140.  				Sprintf(eos(buf), " (%s)", dn);
141.  		} else {
142.  			Strcpy(buf, dn ? dn : actualn);
143.  			if(ocl->oc_class == GEM_CLASS)
144.  				Strcat(buf, (ocl->oc_material == MINERAL) ?
145.  						" stone" : " gem");
146.  			if(un)
147.  				Sprintf(eos(buf), " called %s", un);
148.  		}
149.  		return(buf);
150.  	}
151.  	/* here for ring/scroll/potion/wand */
152.  	if(nn) {
153.  	    if (ocl->oc_unique)
154.  		Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
155.  	    else
156.  		Sprintf(eos(buf), " of %s", actualn);
157.  	}
158.  	if(un)
159.  		Sprintf(eos(buf), " called %s", un);
160.  	if(dn)
161.  		Sprintf(eos(buf), " (%s)", dn);
162.  	return(buf);
163.  }
164.  
165.  /* less verbose result than obj_typename(); either the actual name
166.     or the description (but not both); user-assigned name is ignored */
167.  char *
168.  simple_typename(otyp)
169.  int otyp;
170.  {
171.      char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
172.  
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 */
178.      return bufp;
179.  }
180.  
181.  boolean
182.  obj_is_pname(obj)
183.  register struct obj *obj;
184.  {
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));
189.  }
190.  
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.
197.   */
198.  char *
199.  distant_name(obj, func)
200.  register struct obj *obj;
201.  char *FDECL((*func), (OBJ_P));
202.  {
203.  	char *str;
204.  
205.  	long save_Blinded = Blinded;
206.  	Blinded = 1;
207.  	str = (*func)(obj);
208.  	Blinded = save_Blinded;
209.  	return str;
210.  }
211.  
212.  #endif /* OVLB */
213.  #ifdef OVL1
214.  
215.  char *
216.  xname(obj)
217.  register struct obj *obj;
218.  {
219.  	register char *buf;
220.  	register int typ = obj->otyp;
221.  	register struct objclass *ocl = &objects[typ];
222.  	register int nn = ocl->oc_name_known;
223.  	register const char *actualn = OBJ_NAME(*ocl);
224.  	register const char *dn = OBJ_DESCR(*ocl);
225.  	register const char *un = ocl->oc_uname;
226.  
227.  	buf = nextobuf() + PREFIX;	/* leave room for "17 -3 " */
228.  	if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
229.  		actualn = Japanese_item_name(typ);
230.  
231.  	buf[0] = '\0';
232.  	/*
233.  	 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
234.  	 * This is only required for unique objects and the Fake AoY since the
235.  	 * article printed for the object is tied to the combination of the two
236.  	 * and printing the wrong article gives away information.
237.  	 */
238.  	if (!nn && ocl->oc_uses_known &&
239.  	    (ocl->oc_unique || typ == FAKE_AMULET_OF_YENDOR)) obj->known = 0;
240.  	if (!Blind) obj->dknown = TRUE;
241.  	if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
242.  	if (obj_is_pname(obj))
243.  	    goto nameit;
244.  	switch (obj->oclass) {
245.  	    case AMULET_CLASS:
246.  		if (!obj->dknown)
247.  			Strcpy(buf, "amulet");
248.  		else if (typ == AMULET_OF_YENDOR ||
249.  			 typ == FAKE_AMULET_OF_YENDOR)
250.  			/* each must be identified individually */
251.  			Strcpy(buf, obj->known ? actualn : dn);
252.  		else if (nn)
253.  			Strcpy(buf, actualn);
254.  		else if (un)
255.  			Sprintf(buf,"amulet called %s", un);
256.  		else
257.  			Sprintf(buf,"%s amulet", dn);
258.  		break;
259.  	    case WEAPON_CLASS:
260.  		if (is_poisonable(obj) && obj->opoisoned)
261.  			Strcpy(buf, "poisoned ");
262.  	    case VENOM_CLASS:
263.  	    case TOOL_CLASS:
264.  		if (typ == LENSES)
265.  			Strcpy(buf, "pair of ");
266.  
267.  		if (!obj->dknown)
268.  			Strcat(buf, dn ? dn : actualn);
269.  		else if (nn)
270.  			Strcat(buf, actualn);
271.  		else if (un) {
272.  			Strcat(buf, dn ? dn : actualn);
273.  			Strcat(buf, " called ");
274.  			Strcat(buf, un);
275.  		} else
276.  			Strcat(buf, dn ? dn : actualn);
277.  		/* If we use an() here we'd have to remember never to use */
278.  		/* it whenever calling doname() or xname(). */
279.  		if (typ == FIGURINE)
280.  		    Sprintf(eos(buf), " of a%s %s",
281.  			index(vowels,*(mons[obj->corpsenm].mname)) ? "n" : "",
282.  			mons[obj->corpsenm].mname);
283.  		break;
284.  	    case ARMOR_CLASS:
285.  		/* depends on order of the dragon scales objects */
286.  		if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
287.  			Sprintf(buf, "set of %s", actualn);
288.  			break;
289.  		}
290.  		if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
291.  
292.  		if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
293.  				&& !obj->dknown) {
294.  			Strcpy(buf, "shield");
295.  			break;
296.  		}
297.  		if(obj->otyp == SHIELD_OF_REFLECTION && !obj->dknown) {
298.  			Strcpy(buf, "smooth shield");
299.  			break;
300.  		}
301.  
302.  		if(nn)	Strcat(buf, actualn);
303.  		else if(un) {
304.  			if(is_boots(obj))
305.  				Strcat(buf,"boots");
306.  			else if(is_gloves(obj))
307.  				Strcat(buf,"gloves");
308.  			else if(is_cloak(obj))
309.  				Strcpy(buf,"cloak");
310.  			else if(is_helmet(obj))
311.  				Strcpy(buf,"helmet");
312.  			else if(is_shield(obj))
313.  				Strcpy(buf,"shield");
314.  			else
315.  				Strcpy(buf,"armor");
316.  			Strcat(buf, " called ");
317.  			Strcat(buf, un);
318.  		} else	Strcat(buf, dn);
319.  		break;
320.  	    case FOOD_CLASS:
321.  		if (typ == SLIME_MOLD) {
322.  			register struct fruit *f;
323.  
324.  			for(f=ffruit; f; f = f->nextf) {
325.  				if(f->fid == obj->spe) {
326.  					Strcpy(buf, f->fname);
327.  					break;
328.  				}
329.  			}
330.  			if (!f) impossible("Bad fruit #%d?", obj->spe);
331.  			break;
332.  		}
333.  
334.  		Strcpy(buf, actualn);
335.  		if (typ == TIN && obj->known) {
336.  		    if(obj->spe > 0)
337.  			Strcat(buf, " of spinach");
338.  		    else if (obj->corpsenm == NON_PM)
339.  		        Strcpy(buf, "empty tin");
340.  		    else if (vegetarian(&mons[obj->corpsenm]))
341.  			Sprintf(eos(buf), " of %s", mons[obj->corpsenm].mname);
342.  		    else
343.  			Sprintf(eos(buf), " of %s meat", mons[obj->corpsenm].mname);
344.  		}
345.  		break;
346.  	    case GOLD_CLASS:
347.  	    case CHAIN_CLASS:
348.  		Strcpy(buf, actualn);
349.  		break;
350.  	    case ROCK_CLASS:
351.  		if (typ == STATUE)
352.  		    Sprintf(buf, "%s%s of %s%s",
353.  			(Role_if(PM_ARCHEOLOGIST) && obj->spe) ? "historic " : "" ,
354.  			actualn,
355.  			type_is_pname(&mons[obj->corpsenm]) ? "" :
356.  			  (mons[obj->corpsenm].geno & G_UNIQ) ? "the " :
357.  			    (index(vowels,*(mons[obj->corpsenm].mname)) ?
358.  								"an " : "a "),
359.  			mons[obj->corpsenm].mname);
360.  		else Strcpy(buf, actualn);
361.  		break;
362.  	    case BALL_CLASS:
363.  		Sprintf(buf, "%sheavy iron ball",
364.  			(obj->owt > ocl->oc_weight) ? "very " : "");
365.  		break;
366.  	    case POTION_CLASS:
367.  		if (obj->dknown && obj->odiluted)
368.  			Strcpy(buf, "diluted ");
369.  		if(nn || un || !obj->dknown) {
370.  			Strcat(buf, "potion");
371.  			if(!obj->dknown) break;
372.  			if(nn) {
373.  			    Strcat(buf, " of ");
374.  			    if (typ == POT_WATER &&
375.  				obj->bknown && (obj->blessed || obj->cursed)) {
376.  				Strcat(buf, obj->blessed ? "holy " : "unholy ");
377.  			    }
378.  			    Strcat(buf, actualn);
379.  			} else {
380.  				Strcat(buf, " called ");
381.  				Strcat(buf, un);
382.  			}
383.  		} else {
384.  			Strcat(buf, dn);
385.  			Strcat(buf, " potion");
386.  		}
387.  		break;
388.  	case SCROLL_CLASS:
389.  		Strcpy(buf, "scroll");
390.  		if(!obj->dknown) break;
391.  		if(nn) {
392.  			Strcat(buf, " of ");
393.  			Strcat(buf, actualn);
394.  		} else if(un) {
395.  			Strcat(buf, " called ");
396.  			Strcat(buf, un);
397.  		} else if (ocl->oc_magic) {
398.  			Strcat(buf, " labeled ");
399.  			Strcat(buf, dn);
400.  		} else {
401.  			Strcpy(buf, dn);
402.  			Strcat(buf, " scroll");
403.  		}
404.  		break;
405.  	case WAND_CLASS:
406.  		if(!obj->dknown)
407.  			Strcpy(buf, "wand");
408.  		else if(nn)
409.  			Sprintf(buf, "wand of %s", actualn);
410.  		else if(un)
411.  			Sprintf(buf, "wand called %s", un);
412.  		else
413.  			Sprintf(buf, "%s wand", dn);
414.  		break;
415.  	case SPBOOK_CLASS:
416.  		if (!obj->dknown) {
417.  			Strcpy(buf, "spellbook");
418.  		} else if (nn) {
419.  			if (typ != SPE_BOOK_OF_THE_DEAD)
420.  			    Strcpy(buf, "spellbook of ");
421.  			Strcat(buf, actualn);
422.  		} else if (un) {
423.  			Sprintf(buf, "spellbook called %s", un);
424.  		} else
425.  			Sprintf(buf, "%s spellbook", dn);
426.  		break;
427.  	case RING_CLASS:
428.  		if(!obj->dknown)
429.  			Strcpy(buf, "ring");
430.  		else if(nn)
431.  			Sprintf(buf, "ring of %s", actualn);
432.  		else if(un)
433.  			Sprintf(buf, "ring called %s", un);
434.  		else
435.  			Sprintf(buf, "%s ring", dn);
436.  		break;
437.  	case GEM_CLASS:
438.  	    {
439.  		const char *rock =
440.  			    (ocl->oc_material == MINERAL) ? "stone" : "gem";
441.  		if (!obj->dknown) {
442.  		    Strcpy(buf, rock);
443.  		} else if (!nn) {
444.  		    if (un) Sprintf(buf,"%s called %s", rock, un);
445.  		    else Sprintf(buf, "%s %s", dn, rock);
446.  		} else {
447.  		    Strcpy(buf, actualn);
448.  		    if (GemStone(typ)) Strcat(buf, " stone");
449.  		}
450.  		break;
451.  	    }
452.  	default:
453.  		Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
454.  	}
455.  	if (obj->quan != 1L) Strcpy(buf, makeplural(buf));
456.  
457.  	if (obj->onamelth && obj->dknown) {
458.  		Strcat(buf, " named ");
459.  nameit:
460.  		Strcat(buf, ONAME(obj));
461.  	}
462.  
463.  	if (!strncmpi(buf, "the ", 4)) buf += 4;
464.  	return(buf);
465.  }
466.  
467.  /* xname() output augmented for multishot missile feedback */
468.  char *
469.  mshot_xname(obj)
470.  struct obj *obj;
471.  {
472.      char tmpbuf[BUFSZ];
473.      char *onm = xname(obj);
474.  
475.      if (m_shot.n > 1 && m_shot.o == obj->otyp) {
476.  	/* copy xname's result so that we can reuse its return buffer */
477.  	Strcpy(tmpbuf, onm);
478.  	/* "the Nth arrow"; value will eventually be passed to an() or
479.  	   The(), both of which correctly handle this "the " prefix */
480.  	Sprintf(onm, "the %d%s %s", m_shot.i, ordin(m_shot.i), tmpbuf);
481.      }
482.  
483.      return onm;
484.  }
485.  
486.  #endif /* OVL1 */
487.  #ifdef OVL0
488.  
489.  /* used for naming "the unique_item" instead of "a unique_item" */
490.  boolean
491.  the_unique_obj(obj)
492.  register struct obj *obj;
493.  {
494.      if (!obj->dknown)
495.  	return FALSE;
496.      else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !obj->known)
497.  	return TRUE;		/* lie */
498.      else
499.  	return (boolean)(objects[obj->otyp].oc_unique &&
500.  			 (obj->known || obj->otyp == AMULET_OF_YENDOR));
501.  }
502.  
503.  static void
504.  add_erosion_words(obj,prefix)
505.  struct obj *obj;
506.  char *prefix;
507.  {
508.  	boolean iscrys = (obj->otyp == CRYSKNIFE);
509.  
510.  
511.  	if (!is_damageable(obj) && !iscrys) return;
512.  
513.  	/* The only cases where any of these bits do double duty are for
514.  	 * rotted food and diluted potions, which are all not is_damageable().
515.  	 */
516.  	if (obj->oeroded && !iscrys) {
517.  		switch (obj->oeroded) {
518.  			case 2:	Strcat(prefix, "very "); break;
519.  			case 3:	Strcat(prefix, "thoroughly "); break;
520.  		}			
521.  		Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
522.  	}
523.  	if (obj->oeroded2 && !iscrys) {
524.  		switch (obj->oeroded2) {
525.  			case 2:	Strcat(prefix, "very "); break;
526.  			case 3:	Strcat(prefix, "thoroughly "); break;
527.  		}			
528.  		Strcat(prefix, is_corrodeable(obj) ? "corroded " :
529.  			"rotted ");
530.  	}
531.  	if (obj->rknown && obj->oerodeproof)
532.  		Strcat(prefix,
533.  		       iscrys ? "fixed " :
534.  		       is_rustprone(obj) ? "rustproof " :
535.  		       is_corrodeable(obj) ? "corrodeproof " :	/* "stainless"? */
536.  		       is_flammable(obj) ? "fireproof " : "");
537.  }
538.  
539.  char *
540.  doname(obj)
541.  register struct obj *obj;
542.  {
543.  	boolean ispoisoned = FALSE;
544.  	char prefix[PREFIX];
545.  	char tmpbuf[PREFIX+1];
546.  	/* when we have to add something at the start of prefix instead of the
547.  	 * end (Strcat is used on the end)
548.  	 */
549.  	register char *bp = xname(obj);
550.  
551.  	/* When using xname, we want "poisoned arrow", and when using
552.  	 * doname, we want "poisoned +0 arrow".  This kludge is about the only
553.  	 * way to do it, at least until someone overhauls xname() and doname(),
554.  	 * combining both into one function taking a parameter.
555.  	 */
556.  	/* must check opoisoned--someone can have a weirdly-named fruit */
557.  	if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
558.  		bp += 9;
559.  		ispoisoned = TRUE;
560.  	}
561.  
562.  	if(obj->quan != 1L)
563.  		Sprintf(prefix, "%ld ", obj->quan);
564.  	else if (obj_is_pname(obj) || the_unique_obj(obj)) {
565.  		if (!strncmpi(bp, "the ", 4))
566.  		    bp += 4;
567.  		Strcpy(prefix, "the ");
568.  	} else
569.  		Strcpy(prefix, "a ");
570.  
571.  #ifdef INVISIBLE_OBJECTS
572.  	if (obj->oinvis) Strcat(prefix,"invisible ");
573.  #endif
574.  
575.  	if (obj->bknown &&
576.  	    obj->oclass != GOLD_CLASS &&
577.  	    (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
578.  		|| (!obj->cursed && !obj->blessed))) {
579.  	    /* allow 'blessed clear potion' if we don't know it's holy water;
580.  	     * always allow "uncursed potion of water"
581.  	     */
582.  	    if (obj->cursed)
583.  		Strcat(prefix, "cursed ");
584.  	    else if (obj->blessed)
585.  		Strcat(prefix, "blessed ");
586.  	    else if ((!obj->known || !objects[obj->otyp].oc_charged ||
587.  		      (obj->oclass == ARMOR_CLASS ||
588.  		       obj->oclass == RING_CLASS))
589.  		/* For most items with charges or +/-, if you know how many
590.  		 * charges are left or what the +/- is, then you must have
591.  		 * totally identified the item, so "uncursed" is unneccesary,
592.  		 * because an identified object not described as "blessed" or
593.  		 * "cursed" must be uncursed.
594.  		 *
595.  		 * If the charges or +/- is not known, "uncursed" must be
596.  		 * printed to avoid ambiguity between an item whose curse
597.  		 * status is unknown, and an item known to be uncursed.
598.  		 */
599.  #ifdef MAIL
600.  			&& obj->otyp != SCR_MAIL
601.  #endif
602.  			&& obj->otyp != FAKE_AMULET_OF_YENDOR
603.  			&& obj->otyp != AMULET_OF_YENDOR
604.  			&& !Role_if(PM_PRIEST))
605.  		Strcat(prefix, "uncursed ");
606.  	}
607.  
608.  	if (obj->greased) Strcat(prefix, "greased ");
609.  
610.  	switch(obj->oclass) {
611.  	case AMULET_CLASS:
612.  		if(obj->owornmask & W_AMUL)
613.  			Strcat(bp, " (being worn)");
614.  		break;
615.  	case WEAPON_CLASS:
616.  		if(ispoisoned)
617.  			Strcat(prefix, "poisoned ");
618.  plus:
619.  		add_erosion_words(obj, prefix);
620.  		if(obj->known) {
621.  			Strcat(prefix, sitoa(obj->spe));
622.  			Strcat(prefix, " ");
623.  		}
624.  		break;
625.  	case ARMOR_CLASS:
626.  		if(obj->owornmask & W_ARMOR)
627.  			Strcat(bp, (obj == uskin) ? " (embedded in your skin)" :
628.  				" (being worn)");
629.  		goto plus;
630.  	case TOOL_CLASS:
631.  		/* weptools already get this done when we go to the +n code */
632.  		if (!is_weptool(obj))
633.  		    add_erosion_words(obj, prefix);
634.  		if(obj->owornmask & (W_TOOL /* blindfold */
635.  #ifdef STEED
636.  				| W_SADDLE
637.  #endif
638.  				)) {
639.  			Strcat(bp, " (being worn)");
640.  			break;
641.  		}
642.  		if (obj->otyp == LEASH && obj->leashmon != 0) {
643.  			Strcat(bp, " (in use)");
644.  			break;
645.  		}
646.  		if (is_weptool(obj))
647.  			goto plus;
648.  		if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
649.  			if (!obj->spe)
650.  			    Strcpy(tmpbuf, "no");
651.  			else
652.  			    Sprintf(tmpbuf, "%d", obj->spe);
653.  			Sprintf(eos(bp), " (%s candle%s%s)",
654.  				tmpbuf, plur(obj->spe),
655.  				!obj->lamplit ? " attached" : ", lit");
656.  			break;
657.  		} else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
658.  			obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
659.  			if (Is_candle(obj) &&
660.  			    obj->age < 20L * (long)objects[obj->otyp].oc_cost)
661.  				Strcat(prefix, "partly used ");
662.  			if(obj->lamplit)
663.  				Strcat(bp, " (lit)");
664.  			break;
665.  		}
666.  		if(objects[obj->otyp].oc_charged)
667.  		    goto charges;
668.  		break;
669.  	case WAND_CLASS:
670.  		add_erosion_words(obj, prefix);
671.  charges:
672.  		if(obj->known)
673.  		    Sprintf(eos(bp), " (%d:%d)", (int)obj->recharged, obj->spe);
674.  		break;
675.  	case POTION_CLASS:
676.  		if (obj->otyp == POT_OIL && obj->lamplit)
677.  		    Strcat(bp, " (lit)");
678.  		break;
679.  	case RING_CLASS:
680.  		add_erosion_words(obj, prefix);
681.  ring:
682.  		if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
683.  		if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
684.  		if(obj->owornmask & W_RING) {
685.  		    Strcat(bp, body_part(HAND));
686.  		    Strcat(bp, ")");
687.  		}
688.  		if(obj->known && objects[obj->otyp].oc_charged) {
689.  			Strcat(prefix, sitoa(obj->spe));
690.  			Strcat(prefix, " ");
691.  		}
692.  		break;
693.  	case FOOD_CLASS:
694.  		if (obj->oeaten)
695.  		    Strcat(prefix, "partly eaten ");
696.  		if (obj->otyp == CORPSE) {
697.  		    if (mons[obj->corpsenm].geno & G_UNIQ) {
698.  			Sprintf(prefix, "%s%s ",
699.  				(type_is_pname(&mons[obj->corpsenm]) ?
700.  					"" : "the "),
701.  				s_suffix(mons[obj->corpsenm].mname));
702.  			if (obj->oeaten) Strcat(prefix, "partly eaten ");
703.  		    } else {
704.  			Strcat(prefix, mons[obj->corpsenm].mname);
705.  			Strcat(prefix, " ");
706.  		    }
707.  		} else if (obj->otyp == EGG) {
708.  #if 0	/* corpses don't tell if they're stale either */
709.  		    if (obj->known && stale_egg(obj))
710.  			Strcat(prefix, "stale ");
711.  #endif
712.  		    if (obj->corpsenm >= LOW_PM &&
713.  			    (obj->known ||
714.  			    mvitals[obj->corpsenm].mvflags & MV_KNOWS_EGG)) {
715.  			Strcat(prefix, mons[obj->corpsenm].mname);
716.  			Strcat(prefix, " ");
717.  			if (obj->spe)
718.  			    Strcat(bp, " (laid by you)");
719.  		    }
720.  		}
721.  		if (obj->otyp == MEAT_RING) goto ring;
722.  		break;
723.  	case BALL_CLASS:
724.  	case CHAIN_CLASS:
725.  		add_erosion_words(obj, prefix);
726.  		if(obj->owornmask & W_BALL)
727.  			Strcat(bp, " (chained to you)");
728.  			break;
729.  	}
730.  
731.  	if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
732.  		if (obj->quan != 1L) {
733.  			Strcat(bp, " (wielded)");
734.  		} else {
735.  			const char *hand_s = body_part(HAND);
736.  
737.  			if (bimanual(obj)) hand_s = makeplural(hand_s);
738.  			Sprintf(eos(bp), " (weapon in %s)", hand_s);
739.  		}
740.  	}
741.  	if(obj->owornmask & W_SWAPWEP) {
742.  		if (u.twoweap)
743.  			Sprintf(eos(bp), " (wielded in other %s)",
744.  				body_part(HAND));
745.  		else
746.  			Strcat(bp, " (alternate weapon; not wielded)");
747.  	}
748.  	if(obj->owornmask & W_QUIVER) Strcat(bp, " (in quiver)");
749.  	if(obj->unpaid) {
750.  		xchar ox, oy; 
751.  		long quotedprice = unpaid_cost(obj);
752.  		struct monst *shkp = (struct monst *)0;
753.  
754.  		if (Has_contents(obj) &&
755.  		    get_obj_location(obj, &ox, &oy, BURIED_TOO|CONTAINED_TOO) &&
756.  		    costly_spot(ox, oy) &&
757.  		    (shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))))
758.  			quotedprice += contained_cost(obj, shkp, 0L, FALSE, TRUE);
759.  		Sprintf(eos(bp), " (unpaid, %ld %s)",
760.  			quotedprice, currency(quotedprice));
761.  	}
762.  	if (!strncmp(prefix, "a ", 2) &&
763.  			index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
764.  			&& (*(prefix+2) || (strncmp(bp, "uranium", 7)
765.  				&& strncmp(bp, "unicorn", 7)
766.  				&& strncmp(bp, "eucalyptus", 10)))) {
767.  		Strcpy(tmpbuf, prefix);
768.  		Strcpy(prefix, "an ");
769.  		Strcpy(prefix+3, tmpbuf+2);
770.  	}
771.  	bp = strprepend(bp, prefix);
772.  	return(bp);
773.  }
774.  
775.  #endif /* OVL0 */
776.  #ifdef OVLB
777.  
778.  /* used from invent.c */
779.  boolean
780.  not_fully_identified(otmp)
781.  register struct obj *otmp;
782.  {
783.      /* check fundamental ID hallmarks first */
784.      if (!otmp->known || !otmp->dknown ||
785.  #ifdef MAIL
786.  	    (!otmp->bknown && otmp->otyp != SCR_MAIL) ||
787.  #else
788.  	    !otmp->bknown ||
789.  #endif
790.  	    !objects[otmp->otyp].oc_name_known)	/* ?redundant? */
791.  	return TRUE;
792.      if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
793.  	return TRUE;
794.      /* otmp->rknown is the only item of interest if we reach here */
795.         /*
796.  	*  Note:  if a revision ever allows scrolls to become fireproof or
797.  	*  rings to become shockproof, this checking will need to be revised.
798.  	*  `rknown' ID only matters if xname() will provide the info about it.
799.  	*/
800.      if (otmp->rknown || (otmp->oclass != ARMOR_CLASS &&
801.  			 otmp->oclass != WEAPON_CLASS &&
802.  			 !is_weptool(otmp) &&		    /* (redunant) */
803.  			 otmp->oclass != BALL_CLASS))	    /* (useless) */
804.  	return FALSE;
805.      else	/* lack of `rknown' only matters for vulnerable objects */
806.  	return (boolean)(is_rustprone(otmp) ||
807.  			 is_corrodeable(otmp) ||
808.  			 is_flammable(otmp));
809.  }
810.  
811.  char *
812.  corpse_xname(otmp, ignore_oquan)
813.  struct obj *otmp;
814.  boolean ignore_oquan;	/* to force singular */
815.  {
816.  	char *nambuf = nextobuf();
817.  
818.  	Sprintf(nambuf, "%s corpse", mons[otmp->corpsenm].mname);
819.  
820.  	if (ignore_oquan || otmp->quan < 2)
821.  	    return nambuf;
822.  	else
823.  	    return makeplural(nambuf);
824.  }
825.  
826.  /* xname, unless it's a corpse, then corpse_xname(obj, FALSE) */
827.  char *
828.  cxname(obj)
829.  struct obj *obj;
830.  {
831.  	if (obj->otyp == CORPSE)
832.  	    return corpse_xname(obj, FALSE);
833.  	return xname(obj);
834.  }
835.  
836.  /*
837.   * Used if only one of a collection of objects is named (e.g. in eat.c).
838.   */
839.  const char *
840.  singular(otmp, func)
841.  register struct obj *otmp;
842.  char *FDECL((*func), (OBJ_P));
843.  {
844.  	long savequan;
845.  	char *nam;
846.  
847.  	/* Note: using xname for corpses will not give the monster type */
848.  	if (otmp->otyp == CORPSE && func == xname)
849.  		return corpse_xname(otmp, TRUE);
850.  
851.  	savequan = otmp->quan;
852.  	otmp->quan = 1L;
853.  	nam = (*func)(otmp);
854.  	otmp->quan = savequan;
855.  	return nam;
856.  }
857.  
858.  char *
859.  an(str)
860.  register const char *str;
861.  {
862.  	char *buf = nextobuf();
863.  
864.  	buf[0] = '\0';
865.  
866.  	if (strncmpi(str, "the ", 4) &&
867.  	    strcmp(str, "molten lava") &&
868.  	    strcmp(str, "iron bars") &&
869.  	    strcmp(str, "ice")) {
870.  		if (index(vowels, *str) &&
871.  		    strncmp(str, "useful", 6) &&
872.  		    strncmp(str, "unicorn", 7) &&
873.  		    strncmp(str, "uranium", 7) &&
874.  		    strncmp(str, "eucalyptus", 10))
875.  			Strcpy(buf, "an ");
876.  		else
877.  			Strcpy(buf, "a ");
878.  	}
879.  
880.  	Strcat(buf, str);
881.  	return buf;
882.  }
883.  
884.  char *
885.  An(str)
886.  const char *str;
887.  {
888.  	register char *tmp = an(str);
889.  	*tmp = highc(*tmp);
890.  	return tmp;
891.  }
892.  
893.  /*
894.   * Prepend "the" if necessary; assumes str is a subject derived from xname.
895.   * Use type_is_pname() for monster names, not the().  the() is idempotent.
896.   */
897.  char *
898.  the(str)
899.  const char *str;
900.  {
901.  	char *buf = nextobuf();
902.  	boolean insert_the = FALSE;
903.  
904.  	if (!strncmpi(str, "the ", 4)) {
905.  	    buf[0] = lowc(*str);
906.  	    Strcpy(&buf[1], str+1);
907.  	    return buf;
908.  	} else if (*str < 'A' || *str > 'Z') {
909.  	    /* not a proper name, needs an article */
910.  	    insert_the = TRUE;
911.  	} else {
912.  	    /* Probably a proper name, might not need an article */
913.  	    register char *tmp, *named, *called;
914.  	    int l;
915.  
916.  	    /* some objects have capitalized adjectives in their names */
917.  	    if(((tmp = rindex(str, ' ')) || (tmp = rindex(str, '-'))) &&
918.  	       (tmp[1] < 'A' || tmp[1] > 'Z'))
919.  		insert_the = TRUE;
920.  	    else if (tmp && index(str, ' ') < tmp) {	/* has spaces */
921.  		/* it needs an article if the name contains "of" */
922.  		tmp = strstri(str, " of ");
923.  		named = strstri(str, " named ");
924.  		called = strstri(str, " called ");
925.  		if (called && (!named || called < named)) named = called;
926.  
927.  		if (tmp && (!named || tmp < named))	/* found an "of" */
928.  		    insert_the = TRUE;
929.  		/* stupid special case: lacks "of" but needs "the" */
930.  		else if (!named && (l = strlen(str)) >= 31 &&
931.  		      !strcmp(&str[l - 31], "Platinum Yendorian Express Card"))
932.  		    insert_the = TRUE;
933.  	    }
934.  	}
935.  	if (insert_the)
936.  	    Strcpy(buf, "the ");
937.  	else
938.  	    buf[0] = '\0';
939.  	Strcat(buf, str);
940.  
941.  	return buf;
942.  }
943.  
944.  char *
945.  The(str)
946.  const char *str;
947.  {
948.      register char *tmp = the(str);
949.      *tmp = highc(*tmp);
950.      return tmp;
951.  }
952.  
953.  /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
954.  char *
955.  aobjnam(otmp,verb)
956.  register struct obj *otmp;
957.  register const char *verb;
958.  {
959.  	register char *bp = cxname(otmp);
960.  	char prefix[PREFIX];
961.  
962.  	if(otmp->quan != 1L) {
963.  		Sprintf(prefix, "%ld ", otmp->quan);
964.  		bp = strprepend(bp, prefix);
965.  	}
966.  
967.  	if(verb) {
968.  	    Strcat(bp, " ");
969.  	    Strcat(bp, otense(otmp, verb));
970.  	}
971.  	return(bp);
972.  }
973.  
974.  /* like aobjnam, but prepend "The", not count, and use xname */
975.  char *
976.  Tobjnam(otmp, verb)
977.  register struct obj *otmp;
978.  register const char *verb;
979.  {
980.  	char *bp = The(xname(otmp));
981.  
982.  	if(verb) {
983.  	    Strcat(bp, " ");
984.  	    Strcat(bp, otense(otmp, verb));
985.  	}
986.  	return(bp);
987.  }
988.  
989.  /* return form of the verb (input plural) if xname(otmp) were the subject */
990.  char *
991.  otense(otmp, verb)
992.  register struct obj *otmp;
993.  register const char *verb;
994.  {
995.  	char *buf;
996.  
997.  	/*
998.  	 * verb is given in plural (without trailing s).  Return as input
999.  	 * if the result of xname(otmp) would be plural.  Don't bother
1000. 	 * recomputing xname(otmp) at this time.
1001. 	 */
1002. 	if (!is_plural(otmp))
1003. 	    return vtense((char *)0, verb);
1004. 
1005. 	buf = nextobuf();
1006. 	Strcpy(buf, verb);
1007. 	return buf;
1008. }
1009. 
1010. /* return form of the verb (input plural) for present tense 3rd person subj */
1011. char *
1012. vtense(subj, verb)
1013. register const char *subj;
1014. register const char *verb;
1015. {
1016. 	char *buf = nextobuf();
1017. 	int len;
1018. 	const char *spot;
1019. 	const char *sp;
1020. 
1021. 	/*
1022. 	 * verb is given in plural (without trailing s).  Return as input
1023. 	 * if subj appears to be plural.  Add special cases as necessary.
1024. 	 * Many hard cases can already be handled by using otense() instead.
1025. 	 * If this gets much bigger, consider decomposing makeplural.
1026. 	 * Note: monster names are not expected here (except before corpse).
1027. 	 *
1028. 	 * special case: allow null sobj to get the singular 3rd person
1029. 	 * present tense form so we don't duplicate this code elsewhere.
1030. 	 */
1031. 	if (subj) {
1032. 	    spot = (const char *)0;
1033. 	    for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
1034. 		if (!strncmp(sp, " of ", 4) ||
1035. 		    !strncmp(sp, " called ", 8) ||
1036. 		    !strncmp(sp, " named ", 7) ||
1037. 		    !strncmp(sp, " labeled ", 9)) {
1038. 		    if (sp != subj) spot = sp - 1;
1039. 		    break;
1040. 		}
1041. 	    }
1042. 	    len = strlen(subj);
1043. 	    if (!spot) spot = subj + len - 1;
1044. 
1045. 	    /*
1046. 	     * plural: anything that ends in 's', but not '*us'.
1047. 	     * Guess at a few other special cases that makeplural creates.
1048. 	     */
1049. 	    if ((*spot == 's' && spot != subj && *(spot-1) != 'u') ||
1050. 		((spot - subj) >= 4 && !strncmp(spot-3, "eeth", 4)) ||
1051. 		((spot - subj) >= 3 && !strncmp(spot-3, "feet", 4)) ||
1052. 		((spot - subj) >= 2 && !strncmp(spot-1, "ia", 2)) ||
1053. 		((spot - subj) >= 2 && !strncmp(spot-1, "ae", 2))) {
1054. 		Strcpy(buf, verb);
1055. 		return buf;
1056. 	    }
1057. 	}
1058. 
1059. 	len = strlen(verb);
1060. 	spot = verb + len - 1;
1061. 
1062. 	if (!strcmp(verb, "are"))
1063. 	    Strcpy(buf, "is");
1064. 	else if (!strcmp(verb, "have"))
1065. 	    Strcpy(buf, "has");
1066. 	else if (index("zxs", *spot) ||
1067. 		 (len >= 2 && *spot=='h' && index("cs", *(spot-1))) ||
1068. 		 (len == 2 && *spot == 'o')) {
1069. 	    /* Ends in z, x, s, ch, sh; add an "es" */
1070. 	    Strcpy(buf, verb);
1071. 	    Strcat(buf, "es");
1072. 	} else if (*spot == 'y' && (!index(vowels, *(spot-1)))) {
1073. 	    /* like "y" case in makeplural */
1074. 	    Strcpy(buf, verb);
1075. 	    Strcpy(buf + len - 1, "ies");
1076. 	} else {
1077. 	    Strcpy(buf, verb);
1078. 	    Strcat(buf, "s");
1079. 	}
1080. 
1081. 	return buf;
1082. }
1083. 
1084. /* capitalized variant of doname() */
1085. char *
1086. Doname2(obj)
1087. register struct obj *obj;
1088. {
1089. 	register char *s = doname(obj);
1090. 
1091. 	*s = highc(*s);
1092. 	return(s);
1093. }
1094. 
1095. /* returns "your xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
1096. char *
1097. yname(obj)
1098. struct obj *obj;
1099. {
1100. 	char *outbuf = nextobuf();
1101. 	char *s = shk_your(outbuf, obj);	/* assert( s == outbuf ); */
1102. 	int space_left = BUFSZ - strlen(s) - sizeof " ";
1103. 
1104. 	return strncat(strcat(s, " "), cxname(obj), space_left);
1105. }
1106. 
1107. /* capitalized variant of yname() */
1108. char *
1109. Yname2(obj)
1110. struct obj *obj;
1111. {
1112. 	char *s = yname(obj);
1113. 
1114. 	*s = highc(*s);
1115. 	return s;
1116. }
1117. 
1118. static const char *wrp[] = {
1119. 	"wand", "ring", "potion", "scroll", "gem", "amulet",
1120. 	"spellbook", "spell book",
1121. 	/* for non-specific wishes */
1122. 	"weapon", "armor", "armour", "tool", "food", "comestible",
1123. };
1124. static const char wrpsym[] = {
1125. 	WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, GEM_CLASS,
1126. 	AMULET_CLASS, SPBOOK_CLASS, SPBOOK_CLASS,
1127. 	WEAPON_CLASS, ARMOR_CLASS, ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
1128. 	FOOD_CLASS
1129. };
1130. 
1131. #endif /* OVLB */
1132. #ifdef OVL0
1133. 
1134. /* Plural routine; chiefly used for user-defined fruits.  We have to try to
1135.  * account for everything reasonable the player has; something unreasonable
1136.  * can still break the code.  However, it's still a lot more accurate than
1137.  * "just add an s at the end", which Rogue uses...
1138.  *
1139.  * Also used for plural monster names ("Wiped out all homunculi.")
1140.  * and body parts.
1141.  *
1142.  * Also misused by muse.c to convert 1st person present verbs to 2nd person.
1143.  */
1144. char *
1145. makeplural(oldstr)
1146. const char *oldstr;
1147. {
1148. 	/* Note: cannot use strcmpi here -- it'd give MATZot, CAVEMeN,... */
1149. 	register char *spot;
1150. 	char *str = nextobuf();
1151. 	const char *excess = (char *)0;
1152. 	int len;
1153. 
1154. 	while (*oldstr==' ') oldstr++;
1155. 	if (!oldstr || !*oldstr) {
1156. 		impossible("plural of null?");
1157. 		Strcpy(str, "s");
1158. 		return str;
1159. 	}
1160. 	Strcpy(str, oldstr);
1161. 
1162. 	/*
1163. 	 * Skip changing "pair of" to "pairs of".  According to Webster, usual
1164. 	 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
1165. 	 * and pair for objects and non-humans, e.g. 3 pair of boots.  We don't
1166. 	 * refer to pairs of humans in this game so just skip to the bottom.
1167. 	 */
1168. 	if (!strncmp(str, "pair of ", 8))
1169. 		goto bottom;
1170. 
1171. 	/* Search for common compounds, ex. lump of royal jelly */
1172. 	for(spot=str; *spot; spot++) {
1173. 		if (!strncmp(spot, " of ", 4)
1174. 				|| !strncmp(spot, " labeled ", 9)
1175. 				|| !strncmp(spot, " called ", 8)
1176. 				|| !strncmp(spot, " named ", 7)
1177. 				|| !strcmp(spot, " above") /* lurkers above */
1178. 				|| !strncmp(spot, " versus ", 8)
1179. 				|| !strncmp(spot, " from ", 6)
1180. 				|| !strncmp(spot, " in ", 4)
1181. 				|| !strncmp(spot, " on ", 4)
1182. 				|| !strncmp(spot, " a la ", 6)
1183. 				|| !strncmp(spot, " with", 5)	/* " with "? */
1184. 				|| !strncmp(spot, " de ", 4)
1185. 				|| !strncmp(spot, " d'", 3)
1186. 				|| !strncmp(spot, " du ", 4)) {
1187. 			excess = oldstr + (int) (spot - str);
1188. 			*spot = 0;
1189. 			break;
1190. 		}
1191. 	}
1192. 	spot--;
1193. 	while (*spot==' ') spot--; /* Strip blanks from end */
1194. 	*(spot+1) = 0;
1195. 	/* Now spot is the last character of the string */
1196. 
1197. 	len = strlen(str);
1198. 
1199. 	/* Single letters */
1200. 	if (len==1 || !letter(*spot)) {
1201. 		Strcpy(spot+1, "'s");
1202. 		goto bottom;
1203. 	}
1204. 
1205. 	/* Same singular and plural; mostly Japanese words except for "manes" */
1206. 	if ((len == 2 && !strcmp(str, "ya")) ||
1207. 	    (len >= 2 && !strcmp(spot-1, "ai")) || /* samurai, Uruk-hai */
1208. 	    (len >= 3 && !strcmp(spot-2, " ya")) ||
1209. 	    (len >= 4 &&
1210. 	     (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") ||
1211. 	      !strcmp(spot-3, "deer") || !strcmp(spot-3, "yaki"))) ||
1212. 	    (len >= 5 && (!strcmp(spot-4, "sheep") ||
1213. 			!strcmp(spot-4, "ninja") ||
1214. 			!strcmp(spot-4, "ronin") ||
1215. 			!strcmp(spot-4, "shito") ||
1216. 			!strcmp(spot-7, "shuriken") ||
1217. 			!strcmp(spot-4, "tengu") ||
1218. 			!strcmp(spot-4, "manes"))) ||
1219. 	    (len >= 6 && !strcmp(spot-5, "ki-rin")) ||
1220. 	    (len >= 7 && !strcmp(spot-6, "gunyoki")))
1221. 		goto bottom;
1222. 
1223. 	/* man/men ("Wiped out all cavemen.") */
1224. 	if (len >= 3 && !strcmp(spot-2, "man") &&
1225. 			(len<6 || strcmp(spot-5, "shaman")) &&
1226. 			(len<5 || strcmp(spot-4, "human"))) {
1227. 		*(spot-1) = 'e';
1228. 		goto bottom;
1229. 	}
1230. 
1231. 	/* tooth/teeth */
1232. 	if (len >= 5 && !strcmp(spot-4, "tooth")) {
1233. 		Strcpy(spot-3, "eeth");
1234. 		goto bottom;
1235. 	}
1236. 
1237. 	/* knife/knives, etc... */
1238. 	if (!strcmp(spot-1, "fe")) {
1239. 		Strcpy(spot-1, "ves");
1240. 		goto bottom;
1241. 	} else if (*spot == 'f') {
1242. 		if (index("lr", *(spot-1)) || index(vowels, *(spot-1))) {
1243. 			Strcpy(spot, "ves");
1244. 			goto bottom;
1245. 		} else if (len >= 5 && !strncmp(spot-4, "staf", 4)) {
1246. 			Strcpy(spot-1, "ves");
1247. 			goto bottom;
1248. 		}
1249. 	}
1250. 
1251. 	/* foot/feet (body part) */
1252. 	if (len >= 4 && !strcmp(spot-3, "foot")) {
1253. 		Strcpy(spot-2, "eet");
1254. 		goto bottom;
1255. 	}
1256. 
1257. 	/* ium/ia (mycelia, baluchitheria) */
1258. 	if (len >= 3 && !strcmp(spot-2, "ium")) {
1259. 		*(spot--) = (char)0;
1260. 		*spot = 'a';
1261. 		goto bottom;
1262. 	}
1263. 
1264. 	/* algae, larvae, hyphae (another fungus part) */
1265. 	if ((len >= 4 && !strcmp(spot-3, "alga")) ||
1266. 	    (len >= 5 &&
1267. 	     (!strcmp(spot-4, "hypha") || !strcmp(spot-4, "larva")))) {
1268. 		Strcpy(spot, "ae");
1269. 		goto bottom;
1270. 	}
1271. 
1272. 	/* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
1273. 	if (len > 3 && !strcmp(spot-1, "us") &&
1274. 	    (len < 5 || (strcmp(spot-4, "lotus") &&
1275. 			 (len < 6 || strcmp(spot-5, "wumpus"))))) {
1276. 		*(spot--) = (char)0;
1277. 		*spot = 'i';
1278. 		goto bottom;
1279. 	}
1280. 
1281. 	/* vortex/vortices */
1282. 	if (len >= 6 && !strcmp(spot-3, "rtex")) {
1283. 		Strcpy(spot-1, "ices");
1284. 		goto bottom;
1285. 	}
1286. 
1287. 	/* djinni/djinn (note: also efreeti/efreet) */
1288. 	if (len >= 6 && !strcmp(spot-5, "djinni")) {
1289. 		*spot = (char)0;
1290. 		goto bottom;
1291. 	}
1292. 
1293. 	/* mumak/mumakil */
1294. 	if (len >= 5 && !strcmp(spot-4, "mumak")) {
1295. 		Strcpy(spot+1, "il");
1296. 		goto bottom;
1297. 	}
1298. 
1299. 	/* sis/ses (nemesis) */
1300. 	if (len >= 3 && !strcmp(spot-2, "sis")) {
1301. 		*(spot-1) = 'e';
1302. 		goto bottom;
1303. 	}
1304. 
1305. 	/* erinys/erinyes */
1306. 	if (len >= 6 && !strcmp(spot-5, "erinys")) {
1307. 		Strcpy(spot, "es");
1308. 		goto bottom;
1309. 	}
1310. 
1311. 	/* mouse/mice,louse/lice (not a monster, but possible in food names) */
1312. 	if (len >= 5 && !strcmp(spot-3, "ouse") && index("MmLl", *(spot-4))) {
1313. 		Strcpy(spot-3, "ice");
1314. 		goto bottom;
1315. 	}
1316. 
1317. 	/* matzoh/matzot, possible food name */
1318. 	if (len >= 6 && (!strcmp(spot-5, "matzoh")
1319. 					|| !strcmp(spot-5, "matzah"))) {
1320. 		Strcpy(spot-1, "ot");
1321. 		goto bottom;
1322. 	}
1323. 	if (len >= 5 && (!strcmp(spot-4, "matzo")
1324. 					|| !strcmp(spot-5, "matza"))) {
1325. 		Strcpy(spot, "ot");
1326. 		goto bottom;
1327. 	}
1328. 
1329. 	/* child/children (for wise guys who give their food funny names) */
1330. 	if (len >= 5 && !strcmp(spot-4, "child")) {
1331. 		Strcpy(spot, "dren");
1332. 		goto bottom;
1333. 	}
1334. 
1335. 	/* note: -eau/-eaux (gateau, bordeau...) */
1336. 	/* note: ox/oxen, VAX/VAXen, goose/geese */
1337. 
1338. 	/* Ends in z, x, s, ch, sh; add an "es" */
1339. 	if (index("zxs", *spot)
1340. 			|| (len >= 2 && *spot=='h' && index("cs", *(spot-1)))
1341. 	/* Kludge to get "tomatoes" and "potatoes" right */
1342. 			|| (len >= 4 && !strcmp(spot-2, "ato"))) {
1343. 		Strcpy(spot+1, "es");
1344. 		goto bottom;
1345. 	}
1346. 
1347. 	/* Ends in y preceded by consonant (note: also "qu") change to "ies" */
1348. 	if (*spot == 'y' &&
1349. 	    (!index(vowels, *(spot-1)))) {
1350. 		Strcpy(spot, "ies");
1351. 		goto bottom;
1352. 	}
1353. 
1354. 	/* Default: append an 's' */
1355. 	Strcpy(spot+1, "s");
1356. 
1357. bottom:	if (excess) Strcpy(eos(str), excess);
1358. 	return str;
1359. }
1360. 
1361. #endif /* OVL0 */
1362. 
1363. struct o_range {
1364. 	const char *name, oclass;
1365. 	int  f_o_range, l_o_range;
1366. };
1367. 
1368. #ifndef OVLB
1369. 
1370. STATIC_DCL const struct o_range o_ranges[];
1371. 
1372. #else /* OVLB */
1373. 
1374. /* wishable subranges of objects */
1375. STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
1376. 	{ "bag",	TOOL_CLASS,   SACK,	      BAG_OF_TRICKS },
1377. 	{ "lamp",	TOOL_CLASS,   OIL_LAMP,	      MAGIC_LAMP },
1378. 	{ "candle",	TOOL_CLASS,   TALLOW_CANDLE,  WAX_CANDLE },
1379. 	{ "horn",	TOOL_CLASS,   TOOLED_HORN,    HORN_OF_PLENTY },
1380. 	{ "shield",	ARMOR_CLASS,  SMALL_SHIELD,   SHIELD_OF_REFLECTION },
1381. 	{ "helm",	ARMOR_CLASS,  ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
1382. 	{ "gloves",	ARMOR_CLASS,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
1383. 	{ "gauntlets",	ARMOR_CLASS,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
1384. 	{ "boots",	ARMOR_CLASS,  LOW_BOOTS,      LEVITATION_BOOTS },
1385. 	{ "shoes",	ARMOR_CLASS,  LOW_BOOTS,      IRON_SHOES },
1386. 	{ "cloak",	ARMOR_CLASS,  MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
1387. #ifdef TOURIST
1388. 	{ "shirt",	ARMOR_CLASS,  HAWAIIAN_SHIRT, T_SHIRT },
1389. #endif
1390. 	{ "dragon scales",
1391. 			ARMOR_CLASS,  GRAY_DRAGON_SCALES, YELLOW_DRAGON_SCALES },
1392. 	{ "dragon scale mail",
1393. 			ARMOR_CLASS,  GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL },
1394. 	{ "sword",	WEAPON_CLASS, SHORT_SWORD,    KATANA },
1395. #ifdef WIZARD
1396. 	{ "venom",	VENOM_CLASS,  BLINDING_VENOM, ACID_VENOM },
1397. #endif
1398. 	{ "gray stone",	GEM_CLASS,    LUCKSTONE,      FLINT },
1399. 	{ "grey stone",	GEM_CLASS,    LUCKSTONE,      FLINT },
1400. };
1401. 
1402. #define BSTRCMP(base,ptr,string) ((ptr) < base || strcmp((ptr),string))
1403. #define BSTRCMPI(base,ptr,string) ((ptr) < base || strcmpi((ptr),string))
1404. #define BSTRNCMP(base,ptr,string,num) ((ptr)<base || strncmp((ptr),string,num))
1405. #define BSTRNCMPI(base,ptr,string,num) ((ptr)<base||strncmpi((ptr),string,num))
1406. 
1407. /*
1408.  * Singularize a string the user typed in; this helps reduce the complexity
1409.  * of readobjnam, and is also used in pager.c to singularize the string
1410.  * for which help is sought.
1411.  */
1412. char *
1413. makesingular(oldstr)
1414. const char *oldstr;
1415. {
1416. 	register char *p, *bp;
1417. 	char *str = nextobuf();
1418. 
1419. 	if (!oldstr || !*oldstr) {
1420. 		impossible("singular of null?");
1421. 		str[0] = 0;
1422. 		return str;
1423. 	}
1424. 	Strcpy(str, oldstr);
1425. 	bp = str;
1426. 
1427. 	while (*bp == ' ') bp++;
1428. 	/* find "cloves of garlic", "worthless pieces of blue glass" */
1429. 	if ((p = strstri(bp, "s of ")) != 0) {
1430. 	    /* but don't singularize "gauntlets", "boots", "Eyes of the.." */
1431. 	    if (BSTRNCMPI(bp, p-3, "Eye", 3) &&
1432. 		BSTRNCMP(bp, p-4, "boot", 4) &&
1433. 		BSTRNCMP(bp, p-8, "gauntlet", 8))
1434. 		while ((*p = *(p+1)) != 0) p++;
1435. 	    return bp;
1436. 	}
1437. 
1438. 	/* remove -s or -es (boxes) or -ies (rubies) */
1439. 	p = eos(bp);
1440. 	if (p >= bp+1 && p[-1] == 's') {
1441. 		if (p >= bp+2 && p[-2] == 'e') {
1442. 			if (p >= bp+3 && p[-3] == 'i') {
1443. 				if(!BSTRCMP(bp, p-7, "cookies") ||
1444. 				   !BSTRCMP(bp, p-4, "pies"))
1445. 					goto mins;
1446. 				Strcpy(p-3, "y");
1447. 				return bp;
1448. 			}
1449. 
1450. 			/* note: cloves / knives from clove / knife */
1451. 			if(!BSTRCMP(bp, p-6, "knives")) {
1452. 				Strcpy(p-3, "fe");
1453. 				return bp;
1454. 			}
1455. 
1456. 			if(!BSTRCMP(bp, p-6, "staves")) {
1457. 				Strcpy(p-3, "ff");
1458. 				return bp;
1459. 			}
1460. 
1461. 			if (!BSTRCMPI(bp, p-6, "leaves")) {
1462. 				Strcpy(p-3, "f");
1463. 				return bp;
1464. 			}
1465. 
1466. 			/* note: nurses, axes but boxes */
1467. 			if(!BSTRCMP(bp, p-5, "boxes")) {
1468. 				p[-2] = 0;
1469. 				return bp;
1470. 			}
1471. 			if (!BSTRCMP(bp, p-6, "gloves") ||
1472. 			    !BSTRCMP(bp, p-6, "lenses") ||
1473. 			    !BSTRCMP(bp, p-5, "shoes") ||
1474. 			    !BSTRCMP(bp, p-6, "scales"))
1475. 				return bp;
1476. 		} else if (!BSTRCMP(bp, p-5, "boots") ||
1477. 			   !BSTRCMP(bp, p-9, "gauntlets") ||
1478. 			   !BSTRCMP(bp, p-6, "tricks") ||
1479. 			   !BSTRCMP(bp, p-9, "paralysis") ||
1480. 			   !BSTRCMP(bp, p-5, "glass") ||
1481. 			   !BSTRCMP(bp, p-4, "ness") ||
1482. 			   !BSTRCMP(bp, p-14, "shape changers") ||
1483. 			   !BSTRCMP(bp, p-15, "detect monsters") ||
1484. 			   !BSTRCMPI(bp, p-11, "Aesculapius") || /* staff */
1485. 			   !BSTRCMP(bp, p-10, "eucalyptus") ||
1486. #ifdef WIZARD
1487. 			   !BSTRCMP(bp, p-9, "iron bars") ||
1488. #endif
1489. 			   !BSTRCMP(bp, p-5, "aklys"))
1490. 				return bp;
1491. 	mins:
1492. 		p[-1] = 0;
1493. 	} else {
1494. 		if(!BSTRCMP(bp, p-5, "teeth")) {
1495. 			Strcpy(p-5, "tooth");
1496. 			return bp;
1497. 		}
1498. 		/* here we cannot find the plural suffix */
1499. 	}
1500. 	return bp;
1501. }
1502. 
1503. /* compare user string against object name string using fuzzy matching */
1504. static boolean
1505. wishymatch(u_str, o_str, retry_inverted)
1506. const char *u_str;	/* from user, so might be variant spelling */
1507. const char *o_str;	/* from objects[], so is in canonical form */
1508. boolean retry_inverted;	/* optional extra "of" handling */
1509. {
1510. 	/* ignore spaces & hyphens and upper/lower case when comparing */
1511. 	if (fuzzymatch(u_str, o_str, " -", TRUE)) return TRUE;
1512. 
1513. 	if (retry_inverted) {
1514. 	    const char *u_of, *o_of;
1515. 	    char *p, buf[BUFSZ];
1516. 
1517. 	    /* when just one of the strings is in the form "foo of bar",
1518. 	       convert it into "bar foo" and perform another comparison */
1519. 	    u_of = strstri(u_str, " of ");
1520. 	    o_of = strstri(o_str, " of ");
1521. 	    if (u_of && !o_of) {
1522. 		Strcpy(buf, u_of + 4);
1523. 		p = eos(strcat(buf, " "));
1524. 		while (u_str < u_of) *p++ = *u_str++;
1525. 		*p = '\0';
1526. 		return fuzzymatch(buf, o_str, " -", TRUE);
1527. 	    } else if (o_of && !u_of) {
1528. 		Strcpy(buf, o_of + 4);
1529. 		p = eos(strcat(buf, " "));
1530. 		while (o_str < o_of) *p++ = *o_str++;
1531. 		*p = '\0';
1532. 		return fuzzymatch(u_str, buf, " -", TRUE);
1533. 	    }
1534. 	}
1535. 
1536. 	/* [note: if something like "elven speed boots" ever gets added, these
1537. 	   special cases should be changed to call wishymatch() recursively in
1538. 	   order to get the "of" inversion handling] */
1539. 	if (!strncmp(o_str, "dwarvish ", 9)) {
1540. 	    if (!strncmpi(u_str, "dwarven ", 8))
1541. 		return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
1542. 	} else if (!strncmp(o_str, "elven ", 6)) {
1543. 	    if (!strncmpi(u_str, "elvish ", 7))
1544. 		return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
1545. 	    else if (!strncmpi(u_str, "elfin ", 6))
1546. 		return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
1547. 	} else if (!strcmp(o_str, "aluminum")) {
1548. 		/* this special case doesn't really fit anywhere else... */
1549. 		/* (note that " wand" will have been stripped off by now) */
1550. 	    if (!strcmpi(u_str, "aluminium"))
1551. 		return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
1552. 	}
1553. 
1554. 	return FALSE;
1555. }
1556. 
1557. /* alternate spellings; if the difference is only the presence or
1558.    absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
1559.    vs "pick-axe") then there is no need for inclusion in this list;
1560.    likewise for ``"of" inversions ("boots of speed" vs "speed boots") */
1561. struct alt_spellings {
1562. 	const char *sp;
1563. 	int ob;
1564. } spellings[] = {
1565. 	{ "pickax", PICK_AXE },
1566. 	{ "whip", BULLWHIP },
1567. 	{ "saber", SILVER_SABER },
1568. 	{ "silver sabre", SILVER_SABER },
1569. 	{ "smooth shield", SHIELD_OF_REFLECTION },
1570. 	{ "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
1571. 	{ "grey dragon scales", GRAY_DRAGON_SCALES },
1572. 	{ "enchant armour", SCR_ENCHANT_ARMOR },
1573. 	{ "destroy armour", SCR_DESTROY_ARMOR },
1574. 	{ "scroll of enchant armour", SCR_ENCHANT_ARMOR },
1575. 	{ "scroll of destroy armour", SCR_DESTROY_ARMOR },
1576. 	{ "leather armour", LEATHER_ARMOR },
1577. 	{ "studded leather armour", STUDDED_LEATHER_ARMOR },
1578. 	{ "iron ball", HEAVY_IRON_BALL },
1579. 	{ "lantern", BRASS_LANTERN },
1580. 	{ "mattock", DWARVISH_MATTOCK },
1581. 	{ "amulet of poison resistance", AMULET_VERSUS_POISON },
1582. 	{ "stone", ROCK },
1583. #ifdef TOURIST
1584. 	{ "camera", EXPENSIVE_CAMERA },
1585. 	{ "tee shirt", T_SHIRT },
1586. #endif
1587. 	{ "can", TIN },
1588. 	{ "can opener", TIN_OPENER },
1589. 	{ "kelp", KELP_FROND },
1590. 	{ "eucalyptus", EUCALYPTUS_LEAF },
1591. 	{ "grapple", GRAPPLING_HOOK },
1592. 	{ (const char *)0, 0 },
1593. };
1594. 
1595. /*
1596.  * Return something wished for.  Specifying a null pointer for
1597.  * the user request string results in a random object.  Otherwise,
1598.  * if asking explicitly for "nothing" (or "nil") return no_wish;
1599.  * if not an object return &zeroobj; if an error (no matching object),
1600.  * return null.
1601.  * If from_user is false, we're reading from the wizkit, nothing was typed in.
1602.  */
1603. struct obj *
1604. readobjnam(bp, no_wish, from_user)
1605. register char *bp;
1606. struct obj *no_wish;
1607. boolean from_user;
1608. {
1609. 	register char *p;
1610. 	register int i;
1611. 	register struct obj *otmp;
1612. 	int cnt, spe, spesgn, typ, very, rechrg;
1613. 	int blessed, uncursed, iscursed, ispoisoned, isgreased;
1614. 	int eroded, eroded2, erodeproof;
1615. #ifdef INVISIBLE_OBJECTS
1616. 	int isinvisible;
1617. #endif
1618. 	int halfeaten, mntmp, contents;
1619. 	int islit, unlabeled, ishistoric, isdiluted;
1620. 	struct fruit *f;
1621. 	int ftype = current_fruit;
1622. 	char fruitbuf[BUFSZ];
1623. 	/* Fruits may not mess up the ability to wish for real objects (since
1624. 	 * you can leave a fruit in a bones file and it will be added to
1625. 	 * another person's game), so they must be checked for last, after
1626. 	 * stripping all the possible prefixes and seeing if there's a real
1627. 	 * name in there.  So we have to save the full original name.  However,
1628. 	 * it's still possible to do things like "uncursed burnt Alaska",
1629. 	 * or worse yet, "2 burned 5 course meals", so we need to loop to
1630. 	 * strip off the prefixes again, this time stripping only the ones
1631. 	 * possible on food.
1632. 	 * We could get even more detailed so as to allow food names with
1633. 	 * prefixes that _are_ possible on food, so you could wish for
1634. 	 * "2 3 alarm chilis".  Currently this isn't allowed; options.c
1635. 	 * automatically sticks 'candied' in front of such names.
1636. 	 */
1637. 
1638. 	char oclass;
1639. 	char *un, *dn, *actualn;
1640. 	const char *name=0;
1641. 
1642. 	cnt = spe = spesgn = typ = very = rechrg =
1643. 		blessed = uncursed = iscursed =
1644. #ifdef INVISIBLE_OBJECTS
1645. 		isinvisible =
1646. #endif
1647. 		ispoisoned = isgreased = eroded = eroded2 = erodeproof =
1648. 		halfeaten = islit = unlabeled = ishistoric = isdiluted = 0;
1649. 	mntmp = NON_PM;
1650. #define UNDEFINED 0
1651. #define EMPTY 1
1652. #define SPINACH 2
1653. 	contents = UNDEFINED;
1654. 	oclass = 0;
1655. 	actualn = dn = un = 0;
1656. 
1657. 	if (!bp) goto any;
1658. 	/* first, remove extra whitespace they may have typed */
1659. 	(void)mungspaces(bp);
1660. 	/* allow wishing for "nothing" to preserve wishless conduct...
1661. 	   [now requires "wand of nothing" if that's what was really wanted] */
1662. 	if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")) return no_wish;
1663. 	/* save the [nearly] unmodified choice string */
1664. 	Strcpy(fruitbuf, bp);
1665. 
1666. 	for(;;) {
1667. 		register int l;
1668. 
1669. 		if (!bp || !*bp) goto any;
1670. 		if (!strncmpi(bp, "an ", l=3) ||
1671. 		    !strncmpi(bp, "a ", l=2)) {
1672. 			cnt = 1;
1673. 		} else if (!strncmpi(bp, "the ", l=4)) {
1674. 			;	/* just increment `bp' by `l' below */
1675. 		} else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
1676. 			cnt = atoi(bp);
1677. 			while(digit(*bp)) bp++;
1678. 			while(*bp == ' ') bp++;
1679. 			l = 0;
1680. 		} else if (*bp == '+' || *bp == '-') {
1681. 			spesgn = (*bp++ == '+') ? 1 : -1;
1682. 			spe = atoi(bp);
1683. 			while(digit(*bp)) bp++;
1684. 			while(*bp == ' ') bp++;
1685. 			l = 0;
1686. 		} else if (!strncmpi(bp, "blessed ", l=8) ||
1687. 			   !strncmpi(bp, "holy ", l=5)) {
1688. 			blessed = 1;
1689. 		} else if (!strncmpi(bp, "cursed ", l=7) ||
1690. 			   !strncmpi(bp, "unholy ", l=7)) {
1691. 			iscursed = 1;
1692. 		} else if (!strncmpi(bp, "uncursed ", l=9)) {
1693. 			uncursed = 1;
1694. #ifdef INVISIBLE_OBJECTS
1695. 		} else if (!strncmpi(bp, "invisible ", l=10)) {
1696. 			isinvisible = 1;
1697. #endif
1698. 		} else if (!strncmpi(bp, "rustproof ", l=10) ||
1699. 			   !strncmpi(bp, "erodeproof ", l=11) ||
1700. 			   !strncmpi(bp, "corrodeproof ", l=13) ||
1701. 			   !strncmpi(bp, "fixed ", l=6) ||
1702. 			   !strncmpi(bp, "fireproof ", l=10) ||
1703. 			   !strncmpi(bp, "rotproof ", l=9)) {
1704. 			erodeproof = 1;
1705. 		} else if (!strncmpi(bp,"lit ", l=4) ||
1706. 			   !strncmpi(bp,"burning ", l=8)) {
1707. 			islit = 1;
1708. 		} else if (!strncmpi(bp,"unlit ", l=6) ||
1709. 			   !strncmpi(bp,"extinguished ", l=13)) {
1710. 			islit = 0;
1711. 		/* "unlabeled" and "blank" are synonymous */
1712. 		} else if (!strncmpi(bp,"unlabeled ", l=10) ||
1713. 			   !strncmpi(bp,"unlabelled ", l=11) ||
1714. 			   !strncmpi(bp,"blank ", l=6)) {
1715. 			unlabeled = 1;
1716. 		} else if(!strncmpi(bp, "poisoned ",l=9)
1717. #ifdef WIZARD
1718. 			  || (wizard && !strncmpi(bp, "trapped ",l=8))
1719. #endif
1720. 			  ) {
1721. 			ispoisoned=1;
1722. 		} else if(!strncmpi(bp, "greased ",l=8)) {
1723. 			isgreased=1;
1724. 		} else if (!strncmpi(bp, "very ", l=5)) {
1725. 			/* very rusted very heavy iron ball */
1726. 			very = 1;
1727. 		} else if (!strncmpi(bp, "thoroughly ", l=11)) {
1728. 			very = 2;
1729. 		} else if (!strncmpi(bp, "rusty ", l=6) ||
1730. 			   !strncmpi(bp, "rusted ", l=7) ||
1731. 			   !strncmpi(bp, "burnt ", l=6) ||
1732. 			   !strncmpi(bp, "burned ", l=7)) {
1733. 			eroded = 1 + very;
1734. 			very = 0;
1735. 		} else if (!strncmpi(bp, "corroded ", l=9) ||
1736. 			   !strncmpi(bp, "rotted ", l=7)) {
1737. 			eroded2 = 1 + very;
1738. 			very = 0;
1739. 		} else if (!strncmpi(bp, "partly eaten ", l=13)) {
1740. 			halfeaten = 1;
1741. 		} else if (!strncmpi(bp, "historic ", l=9)) {
1742. 			ishistoric = 1;
1743. 		} else if (!strncmpi(bp, "diluted ", l=8)) {
1744. 			isdiluted = 1;
1745. 		} else if(!strncmpi(bp, "empty ", l=6)) {
1746. 			contents = EMPTY;
1747. 		} else break;
1748. 		bp += l;
1749. 	}
1750. 	if(!cnt) cnt = 1;		/* %% what with "gems" etc. ? */
1751. 	if (strlen(bp) > 1) {
1752. 	    if ((p = rindex(bp, '(')) != 0) {
1753. 		if (p > bp && p[-1] == ' ') p[-1] = 0;
1754. 		else *p = 0;
1755. 		p++;
1756. 		if (!strcmpi(p, "lit)")) {
1757. 		    islit = 1;
1758. 		} else {
1759. 		    spe = atoi(p);
1760. 		    while (digit(*p)) p++;
1761. 		    if (*p == ':') {
1762. 			p++;
1763. 			rechrg = spe;
1764. 			spe = atoi(p);
1765. 			while (digit(*p)) p++;
1766. 		    }
1767. 		    if (*p != ')') {
1768. 			spe = rechrg = 0;
1769. 		    } else {
1770. 			spesgn = 1;
1771. 			p++;
1772. 			if (*p) Strcat(bp, p);
1773. 		    }
1774. 		}
1775. 	    }
1776. 	}
1777. /*
1778.    otmp->spe is type schar; so we don't want spe to be any bigger or smaller.
1779.    also, spe should always be positive  -- some cheaters may try to confuse
1780.    atoi()
1781. */
1782. 	if (spe < 0) {
1783. 		spesgn = -1;	/* cheaters get what they deserve */
1784. 		spe = abs(spe);
1785. 	}
1786. 	if (spe > SCHAR_LIM)
1787. 		spe = SCHAR_LIM;
1788. 	if (rechrg < 0 || rechrg > 7) rechrg = 7;	/* recharge_limit */
1789. 
1790. 	/* now we have the actual name, as delivered by xname, say
1791. 		green potions called whisky
1792. 		scrolls labeled "QWERTY"
1793. 		egg
1794. 		fortune cookies
1795. 		very heavy iron ball named hoei
1796. 		wand of wishing
1797. 		elven cloak
1798. 	*/
1799. 	if ((p = strstri(bp, " named ")) != 0) {
1800. 		*p = 0;
1801. 		name = p+7;
1802. 	}
1803. 	if ((p = strstri(bp, " called ")) != 0) {
1804. 		*p = 0;
1805. 		un = p+8;
1806. 		/* "helmet called telepathy" is not "helmet" (a specific type)
1807. 		 * "shield called reflection" is not "shield" (a general type)
1808. 		 */
1809. 		for(i = 0; i < SIZE(o_ranges); i++)
1810. 		    if(!strcmpi(bp, o_ranges[i].name)) {
1811. 			oclass = o_ranges[i].oclass;
1812. 			goto srch;
1813. 		    }
1814. 	}
1815. 	if ((p = strstri(bp, " labeled ")) != 0) {
1816. 		*p = 0;
1817. 		dn = p+9;
1818. 	} else if ((p = strstri(bp, " labelled ")) != 0) {
1819. 		*p = 0;
1820. 		dn = p+10;
1821. 	}
1822. 	if ((p = strstri(bp, " of spinach")) != 0) {
1823. 		*p = 0;
1824. 		contents = SPINACH;
1825. 	}
1826. 
1827. 	/*
1828. 	Skip over "pair of ", "pairs of", "set of" and "sets of".
1829. 
1830. 	Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
1831. 	English either way.  See makeplural() for more on pair/pairs.
1832. 
1833. 	We should only double count if the object in question is not
1834. 	refered to as a "pair of".  E.g. We should double if the player
1835. 	types "pair of spears", but not if the player types "pair of
1836. 	lenses".  Luckily (?) all objects that are refered to as pairs
1837. 	-- boots, gloves, and lenses -- are also not mergable, so cnt is
1838. 	ignored anyway.
1839. 	*/
1840. 	if(!strncmpi(bp, "pair of ",8)) {
1841. 		bp += 8;
1842. 		cnt *= 2;
1843. 	} else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) {
1844. 		bp += 9;
1845. 		cnt *= 2;
1846. 	} else if (!strncmpi(bp, "set of ",7)) {
1847. 		bp += 7;
1848. 	} else if (!strncmpi(bp, "sets of ",8)) {
1849. 		bp += 8;
1850. 	}
1851. 
1852. 	/*
1853. 	 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
1854. 	 * Don't check if it's a wand or spellbook.
1855. 	 * (avoid "wand/finger of death" confusion).
1856. 	 */
1857. 	if (!strstri(bp, "wand ")
1858. 	 && !strstri(bp, "spellbook ")
1859. 	 && !strstri(bp, "finger ")) {
1860. 	    if ((p = strstri(bp, " of ")) != 0
1861. 		&& (mntmp = name_to_mon(p+4)) >= LOW_PM)
1862. 		*p = 0;
1863. 	}
1864. 	/* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
1865. 	if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
1866. 	if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
1867. 	if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
1868. 	if (strncmpi(bp, "master key", 10)) /* not the "master" rank */
1869. 	if (mntmp < LOW_PM && strlen(bp) > 2 &&
1870. 	    (mntmp = name_to_mon(bp)) >= LOW_PM) {
1871. 		int mntmptoo, mntmplen;	/* double check for rank title */
1872. 		char *obp = bp;
1873. 		mntmptoo = title_to_mon(bp, (int *)0, &mntmplen);
1874. 		bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen;
1875. 		if (*bp == ' ') bp++;
1876. 		else if (!strncmpi(bp, "s ", 2)) bp += 2;
1877. 		else if (!strncmpi(bp, "es ", 3)) bp += 3;
1878. 		else if (!*bp && !actualn && !dn && !un && !oclass) {
1879. 		    /* no referent; they don't really mean a monster type */
1880. 		    bp = obp;
1881. 		    mntmp = NON_PM;
1882. 		}
1883. 	}
1884. 
1885. 	/* first change to singular if necessary */
1886. 	if (*bp) {
1887. 		char *sng = makesingular(bp);
1888. 		if (strcmp(bp, sng)) {
1889. 			if (cnt == 1) cnt = 2;
1890. 			Strcpy(bp, sng);
1891. 		}
1892. 	}
1893. 
1894. 	/* Alternate spellings (pick-ax, silver sabre, &c) */
1895.     {
1896. 	struct alt_spellings *as = spellings;
1897. 
1898. 	while (as->sp) {
1899. 		if (fuzzymatch(bp, as->sp, " -", TRUE)) {
1900. 			typ = as->ob;
1901. 			goto typfnd;
1902. 		}
1903. 		as++;
1904. 	}
1905.     }
1906. 
1907. 	/* dragon scales - assumes order of dragons */
1908. 	if(!strcmpi(bp, "scales") &&
1909. 			mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) {
1910. 		typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
1911. 		mntmp = NON_PM;	/* no monster */
1912. 		goto typfnd;
1913. 	}
1914. 
1915. 	p = eos(bp);
1916. 	if(!BSTRCMPI(bp, p-10, "holy water")) {
1917. 		typ = POT_WATER;
1918. 		if ((p-bp) >= 12 && *(p-12) == 'u')
1919. 			iscursed = 1; /* unholy water */
1920. 		else blessed = 1;
1921. 		goto typfnd;
1922. 	}
1923. 	if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) {
1924. 		typ = SCR_BLANK_PAPER;
1925. 		goto typfnd;
1926. 	}
1927. 	if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) {
1928. 		typ = SPE_BLANK_PAPER;
1929. 		goto typfnd;
1930. 	}
1931. 	/*
1932. 	 * NOTE: Gold pieces are handled as objects nowadays, and therefore
1933. 	 * this section should probably be reconsidered as well as the entire
1934. 	 * gold/money concept.  Maybe we want to add other monetary units as
1935. 	 * well in the future. (TH)
1936. 	 */
1937. 	if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
1938. 	   !strcmpi(bp, "gold") || !strcmpi(bp, "money") ||
1939. 	   !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
1940. 			if (cnt > 5000
1941. #ifdef WIZARD
1942. 					&& !wizard
1943. #endif
1944. 						) cnt=5000;
1945. 		if (cnt < 1) cnt=1;
1946. #ifndef GOLDOBJ
1947. 		if (from_user)
1948. 		    pline("%d gold piece%s.", cnt, plur(cnt));
1949. 		u.ugold += cnt;
1950. 		flags.botl=1;
1951. 		return (&zeroobj);
1952. #else
1953.                 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
1954. 		otmp->quan = cnt;
1955.                 otmp->owt = weight(otmp);
1956. 		flags.botl=1;
1957. 		return (otmp);
1958. #endif
1959. 	}
1960. 	if (strlen(bp) == 1 &&
1961. 	   (i = def_char_to_objclass(*bp)) < MAXOCLASSES && i > ILLOBJ_CLASS
1962. #ifdef WIZARD
1963. 	    && (wizard || i != VENOM_CLASS)
1964. #else
1965. 	    && i != VENOM_CLASS
1966. #endif
1967. 	    ) {
1968. 		oclass = i;
1969. 		goto any;
1970. 	}
1971. 
1972. 	/* Search for class names: XXXXX potion, scroll of XXXXX.  Avoid */
1973. 	/* false hits on, e.g., rings for "ring mail". */
1974. 	if(strncmpi(bp, "enchant ", 8) &&
1975. 	   strncmpi(bp, "destroy ", 8) &&
1976. 	   strncmpi(bp, "food detection", 14) &&
1977. 	   strncmpi(bp, "ring mail", 9) &&
1978. 	   strncmpi(bp, "studded leather arm", 19) &&
1979. 	   strncmpi(bp, "leather arm", 11) &&
1980. 	   strncmpi(bp, "tooled horn", 11) &&
1981. 	   strncmpi(bp, "food ration", 11) &&
1982. 	   strncmpi(bp, "meat ring", 9)
1983. 	)
1984. 	for (i = 0; i < (int)(sizeof wrpsym); i++) {
1985. 		register int j = strlen(wrp[i]);
1986. 		if(!strncmpi(bp, wrp[i], j)){
1987. 			oclass = wrpsym[i];
1988. 			if(oclass != AMULET_CLASS) {
1989. 			    bp += j;
1990. 			    if(!strncmpi(bp, " of ", 4)) actualn = bp+4;
1991. 			    /* else if(*bp) ?? */
1992. 			} else
1993. 			    actualn = bp;
1994. 			goto srch;
1995. 		}
1996. 		if(!BSTRCMPI(bp, p-j, wrp[i])){
1997. 			oclass = wrpsym[i];
1998. 			p -= j;
1999. 			*p = 0;
2000. 			if(p > bp && p[-1] == ' ') p[-1] = 0;
2001. 			actualn = dn = bp;
2002. 			goto srch;
2003. 		}
2004. 	}
2005. 
2006. 	/* "grey stone" check must be before general "stone" */
2007. 	for (i = 0; i < SIZE(o_ranges); i++)
2008. 	    if(!strcmpi(bp, o_ranges[i].name)) {
2009. 		typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
2010. 		goto typfnd;
2011. 	    }
2012. 
2013. 	if (!BSTRCMPI(bp, p-6, " stone")) {
2014. 		p[-6] = 0;
2015. 		oclass = GEM_CLASS;
2016. 		dn = actualn = bp;
2017. 		goto srch;
2018. 	} else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) {
2019. 		register char *g = bp;
2020. 		if (strstri(g, "broken")) return (struct obj *)0;
2021. 		if (!strncmpi(g, "worthless ", 10)) g += 10;
2022. 		if (!strncmpi(g, "piece of ", 9)) g += 9;
2023. 		if (!strncmpi(g, "colored ", 8)) g += 8;
2024. 		else if (!strncmpi(g, "coloured ", 9)) g += 9;
2025. 		if (!strcmpi(g, "glass")) {	/* choose random color */
2026. 			/* 9 different kinds */
2027. 			typ = LAST_GEM + rnd(9);
2028. 			if (objects[typ].oc_class == GEM_CLASS) goto typfnd;
2029. 			else typ = 0;	/* somebody changed objects[]? punt */
2030. 		} else if (g > bp) {	/* try to construct canonical form */
2031. 			char tbuf[BUFSZ];
2032. 			Strcpy(tbuf, "worthless piece of ");
2033. 			Strcat(tbuf, g);  /* assume it starts with the color */
2034. 			Strcpy(bp, tbuf);
2035. 		}
2036. 	}
2037. 
2038. 	actualn = bp;
2039. 	if (!dn) dn = actualn; /* ex. "skull cap" */
2040. srch:
2041. 	/* check real names of gems first */
2042. 	if(!oclass && actualn) {
2043. 	    for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
2044. 		register const char *zn;
2045. 
2046. 		if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
2047. 		    typ = i;
2048. 		    goto typfnd;
2049. 		}
2050. 	    }
2051. 	}
2052. 	i = oclass ? bases[(int)oclass] : 1;
2053. 	while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){
2054. 		register const char *zn;
2055. 
2056. 		if (actualn && (zn = OBJ_NAME(objects[i])) != 0 &&
2057. 			    wishymatch(actualn, zn, TRUE)) {
2058. 			typ = i;
2059. 			goto typfnd;
2060. 		}
2061. 		if (dn && (zn = OBJ_DESCR(objects[i])) != 0 &&
2062. 			    wishymatch(dn, zn, FALSE)) {
2063. 			/* don't match extra descriptions (w/o real name) */
2064. 			if (!OBJ_NAME(objects[i])) return (struct obj *)0;
2065. 			typ = i;
2066. 			goto typfnd;
2067. 		}
2068. 		if (un && (zn = objects[i].oc_uname) != 0 &&
2069. 			    wishymatch(un, zn, FALSE)) {
2070. 			typ = i;
2071. 			goto typfnd;
2072. 		}
2073. 		i++;
2074. 	}
2075. 	if (actualn) {
2076. 		struct Jitem *j = Japanese_items;
2077. 		while(j->item) {
2078. 			if (actualn && !strcmpi(actualn, j->name)) {
2079. 				typ = j->item;
2080. 				goto typfnd;
2081. 			}
2082. 			j++;
2083. 		}
2084. 	}
2085. 	if (!strcmpi(bp, "spinach")) {
2086. 		contents = SPINACH;
2087. 		typ = TIN;
2088. 		goto typfnd;
2089. 	}
2090. 	/* Note: not strncmpi.  2 fruits, one capital, one not, are possible. */
2091. 	{
2092. 	    char *fp;
2093. 	    int l, cntf;
2094. 	    int blessedf, iscursedf, uncursedf, halfeatenf;
2095. 
2096. 	    blessedf = iscursedf = uncursedf = halfeatenf = 0;
2097. 	    cntf = 0;
2098. 
2099. 	    fp = fruitbuf;
2100. 	    for(;;) {
2101. 		if (!fp || !*fp) break;
2102. 		if (!strncmpi(fp, "an ", l=3) ||
2103. 		    !strncmpi(fp, "a ", l=2)) {
2104. 			cntf = 1;
2105. 		} else if (!cntf && digit(*fp)) {
2106. 			cntf = atoi(fp);
2107. 			while(digit(*fp)) fp++;
2108. 			while(*fp == ' ') fp++;
2109. 			l = 0;
2110. 		} else if (!strncmpi(fp, "blessed ", l=8)) {
2111. 			blessedf = 1;
2112. 		} else if (!strncmpi(fp, "cursed ", l=7)) {
2113. 			iscursedf = 1;
2114. 		} else if (!strncmpi(fp, "uncursed ", l=9)) {
2115. 			uncursedf = 1;
2116. 		} else if (!strncmpi(fp, "partly eaten ", l=13)) {
2117. 			halfeatenf = 1;
2118. 		} else break;
2119. 		fp += l;
2120. 	    }
2121. 
2122. 	    for(f=ffruit; f; f = f->nextf) {
2123. 		char *f1 = f->fname, *f2 = makeplural(f->fname);
2124. 
2125. 		if(!strncmp(fp, f1, strlen(f1)) ||
2126. 					!strncmp(fp, f2, strlen(f2))) {
2127. 			typ = SLIME_MOLD;
2128. 			blessed = blessedf;
2129. 			iscursed = iscursedf;
2130. 			uncursed = uncursedf;
2131. 			halfeaten = halfeatenf;
2132. 			cnt = cntf;
2133. 			ftype = f->fid;
2134. 			goto typfnd;
2135. 		}
2136. 	    }
2137. 	}
2138. 
2139. 	if(!oclass && actualn) {
2140. 	    short objtyp;
2141. 
2142. 	    /* Perhaps it's an artifact specified by name, not type */
2143. 	    name = artifact_name(actualn, &objtyp);
2144. 	    if(name) {
2145. 		typ = objtyp;
2146. 		goto typfnd;
2147. 	    }
2148. 	}
2149. #ifdef WIZARD
2150. 	/* Let wizards wish for traps --KAA */
2151. 	/* must come after objects check so wizards can still wish for
2152. 	 * trap objects like beartraps
2153. 	 */
2154. 	if (wizard && from_user) {
2155. 		int trap;
2156. 
2157. 		for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
2158. 			const char *tname;
2159. 
2160. 			tname = defsyms[trap_to_defsym(trap)].explanation;
2161. 			if (!strncmpi(tname, bp, strlen(tname))) {
2162. 				/* avoid stupid mistakes */
2163. 				if((trap == TRAPDOOR || trap == HOLE)
2164. 				      && !Can_fall_thru(&u.uz)) trap = ROCKTRAP;
2165. 				(void) maketrap(u.ux, u.uy, trap);
2166. 				pline("%s.", An(tname));
2167. 				return(&zeroobj);
2168. 			}
2169. 		}
2170. 		/* or some other dungeon features -dlc */
2171. 		p = eos(bp);
2172. 		if(!BSTRCMP(bp, p-8, "fountain")) {
2173. 			levl[u.ux][u.uy].typ = FOUNTAIN;
2174. 			level.flags.nfountains++;
2175. 			if(!strncmpi(bp, "magic ", 6))
2176. 				levl[u.ux][u.uy].blessedftn = 1;
2177. 			pline("A %sfountain.",
2178. 			      levl[u.ux][u.uy].blessedftn ? "magic " : "");
2179. 			newsym(u.ux, u.uy);
2180. 			return(&zeroobj);
2181. 		}
2182. 		if(!BSTRCMP(bp, p-6, "throne")) {
2183. 			levl[u.ux][u.uy].typ = THRONE;
2184. 			pline("A throne.");
2185. 			newsym(u.ux, u.uy);
2186. 			return(&zeroobj);
2187. 		}
2188. # ifdef SINKS
2189. 		if(!BSTRCMP(bp, p-4, "sink")) {
2190. 			levl[u.ux][u.uy].typ = SINK;
2191. 			level.flags.nsinks++;
2192. 			pline("A sink.");
2193. 			newsym(u.ux, u.uy);
2194. 			return &zeroobj;
2195. 		}
2196. # endif
2197. 		if(!BSTRCMP(bp, p-4, "pool")) {
2198. 			levl[u.ux][u.uy].typ = POOL;
2199. 			del_engr_at(u.ux, u.uy);
2200. 			pline("A pool.");
2201. 			/* Must manually make kelp! */
2202. 			water_damage(level.objects[u.ux][u.uy], FALSE, TRUE);
2203. 			newsym(u.ux, u.uy);
2204. 			return &zeroobj;
2205. 		}
2206. 		if (!BSTRCMP(bp, p-4, "lava")) {  /* also matches "molten lava" */
2207. 			levl[u.ux][u.uy].typ = LAVAPOOL;
2208. 			del_engr_at(u.ux, u.uy);
2209. 			pline("A pool of molten lava.");
2210. 			if (!(Levitation || Flying)) (void) lava_effects();
2211. 			newsym(u.ux, u.uy);
2212. 			return &zeroobj;
2213. 		}
2214. 
2215. 		if(!BSTRCMP(bp, p-5, "altar")) {
2216. 		    aligntyp al;
2217. 
2218. 		    levl[u.ux][u.uy].typ = ALTAR;
2219. 		    if(!strncmpi(bp, "chaotic ", 8))
2220. 			al = A_CHAOTIC;
2221. 		    else if(!strncmpi(bp, "neutral ", 8))
2222. 			al = A_NEUTRAL;
2223. 		    else if(!strncmpi(bp, "lawful ", 7))
2224. 			al = A_LAWFUL;
2225. 		    else if(!strncmpi(bp, "unaligned ", 10))
2226. 			al = A_NONE;
2227. 		    else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
2228. 			al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1;
2229. 		    levl[u.ux][u.uy].altarmask = Align2amask( al );
2230. 		    pline("%s altar.", An(align_str(al)));
2231. 		    newsym(u.ux, u.uy);
2232. 		    return(&zeroobj);
2233. 		}
2234. 
2235. 		if(!BSTRCMP(bp, p-5, "grave") || !BSTRCMP(bp, p-9, "headstone")) {
2236. 		    make_grave(u.ux, u.uy, (char *) 0);
2237. 		    pline("A grave.");
2238. 		    newsym(u.ux, u.uy);
2239. 		    return(&zeroobj);
2240. 		}
2241. 
2242. 		if(!BSTRCMP(bp, p-4, "tree")) {
2243. 		    levl[u.ux][u.uy].typ = TREE;
2244. 		    pline("A tree.");
2245. 		    newsym(u.ux, u.uy);
2246. 		    block_point(u.ux, u.uy);
2247. 		    return &zeroobj;
2248. 		}
2249. 
2250. 		if(!BSTRCMP(bp, p-4, "bars")) {
2251. 		    levl[u.ux][u.uy].typ = IRONBARS;
2252. 		    pline("Iron bars.");
2253. 		    newsym(u.ux, u.uy);
2254. 		    return &zeroobj;
2255. 		}
2256. 	}
2257. #endif
2258. 	if(!oclass) return((struct obj *)0);
2259. any:
2260. 	if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))];
2261. typfnd:
2262. 	if (typ) oclass = objects[typ].oc_class;
2263. 
2264. 	/* check for some objects that are not allowed */
2265. 	if (typ && objects[typ].oc_unique) {
2266. #ifdef WIZARD
2267. 	    if (wizard)
2268. 		;	/* allow unique objects */
2269. 	    else
2270. #endif
2271. 	    switch (typ) {
2272. 		case AMULET_OF_YENDOR:
2273. 		    typ = FAKE_AMULET_OF_YENDOR;
2274. 		    break;
2275. 		case CANDELABRUM_OF_INVOCATION:
2276. 		    typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
2277. 		    break;
2278. 		case BELL_OF_OPENING:
2279. 		    typ = BELL;
2280. 		    break;
2281. 		case SPE_BOOK_OF_THE_DEAD:
2282. 		    typ = SPE_BLANK_PAPER;
2283. 		    break;
2284. 	    }
2285. 	}
2286. 
2287. 	/* catch any other non-wishable objects */
2288. 	if (objects[typ].oc_nowish
2289. #ifdef WIZARD
2290. 	    && !wizard
2291. #endif
2292. 	    )
2293. 	    return((struct obj *)0);
2294. 
2295. 	/* convert magic lamps to regular lamps before lighting them or setting
2296. 	   the charges */
2297. 	if (typ == MAGIC_LAMP
2298. #ifdef WIZARD
2299. 				&& !wizard
2300. #endif
2301. 						)
2302. 	    typ = OIL_LAMP;
2303. 
2304. 	if(typ) {
2305. 		otmp = mksobj(typ, TRUE, FALSE);
2306. 	} else {
2307. 		otmp = mkobj(oclass, FALSE);
2308. 		if (otmp) typ = otmp->otyp;
2309. 	}
2310. 
2311. 	if (islit &&
2312. 		(typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN ||
2313. 		 Is_candle(otmp) || typ == POT_OIL)) {
2314. 	    place_object(otmp, u.ux, u.uy);  /* make it viable light source */
2315. 	    begin_burn(otmp, FALSE);
2316. 	    obj_extract_self(otmp);	 /* now release it for caller's use */
2317. 	}
2318. 
2319. 	if(cnt > 0 && objects[typ].oc_merge && oclass != SPBOOK_CLASS &&
2320. 		(cnt < rnd(6) ||
2321. #ifdef WIZARD
2322. 		wizard ||
2323. #endif
2324. 		 (cnt <= 7 && Is_candle(otmp)) ||
2325. 		 (cnt <= 20 &&
2326. 		  ((oclass == WEAPON_CLASS && is_ammo(otmp))
2327. 				|| typ == ROCK || is_missile(otmp)))))
2328. 			otmp->quan = (long) cnt;
2329. 
2330. #ifdef WIZARD
2331. 	if (oclass == VENOM_CLASS) otmp->spe = 1;
2332. #endif
2333. 
2334. 	if (spesgn == 0) spe = otmp->spe;
2335. #ifdef WIZARD
2336. 	else if (wizard) /* no alteration to spe */ ;
2337. #endif
2338. 	else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS ||
2339. 		 is_weptool(otmp) ||
2340. 			(oclass==RING_CLASS && objects[typ].oc_charged)) {
2341. 		if(spe > rnd(5) && spe > otmp->spe) spe = 0;
2342. 		if(spe > 2 && Luck < 0) spesgn = -1;
2343. 	} else {
2344. 		if (oclass == WAND_CLASS) {
2345. 			if (spe > 1 && spesgn == -1) spe = 1;
2346. 		} else {
2347. 			if (spe > 0 && spesgn == -1) spe = 0;
2348. 		}
2349. 		if (spe > otmp->spe) spe = otmp->spe;
2350. 	}
2351. 
2352. 	if (spesgn == -1) spe = -spe;
2353. 
2354. 	/* set otmp->spe.  This may, or may not, use spe... */
2355. 	switch (typ) {
2356. 		case TIN: if (contents==EMPTY) {
2357. 				otmp->corpsenm = NON_PM;
2358. 				otmp->spe = 0;
2359. 			} else if (contents==SPINACH) {
2360. 				otmp->corpsenm = NON_PM;
2361. 				otmp->spe = 1;
2362. 			}
2363. 			break;
2364. 		case SLIME_MOLD: otmp->spe = ftype;
2365. 			/* Fall through */
2366. 		case SKELETON_KEY: case CHEST: case LARGE_BOX:
2367. 		case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
2368. 			/* otmp->cobj already done in mksobj() */
2369. 				break;
2370. #ifdef MAIL
2371. 		case SCR_MAIL: otmp->spe = 1; break;
2372. #endif
2373. 		case WAN_WISHING:
2374. #ifdef WIZARD
2375. 			if (!wizard) {
2376. #endif
2377. 				otmp->spe = (rn2(10) ? -1 : 0);
2378. 				break;
2379. #ifdef WIZARD
2380. 			}
2381. 			/* fall through, if wizard */
2382. #endif
2383. 		default: otmp->spe = spe;
2384. 	}
2385. 
2386. 	/* set otmp->corpsenm or dragon scale [mail] */
2387. 	if (mntmp >= LOW_PM) {
2388. 		if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM;
2389. 
2390. 		switch (typ) {
2391. 		case TIN:
2392. 			otmp->spe = 0; /* No spinach */
2393. 			if (dead_species(mntmp, FALSE)) {
2394. 			    otmp->corpsenm = NON_PM;	/* it's empty */
2395. 			} else if (!(mons[mntmp].geno & G_UNIQ) &&
2396. 				   !(mvitals[mntmp].mvflags & G_NOCORPSE) &&
2397. 				   mons[mntmp].cnutrit != 0) {
2398. 			    otmp->corpsenm = mntmp;
2399. 			}
2400. 			break;
2401. 		case CORPSE:
2402. 			if (!(mons[mntmp].geno & G_UNIQ) &&
2403. 				   !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
2404. 			    /* beware of random troll or lizard corpse,
2405. 			       or of ordinary one being forced to such */
2406. 			    if (otmp->timed) obj_stop_timers(otmp);
2407. 			    otmp->corpsenm = mntmp;
2408. 			    start_corpse_timeout(otmp);
2409. 			}
2410. 			break;
2411. 		case FIGURINE:
2412. 			if (!(mons[mntmp].geno & G_UNIQ)
2413. 			    && !is_human(&mons[mntmp])
2414. #ifdef MAIL
2415. 			    && mntmp != PM_MAIL_DAEMON
2416. #endif
2417. 							)
2418. 				otmp->corpsenm = mntmp;
2419. 			break;
2420. 		case EGG:
2421. 			mntmp = can_be_hatched(mntmp);
2422. 			if (mntmp != NON_PM) {
2423. 			    otmp->corpsenm = mntmp;
2424. 			    if (!dead_species(mntmp, TRUE))
2425. 				attach_egg_hatch_timeout(otmp);
2426. 			    else
2427. 				kill_egg(otmp);
2428. 			}
2429. 			break;
2430. 		case STATUE: otmp->corpsenm = mntmp;
2431. 			if (Has_contents(otmp) && verysmall(&mons[mntmp]))
2432. 			    delete_contents(otmp);	/* no spellbook */
2433. 			otmp->spe = ishistoric;
2434. 			break;
2435. 		case SCALE_MAIL:
2436. 			/* Dragon mail - depends on the order of objects */
2437. 			/*		 & dragons.			 */
2438. 			if (mntmp >= PM_GRAY_DRAGON &&
2439. 						mntmp <= PM_YELLOW_DRAGON)
2440. 			    otmp->otyp = GRAY_DRAGON_SCALE_MAIL +
2441. 						    mntmp - PM_GRAY_DRAGON;
2442. 			break;
2443. 		}
2444. 	}
2445. 
2446. 	/* set blessed/cursed -- setting the fields directly is safe
2447. 	 * since weight() is called below and addinv() will take care
2448. 	 * of luck */
2449. 	if (iscursed) {
2450. 		curse(otmp);
2451. 	} else if (uncursed) {
2452. 		otmp->blessed = 0;
2453. 		otmp->cursed = (Luck < 0
2454. #ifdef WIZARD
2455. 					 && !wizard
2456. #endif
2457. 							);
2458. 	} else if (blessed) {
2459. 		otmp->blessed = (Luck >= 0
2460. #ifdef WIZARD
2461. 					 || wizard
2462. #endif
2463. 							);
2464. 		otmp->cursed = (Luck < 0
2465. #ifdef WIZARD
2466. 					 && !wizard
2467. #endif
2468. 							);
2469. 	} else if (spesgn < 0) {
2470. 		curse(otmp);
2471. 	}
2472. 
2473. #ifdef INVISIBLE_OBJECTS
2474. 	if (isinvisible) otmp->oinvis = 1;
2475. #endif
2476. 
2477. 	/* set eroded */
2478. 	if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
2479. 	    if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
2480. 		    otmp->oeroded = eroded;
2481. 	    if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
2482. 		    otmp->oeroded2 = eroded2;
2483. 
2484. 	    /* set erodeproof */
2485. 	    if (erodeproof && !eroded && !eroded2)
2486. 		    otmp->oerodeproof = (Luck >= 0
2487. #ifdef WIZARD
2488. 					     || wizard
2489. #endif
2490. 					);
2491. 	}
2492. 
2493. 	/* set otmp->recharged */
2494. 	if (oclass == WAND_CLASS) {
2495. 	    /* prevent wishing abuse */
2496. 	    if (otmp->otyp == WAN_WISHING
2497. #ifdef WIZARD
2498. 		    && !wizard
2499. #endif
2500. 		) rechrg = 1;
2501. 	    otmp->recharged = (unsigned)rechrg;
2502. 	}
2503. 
2504. 	/* set poisoned */
2505. 	if (ispoisoned) {
2506. 	    if (is_poisonable(otmp))
2507. 		otmp->opoisoned = (Luck >= 0);
2508. 	    else if (Is_box(otmp) || typ == TIN)
2509. 		otmp->otrapped = 1;
2510. 	    else if (oclass == FOOD_CLASS)
2511. 		/* try to taint by making it as old as possible */
2512. 		otmp->age = 1L;
2513. 	}
2514. 
2515. 	if (isgreased) otmp->greased = 1;
2516. 
2517. 	if (isdiluted && otmp->oclass == POTION_CLASS &&
2518. 			otmp->otyp != POT_WATER)
2519. 		otmp->odiluted = 1;
2520. 
2521. 	if (name) {
2522. 		const char *aname;
2523. 		short objtyp;
2524. 
2525. 		/* an artifact name might need capitalization fixing */
2526. 		aname = artifact_name(name, &objtyp);
2527. 		if (aname && objtyp == otmp->otyp) name = aname;
2528. 
2529. 		otmp = oname(otmp, name);
2530. 		if (otmp->oartifact) {
2531. 			otmp->quan = 1L;
2532. 			u.uconduct.wisharti++;	/* KMH, conduct */
2533. 		}
2534. 	}
2535. 
2536. 	/* more wishing abuse: don't allow wishing for certain artifacts */
2537. 	/* and make them pay; charge them for the wish anyway! */
2538. 	if ((is_quest_artifact(otmp) ||
2539. 	     (otmp->oartifact && rn2(nartifact_exist()) > 1))
2540. #ifdef WIZARD
2541. 	    && !wizard
2542. #endif
2543. 	    ) {
2544. 	    artifact_exists(otmp, ONAME(otmp), FALSE);
2545. 	    obfree(otmp, (struct obj *) 0);
2546. 	    otmp = &zeroobj;
2547. 	    pline("For a moment, you feel %s in your %s, but it disappears!",
2548. 		  something,
2549. 		  makeplural(body_part(HAND)));
2550. 	}
2551. 
2552. 	if (halfeaten && otmp->oclass == FOOD_CLASS) {
2553. 		if (otmp->otyp == CORPSE)
2554. 			otmp->oeaten = mons[otmp->corpsenm].cnutrit;
2555. 		else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
2556. 		/* (do this adjustment before setting up object's weight) */
2557. 		consume_oeaten(otmp, 1);
2558. 	}
2559. 	otmp->owt = weight(otmp);
2560. 	if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
2561. 
2562. 	return(otmp);
2563. }
2564. 
2565. int
2566. rnd_class(first,last)
2567. int first,last;
2568. {
2569. 	int i, x, sum=0;
2570. 
2571. 	if (first == last)
2572. 	    return (first);
2573. 	for(i=first; i<=last; i++)
2574. 		sum += objects[i].oc_prob;
2575. 	if (!sum) /* all zero */
2576. 		return first + rn2(last-first+1);
2577. 	x = rnd(sum);
2578. 	for(i=first; i<=last; i++)
2579. 		if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
2580. 			return i;
2581. 	return 0;
2582. }
2583. 
2584. STATIC_OVL const char *
2585. Japanese_item_name(i)
2586. int i;
2587. {
2588. 	struct Jitem *j = Japanese_items;
2589. 
2590. 	while(j->item) {
2591. 		if (i == j->item)
2592. 			return j->name;
2593. 		j++;
2594. 	}
2595. 	return (const char *)0;
2596. }
2597. 
2598. const char *
2599. cloak_simple_name(cloak)
2600. struct obj *cloak;
2601. {
2602.     if (cloak) {
2603. 	switch (cloak->otyp) {
2604. 	case ROBE:
2605. 	    return "robe";
2606. 	case MUMMY_WRAPPING:
2607. 	    return "wrapping";
2608. 	case ALCHEMY_SMOCK:
2609. 	    return (objects[cloak->otyp].oc_name_known &&
2610. 			cloak->dknown) ? "smock" : "apron";
2611. 	default:
2612. 	    break;
2613. 	}
2614.     }
2615.     return "cloak";
2616. }
2617. 
2618. #endif /* OVLB */
2619. 
2620. /*objnam.c*/