Source:SLASH'EM 0.0.7E7F2/objnam.c

Below is the full text to objnam.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/objnam.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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