About: Source:NetHack 3.3.0/objnam.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to objnam.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/objnam.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

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