Source:NetHack 3.1.0/invent.c
Revision as of 06:36, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.1.0/invent.c moved to Source:NetHack 3.1.0/invent.c: Robot: moved page)
Below is the full text to invent.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/invent.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)invent.c 3.1 92/12/11 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "artifact.h" 7. 8. #define NOINVSYM '#' 9. #define CONTAINED_SYM '>' /* designator for inside a container */ 10. 11. #ifdef OVL1 12. static void NDECL(reorder_invent); 13. static boolean FDECL(mergable,(struct obj *,struct obj *)); 14. static int FDECL(merged,(struct obj *,struct obj *,int)); 15. #endif /* OVL1 */ 16. STATIC_DCL void FDECL(assigninvlet,(struct obj *)); 17. STATIC_DCL void FDECL(unlinkinv,(struct obj*)); 18. STATIC_DCL void FDECL(compactify,(char *)); 19. STATIC_PTR int FDECL(ckunpaid,(struct obj *)); 20. #ifdef OVLB 21. static struct obj *FDECL(find_unpaid,(struct obj *,struct obj **)); 22. static boolean NDECL(wearing_armor); 23. static boolean FDECL(is_worn,(struct obj *)); 24. #endif /* OVLB */ 25. STATIC_DCL char FDECL(obj_to_let,(struct obj *)); 26. 27. #ifdef OVLB 28. 29. static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */ 30. 31. char inv_order[] = { /* manipulated in options.c, used below */ 32. AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS, SCROLL_CLASS, 33. SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS, TOOL_CLASS, 34. GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0 }; 35. 36. #ifdef WIZARD 37. /* wizards can wish for venom, which will become an invisible inventory 38. * item without this. putting it in inv_order would mean venom would 39. * suddenly become a choice for all the inventory-class commands, which 40. * would probably cause mass confusion. the test for inventory venom 41. * is only WIZARD and not wizard because the wizard can leave venom lying 42. * around on a bones level for normal players to find. 43. */ 44. static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */ 45. #endif 46. 47. STATIC_OVL void 48. assigninvlet(otmp) 49. register struct obj *otmp; 50. { 51. boolean inuse[52]; 52. register int i; 53. register struct obj *obj; 54. 55. for(i = 0; i < 52; i++) inuse[i] = FALSE; 56. for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 57. i = obj->invlet; 58. if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 59. if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 60. if(i == otmp->invlet) otmp->invlet = 0; 61. } 62. if((i = otmp->invlet) && 63. (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 64. return; 65. for(i = lastinvnr+1; i != lastinvnr; i++) { 66. if(i == 52) { i = -1; continue; } 67. if(!inuse[i]) break; 68. } 69. otmp->invlet = (inuse[i] ? NOINVSYM : 70. (i < 26) ? ('a'+i) : ('A'+i-26)); 71. lastinvnr = i; 72. } 73. 74. #endif /* OVLB */ 75. #ifdef OVL1 76. 77. /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */ 78. #define inv_rank(o) ((o)->invlet ^ 040) 79. 80. /* sort the inventory; used by addinv() and doorganize() */ 81. static void 82. reorder_invent() 83. { 84. struct obj *otmp, *prev, *next; 85. boolean need_more_sorting; 86. 87. do { 88. /* 89. * We expect at most one item to be out of order, so this 90. * isn't nearly as inefficient as it may first appear. 91. */ 92. need_more_sorting = FALSE; 93. for (otmp = invent, prev = 0; otmp; ) { 94. next = otmp->nobj; 95. if (next && inv_rank(next) < inv_rank(otmp)) { 96. need_more_sorting = TRUE; 97. if (prev) prev->nobj = next; 98. else invent = next; 99. otmp->nobj = next->nobj; 100. next->nobj = otmp; 101. prev = next; 102. } else { 103. prev = otmp; 104. otmp = next; 105. } 106. } 107. } while (need_more_sorting); 108. } 109. 110. #undef inv_rank 111. 112. /* merge obj with otmp and delete obj if types agree */ 113. STATIC_OVL int 114. merged(otmp, obj, lose) 115. register struct obj *otmp, *obj; 116. register int lose; 117. { 118. if(mergable(otmp, obj)) { 119. /* Approximate age: we do it this way because if we were to 120. * do it "accurately" (merge only when ages are identical) 121. * we'd wind up never merging any corpses. 122. * otmp->age = otmp->age*(1-proportion) + obj->age*proportion; 123. */ 124. otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan)) 125. / (otmp->quan + obj->quan); 126. otmp->quan += obj->quan; 127. otmp->owt += obj->owt; 128. if(!otmp->onamelth && obj->onamelth) 129. otmp = oname(otmp, ONAME(obj), 1); 130. if(lose) freeobj(obj); 131. obfree(obj,otmp); /* free(obj), bill->otmp */ 132. return(1); 133. } else return(0); 134. } 135. 136. struct obj * 137. addinv(obj) 138. register struct obj *obj; 139. { 140. register struct obj *otmp, *prev; 141. 142. if (obj->otyp == GOLD_PIECE) { 143. u.ugold += obj->quan; 144. flags.botl = 1; 145. return obj; 146. } else if (obj->otyp == AMULET_OF_YENDOR) { 147. if (u.uhave.amulet) impossible ("already have amulet?"); 148. u.uhave.amulet = 1; 149. } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) { 150. if (u.uhave.menorah) impossible ("already have candelabrum?"); 151. u.uhave.menorah = 1; 152. } else if (obj->otyp == BELL_OF_OPENING) { 153. if (u.uhave.bell) impossible ("already have silver bell?"); 154. u.uhave.bell = 1; 155. } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 156. if (u.uhave.book) impossible ("already have the book?"); 157. u.uhave.book = 1; 158. #ifdef MULDGN 159. } else if (is_quest_artifact(obj)) { 160. if (u.uhave.questart) impossible ("already have the artifact?"); 161. u.uhave.questart = 1; 162. artitouch(); 163. set_artifact_intrinsic(obj, 1, W_ART); 164. #endif 165. } else if(obj->oartifact) { 166. set_artifact_intrinsic(obj, 1, W_ART); 167. } 168. /* merge if possible; find end of chain in the process */ 169. for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj) 170. if (merged(otmp, obj, 0)) { 171. obj = otmp; 172. goto added; 173. } 174. /* didn't merge, so insert into chain */ 175. if (flags.invlet_constant || !prev) { 176. if (flags.invlet_constant) assigninvlet(obj); 177. obj->nobj = invent; /* insert at beginning */ 178. invent = obj; 179. if (flags.invlet_constant) reorder_invent(); 180. } else { 181. prev->nobj = obj; /* insert at end */ 182. obj->nobj = 0; 183. } 184. 185. added: 186. if (obj->otyp == LUCKSTONE 187. || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) { 188. /* new luckstone must be in inventory by this point 189. * for correct calculation */ 190. if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD; 191. else u.moreluck = -LUCKADD; 192. } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) 193. check_lamps(); 194. update_inventory(); 195. return(obj); 196. } 197. 198. #endif /* OVL1 */ 199. #ifdef OVLB 200. 201. /* Add an item to the inventory unless we're fumbling, and give a message. 202. * If there aren't any free inventory slots, we'll drop it instead. 203. * If both success and failure messages are NULL, then we're just doing the 204. * fumbling/slot-limit checking for a silent grab. 205. * Note: will drop the whole bunch if the object merges first. 206. */ 207. struct obj * 208. hold_another_object(obj, drop_fmt, drop_arg, hold_msg) 209. struct obj *obj; 210. const char *drop_fmt, *drop_arg, *hold_msg; 211. { 212. long oquan = obj->quan; 213. if (!Blind) obj->dknown = 1; /* maximize mergibility */ 214. if (Fumbling) { 215. if (drop_fmt) pline(drop_fmt, drop_arg); 216. dropy(obj); 217. } else { 218. obj = addinv(obj); 219. if (inv_cnt() > 52 220. || ((obj->otyp != LOADSTONE || !obj->cursed) 221. && near_capacity() >= OVERLOADED)) { 222. if (drop_fmt) pline(drop_fmt, drop_arg); 223. dropx(obj); 224. } else { 225. if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan); 226. } 227. } 228. return obj; 229. } 230. 231. void 232. useup(obj) 233. register struct obj *obj; 234. { 235. /* Note: This works correctly for containers because they */ 236. /* (containers) don't merge. */ 237. if(obj->quan > 1L){ 238. #ifndef NO_SIGNAL 239. obj->in_use = FALSE; /* no longer in use */ 240. #endif 241. obj->quan--; 242. obj->owt = weight(obj); 243. } else { 244. setnotworn(obj); 245. freeinv(obj); 246. obfree(obj, (struct obj *) 0); /* deletes contents also */ 247. } 248. } 249. 250. #endif /* OVLB */ 251. #ifdef OVL3 252. 253. /* used by freeinv and doorganize to do list manipulation */ 254. STATIC_OVL 255. void 256. unlinkinv(obj) 257. register struct obj *obj; 258. { 259. register struct obj *otmp; 260. 261. if(obj == invent) 262. invent = invent->nobj; 263. else { 264. for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) 265. if(!otmp->nobj) panic("unlinkinv"); 266. otmp->nobj = obj->nobj; 267. } 268. obj->nobj = 0; 269. } 270. 271. void 272. freeinv(obj) 273. register struct obj *obj; 274. { 275. unlinkinv(obj); 276. 277. if (obj->otyp == GOLD_PIECE) { 278. u.ugold -= obj->quan; 279. flags.botl = 1; 280. return; 281. } else if (obj->otyp == AMULET_OF_YENDOR) { 282. if (!u.uhave.amulet) impossible ("don't have amulet?"); 283. u.uhave.amulet = 0; 284. } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) { 285. if (!u.uhave.menorah) impossible ("don't have candelabrum?"); 286. u.uhave.menorah = 0; 287. } else if (obj->otyp == BELL_OF_OPENING) { 288. if (!u.uhave.bell) impossible ("don't have silver bell?"); 289. u.uhave.bell = 0; 290. } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 291. if (!u.uhave.book) impossible ("don't have the book?"); 292. u.uhave.book = 0; 293. #ifdef MULDGN 294. } else if (is_quest_artifact(obj)) { 295. if(!u.uhave.questart) impossible ("don't have the artifact?"); 296. u.uhave.questart = 0; 297. set_artifact_intrinsic(obj, 0, W_ART); 298. #endif 299. } else if (obj->oartifact) { 300. set_artifact_intrinsic(obj, 0, W_ART); 301. } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP 302. || obj->otyp == BRASS_LANTERN) { 303. if (obj->lamplit) { 304. obj->lamplit = 0; 305. if (!Blind) pline("%s goes out!", The(xname(obj))); 306. } 307. check_lamps(); 308. } else if (obj->otyp == LOADSTONE) { 309. curse(obj); 310. } else if (obj->otyp == LUCKSTONE 311. || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) { 312. int luckbon = stone_luck(TRUE); 313. if (!luckbon && !carrying(LUCKSTONE)) u.moreluck = 0; 314. else if (luckbon >= 0) u.moreluck = LUCKADD; 315. else u.moreluck = -LUCKADD; 316. flags.botl = 1; 317. } 318. update_inventory(); 319. } 320. 321. void 322. delallobj(x, y) 323. int x, y; 324. { 325. struct obj *otmp, *otmp2; 326. 327. for (otmp = level.objects[x][y]; otmp; otmp = otmp2) { 328. otmp2 = otmp->nexthere; 329. if (otmp == uball) 330. unpunish(); 331. if (otmp == uchain) 332. continue; 333. delobj(otmp); 334. } 335. } 336. 337. #endif /* OVL3 */ 338. #ifdef OVL2 339. 340. /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 341. void 342. delobj(obj) 343. register struct obj *obj; 344. { 345. #ifdef WALKIES 346. if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj); 347. #endif 348. freeobj(obj); 349. newsym(obj->ox,obj->oy); 350. obfree(obj, (struct obj *) 0); /* frees contents also */ 351. } 352. 353. /* unlink obj from chain starting with fobj */ 354. void 355. freeobj(obj) 356. register struct obj *obj; 357. { 358. register struct obj *otmp; 359. 360. if (obj == fobj) 361. fobj = fobj->nobj; 362. else { 363. for(otmp = fobj; otmp; otmp = otmp->nobj) 364. if (otmp->nobj == obj) { 365. otmp->nobj = obj->nobj; 366. break; 367. } 368. if (!otmp) panic("error in freeobj"); 369. } 370. remove_object(obj); 371. } 372. 373. #endif /* OVL2 */ 374. #ifdef OVL0 375. 376. struct obj * 377. sobj_at(n,x,y) 378. register int n, x, y; 379. { 380. register struct obj *otmp; 381. 382. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 383. if(otmp->otyp == n) 384. return(otmp); 385. return((struct obj *)0); 386. } 387. 388. #endif /* OVL0 */ 389. #ifdef OVLB 390. 391. int 392. carried(obj) 393. register struct obj *obj; 394. { 395. register struct obj *otmp; 396. 397. for(otmp = invent; otmp; otmp = otmp->nobj) 398. if(otmp == obj) return(1); 399. return(0); 400. } 401. 402. struct obj * 403. carrying(type) 404. register int type; 405. { 406. register struct obj *otmp; 407. 408. for(otmp = invent; otmp; otmp = otmp->nobj) 409. if(otmp->otyp == type) 410. return(otmp); 411. return((struct obj *) 0); 412. } 413. 414. boolean 415. have_lizard() 416. { 417. register struct obj *otmp; 418. 419. for(otmp = invent; otmp; otmp = otmp->nobj) 420. if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD) 421. return(TRUE); 422. return(FALSE); 423. } 424. 425. struct obj * 426. o_on(id, objchn) 427. unsigned int id; 428. register struct obj *objchn; 429. { 430. struct obj *temp; 431. 432. while(objchn) { 433. if(objchn->o_id == id) return(objchn); 434. if (Is_container(objchn) && (temp = o_on(id,objchn->cobj))) 435. return temp; 436. objchn = objchn->nobj; 437. } 438. return((struct obj *) 0); 439. } 440. 441. boolean 442. obj_here(obj, x, y) 443. register struct obj *obj; 444. int x, y; 445. { 446. register struct obj *otmp; 447. 448. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 449. if(obj == otmp) return(TRUE); 450. return(FALSE); 451. } 452. 453. #endif /* OVLB */ 454. #ifdef OVL2 455. 456. struct obj * 457. g_at(x,y) 458. register int x, y; 459. { 460. register struct obj *obj = level.objects[x][y]; 461. while(obj) { 462. if (obj->otyp == GOLD_PIECE) return obj; 463. obj = obj->nexthere; 464. } 465. return((struct obj *)0); 466. } 467. 468. #endif /* OVL2 */ 469. #ifdef OVLB 470. 471. /* Make a gold object from the hero's gold. */ 472. struct obj * 473. mkgoldobj(q) 474. register long q; 475. { 476. register struct obj *otmp; 477. 478. otmp = mksobj(GOLD_PIECE, FALSE, FALSE); 479. u.ugold -= q; 480. otmp->quan = q; 481. otmp->owt = weight(otmp); 482. flags.botl = 1; 483. return(otmp); 484. } 485. 486. #endif /* OVLB */ 487. #ifdef OVL1 488. 489. STATIC_OVL void 490. compactify(buf) 491. register char *buf; 492. /* compact a string of inventory letters by dashing runs of letters */ 493. { 494. register int i1 = 1, i2 = 1; 495. register char ilet, ilet1, ilet2; 496. 497. ilet2 = buf[0]; 498. ilet1 = buf[1]; 499. buf[++i2] = buf[++i1]; 500. ilet = buf[i1]; 501. while(ilet) { 502. if(ilet == ilet1+1) { 503. if(ilet1 == ilet2+1) 504. buf[i2 - 1] = ilet1 = '-'; 505. else if(ilet2 == '-') { 506. buf[i2 - 1] = ++ilet1; 507. buf[i2] = buf[++i1]; 508. ilet = buf[i1]; 509. continue; 510. } 511. } 512. ilet2 = ilet1; 513. ilet1 = ilet; 514. buf[++i2] = buf[++i1]; 515. ilet = buf[i1]; 516. } 517. } 518. 519. /* 520. * getobj returns: 521. * struct obj *xxx: object to do something with. 522. * (struct obj *) 0 error return: no object. 523. * &zeroobj explicitly no object (as in w-). 524. */ 525. struct obj * 526. getobj(let,word) 527. register const char *let,*word; 528. { 529. register struct obj *otmp; 530. register char ilet; 531. char buf[BUFSZ], qbuf[QBUFSZ]; 532. char lets[BUFSZ]; 533. register int foo = 0; 534. register char *bp = buf; 535. xchar allowcnt = 0; /* 0, 1 or 2 */ 536. boolean allowgold = FALSE, usegold = FALSE; 537. /* Two possibilities: they can't use gold because it's illegal, 538. * or they can't use gold because they don't have any. 539. */ 540. boolean allowall = FALSE; 541. boolean allownone = FALSE; 542. xchar foox = 0; 543. long cnt; 544. boolean prezero = FALSE; 545. 546. if(*let == ALLOW_COUNT) let++, allowcnt = 1; 547. if(*let == GOLD_CLASS) let++, 548. usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE); 549. #ifdef POLYSELF 550. /* Equivalent of an "ugly check" for gold */ 551. if (usegold && !strcmp(word, "eat") && !metallivorous(uasmon)) 552. usegold = allowgold = FALSE; 553. #endif 554. if(*let == ALL_CLASSES) let++, allowall = TRUE; 555. if(*let == ALLOW_NONE) let++, allownone = TRUE; 556. /* "ugly check" for reading fortune cookies, part 1 */ 557. if(allowall && !strcmp(word, "read")) allowall = FALSE; 558. 559. if(allownone) *bp++ = '-'; 560. if(allowgold) *bp++ = def_oc_syms[GOLD_CLASS]; 561. if(bp > buf && bp[-1] == '-') *bp++ = ' '; 562. 563. ilet = 'a'; 564. for(otmp = invent; otmp; otmp = otmp->nobj){ 565. if(!*let || index(let, otmp->oclass)) { 566. bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; 567. 568. /* ugly check: remove inappropriate things */ 569. if((!strcmp(word, "take off") && 570. (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) 571. || (otmp==uarm && uarmc) 572. #ifdef TOURIST 573. || (otmp==uarmu && (uarm || uarmc)) 574. #endif 575. )) 576. || (!strcmp(word, "wear") && 577. (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) 578. /* already worn */ 579. || (!strcmp(word, "wield") && 580. (otmp->owornmask & W_WEP)) 581. ) { 582. foo--; 583. foox++; 584. } 585. 586. /* Second ugly check; unlike the first it won't trigger an 587. * "else" in "you don't have anything else to ___". 588. */ 589. else if ((!strcmp(word, "wear") && 590. (otmp->oclass == TOOL_CLASS && 591. otmp->otyp != BLINDFOLD && otmp->otyp != TOWEL)) 592. #ifdef POLYSELF 593. || (!strcmp(word, "eat") && !is_edible(otmp)) 594. #endif 595. || (!strcmp(word, "can") && 596. (otmp->otyp != CORPSE)) 597. || (!strcmp(word, "write with") && 598. (otmp->oclass == TOOL_CLASS && 599. otmp->otyp != MAGIC_MARKER && otmp->otyp != TOWEL)) 600. || (!strcmp(word, "rub") && 601. (otmp->oclass == TOOL_CLASS && 602. otmp->otyp != OIL_LAMP && otmp->otyp != MAGIC_LAMP && 603. otmp->otyp != BRASS_LANTERN)) 604. || (!strcmp(word, "wield") && 605. (otmp->oclass == TOOL_CLASS && 606. otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN)) 607. ) 608. foo--; 609. } else { 610. 611. /* "ugly check" for reading fortune cookies, part 2 */ 612. if ((!strcmp(word, "read") && otmp->otyp == FORTUNE_COOKIE)) 613. allowall = TRUE; 614. } 615. 616. if(ilet == 'z') ilet = 'A'; else ilet++; 617. } 618. bp[foo] = 0; 619. if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 620. Strcpy(lets, bp); /* necessary since we destroy buf */ 621. if(foo > 5) /* compactify string */ 622. compactify(bp); 623. 624. if(!foo && !allowall && !allowgold && !allownone) { 625. You("don't have anything %sto %s.", 626. foox ? "else " : "", word); 627. return((struct obj *)0); 628. } 629. for(;;) { 630. cnt = 0; 631. if (allowcnt == 2) allowcnt = 1; /* abort previous count */ 632. if(!buf[0]) { 633. Sprintf(qbuf, "What do you want to %s? [*]", word); 634. } else { 635. Sprintf(qbuf, "What do you want to %s? [%s or ?*]", 636. word, buf); 637. } 638. #ifdef REDO 639. if(!in_doagain) 640. ilet = yn_function(qbuf, NULL, '\0'); 641. else 642. #endif 643. ilet = readchar(); 644. if(ilet == '0') prezero = TRUE; 645. while(digit(ilet) && allowcnt) { 646. #ifdef REDO 647. if (ilet != '?' && ilet != '*') savech(ilet); 648. #endif 649. cnt = 10*cnt + (ilet - '0'); 650. allowcnt = 2; /* signal presence of cnt */ 651. ilet = readchar(); 652. } 653. if(digit(ilet)) { 654. pline("No count allowed with this command."); 655. continue; 656. } 657. if(index(quitchars,ilet)) { 658. if(flags.verbose) 659. pline("Never mind."); 660. return((struct obj *)0); 661. } 662. if(ilet == '-') { 663. return(allownone ? &zeroobj : (struct obj *) 0); 664. } 665. if(ilet == def_oc_syms[GOLD_CLASS]) { 666. if(!usegold){ 667. You("cannot %s gold.", word); 668. return(struct obj *)0; 669. } else if (!allowgold) { 670. You("are not carrying any gold."); 671. return(struct obj *)0; 672. } 673. if(cnt == 0 && prezero) return((struct obj *)0); 674. /* Historic note: early Nethack had a bug which was 675. * first reported for Larn, where trying to drop 2^32-n 676. * gold pieces was allowed, and did interesting things 677. * to your money supply. The LRS is the tax bureau 678. * from Larn. 679. */ 680. if(cnt < 0) { 681. pline("The LRS would be very interested to know you have that much."); 682. return(struct obj *)0; 683. } 684. 685. if(!(allowcnt == 2 && cnt < u.ugold)) 686. cnt = u.ugold; 687. return(mkgoldobj(cnt)); 688. } 689. if(allowcnt == 2 && !strcmp(word,"throw")) { 690. /* permit counts for throwing gold, but don't accept 691. * counts for other things since the throw code will 692. * split off a single item anyway */ 693. allowcnt = 1; 694. if(cnt == 0 && prezero) return((struct obj *)0); 695. if(cnt > 1) { 696. You("can only throw one item at a time."); 697. continue; 698. } 699. } 700. if(ilet == '?' || ilet == '*') { 701. ilet = display_inventory(ilet == '?' ? lets : NULL, FALSE); 702. if(!ilet) continue; 703. if(ilet == '\033') { 704. if(flags.verbose) 705. pline("Never mind."); 706. return((struct obj *)0); 707. } 708. /* they typed a letter (not a space) at the prompt */ 709. } 710. #ifdef REDO 711. savech(ilet); 712. #endif 713. if(flags.invlet_constant) { 714. for(otmp = invent; otmp; otmp = otmp->nobj) 715. if(otmp->invlet == ilet) break; 716. } else { 717. if(ilet >= 'A' && ilet <= 'Z') ilet += 'z' - 'A' + 1; 718. ilet -= 'a'; 719. for(otmp = invent; otmp && ilet; 720. ilet--, otmp = otmp->nobj) ; 721. } 722. if(!otmp) { 723. You("don't have that object."); 724. continue; 725. } else if (cnt < 0 || otmp->quan < cnt) { 726. You("don't have that many! You have only %ld.", 727. otmp->quan); 728. continue; 729. } 730. break; 731. } 732. if(!allowall && let && !index(let,otmp->oclass)) { 733. pline(silly_thing_to, word); 734. return((struct obj *)0); 735. } 736. if(allowcnt == 2) { /* cnt given */ 737. if(cnt == 0) return (struct obj *)0; 738. if(cnt != otmp->quan) { 739. register struct obj *obj = splitobj(otmp, cnt); 740. /* Very ugly kludge necessary to prevent someone from trying 741. * to drop one of several loadstones and having the loadstone 742. * now be separate. 743. */ 744. if (!strcmp(word, "drop") && 745. obj->otyp == LOADSTONE && obj->cursed) 746. otmp->corpsenm = obj->invlet; 747. if(otmp == uwep) setuwep(obj); 748. } 749. } 750. return(otmp); 751. } 752. 753. #endif /* OVL1 */ 754. #ifdef OVLB 755. 756. STATIC_PTR int 757. ckunpaid(otmp) 758. register struct obj *otmp; 759. { 760. return((int)(otmp->unpaid)); 761. } 762. 763. static boolean 764. wearing_armor() { 765. return(uarm || uarmc || uarmf || uarmg || uarmh || uarms 766. #ifdef TOURIST 767. || uarmu 768. #endif 769. ); 770. } 771. 772. static boolean 773. is_worn(otmp) 774. register struct obj *otmp; 775. { 776. return(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP))); 777. } 778. 779. static const char NEARDATA removeables[] = 780. { ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 }; 781. 782. /* interactive version of getobj - used for Drop, Identify and */ 783. /* Takeoff (A). Return the number of times fn was called successfully */ 784. int 785. ggetobj(word, fn, mx) 786. register const char *word; 787. register int FDECL((*fn),(OBJ_P)), mx; 788. { 789. char buf[BUFSZ], qbuf[QBUFSZ]; 790. register char *ip; 791. register char sym; 792. register int oletct = 0, iletct = 0; 793. register boolean allflag = FALSE; 794. char olets[20], ilets[20]; 795. int FDECL((*ckfn),(OBJ_P)) = (int (*)()) 0; 796. xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */ 797. register boolean takeoff = !strcmp(word, "take off"); 798. struct obj *obj; 799. int unpaid, oc_of_sym; 800. 801. if(takeoff && !wearing_armor() && !uwep && !uamul && 802. !uleft && !uright && !ublindf) { 803. You("are not wearing anything."); 804. return(0); 805. } 806. if(!invent && !allowgold){ 807. You("have nothing to %s.", word); 808. return(0); 809. } 810. 811. if (allowgold) ilets[iletct++] = def_oc_syms[GOLD_CLASS]; 812. ilets[iletct] = '\0'; /* terminate for index() */ 813. unpaid = 0; 814. for (obj = invent; obj; obj = obj->nobj) { 815. sym = (char) def_oc_syms[(int) obj->oclass]; 816. if (!index(ilets, sym) && (!takeoff || is_worn(obj))) { 817. ilets[iletct++] = sym; 818. /* necessary because of index() being used above */ 819. ilets[iletct] = '\0'; 820. } 821. 822. if (obj->unpaid) unpaid = 1; 823. } 824. 825. if (!takeoff && (unpaid || invent)) { 826. ilets[iletct++] = ' '; 827. if (unpaid) ilets[iletct++] = 'u'; 828. if (invent) ilets[iletct++] = 'a'; 829. } 830. ilets[iletct] = '\0'; /* outside the if to catch iletct==0 case */ 831. 832. Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]", 833. word, ilets); 834. getlin(qbuf, buf); 835. if(buf[0] == '\033') { 836. clear_nhwindow(WIN_MESSAGE); 837. return(0); 838. } 839. ip = buf; 840. olets[0] = 0; 841. while ((sym = *ip++) != 0) { 842. if(sym == ' ') continue; 843. oc_of_sym = def_char_to_objclass(sym); 844. if(takeoff && !(uwep && oc_of_sym == uwep->oclass) 845. && (oc_of_sym != MAXOCLASSES)) { 846. if(!index(removeables,oc_of_sym)) { 847. pline("Not applicable."); 848. return(0); 849. } else if(oc_of_sym == ARMOR_CLASS && !wearing_armor()) { 850. You("are not wearing any armor."); 851. return(0); 852. } else if(oc_of_sym == WEAPON_CLASS && !uwep) { 853. You("are not wielding anything."); 854. return(0); 855. } else if(oc_of_sym == RING_CLASS && !uright && !uleft) { 856. You("are not wearing rings."); 857. return(0); 858. } else if(oc_of_sym == AMULET_CLASS && !uamul) { 859. You("are not wearing an amulet."); 860. return(0); 861. } else if(oc_of_sym == TOOL_CLASS && !ublindf) { 862. You("are not wearing a blindfold."); 863. return(0); 864. } 865. } 866. if(oc_of_sym == GOLD_CLASS) { 867. if(allowgold == 1) 868. (*fn)(mkgoldobj(u.ugold)); 869. else if(!u.ugold) 870. You("have no gold."); 871. allowgold = 2; 872. } else if(sym == 'a' || sym == 'A') 873. allflag = TRUE; 874. else if(sym == 'u' || sym == 'U') 875. ckfn = ckunpaid; 876. else if (oc_of_sym == MAXOCLASSES) 877. You("don't have any %c's.", sym); 878. else if (oc_of_sym != VENOM_CLASS) {/* venom doesn't show up */ 879. if (!index(olets, oc_of_sym)) { 880. olets[oletct++] = oc_of_sym; 881. olets[oletct] = 0; 882. } 883. } 884. } 885. if(allowgold == 2 && !oletct) 886. return 1; /* you dropped gold (or at least tried to) */ 887. else 888. return askchain((struct obj **)&invent, olets, allflag, 889. fn, ckfn, mx, word); 890. } 891. 892. /* 893. * Walk through the chain starting at objchn and ask for all objects 894. * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) 895. * whether the action in question (i.e., fn) has to be performed. 896. * If allflag then no questions are asked. Max gives the max nr of 897. * objects to be treated. Return the number of objects treated. 898. */ 899. int 900. askchain(objchn, olets, allflag, fn, ckfn, mx, word) 901. struct obj **objchn; 902. register int allflag, mx; 903. register const char *olets, *word; /* olets is an Obj Class char array */ 904. register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); 905. { 906. register struct obj *otmp, *otmp2; 907. register char sym, ilet; 908. register int cnt = 0, dud = 0, tmp; 909. boolean takeoff, nodot, ident, ininv; 910. char qbuf[QBUFSZ]; 911. 912. takeoff = !strcmp(word, "take off"); 913. ident = !strcmp(word, "identify"); 914. nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || 915. ident || takeoff); 916. ininv = (*objchn == invent); 917. /* Changed so the askchain is interrogated in the order specified. 918. * For example, if a person specifies =/ then first all rings will be 919. * asked about followed by all wands -dgk 920. */ 921. nextclass: 922. ilet = 'a'-1; 923. if ((*objchn)->otyp == GOLD_PIECE) ilet--; /* extra iteration */ 924. for (otmp = *objchn; otmp; otmp = otmp2) { 925. if(ilet == 'z') ilet = 'A'; else ilet++; 926. otmp2 = otmp->nobj; 927. if (olets && *olets && otmp->oclass != *olets) continue; 928. if(takeoff && !is_worn(otmp)) continue; 929. if(ckfn && !(*ckfn)(otmp)) continue; 930. if(!allflag) { 931. Strcpy(qbuf, ininv ? 932. xprname(otmp, ilet, !nodot, 0L) : doname(otmp)); 933. Strcat(qbuf, "?"); 934. sym = (takeoff || ident || otmp->quan < 2L) ? 935. nyaq(qbuf) : nyNaq(qbuf); 936. } 937. else sym = 'y'; 938. 939. if (sym == '#') { 940. /* Number was entered; split the object unless it corresponds 941. to 'none' or 'all'. 2 special cases: cursed loadstones and 942. welded weapons (eg, multiple daggers) will remain as merged 943. unit; done to avoid splitting an object that won't be 944. droppable (even if we're picking up rather than dropping). 945. */ 946. if (!yn_number) 947. sym = 'n'; 948. else { 949. sym = 'y'; 950. if (yn_number < otmp->quan && !welded(otmp) && 951. (!otmp->cursed || otmp->otyp != LOADSTONE)) { 952. struct obj *otmpx = splitobj(otmp, yn_number); 953. if (!otmpx || otmpx->nobj != otmp2) 954. impossible("bad object split in askchain"); 955. } 956. } 957. } 958. switch(sym){ 959. case 'a': 960. allflag = 1; 961. case 'y': 962. tmp = (*fn)(otmp); 963. if(tmp < 0) goto ret; 964. cnt += tmp; 965. if(--mx == 0) goto ret; 966. case 'n': 967. if(nodot) dud++; 968. default: 969. break; 970. case 'q': 971. goto ret; 972. } 973. } 974. if (olets && *olets && *++olets) 975. goto nextclass; 976. if(!takeoff && (dud || cnt)) pline("That was all."); 977. else if(!dud && !cnt) pline("No applicable objects."); 978. ret: 979. return(cnt); 980. } 981. 982. #endif /* OVLB */ 983. #ifdef OVL2 984. 985. STATIC_OVL char 986. obj_to_let(obj) /* should of course only be called for things in invent */ 987. register struct obj *obj; 988. { 989. register struct obj *otmp; 990. register char ilet; 991. 992. if (obj->otyp == GOLD_PIECE) 993. return GOLD_SYM; 994. else if (flags.invlet_constant) 995. return obj->invlet; 996. ilet = 'a'; 997. for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) 998. if(++ilet > 'z') ilet = 'A'; 999. return(otmp ? ilet : NOINVSYM); 1000. } 1001. 1002. /* 1003. * Print the indicated quantity of the given object. If quan == 0L then use 1004. * the current quantity. 1005. */ 1006. void 1007. prinv(prefix, obj, quan) 1008. const char *prefix; 1009. register struct obj *obj; 1010. long quan; 1011. { 1012. #ifdef GCC_WARN 1013. long savequan = 0; 1014. #else 1015. long savequan; 1016. #endif 1017. if ( !prefix ) prefix = ""; 1018. if (quan) { 1019. savequan = obj->quan; 1020. obj->quan = quan; 1021. } 1022. pline("%s%s%s", 1023. prefix, *prefix ? " " : "", 1024. xprname(obj, obj_to_let(obj), TRUE, 0L)); 1025. if (quan) obj->quan = savequan; 1026. } 1027. 1028. #endif /* OVL2 */ 1029. #ifdef OVL1 1030. 1031. char * 1032. xprname(obj,let,dot,cost) 1033. register struct obj *obj; 1034. register char let; 1035. register boolean dot; /* append period; (dot && cost => Iu) */ 1036. register long cost; /* cost (for inventory of unpaid or expended items) */ 1037. { 1038. #ifdef LINT /* handle static char li[BUFSZ]; */ 1039. char li[BUFSZ]; 1040. #else 1041. static char li[BUFSZ]; 1042. #endif 1043. boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM; 1044. /* 1045. * If let is: 1046. * * Then obj == NULL and we are printing a total amount. 1047. * > Then the object is contained and doesn't have an inventory letter. 1048. */ 1049. if (cost != 0 || let == '*') { 1050. /* if dot is true, we're doing Iu, otherwise Ix */ 1051. Sprintf(li, "%c - %-45s %6ld zorkmid%s", 1052. (dot && use_invlet ? obj->invlet : let), 1053. (let != '*' ? doname(obj) : "Total:"), cost, plur(cost)); 1054. } else if (obj->otyp == GOLD_PIECE) { 1055. Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan), 1056. (dot ? "." : "")); 1057. } else { 1058. /* ordinary inventory display or pickup message */ 1059. Sprintf(li, "%c - %s", 1060. (use_invlet ? obj->invlet : let), 1061. doname(obj)); 1062. if(dot) Strcat(li,"."); 1063. } 1064. return li; 1065. } 1066. 1067. #endif /* OVL1 */ 1068. #ifdef OVLB 1069. 1070. int 1071. ddoinv() 1072. { 1073. (void) display_inventory(NULL, FALSE); 1074. return 0; 1075. } 1076. 1077. /* 1078. * find_unpaid() 1079. * 1080. * Scan the given list of objects. If last_found is NULL, return the first 1081. * unpaid object found. If last_found is not NULL, then skip over unpaid 1082. * objects until last_found is reached, then set last_found to NULL so the 1083. * next unpaid object is returned. This routine recursively follows 1084. * containers. 1085. */ 1086. static struct obj * 1087. find_unpaid(list, last_found) 1088. struct obj *list, **last_found; 1089. { 1090. struct obj *obj; 1091. 1092. while (list) { 1093. if (list->unpaid) { 1094. if (*last_found) { 1095. /* still looking for previous unpaid object */ 1096. if (list == *last_found) 1097. *last_found = (struct obj *) 0; 1098. } else 1099. return (*last_found = list); 1100. } 1101. if (Is_container(list) && list->cobj) { 1102. if ((obj = find_unpaid(list->cobj, last_found)) != 0) 1103. return obj; 1104. } 1105. list = list->nobj; 1106. } 1107. return (struct obj *) 0; 1108. } 1109. 1110. /* 1111. * If lets == NULL or "", list all objects in the inventory. Otherwise, 1112. * list all objects with object classes that match the order in lets. 1113. * The last letter could possibly be a '>' which means list unpaid contained 1114. * objects. 1115. * Returns the letter identifier of a selected item, or 0 (nothing was 1116. * selected), or '\033' (the menu was cancelled). 1117. */ 1118. char 1119. display_inventory(lets,show_cost) 1120. register const char *lets; 1121. boolean show_cost; 1122. { 1123. register struct obj *otmp; 1124. struct obj *z_obj; 1125. register char ilet; 1126. char *invlet = inv_order; 1127. int classcount; 1128. #if defined(LINT) || defined(GCC_WARN) 1129. int save_unpaid = 0; 1130. #else 1131. int save_unpaid; 1132. #endif 1133. long cost, totcost; 1134. boolean do_containers = FALSE; 1135. 1136. if(!invent){ 1137. pline("Not carrying anything."); 1138. return 0; 1139. } 1140. if (lets != NULL) { 1141. int ct = strlen(lets); /* count number of inventory slots to show */ 1142. /* If we've got unpaid items in containers, count all unpaid 1143. objects. At least one won't be in any inventory slot. */ 1144. do_containers = (ct && lets[ct-1] == CONTAINED_SYM); 1145. if (do_containers && ct == 1) ct = count_unpaid(invent); 1146. /* if only one item of interest, use pline instead of menus */ 1147. if (ct == 1) { 1148. if (do_containers) { /* single non-inventory object */ 1149. z_obj = (struct obj *) 0; 1150. if ((otmp = find_unpaid(invent, &z_obj)) != 0) 1151. pline(xprname(otmp, CONTAINED_SYM, TRUE, 1152. (show_cost ? unpaid_cost(otmp) : 0L))); 1153. else 1154. impossible( 1155. "display_inventory: no singular unpaid contained objects"); 1156. } else { 1157. for(otmp = invent; otmp; otmp = otmp->nobj) { 1158. if (otmp->invlet == lets[0]) { 1159. pline(xprname(otmp, lets[0], TRUE, 1160. (show_cost ? unpaid_cost(otmp) : 0L))); 1161. break; 1162. } 1163. } 1164. } 1165. return 0; 1166. } 1167. } 1168. 1169. start_menu(WIN_INVEN); 1170. cost = totcost = 0; 1171. nextclass: 1172. classcount = 0; 1173. ilet = 'a'; 1174. for(otmp = invent; otmp; otmp = otmp->nobj) { 1175. if(flags.invlet_constant) ilet = otmp->invlet; 1176. if(!lets || !*lets || index(lets, ilet)) { 1177. if (!flags.sortpack || otmp->oclass == *invlet) { 1178. if (flags.sortpack && !classcount) { 1179. add_menu(WIN_INVEN, 0, ATR_INVERSE, 1180. let_to_name(*invlet, show_cost)); 1181. classcount++; 1182. } 1183. if (show_cost) { 1184. totcost += cost = unpaid_cost(otmp); 1185. /* suppress "(unpaid)" suffix */ 1186. save_unpaid = otmp->unpaid; 1187. otmp->unpaid = 0; 1188. } 1189. add_menu(WIN_INVEN, ilet, 0, 1190. xprname(otmp, ilet, TRUE, cost)); 1191. if (show_cost) otmp->unpaid = save_unpaid; 1192. } 1193. } 1194. if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 1195. } 1196. if (flags.sortpack) { 1197. if (*++invlet) goto nextclass; 1198. #ifdef WIZARD 1199. if (--invlet != venom_inv) { 1200. invlet = venom_inv; 1201. goto nextclass; 1202. } 1203. #endif 1204. } 1205. 1206. /* right now, we only do this for unpaid items, so always do cost */ 1207. if (do_containers) { 1208. if (flags.sortpack) add_menu(WIN_INVEN, 0, ATR_INVERSE, 1209. let_to_name(CONTAINED_SYM, 1)); 1210. /* 1211. * Search through the container objects in the inventory for 1212. * unpaid items. Note that we check each container, not 1213. * the invent list. This is because the invent list could 1214. * have unpaid items that have been already listed. 1215. */ 1216. for (otmp = invent; otmp; otmp = otmp->nobj) { 1217. if (Is_container(otmp) && otmp->cobj) { 1218. z_obj = (struct obj *) 0; /* haven't found any */ 1219. while (find_unpaid(otmp->cobj, (struct obj **)&z_obj)) { 1220. totcost += cost = unpaid_cost(z_obj); 1221. save_unpaid = z_obj->unpaid; 1222. z_obj->unpaid = 0; /* suppress "(unpaid)" suffix */ 1223. add_menu(WIN_INVEN, 0, 0, 1224. xprname(z_obj, CONTAINED_SYM, TRUE, cost)); 1225. z_obj->unpaid = save_unpaid; 1226. } 1227. } 1228. } 1229. } 1230. 1231. if (show_cost) { 1232. /* give 'Totals' line */ 1233. add_menu(WIN_INVEN, 0, 0, ""); 1234. add_menu(WIN_INVEN, 0, 0, 1235. xprname((struct obj *)0, '*', FALSE, totcost)); 1236. } 1237. end_menu(WIN_INVEN, '\033', "\033 ", NULL); 1238. return select_menu(WIN_INVEN); 1239. } 1240. 1241. /* 1242. * Returns the number of unpaid items within the given list. This includes 1243. * contained objects. 1244. */ 1245. int 1246. count_unpaid(list) 1247. struct obj *list; 1248. { 1249. int count = 0; 1250. 1251. while (list) { 1252. if (list->unpaid) count++; 1253. if (Is_container(list) && list->cobj) 1254. count += count_unpaid(list->cobj); 1255. list = list->nobj; 1256. } 1257. return count; 1258. } 1259. 1260. int 1261. dotypeinv() /* free after Robert Viduya */ 1262. /* Changed to one type only, so you don't have to type return */ 1263. { 1264. char c, ilet; 1265. char stuff[BUFSZ]; 1266. register int stct; 1267. register struct obj *otmp; 1268. boolean billx = *u.ushops && doinvbill(0); 1269. boolean do_unpd = FALSE; 1270. int unpd, class; 1271. 1272. if (!invent && !u.ugold && !billx) { 1273. You("aren't carrying anything."); 1274. return 0; 1275. } 1276. 1277. Strcpy(stuff, "What type of object do you want an inventory of? ["); 1278. /* collect a list of classes of objects carried, for use as a prompt */ 1279. stct = collect_obj_classes(eos(stuff), invent, FALSE, (u.ugold != 0)); 1280. unpd = count_unpaid(invent); 1281. if(unpd) Strcat(stuff, "u"); 1282. if(billx) Strcat(stuff, "x"); 1283. Strcat(stuff, "]"); 1284. 1285. if(stct > 1) { 1286. c = yn_function(stuff, NULL, '\0'); 1287. #ifdef REDO 1288. savech(c); 1289. #endif 1290. if(c == '\0') { 1291. clear_nhwindow(WIN_MESSAGE); 1292. return 0; 1293. } 1294. } else 1295. c = stuff[0]; 1296. 1297. if(c == 'x' || c == 'X') { 1298. if(billx) 1299. (void) doinvbill(1); 1300. else 1301. pline("No used-up objects on the shopping bill."); 1302. return(0); 1303. } 1304. 1305. if (c == 'u' || c == 'U') { 1306. if (!unpd) { 1307. You("are not carrying any unpaid objects."); 1308. return(0); 1309. } 1310. do_unpd = TRUE; 1311. } 1312. 1313. class = def_char_to_objclass(c); /* change to object class */ 1314. 1315. if(class == GOLD_CLASS) 1316. return(doprgold()); 1317. 1318. /* collect all items which match the selected objclass */ 1319. stct = 0; 1320. ilet = 'a'; 1321. for (otmp = invent; otmp; otmp = otmp->nobj) { 1322. if(flags.invlet_constant) ilet = otmp->invlet; 1323. if (class == otmp->oclass || (do_unpd && otmp->unpaid)) { 1324. stuff[stct++] = ilet; 1325. --unpd; /* decrement unpaid count */ 1326. } 1327. if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 1328. } 1329. /* unpd is now the number of unpaid contained objects */ 1330. if (do_unpd && unpd) 1331. stuff[stct++] = CONTAINED_SYM; /* list contained unpaid items */ 1332. 1333. stuff[stct] = '\0'; 1334. if(stct == 0) 1335. You("have no such objects."); 1336. else 1337. (void) display_inventory(stuff, do_unpd); 1338. 1339. return(0); 1340. } 1341. 1342. /* look at what is here */ 1343. int 1344. dolook() 1345. { 1346. register struct obj *otmp, *otmp0; 1347. struct trap *trap; 1348. const char *verb = Blind ? "feel" : "see"; 1349. const char *dfeature = (char*) 0; 1350. char fbuf[BUFSZ], fbuf2[BUFSZ]; 1351. int ct; 1352. boolean no_article = FALSE; 1353. winid tmpwin; 1354. 1355. if(u.uswallow) { 1356. You("%s no objects here.", verb); 1357. return(!!Blind); 1358. } 1359. read_engr_at(u.ux, u.uy); /* Eric Backus */ 1360. if ((trap = t_at(u.ux,u.uy)) && trap->tseen) 1361. pline("There is a%s here.", traps[trap->ttyp]); 1362. 1363. otmp0 = level.objects[u.ux][u.uy]; 1364. 1365. if(IS_DOOR(levl[u.ux][u.uy].typ)) { 1366. switch(levl[u.ux][u.uy].doormask) { 1367. case D_NODOOR: 1368. dfeature = "doorway"; break; 1369. case D_ISOPEN: 1370. dfeature = "open door"; break; 1371. case D_BROKEN: 1372. dfeature = "broken door"; break; 1373. default: 1374. dfeature = "closed door"; 1375. } 1376. } else if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) 1377. /* added by GAN 10/30/86 */ 1378. dfeature = "fountain"; 1379. else if(IS_THRONE(levl[u.ux][u.uy].typ)) 1380. dfeature = "opulent throne"; 1381. else if(is_lava(u.ux,u.uy)) 1382. dfeature = "molten lava", no_article = TRUE; 1383. else if(is_ice(u.ux,u.uy)) 1384. dfeature = "ice", no_article = TRUE; 1385. else if(is_pool(u.ux,u.uy) && !Underwater) 1386. dfeature = "pool of water"; 1387. #ifdef SINKS 1388. else if(IS_SINK(levl[u.ux][u.uy].typ)) 1389. dfeature = "kitchen sink"; 1390. #endif 1391. else if(IS_ALTAR(levl[u.ux][u.uy].typ)) { 1392. Sprintf(fbuf2, "altar to %s (%s)", 1393. a_gname(), 1394. align_str(Amask2align(levl[u.ux][u.uy].altarmask 1395. & ~AM_SHRINE))); 1396. dfeature = fbuf2; 1397. } else if(u.ux == xupstair && u.uy == yupstair) 1398. dfeature = "stairway up"; 1399. else if(u.ux == xdnstair && u.uy == ydnstair) 1400. dfeature = "stairway down"; 1401. else if(u.ux == sstairs.sx && u.uy == sstairs.sy) { 1402. if (sstairs.up) 1403. dfeature = "stairway up"; 1404. else 1405. dfeature = "stairway down"; 1406. } else if(u.ux == xupladder && u.uy == yupladder) 1407. dfeature = "ladder up"; 1408. else if(u.ux == xdnladder && u.uy == ydnladder) 1409. dfeature = "ladder down"; 1410. else if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) 1411. dfeature = "lowered drawbridge"; 1412. 1413. if (Blind) { 1414. You("try to feel what is %s.", 1415. Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ? 1416. "floating here" : 1417. "lying here on the floor"); 1418. if (Levitation && 1419. !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) { 1420. pline("But you can't reach it!"); 1421. return(0); 1422. } 1423. } 1424. 1425. if (dfeature) 1426. Sprintf(fbuf, "There is %s%s here.", 1427. no_article ? "" : 1428. index(vowels,dfeature[0]) ? "an " : "a ", 1429. dfeature); 1430. 1431. if(!otmp0 || (is_pool(u.ux,u.uy) && !Underwater)) { 1432. if(dfeature) pline(fbuf); 1433. if(Blind || !dfeature) 1434. You("%s no objects here.", verb); 1435. return(!!Blind); 1436. } 1437. /* we know there is something here */ 1438. 1439. /* find out if there is more than one object there */ 1440. for (ct = 0, otmp = otmp0; otmp; otmp = otmp->nexthere) 1441. if (++ct > 1) break; 1442. 1443. if (ct == 1) { 1444. if (dfeature) pline(fbuf); 1445. You("%s here %s.", verb, doname(otmp0)); 1446. } else { 1447. display_nhwindow(NHW_MESSAGE, FALSE); 1448. tmpwin = create_nhwindow(NHW_MENU); 1449. if(dfeature) { 1450. putstr(tmpwin, 0, fbuf); 1451. putstr(tmpwin, 0, ""); 1452. } 1453. putstr(tmpwin, 0, "Things that are here:"); 1454. for(otmp = otmp0; otmp; otmp = otmp->nexthere) { 1455. putstr(tmpwin, 0, doname(otmp)); 1456. 1457. if(Blind && !uarmg && 1458. #ifdef POLYSELF 1459. !resists_ston(uasmon) && 1460. #endif 1461. (otmp->otyp == CORPSE && 1462. otmp->corpsenm == PM_COCKATRICE)) { 1463. #if defined(POLYSELF) 1464. if(poly_when_stoned(uasmon)) { 1465. You("touched the cockatrice corpse with your bare hands."); 1466. (void) polymon(PM_STONE_GOLEM); 1467. } else 1468. #endif 1469. { 1470. pline("Touching the cockatrice corpse is a fatal mistake..."); 1471. You("turn to stone..."); 1472. killer_format = KILLED_BY_AN; 1473. killer = "cockatrice corpse"; 1474. done(STONING); 1475. } 1476. } 1477. } 1478. display_nhwindow(tmpwin, TRUE); 1479. destroy_nhwindow(tmpwin); 1480. } 1481. return(!!Blind); 1482. } 1483. 1484. #endif /* OVLB */ 1485. #ifdef OVL1 1486. 1487. void 1488. stackobj(obj) 1489. register struct obj *obj; 1490. { 1491. register struct obj *otmp; 1492. 1493. for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere) 1494. if(otmp != obj && merged(obj,otmp,1)) 1495. break; 1496. return; 1497. } 1498. 1499. static boolean 1500. mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ 1501. register struct obj *otmp, *obj; 1502. { 1503. if(obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid || 1504. obj->spe != otmp->spe || obj->dknown != otmp->dknown || 1505. (obj->bknown != otmp->bknown && pl_character[0] != 'P') || 1506. obj->cursed != otmp->cursed || obj->blessed != otmp->blessed || 1507. obj->no_charge != otmp->no_charge || 1508. obj->obroken != otmp->obroken || 1509. obj->otrapped != otmp->otrapped || 1510. obj->oeroded != otmp->oeroded) 1511. return(FALSE); 1512. 1513. if((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) && 1514. (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown)) 1515. return FALSE; 1516. 1517. if(obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten || 1518. obj->orotten != otmp->orotten)) 1519. return(FALSE); 1520. 1521. if(obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) { 1522. if((obj->corpsenm != otmp->corpsenm) || 1523. (ONAME(obj) && strcmp(ONAME(obj), ONAME(otmp)))) 1524. return FALSE; 1525. } 1526. 1527. /* if they have names, make sure they're the same */ 1528. if ( (obj->onamelth != otmp->onamelth && 1529. ((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE) 1530. ) || 1531. (obj->onamelth && 1532. strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth))) 1533. return FALSE; 1534. 1535. if(obj->oartifact != otmp->oartifact) return FALSE; 1536. 1537. if(obj->known == otmp->known || 1538. !objects[otmp->otyp].oc_uses_known) { 1539. return(objects[obj->otyp].oc_merge); 1540. } else return(FALSE); 1541. } 1542. 1543. #endif /* OVL1 */ 1544. #ifdef OVLB 1545. 1546. int 1547. doprgold(){ 1548. if(!u.ugold) 1549. You("do not carry any gold."); 1550. else 1551. You("are carrying %ld gold piece%s.", u.ugold, plur(u.ugold)); 1552. return 0; 1553. } 1554. 1555. int 1556. doprwep() 1557. { 1558. if(!uwep) You("are empty %s.", body_part(HANDED)); 1559. else prinv(NULL, uwep, 0L); 1560. return 0; 1561. } 1562. 1563. int 1564. doprarm(){ 1565. if(!wearing_armor()) 1566. You("are not wearing any armor."); 1567. else { 1568. #ifdef TOURIST 1569. char lets[8]; 1570. #else 1571. char lets[7]; 1572. #endif 1573. register int ct = 0; 1574. 1575. #ifdef TOURIST 1576. if(uarmu) lets[ct++] = obj_to_let(uarmu); 1577. #endif 1578. if(uarm) lets[ct++] = obj_to_let(uarm); 1579. if(uarmc) lets[ct++] = obj_to_let(uarmc); 1580. if(uarmh) lets[ct++] = obj_to_let(uarmh); 1581. if(uarms) lets[ct++] = obj_to_let(uarms); 1582. if(uarmg) lets[ct++] = obj_to_let(uarmg); 1583. if(uarmf) lets[ct++] = obj_to_let(uarmf); 1584. lets[ct] = 0; 1585. (void) display_inventory(lets, FALSE); 1586. } 1587. return 0; 1588. } 1589. 1590. int 1591. doprring(){ 1592. if(!uleft && !uright) 1593. You("are not wearing any rings."); 1594. else { 1595. char lets[3]; 1596. register int ct = 0; 1597. 1598. if(uleft) lets[ct++] = obj_to_let(uleft); 1599. if(uright) lets[ct++] = obj_to_let(uright); 1600. lets[ct] = 0; 1601. (void) display_inventory(lets, FALSE); 1602. } 1603. return 0; 1604. } 1605. 1606. int 1607. dopramulet(){ 1608. if (!uamul) 1609. You("are not wearing an amulet."); 1610. else 1611. prinv(NULL, uamul, 0L); 1612. return 0; 1613. } 1614. 1615. int 1616. doprtool(){ 1617. register struct obj *otmp; 1618. register int ct=0; 1619. char lets[3]; /* Maximum: pick-axe, blindfold */ 1620. 1621. for(otmp = invent; otmp; otmp = otmp->nobj) { 1622. if (((otmp->owornmask & W_TOOL) && otmp->oclass==TOOL_CLASS) 1623. || (otmp==uwep && 1624. (otmp->otyp==PICK_AXE || otmp->otyp==TIN_OPENER))) 1625. lets[ct++] = obj_to_let(otmp); 1626. } 1627. lets[ct] = 0; 1628. if (!ct) You("are not using any tools."); 1629. else (void) display_inventory(lets, FALSE); 1630. return 0; 1631. } 1632. 1633. /* 1634. * uses up an object that's on the floor, charging for it as necessary 1635. */ 1636. void 1637. useupf(obj) 1638. register struct obj *obj; 1639. { 1640. register struct obj *otmp; 1641. 1642. /* burn_floor_paper() keeps an object pointer that it tries to 1643. * useupf() multiple times, so obj must survive if plural */ 1644. if(obj->quan > 1L) 1645. otmp = splitobj(obj, obj->quan - 1L); 1646. else 1647. otmp = obj; 1648. if(costly_spot(otmp->ox, otmp->oy)) { 1649. if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0))) 1650. addtobill(otmp, FALSE, FALSE, FALSE); 1651. else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE); 1652. } 1653. delobj(otmp); 1654. } 1655. 1656. #endif /* OVLB */ 1657. #ifdef OVL1 1658. 1659. extern const char obj_symbols[]; /* o_init.c */ 1660. /* 1661. * Conversion from a symbol to a string for printing object classes. 1662. * This must match the array obj_symbols[]. 1663. */ 1664. static const char NEARDATA *names[] = { 1665. "Illegal objects", "Amulets", "Coins", "Comestibles", "Weapons", 1666. "Tools", "Iron balls", "Chains", "Boulders/Statues", "Armor", 1667. "Potions", "Scrolls", "Wands", "Spellbooks", "Rings", "Gems" 1668. }; 1669. 1670. static const char NEARDATA oth_symbols[] = { 1671. #ifdef WIZARD 1672. VENOM_CLASS, 1673. #endif 1674. CONTAINED_SYM, 1675. '\0' 1676. }; 1677. 1678. static const char NEARDATA *oth_names[] = { 1679. #ifdef WIZARD 1680. "Venoms", 1681. #endif 1682. "Bagged/Boxed items" 1683. }; 1684. 1685. char * 1686. let_to_name(let,unpaid) 1687. char let; 1688. boolean unpaid; 1689. { 1690. const char *class_name; 1691. const char *pos = index(obj_symbols, let); 1692. int len; 1693. static char NEARDATA *buf = NULL; 1694. static unsigned NEARDATA bufsiz = 0; 1695. 1696. if (pos) 1697. class_name = names[pos - obj_symbols]; 1698. else if ((pos = index(oth_symbols, let)) != 0) 1699. class_name = oth_names[pos - oth_symbols]; 1700. else 1701. class_name = names[0]; 1702. 1703. len = strlen(class_name) 1704. + (unpaid ? sizeof("unpaid_") : 1); /* count terminating NUL */ 1705. if (len > bufsiz) { 1706. if (buf) free((genericptr_t)buf), buf = NULL; 1707. bufsiz = len + 10; /* add slop to avoid incremental reallocations */ 1708. buf = (char *) alloc(bufsiz); 1709. } 1710. if (unpaid) 1711. Strcat(strcpy(buf, "Unpaid "), class_name); 1712. else 1713. Strcpy(buf, class_name); 1714. return (buf); 1715. } 1716. 1717. #endif /* OVL1 */ 1718. #ifdef OVLB 1719. 1720. void 1721. reassign() 1722. { 1723. register int i; 1724. register struct obj *obj; 1725. 1726. for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1727. obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1728. lastinvnr = i; 1729. } 1730. 1731. #endif /* OVLB */ 1732. #ifdef OVL1 1733. int 1734. doorganize() /* inventory organizer by Del Lamb */ 1735. { 1736. register struct obj *obj, *otmp; 1737. register int ix, cur; 1738. register char let; 1739. char alphabet[52+1], buf[52+1]; 1740. char qbuf[QBUFSZ]; 1741. char allow_all[2]; 1742. const char *adj_type; 1743. 1744. /* check to see if the inventory is of the fixed kind */ 1745. if (!flags.invlet_constant ) { 1746. pline("Sorry, only fixed inventories can be adjusted."); 1747. return(0); 1748. } 1749. #if 0 1750. /* check to see if the inventory has any gaps left in it */ 1751. if (inv_cnt() >= 52) { 1752. pline("Sorry, no available letters for adjustment."); 1753. return(0); 1754. } 1755. #endif 1756. /* get a pointer to the object the user wants to organize */ 1757. allow_all[0] = ALL_CLASSES; allow_all[1] = '\0'; 1758. if (!(obj = getobj(allow_all,"adjust"))) return(0); 1759. 1760. /* initialize the list with all upper and lower case letters */ 1761. for (let = 'a', ix = 0; let <= 'z';) alphabet[ix++] = let++; 1762. for (let = 'A', ix = 26; let <= 'Z';) alphabet[ix++] = let++; 1763. alphabet[52] = 0; 1764. 1765. /* blank out all the letters currently in use in the inventory */ 1766. /* except those that will be merged with the selected object */ 1767. for (otmp = invent; otmp; otmp = otmp->nobj) 1768. if (otmp != obj && !mergable(otmp,obj)) 1769. if (otmp->invlet <= 'Z') 1770. alphabet[(otmp->invlet) - 'A' + 26] = ' '; 1771. else alphabet[(otmp->invlet) - 'a'] = ' '; 1772. 1773. /* compact the list by removing all the blanks */ 1774. for (ix = cur = 0; ix <= 52; ix++) 1775. if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix]; 1776. 1777. /* and by dashing runs of letters */ 1778. if(cur > 5) compactify(buf); 1779. 1780. /* get new letter to use as inventory letter */ 1781. for (;;) { 1782. Sprintf(qbuf, "Adjust letter to what [%s]?",buf); 1783. let = yn_function(qbuf, NULL, '\0'); 1784. if(index(quitchars,let)) { 1785. pline("Never mind."); 1786. return(0); 1787. } 1788. if (let == '@' || !letter(let)) 1789. pline("Select an inventory slot letter."); 1790. else 1791. break; 1792. } 1793. 1794. /* change the inventory and print the resulting item */ 1795. adj_type = "Moving:"; 1796. 1797. /* 1798. * don't use freeinv/addinv to avoid double-touching artifacts, 1799. * dousing lamps, losing luck, cursing loadstone, etc. 1800. */ 1801. unlinkinv(obj); 1802. 1803. for (otmp = invent; otmp;) 1804. if (merged(otmp,obj,0)) { 1805. adj_type = "Merging:"; 1806. obj = otmp; 1807. otmp = otmp->nobj; 1808. unlinkinv(obj); 1809. } else { 1810. if (otmp->invlet == let) { 1811. adj_type = "Swapping:"; 1812. otmp->invlet = obj->invlet; 1813. } 1814. otmp = otmp->nobj; 1815. } 1816. 1817. /* inline addinv (assuming flags.invlet_constant and !merged) */ 1818. obj->invlet = let; 1819. obj->nobj = invent; /* insert at beginning */ 1820. invent = obj; 1821. reorder_invent(); 1822. 1823. prinv(adj_type, obj, 0L); 1824. update_inventory(); 1825. return(0); 1826. } 1827. 1828. #endif /* OVL1 */ 1829. 1830. /*invent.c*/