abstract
| - Below is the full text to invent.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/invent.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)invent.c 3.2 96/03/03 */ 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 void FDECL(invdisp_nothing, (const char *,const char *)); 15. static boolean FDECL(worn_wield_only, (struct obj *)); 16. static boolean FDECL(only_here, (struct obj *)); 17. #endif /* OVL1 */ 18. STATIC_DCL void FDECL(compactify,(char *)); 19. STATIC_PTR int FDECL(ckunpaid,(struct obj *)); 20. #ifdef OVLB 21. static boolean FDECL(this_type_only, (struct obj *)); 22. static void NDECL(dounpaid); 23. static struct obj *FDECL(find_unpaid,(struct obj *,struct obj **)); 24. static void FDECL(fully_identify_obj, (struct obj *)); 25. static void FDECL(menu_identify, (int)); 26. static void FDECL(feel_cockatrice, (struct obj *)); 27. #endif /* OVLB */ 28. STATIC_DCL char FDECL(obj_to_let,(struct obj *)); 29. 30. 31. #ifdef OVLB 32. 33. static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */ 34. 35. #ifdef WIZARD 36. /* wizards can wish for venom, which will become an invisible inventory 37. * item without this. putting it in inv_order would mean venom would 38. * suddenly become a choice for all the inventory-class commands, which 39. * would probably cause mass confusion. the test for inventory venom 40. * is only WIZARD and not wizard because the wizard can leave venom lying 41. * around on a bones level for normal players to find. 42. */ 43. static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */ 44. #endif 45. 46. void 47. assigninvlet(otmp) 48. register struct obj *otmp; 49. { 50. boolean inuse[52]; 51. register int i; 52. register struct obj *obj; 53. 54. for(i = 0; i < 52; i++) inuse[i] = FALSE; 55. for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 56. i = obj->invlet; 57. if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 58. if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 59. if(i == otmp->invlet) otmp->invlet = 0; 60. } 61. if((i = otmp->invlet) && 62. (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 63. return; 64. for(i = lastinvnr+1; i != lastinvnr; i++) { 65. if(i == 52) { i = -1; continue; } 66. if(!inuse[i]) break; 67. } 68. otmp->invlet = (inuse[i] ? NOINVSYM : 69. (i < 26) ? ('a'+i) : ('A'+i-26)); 70. lastinvnr = i; 71. } 72. 73. #endif /* OVLB */ 74. #ifdef OVL1 75. 76. /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */ 77. #define inv_rank(o) ((o)->invlet ^ 040) 78. 79. /* sort the inventory; used by addinv() and doorganize() */ 80. static void 81. reorder_invent() 82. { 83. struct obj *otmp, *prev, *next; 84. boolean need_more_sorting; 85. 86. do { 87. /* 88. * We expect at most one item to be out of order, so this 89. * isn't nearly as inefficient as it may first appear. 90. */ 91. need_more_sorting = FALSE; 92. for (otmp = invent, prev = 0; otmp; ) { 93. next = otmp->nobj; 94. if (next && inv_rank(next) < inv_rank(otmp)) { 95. need_more_sorting = TRUE; 96. if (prev) prev->nobj = next; 97. else invent = next; 98. otmp->nobj = next->nobj; 99. next->nobj = otmp; 100. prev = next; 101. } else { 102. prev = otmp; 103. otmp = next; 104. } 105. } 106. } while (need_more_sorting); 107. } 108. 109. #undef inv_rank 110. 111. /* scan a list of objects to see whether another object will merge with 112. one of them; used in pickup.c */ 113. struct obj * 114. merge_choice(objlist, obj) 115. struct obj *objlist, *obj; 116. { 117. if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */ 118. return (struct obj *)0; 119. while (objlist) { 120. if (mergable(objlist, obj)) return objlist; 121. objlist = objlist->nobj; 122. } 123. return (struct obj *)0; 124. } 125. 126. /* merge obj with otmp and delete obj if types agree */ 127. int 128. merged(potmp, pobj) 129. struct obj **potmp, **pobj; 130. { 131. register struct obj *otmp = *potmp, *obj = *pobj; 132. 133. if(mergable(otmp, obj)) { 134. /* Approximate age: we do it this way because if we were to 135. * do it "accurately" (merge only when ages are identical) 136. * we'd wind up never merging any corpses. 137. * otmp->age = otmp->age*(1-proportion) + obj->age*proportion; 138. * 139. * Don't do the age manipulation if lit. We would need 140. * to stop the burn on both items, then merge the age, 141. * then restart the burn. 142. */ 143. if (!obj->lamplit) 144. otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan)) 145. / (otmp->quan + obj->quan); 146. 147. otmp->quan += obj->quan; 148. otmp->owt += obj->owt; 149. if(!otmp->onamelth && obj->onamelth) 150. otmp = *potmp = oname(otmp, ONAME(obj)); 151. obj_extract_self(obj); 152. 153. /* really should merge the timeouts */ 154. if (obj->lamplit) end_burn(obj, TRUE); 155. if (obj->timed) obj_stop_timers(obj); /* follows end_burn */ 156. 157. /* fixup for `#adjust' merging wielded darts, daggers, &c */ 158. if (obj->owornmask) { 159. otmp->owornmask |= obj->owornmask; 160. /* (it isn't necessary to "unwear" `obj' first) */ 161. if (otmp->where == OBJ_INVENT) 162. setworn(otmp, otmp->owornmask); 163. #if 0 164. /* (this should never be necessary, since items 165. already in a monster's inventory don't ever get 166. merged into other objects [only vice versa]) */ 167. else if (otmp->where == OBJ_MINVENT) { 168. if (obj == MON_WEP(otmp->ocarry)) 169. MON_WEP(otmp->ocarry) = otmp; 170. } 171. #endif 172. } 173. obfree(obj,otmp); /* free(obj), bill->otmp */ 174. return(1); 175. } 176. return 0; 177. } 178. 179. struct obj * 180. addinv(obj) 181. struct obj *obj; 182. { 183. struct obj *otmp, *prev; 184. 185. if (obj->where != OBJ_FREE) 186. panic("addinv: obj not free"); 187. 188. if (obj->oclass == GOLD_CLASS) { 189. u.ugold += obj->quan; 190. flags.botl = 1; 191. return obj; 192. } else if (obj->otyp == AMULET_OF_YENDOR) { 193. if (u.uhave.amulet) impossible ("already have amulet?"); 194. u.uhave.amulet = 1; 195. } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) { 196. if (u.uhave.menorah) impossible ("already have candelabrum?"); 197. u.uhave.menorah = 1; 198. } else if (obj->otyp == BELL_OF_OPENING) { 199. if (u.uhave.bell) impossible ("already have silver bell?"); 200. u.uhave.bell = 1; 201. } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 202. if (u.uhave.book) impossible ("already have the book?"); 203. u.uhave.book = 1; 204. } else if (is_quest_artifact(obj)) { 205. if (u.uhave.questart) impossible ("already have the artifact?"); 206. u.uhave.questart = 1; 207. artitouch(); 208. set_artifact_intrinsic(obj, 1, W_ART); 209. } else if(obj->oartifact) { 210. set_artifact_intrinsic(obj, 1, W_ART); 211. } 212. /* merge if possible; find end of chain in the process */ 213. for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj) 214. if (merged(&otmp, &obj)) { 215. obj = otmp; 216. goto added; 217. } 218. /* didn't merge, so insert into chain */ 219. if (flags.invlet_constant || !prev) { 220. if (flags.invlet_constant) assigninvlet(obj); 221. obj->nobj = invent; /* insert at beginning */ 222. invent = obj; 223. if (flags.invlet_constant) reorder_invent(); 224. } else { 225. prev->nobj = obj; /* insert at end */ 226. obj->nobj = 0; 227. } 228. obj->where = OBJ_INVENT; 229. 230. added: 231. if (obj->otyp == LUCKSTONE 232. || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) { 233. /* new luckstone must be in inventory by this point 234. * for correct calculation */ 235. set_moreluck(); 236. } 237. update_inventory(); 238. return(obj); 239. } 240. 241. #endif /* OVL1 */ 242. #ifdef OVLB 243. 244. /* Add an item to the inventory unless we're fumbling, and give a message. 245. * If there aren't any free inventory slots, we'll drop it instead. 246. * If both success and failure messages are NULL, then we're just doing the 247. * fumbling/slot-limit checking for a silent grab. 248. */ 249. struct obj * 250. hold_another_object(obj, drop_fmt, drop_arg, hold_msg) 251. struct obj *obj; 252. const char *drop_fmt, *drop_arg, *hold_msg; 253. { 254. if (!Blind) obj->dknown = 1; /* maximize mergibility */ 255. if (Fumbling) { 256. if (drop_fmt) pline(drop_fmt, drop_arg); 257. dropy(obj); 258. } else { 259. long oquan = obj->quan; 260. int prev_encumbr = near_capacity(); /* before addinv() */ 261. /* encumbrance only matters if it would now become worse 262. than max( current_value, stressed ) */ 263. if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER; 264. obj = addinv(obj); 265. if (inv_cnt() > 52 266. || ((obj->otyp != LOADSTONE || !obj->cursed) 267. && near_capacity() > prev_encumbr)) { 268. if (drop_fmt) pline(drop_fmt, drop_arg); 269. /* undo any merge which took place */ 270. if (obj->quan > oquan) { 271. struct obj *otmp = splitobj(obj, oquan); 272. /* might have merged with weapon */ 273. if (obj->owornmask) 274. setworn(otmp, obj->owornmask); 275. } 276. dropx(obj); 277. } else { 278. if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan); 279. } 280. } 281. return obj; 282. } 283. 284. void 285. useup(obj) 286. register struct obj *obj; 287. { 288. /* Note: This works correctly for containers because they */ 289. /* (containers) don't merge. */ 290. if(obj->quan > 1L){ 291. #ifndef NO_SIGNAL 292. obj->in_use = FALSE; /* no longer in use */ 293. #endif 294. obj->quan--; 295. obj->owt = weight(obj); 296. update_inventory(); 297. } else { 298. setnotworn(obj); 299. freeinv(obj); 300. obfree(obj, (struct obj *) 0); /* deletes contents also */ 301. } 302. } 303. 304. #endif /* OVLB */ 305. #ifdef OVL3 306. 307. void 308. freeinv(obj) 309. register struct obj *obj; 310. { 311. extract_nobj(obj, &invent); 312. 313. if (obj->oclass == GOLD_CLASS) { 314. u.ugold -= obj->quan; 315. flags.botl = 1; 316. return; 317. } else if (obj->otyp == AMULET_OF_YENDOR) { 318. if (!u.uhave.amulet) impossible ("don't have amulet?"); 319. u.uhave.amulet = 0; 320. } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) { 321. if (!u.uhave.menorah) impossible ("don't have candelabrum?"); 322. u.uhave.menorah = 0; 323. } else if (obj->otyp == BELL_OF_OPENING) { 324. if (!u.uhave.bell) impossible ("don't have silver bell?"); 325. u.uhave.bell = 0; 326. } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 327. if (!u.uhave.book) impossible ("don't have the book?"); 328. u.uhave.book = 0; 329. } else if (is_quest_artifact(obj)) { 330. if(!u.uhave.questart) impossible ("don't have the artifact?"); 331. u.uhave.questart = 0; 332. set_artifact_intrinsic(obj, 0, W_ART); 333. } else if (obj->oartifact) { 334. set_artifact_intrinsic(obj, 0, W_ART); 335. } else if (obj->otyp == LOADSTONE) { 336. curse(obj); 337. } else if (obj->otyp == LUCKSTONE 338. || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) { 339. set_moreluck(); 340. flags.botl = 1; 341. } 342. update_inventory(); 343. } 344. 345. void 346. delallobj(x, y) 347. int x, y; 348. { 349. struct obj *otmp, *otmp2; 350. 351. for (otmp = level.objects[x][y]; otmp; otmp = otmp2) { 352. if (otmp == uball) 353. unpunish(); 354. /* after unpunish(), or might get deallocated chain */ 355. otmp2 = otmp->nexthere; 356. if (otmp == uchain) 357. continue; 358. delobj(otmp); 359. } 360. } 361. 362. #endif /* OVL3 */ 363. #ifdef OVL2 364. 365. /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 366. void 367. delobj(obj) 368. register struct obj *obj; 369. { 370. if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj); 371. if (obj->otyp == AMULET_OF_YENDOR || 372. obj->otyp == CANDELABRUM_OF_INVOCATION || 373. obj->otyp == BELL_OF_OPENING || 374. obj->otyp == SPE_BOOK_OF_THE_DEAD) { 375. /* player might be doing something stupid, but we 376. * can't guarantee that. assume special artifacts 377. * are indestructible via drawbridges, and exploding 378. * chests, and golem creation, and ... 379. */ 380. return; 381. } 382. obj_extract_self(obj); 383. newsym(obj->ox,obj->oy); 384. obfree(obj, (struct obj *) 0); /* frees contents also */ 385. } 386. 387. #endif /* OVL2 */ 388. #ifdef OVL0 389. 390. struct obj * 391. sobj_at(n,x,y) 392. register int n, x, y; 393. { 394. register struct obj *otmp; 395. 396. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 397. if(otmp->otyp == n) 398. return(otmp); 399. return((struct obj *)0); 400. } 401. 402. #endif /* OVL0 */ 403. #ifdef OVLB 404. 405. struct obj * 406. carrying(type) 407. register int type; 408. { 409. register struct obj *otmp; 410. 411. for(otmp = invent; otmp; otmp = otmp->nobj) 412. if(otmp->otyp == type) 413. return(otmp); 414. return((struct obj *) 0); 415. } 416. 417. boolean 418. have_lizard() 419. { 420. register struct obj *otmp; 421. 422. for(otmp = invent; otmp; otmp = otmp->nobj) 423. if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD) 424. return(TRUE); 425. return(FALSE); 426. } 427. 428. struct obj * 429. o_on(id, objchn) 430. unsigned int id; 431. register struct obj *objchn; 432. { 433. struct obj *temp; 434. 435. while(objchn) { 436. if(objchn->o_id == id) return(objchn); 437. if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj))) 438. return temp; 439. objchn = objchn->nobj; 440. } 441. return((struct obj *) 0); 442. } 443. 444. boolean 445. obj_here(obj, x, y) 446. register struct obj *obj; 447. int x, y; 448. { 449. register struct obj *otmp; 450. 451. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 452. if(obj == otmp) return(TRUE); 453. return(FALSE); 454. } 455. 456. #endif /* OVLB */ 457. #ifdef OVL2 458. 459. struct obj * 460. g_at(x,y) 461. register int x, y; 462. { 463. register struct obj *obj = level.objects[x][y]; 464. while(obj) { 465. if (obj->oclass == GOLD_CLASS) return obj; 466. obj = obj->nexthere; 467. } 468. return((struct obj *)0); 469. } 470. 471. #endif /* OVL2 */ 472. #ifdef OVLB 473. 474. /* Make a gold object from the hero's gold. */ 475. struct obj * 476. mkgoldobj(q) 477. register long q; 478. { 479. register struct obj *otmp; 480. 481. otmp = mksobj(GOLD_PIECE, FALSE, FALSE); 482. u.ugold -= q; 483. otmp->quan = q; 484. otmp->owt = weight(otmp); 485. flags.botl = 1; 486. return(otmp); 487. } 488. 489. #endif /* OVLB */ 490. #ifdef OVL1 491. 492. STATIC_OVL void 493. compactify(buf) 494. register char *buf; 495. /* compact a string of inventory letters by dashing runs of letters */ 496. { 497. register int i1 = 1, i2 = 1; 498. register char ilet, ilet1, ilet2; 499. 500. ilet2 = buf[0]; 501. ilet1 = buf[1]; 502. buf[++i2] = buf[++i1]; 503. ilet = buf[i1]; 504. while(ilet) { 505. if(ilet == ilet1+1) { 506. if(ilet1 == ilet2+1) 507. buf[i2 - 1] = ilet1 = '-'; 508. else if(ilet2 == '-') { 509. buf[i2 - 1] = ++ilet1; 510. buf[i2] = buf[++i1]; 511. ilet = buf[i1]; 512. continue; 513. } 514. } 515. ilet2 = ilet1; 516. ilet1 = ilet; 517. buf[++i2] = buf[++i1]; 518. ilet = buf[i1]; 519. } 520. } 521. 522. /* 523. * getobj returns: 524. * struct obj *xxx: object to do something with. 525. * (struct obj *) 0 error return: no object. 526. * &zeroobj explicitly no object (as in w-). 527. */ 528. struct obj * 529. getobj(let,word) 530. register const char *let,*word; 531. { 532. register struct obj *otmp; 533. register char ilet; 534. char buf[BUFSZ], qbuf[QBUFSZ]; 535. char lets[BUFSZ]; 536. register int foo = 0; 537. register char *bp = buf; 538. xchar allowcnt = 0; /* 0, 1 or 2 */ 539. boolean allowgold = FALSE, usegold = FALSE; 540. /* Two possibilities: they can't use gold because it's illegal, 541. * or they can't use gold because they don't have any. 542. */ 543. boolean allowall = FALSE; 544. boolean allownone = FALSE; 545. xchar foox = 0; 546. long cnt; 547. boolean prezero = FALSE; 548. 549. if(*let == ALLOW_COUNT) let++, allowcnt = 1; 550. if(*let == GOLD_CLASS) let++, 551. usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE); 552. 553. /* Equivalent of an "ugly check" for gold */ 554. if (usegold && !strcmp(word, "eat") && !metallivorous(uasmon)) 555. usegold = allowgold = FALSE; 556. 557. if(*let == ALL_CLASSES) let++, allowall = TRUE; 558. if(*let == ALLOW_NONE) let++, allownone = TRUE; 559. /* "ugly check" for reading fortune cookies, part 1 */ 560. /* The normal 'ugly check' keeps the object on the inventory list. 561. * We don't want to do that for shirts/cookies, so the check for 562. * them is handled a bit differently (and also requires that we set 563. * allowall in the caller) 564. */ 565. if(allowall && !strcmp(word, "read")) allowall = FALSE; 566. 567. if(allownone) *bp++ = '-'; 568. if(allowgold) *bp++ = def_oc_syms[GOLD_CLASS]; 569. if(bp > buf && bp[-1] == '-') *bp++ = ' '; 570. 571. ilet = 'a'; 572. for (otmp = invent; otmp; otmp = otmp->nobj) { 573. if (!flags.invlet_constant) otmp->invlet = ilet; /* reassign() */ 574. if (!*let || index(let, otmp->oclass)) { 575. register int otyp = otmp->otyp; 576. bp[foo++] = otmp->invlet; 577. 578. /* ugly check: remove inappropriate things */ 579. if((!strcmp(word, "take off") && 580. (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) 581. || (otmp==uarm && uarmc) 582. #ifdef TOURIST 583. || (otmp==uarmu && (uarm || uarmc)) 584. #endif 585. )) 586. || (!strcmp(word, "wear") && 587. (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) 588. /* already worn */ 589. || (!strcmp(word, "wield") && 590. (otmp->owornmask & W_WEP)) 591. ) { 592. foo--; 593. foox++; 594. } 595. 596. /* Second ugly check; unlike the first it won't trigger an 597. * "else" in "you don't have anything else to ___". 598. */ 599. else if ((!strcmp(word, "wear") && 600. (otmp->oclass == TOOL_CLASS && 601. otyp != BLINDFOLD && otyp != TOWEL)) 602. || (!strcmp(word, "wield") && 603. (otmp->oclass == TOOL_CLASS && !is_weptool(otmp))) 604. || (!strcmp(word, "eat") && !is_edible(otmp)) 605. || (!strcmp(word, "sacrifice") && 606. (otyp != CORPSE && 607. otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR)) 608. || (!strcmp(word, "write with") && 609. (otmp->oclass == TOOL_CLASS && 610. otyp != MAGIC_MARKER && otyp != TOWEL)) 611. || (!strcmp(word, "tin") && 612. (otyp != CORPSE || !tinnable(otmp))) 613. || (!strcmp(word, "rub") && 614. (otmp->oclass == TOOL_CLASS && 615. otyp != OIL_LAMP && otyp != MAGIC_LAMP && 616. otyp != BRASS_LANTERN)) 617. || ((!strcmp(word, "use or apply") || 618. !strcmp(word, "untrap with")) && 619. /* only applicable weapon is BULLWHIP */ 620. ((otmp->oclass == WEAPON_CLASS && otyp != BULLWHIP) 621. || (otmp->oclass == POTION_CLASS && 622. /* only applicable potion is oil, and it will only 623. be offered as a choice when already discovered */ 624. (otyp != POT_OIL || !otmp->dknown || 625. !objects[POT_OIL].oc_name_known)))) 626. || (!strcmp(word, "invoke") && 627. (!otmp->oartifact && !objects[otyp].oc_unique && 628. (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) && 629. otyp != CRYSTAL_BALL && /* #invoke synonym for apply */ 630. /* note: presenting the possibility of invoking non-artifact 631. mirrors and/or lamps is a simply a cruel deception... */ 632. otyp != MIRROR && otyp != MAGIC_LAMP && 633. (otyp != OIL_LAMP || /* don't list known oil lamp */ 634. (otmp->dknown && objects[OIL_LAMP].oc_name_known)))) 635. || (!strcmp(word, "untrap with") && 636. (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)) 637. || (!strcmp(word, "charge") && !is_chargeable(otmp)) 638. ) 639. foo--; 640. } else { 641. 642. /* "ugly check" for reading fortune cookies, part 2 */ 643. if ((!strcmp(word, "read") && 644. (otmp->otyp == FORTUNE_COOKIE 645. #ifdef TOURIST 646. || otmp->otyp == T_SHIRT 647. #endif 648. ))) 649. allowall = TRUE; 650. } 651. 652. if(ilet == 'z') ilet = 'A'; else ilet++; 653. } 654. bp[foo] = 0; 655. if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 656. Strcpy(lets, bp); /* necessary since we destroy buf */ 657. if(foo > 5) /* compactify string */ 658. compactify(bp); 659. 660. if(!foo && !allowall && !allowgold && !allownone) { 661. You("don't have anything %sto %s.", 662. foox ? "else " : "", word); 663. return((struct obj *)0); 664. } 665. for(;;) { 666. cnt = 0; 667. if (allowcnt == 2) allowcnt = 1; /* abort previous count */ 668. if(!buf[0]) { 669. Sprintf(qbuf, "What do you want to %s? [*]", word); 670. } else { 671. Sprintf(qbuf, "What do you want to %s? [%s or ?*]", 672. word, buf); 673. } 674. #ifdef REDO 675. if (in_doagain) 676. ilet = readchar(); 677. else 678. #endif 679. ilet = yn_function(qbuf, (char *)0, '\0'); 680. if(ilet == '0') prezero = TRUE; 681. while(digit(ilet) && allowcnt) { 682. #ifdef REDO 683. if (ilet != '?' && ilet != '*') savech(ilet); 684. #endif 685. cnt = 10*cnt + (ilet - '0'); 686. allowcnt = 2; /* signal presence of cnt */ 687. ilet = readchar(); 688. } 689. if(digit(ilet)) { 690. pline("No count allowed with this command."); 691. continue; 692. } 693. if(index(quitchars,ilet)) { 694. if(flags.verbose) 695. pline("Never mind."); 696. return((struct obj *)0); 697. } 698. if(ilet == '-') { 699. return(allownone ? &zeroobj : (struct obj *) 0); 700. } 701. if(ilet == def_oc_syms[GOLD_CLASS]) { 702. if(!usegold){ 703. You("cannot %s gold.", word); 704. return(struct obj *)0; 705. } else if (!allowgold) { 706. You("are not carrying any gold."); 707. return(struct obj *)0; 708. } 709. if(cnt == 0 && prezero) return((struct obj *)0); 710. /* Historic note: early Nethack had a bug which was 711. * first reported for Larn, where trying to drop 2^32-n 712. * gold pieces was allowed, and did interesting things 713. * to your money supply. The LRS is the tax bureau 714. * from Larn. 715. */ 716. if(cnt < 0) { 717. pline_The("LRS would be very interested to know you have that much."); 718. return(struct obj *)0; 719. } 720. 721. if(!(allowcnt == 2 && cnt < u.ugold)) 722. cnt = u.ugold; 723. return(mkgoldobj(cnt)); 724. } 725. if(allowcnt == 2 && !strcmp(word,"throw")) { 726. /* permit counts for throwing gold, but don't accept 727. * counts for other things since the throw code will 728. * split off a single item anyway */ 729. allowcnt = 1; 730. if(cnt == 0 && prezero) return((struct obj *)0); 731. if(cnt > 1) { 732. You("can only throw one item at a time."); 733. continue; 734. } 735. } 736. if(ilet == '?' || ilet == '*') { 737. ilet = display_inventory(ilet=='?' ? lets:(char *)0, TRUE); 738. if(!ilet) continue; 739. if(ilet == '\033') { 740. if(flags.verbose) 741. pline("Never mind."); 742. return((struct obj *)0); 743. } 744. /* they typed a letter (not a space) at the prompt */ 745. } 746. #ifdef REDO 747. savech(ilet); 748. #endif 749. for (otmp = invent; otmp; otmp = otmp->nobj) 750. if (otmp->invlet == ilet) break; 751. if(!otmp) { 752. You("don't have that object."); 753. #ifdef REDO 754. if (in_doagain) return((struct obj *) 0); 755. #endif 756. continue; 757. } else if (cnt < 0 || otmp->quan < cnt) { 758. You("don't have that many! You have only %ld.", 759. otmp->quan); 760. #ifdef REDO 761. if (in_doagain) return((struct obj *) 0); 762. #endif 763. continue; 764. } 765. break; 766. } 767. if(!allowall && let && !index(let,otmp->oclass)) { 768. pline(silly_thing_to, word); 769. return((struct obj *)0); 770. } 771. if(allowcnt == 2) { /* cnt given */ 772. if(cnt == 0) return (struct obj *)0; 773. if(cnt != otmp->quan) { 774. register struct obj *obj = splitobj(otmp, cnt); 775. /* Very ugly kludge necessary to prevent someone from trying 776. * to drop one of several loadstones and having the loadstone 777. * now be separate. 778. */ 779. if (!strcmp(word, "drop") && 780. obj->otyp == LOADSTONE && obj->cursed) 781. otmp->corpsenm = obj->invlet; 782. if(otmp == uwep) setuwep(obj); 783. } 784. } 785. return(otmp); 786. } 787. 788. #endif /* OVL1 */ 789. #ifdef OVLB 790. 791. STATIC_PTR int 792. ckunpaid(otmp) 793. register struct obj *otmp; 794. { 795. return((int)(otmp->unpaid)); 796. } 797. 798. boolean 799. wearing_armor() 800. { 801. return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms 802. #ifdef TOURIST 803. || uarmu 804. #endif 805. )); 806. } 807. 808. boolean 809. is_worn(otmp) 810. register struct obj *otmp; 811. { 812. return((boolean)(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP)))); 813. } 814. 815. static NEARDATA const char removeables[] = 816. { ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 }; 817. 818. /* interactive version of getobj - used for Drop, Identify and */ 819. /* Takeoff (A). Return the number of times fn was called successfully */ 820. /* If combo is TRUE, we just use this to get a category list */ 821. int 822. ggetobj(word, fn, mx, combo) 823. const char *word; 824. int FDECL((*fn),(OBJ_P)), mx; 825. boolean combo; /* combination menu flag */ 826. { 827. int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0; 828. boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0; 829. boolean takeoff, ident, allflag, m_seen; 830. int oletct, iletct, allowgold, unpaid, oc_of_sym; 831. char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5]; 832. char buf[BUFSZ], qbuf[QBUFSZ]; 833. 834. allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; 835. takeoff = ident = allflag = m_seen = FALSE; 836. if(!invent && !allowgold){ 837. You("have nothing to %s.", word); 838. return(0); 839. } 840. if (combo) add_valid_menu_class(0); /* reset */ 841. if (!strcmp(word, "take off")) { 842. takeoff = TRUE; 843. filter = is_worn; 844. } else if (!strcmp(word, "identify")) { 845. ident = TRUE; 846. filter = not_fully_identified; 847. } 848. 849. iletct = collect_obj_classes(ilets, invent, 850. FALSE, (allowgold != 0), filter); 851. unpaid = count_unpaid(invent); 852. 853. if (ident && !iletct) { 854. return -1; /* no further identifications */ 855. } else if (!takeoff && (unpaid || invent)) { 856. ilets[iletct++] = ' '; 857. if (unpaid) ilets[iletct++] = 'u'; 858. if (invent) ilets[iletct++] = 'a'; 859. } else if (takeoff && invent) { 860. ilets[iletct++] = ' '; 861. } 862. ilets[iletct++] = 'i'; 863. if (!combo) 864. ilets[iletct++] = 'm'; /* allow menu presentation on request */ 865. ilets[iletct] = '\0'; 866. 867. for (;;) { 868. Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]", 869. word, ilets); 870. getlin(qbuf, buf); 871. if (buf[0] == '\033') return(0); 872. if (index(buf, 'i')) 873. (void) display_inventory((char *)0, FALSE); 874. else 875. break; 876. } 877. 878. ip = buf; 879. olets[oletct = 0] = '\0'; 880. while ((sym = *ip++) != '\0') { 881. if (sym == ' ') continue; 882. oc_of_sym = def_char_to_objclass(sym); 883. if (takeoff && !(uwep && oc_of_sym == uwep->oclass) && 884. (oc_of_sym != MAXOCLASSES)) { 885. if (!index(removeables, oc_of_sym)) { 886. pline("Not applicable."); 887. return 0; 888. } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) { 889. You("are not wearing any armor."); 890. return 0; 891. } else if (oc_of_sym == WEAPON_CLASS && !uwep) { 892. You("are not wielding anything."); 893. return 0; 894. } else if (oc_of_sym == RING_CLASS && !uright && !uleft) { 895. You("are not wearing rings."); 896. return 0; 897. } else if (oc_of_sym == AMULET_CLASS && !uamul) { 898. You("are not wearing an amulet."); 899. return 0; 900. } else if (oc_of_sym == TOOL_CLASS && !ublindf) { 901. You("are not wearing a blindfold."); 902. return 0; 903. } 904. } 905. 906. if (oc_of_sym == GOLD_CLASS && !combo) { 907. if (allowgold == 1) 908. (*fn)(mkgoldobj(u.ugold)); 909. else if (!u.ugold) 910. You("have no gold."); 911. allowgold = 2; 912. } else if (sym == 'a' || sym == 'A') { 913. allflag = TRUE; 914. } else if (sym == 'u' || sym == 'U') { 915. add_valid_menu_class('u'); 916. ckfn = ckunpaid; 917. } else if (sym == 'm') { 918. m_seen = TRUE; 919. } else if (oc_of_sym == MAXOCLASSES) { 920. You("don't have any %c's.", sym); 921. } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */ 922. if (!index(olets, oc_of_sym)) { 923. add_valid_menu_class(oc_of_sym); 924. olets[oletct++] = oc_of_sym; 925. olets[oletct] = 0; 926. } 927. } 928. } 929. 930. if (m_seen) 931. return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3; 932. else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) 933. return 0; 934. else if (allowgold == 2 && !oletct) 935. return 1; /* you dropped gold (or at least tried to) */ 936. else 937. return askchain(&invent, olets, allflag, fn, ckfn, mx, word); 938. } 939. 940. /* 941. * Walk through the chain starting at objchn and ask for all objects 942. * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull) 943. * whether the action in question (i.e., fn) has to be performed. 944. * If allflag then no questions are asked. Max gives the max nr of 945. * objects to be treated. Return the number of objects treated. 946. */ 947. int 948. askchain(objchn, olets, allflag, fn, ckfn, mx, word) 949. struct obj **objchn; 950. register int allflag, mx; 951. register const char *olets, *word; /* olets is an Obj Class char array */ 952. register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); 953. { 954. register struct obj *otmp, *otmp2; 955. register char sym, ilet; 956. register int cnt = 0, dud = 0, tmp; 957. boolean takeoff, nodot, ident, ininv; 958. char qbuf[QBUFSZ]; 959. 960. takeoff = !strcmp(word, "take off"); 961. ident = !strcmp(word, "identify"); 962. nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || 963. ident || takeoff); 964. ininv = (*objchn == invent); 965. /* Changed so the askchain is interrogated in the order specified. 966. * For example, if a person specifies =/ then first all rings will be 967. * asked about followed by all wands -dgk 968. */ 969. nextclass: 970. ilet = 'a'-1; 971. if (*objchn && (*objchn)->oclass == GOLD_CLASS) 972. ilet--; /* extra iteration */ 973. for (otmp = *objchn; otmp; otmp = otmp2) { 974. if(ilet == 'z') ilet = 'A'; else ilet++; 975. otmp2 = otmp->nobj; 976. if (olets && *olets && otmp->oclass != *olets) continue; 977. if (takeoff && !is_worn(otmp)) continue; 978. if (ident && !not_fully_identified(otmp)) continue; 979. if (ckfn && !(*ckfn)(otmp)) continue; 980. if (!allflag) { 981. Strcpy(qbuf, !ininv ? doname(otmp) : 982. xprname(otmp, (char *)0, ilet, !nodot, 0L)); 983. Strcat(qbuf, "?"); 984. sym = (takeoff || ident || otmp->quan < 2L) ? 985. nyaq(qbuf) : nyNaq(qbuf); 986. } 987. else sym = 'y'; 988. 989. if (sym == '#') { 990. /* Number was entered; split the object unless it corresponds 991. to 'none' or 'all'. 2 special cases: cursed loadstones and 992. welded weapons (eg, multiple daggers) will remain as merged 993. unit; done to avoid splitting an object that won't be 994. droppable (even if we're picking up rather than dropping). 995. */ 996. if (!yn_number) 997. sym = 'n'; 998. else { 999. sym = 'y'; 1000. if (yn_number < otmp->quan && !welded(otmp) && 1001. (!otmp->cursed || otmp->otyp != LOADSTONE)) { 1002. struct obj *otmpx = splitobj(otmp, yn_number); 1003. if (!otmpx || otmpx->nobj != otmp2) 1004. impossible("bad object split in askchain"); 1005. /* assume other worn items aren't mergable */ 1006. if (otmp == uwep) setuwep(otmpx); 1007. } 1008. } 1009. } 1010. switch(sym){ 1011. case 'a': 1012. allflag = 1; 1013. case 'y': 1014. tmp = (*fn)(otmp); 1015. if(tmp < 0) goto ret; 1016. cnt += tmp; 1017. if(--mx == 0) goto ret; 1018. case 'n': 1019. if(nodot) dud++; 1020. default: 1021. break; 1022. case 'q': 1023. /* special case for seffects() */ 1024. if (ident) cnt = -1; 1025. goto ret; 1026. } 1027. } 1028. if (olets && *olets && *++olets) 1029. goto nextclass; 1030. if(!takeoff && (dud || cnt)) pline("That was all."); 1031. else if(!dud && !cnt) pline("No applicable objects."); 1032. ret: 1033. return(cnt); 1034. } 1035. 1036. 1037. /* 1038. * Object identification routines: 1039. */ 1040. 1041. /* make an object actually be identified; no display updating */ 1042. static void 1043. fully_identify_obj(otmp) 1044. struct obj *otmp; 1045. { 1046. makeknown(otmp->otyp); 1047. otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1; 1048. if (otmp->otyp == EGG && otmp->corpsenm != NON_PM) 1049. learn_egg_type(otmp->corpsenm); 1050. } 1051. 1052. /* ggetobj callback routine; identify an object and give immediate feedback */ 1053. int 1054. identify(otmp) 1055. struct obj *otmp; 1056. { 1057. fully_identify_obj(otmp); 1058. prinv((char *)0, otmp, 0L); 1059. return 1; 1060. } 1061. 1062. /* menu of unidentified objects; select and identify up to id_limit of them */ 1063. static void 1064. menu_identify(id_limit) 1065. int id_limit; 1066. { 1067. menu_item *pick_list; 1068. int n, i, first = 1; 1069. char buf[BUFSZ]; 1070. /* assumptions: id_limit > 0 and at least one unID'd item is present */ 1071. 1072. while (id_limit) { 1073. Sprintf(buf, "What would you like to identify %s?", 1074. first ? "first" : "next"); 1075. n = query_objlist(buf, invent, SIGNAL_NOMENU|USE_INVLET|INVORDER_SORT, 1076. &pick_list, PICK_ANY, not_fully_identified); 1077. 1078. if (n > 0) { 1079. if (n > id_limit) n = id_limit; 1080. for (i = 0; i < n; i++, id_limit--) 1081. (void) identify(pick_list[i].item.a_obj); 1082. free((genericptr_t) pick_list); 1083. mark_synch(); /* Before we loop to pop open another menu */ 1084. } else { 1085. if (n < 0) pline("That was all."); 1086. id_limit = 0; /* Stop now */ 1087. } 1088. first = 0; 1089. } 1090. } 1091. 1092. /* dialog with user to identify a given number of items; 0 means all */ 1093. void 1094. identify_pack(id_limit) 1095. int id_limit; 1096. { 1097. struct obj *obj, *the_obj; 1098. int n, unid_cnt; 1099. 1100. unid_cnt = 0; 1101. the_obj = 0; /* if unid_cnt ends up 1, this will be it */ 1102. for (obj = invent; obj; obj = obj->nobj) 1103. if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj; 1104. 1105. if (!unid_cnt) { 1106. You("have already identified all of your possessions."); 1107. } else if (!id_limit) { 1108. /* identify everything */ 1109. if (unid_cnt == 1) { 1110. (void) identify(the_obj); 1111. } else { 1112. 1113. /* TODO: use fully_identify_obj and cornline/menu/whatever here */ 1114. for (obj = invent; obj; obj = obj->nobj) 1115. if (not_fully_identified(obj)) (void) identify(obj); 1116. 1117. } 1118. } else { 1119. /* identify up to `id_limit' items */ 1120. n = 0; 1121. if (flags.menu_style == MENU_TRADITIONAL) 1122. do { 1123. n = ggetobj("identify", identify, id_limit, FALSE); 1124. if (n < 0) break; /* quit or no eligible items */ 1125. } while ((id_limit -= n) > 0); 1126. if (n == 0 || n < -1) 1127. menu_identify(id_limit); 1128. } 1129. update_inventory(); 1130. } 1131. 1132. #endif /* OVLB */ 1133. #ifdef OVL2 1134. 1135. STATIC_OVL char 1136. obj_to_let(obj) /* should of course only be called for things in invent */ 1137. register struct obj *obj; 1138. { 1139. if (obj->oclass == GOLD_CLASS) 1140. return GOLD_SYM; 1141. if (!flags.invlet_constant) { 1142. obj->invlet = NOINVSYM; 1143. reassign(); 1144. } 1145. return obj->invlet; 1146. } 1147. 1148. /* 1149. * Print the indicated quantity of the given object. If quan == 0L then use 1150. * the current quantity. 1151. */ 1152. void 1153. prinv(prefix, obj, quan) 1154. const char *prefix; 1155. register struct obj *obj; 1156. long quan; 1157. { 1158. long savequan = obj->quan; 1159. if (quan) obj->quan = quan; 1160. if (!prefix) prefix = ""; 1161. pline("%s%s%s", 1162. prefix, *prefix ? " " : "", 1163. xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L)); 1164. if (quan) obj->quan = savequan; 1165. } 1166. 1167. #endif /* OVL2 */ 1168. #ifdef OVL1 1169. 1170. char * 1171. xprname(obj, txt, let, dot, cost) 1172. struct obj *obj; 1173. const char *txt; /* text to print instead of obj */ 1174. char let; /* inventory letter */ 1175. boolean dot; /* append period; (dot && cost => Iu) */ 1176. long cost; /* cost (for inventory of unpaid or expended items) */ 1177. { 1178. #ifdef LINT /* handle static char li[BUFSZ]; */ 1179. char li[BUFSZ]; 1180. #else 1181. static char li[BUFSZ]; 1182. #endif 1183. boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM; 1184. /* 1185. * If let is: 1186. * * Then obj == null and we are printing a total amount. 1187. * > Then the object is contained and doesn't have an inventory letter. 1188. */ 1189. if (cost != 0 || let == '*') { 1190. /* if dot is true, we're doing Iu, otherwise Ix */ 1191. Sprintf(li, "%c - %-45s %6ld zorkmid%s", 1192. (dot && use_invlet ? obj->invlet : let), 1193. (txt ? txt : doname(obj)), cost, plur(cost)); 1194. } else if (obj->oclass == GOLD_CLASS) { 1195. Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan), 1196. (dot ? "." : "")); 1197. } else { 1198. /* ordinary inventory display or pickup message */ 1199. Sprintf(li, "%c - %s%s", 1200. (use_invlet ? obj->invlet : let), 1201. (txt ? txt : doname(obj)), (dot ? "." : "")); 1202. } 1203. return li; 1204. } 1205. 1206. #endif /* OVL1 */ 1207. #ifdef OVLB 1208. 1209. /* the 'i' command */ 1210. int 1211. ddoinv() 1212. { 1213. (void) display_inventory((char *)0, FALSE); 1214. return 0; 1215. } 1216. 1217. /* 1218. * find_unpaid() 1219. * 1220. * Scan the given list of objects. If last_found is NULL, return the first 1221. * unpaid object found. If last_found is not NULL, then skip over unpaid 1222. * objects until last_found is reached, then set last_found to NULL so the 1223. * next unpaid object is returned. This routine recursively follows 1224. * containers. 1225. */ 1226. static struct obj * 1227. find_unpaid(list, last_found) 1228. struct obj *list, **last_found; 1229. { 1230. struct obj *obj; 1231. 1232. while (list) { 1233. if (list->unpaid) { 1234. if (*last_found) { 1235. /* still looking for previous unpaid object */ 1236. if (list == *last_found) 1237. *last_found = (struct obj *) 0; 1238. } else 1239. return (*last_found = list); 1240. } 1241. if (Has_contents(list)) { 1242. if ((obj = find_unpaid(list->cobj, last_found)) != 0) 1243. return obj; 1244. } 1245. list = list->nobj; 1246. } 1247. return (struct obj *) 0; 1248. } 1249. 1250. /* 1251. * If lets == NULL or "", list all objects in the inventory. Otherwise, 1252. * list all objects with object classes that match the order in lets. 1253. * 1254. * Returns the letter identifier of a selected item, or 0 if nothing 1255. * was selected. 1256. */ 1257. char 1258. display_inventory(lets, want_reply) 1259. register const char *lets; 1260. boolean want_reply; 1261. { 1262. struct obj *otmp; 1263. char ilet, ret; 1264. char *invlet = flags.inv_order; 1265. int n, classcount; 1266. winid win; /* windows being used */ 1267. static winid local_win = WIN_ERR; /* window for partial menus */ 1268. anything any; 1269. menu_item *selected; 1270. 1271. /* overriden by global flag */ 1272. if (flags.perm_invent) { 1273. win = (lets && *lets) ? local_win : WIN_INVEN; 1274. /* create the first time used */ 1275. if (win == WIN_ERR) 1276. win = local_win = create_nhwindow(NHW_MENU); 1277. } else 1278. win = WIN_INVEN; 1279. 1280. if (!invent) { 1281. pline("Not carrying anything%s.", u.ugold ? " except gold" : ""); 1282. return 0; 1283. } 1284. 1285. /* oxymoron? temporarily assign permanent inventory letters */ 1286. if (!flags.invlet_constant) reassign(); 1287. 1288. if (lets && strlen(lets) == 1) { 1289. /* when only one item of interest, use pline instead of menus; 1290. we actually use a fake message-line menu in order to allow 1291. the user to perform selection at the --More-- prompt for tty */ 1292. ret = '\0'; 1293. for (otmp = invent; otmp; otmp = otmp->nobj) { 1294. if (otmp->invlet == lets[0]) { 1295. ret = message_menu(lets[0], 1296. want_reply ? PICK_ONE : PICK_NONE, 1297. xprname(otmp, (char *)0, lets[0], TRUE, 0L)); 1298. break; 1299. } 1300. } 1301. return ret; 1302. } 1303. 1304. start_menu(win); 1305. nextclass: 1306. classcount = 0; 1307. any.a_void = 0; /* set all bits to zero */ 1308. for(otmp = invent; otmp; otmp = otmp->nobj) { 1309. ilet = otmp->invlet; 1310. if(!lets || !*lets || index(lets, ilet)) { 1311. if (!flags.sortpack || otmp->oclass == *invlet) { 1312. if (flags.sortpack && !classcount) { 1313. any.a_void = 0; /* zero */ 1314. add_menu(win, NO_GLYPH, &any, 0, ATR_INVERSE, 1315. let_to_name(*invlet, FALSE), MENU_UNSELECTED); 1316. classcount++; 1317. } 1318. any.a_char = ilet; 1319. add_menu(win, obj_to_glyph(otmp), 1320. &any, ilet, ATR_NONE, doname(otmp), 1321. MENU_UNSELECTED); 1322. } 1323. } 1324. } 1325. if (flags.sortpack) { 1326. if (*++invlet) goto nextclass; 1327. #ifdef WIZARD 1328. if (--invlet != venom_inv) { 1329. invlet = venom_inv; 1330. goto nextclass; 1331. } 1332. #endif 1333. } 1334. end_menu(win, (char *) 0); 1335. 1336. n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected); 1337. if (n > 0) { 1338. ret = selected[0].item.a_char; 1339. free((genericptr_t)selected); 1340. } else 1341. ret = !n ? '\0' : '\033'; /* cancelled */ 1342. 1343. return ret; 1344. } 1345. 1346. /* 1347. * Returns the number of unpaid items within the given list. This includes 1348. * contained objects. 1349. */ 1350. int 1351. count_unpaid(list) 1352. struct obj *list; 1353. { 1354. int count = 0; 1355. 1356. while (list) { 1357. if (list->unpaid) count++; 1358. if (Has_contents(list)) 1359. count += count_unpaid(list->cobj); 1360. list = list->nobj; 1361. } 1362. return count; 1363. } 1364. 1365. static void 1366. dounpaid() 1367. { 1368. winid win; 1369. struct obj *otmp, *marker; 1370. register char ilet; 1371. char *invlet = flags.inv_order; 1372. int classcount, count, num_so_far; 1373. int save_unpaid = 0; /* lint init */ 1374. long cost, totcost; 1375. 1376. count = count_unpaid(invent); 1377. 1378. if (count == 1) { 1379. marker = (struct obj *) 0; 1380. otmp = find_unpaid(invent, &marker); 1381. 1382. /* see if the unpaid item is in the top level inventory */ 1383. for (marker = invent; marker; marker = marker->nobj) 1384. if (marker == otmp) break; 1385. 1386. pline("%s", xprname(otmp, distant_name(otmp, doname), 1387. marker ? otmp->invlet : CONTAINED_SYM, 1388. TRUE, unpaid_cost(otmp))); 1389. return; 1390. } 1391. 1392. win = create_nhwindow(NHW_MENU); 1393. cost = totcost = 0; 1394. num_so_far = 0; /* count of # printed so far */ 1395. if (!flags.invlet_constant) reassign(); 1396. 1397. do { 1398. classcount = 0; 1399. for (otmp = invent; otmp; otmp = otmp->nobj) { 1400. ilet = otmp->invlet; 1401. if (otmp->unpaid) { 1402. if (!flags.sortpack || otmp->oclass == *invlet) { 1403. if (flags.sortpack && !classcount) { 1404. putstr(win, 0, let_to_name(*invlet, TRUE)); 1405. classcount++; 1406. } 1407. 1408. totcost += cost = unpaid_cost(otmp); 1409. /* suppress "(unpaid)" suffix */ 1410. save_unpaid = otmp->unpaid; 1411. otmp->unpaid = 0; 1412. putstr(win, 0, xprname(otmp, distant_name(otmp, doname), 1413. ilet, TRUE, cost)); 1414. otmp->unpaid = save_unpaid; 1415. num_so_far++; 1416. } 1417. } 1418. } 1419. } while (flags.sortpack && (*++invlet)); 1420. 1421. if (count > num_so_far) { 1422. /* something unpaid is contained */ 1423. if (flags.sortpack) 1424. putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE)); 1425. /* 1426. * Search through the container objects in the inventory for 1427. * unpaid items. The top level inventory items have already 1428. * been listed. 1429. */ 1430. for (otmp = invent; otmp; otmp = otmp->nobj) { 1431. if (Has_contents(otmp)) { 1432. marker = (struct obj *) 0; /* haven't found any */ 1433. while (find_unpaid(otmp->cobj, &marker)) { 1434. totcost += cost = unpaid_cost(marker); 1435. save_unpaid = marker->unpaid; 1436. marker->unpaid = 0; /* suppress "(unpaid)" suffix */ 1437. putstr(win, 0, 1438. xprname(marker, distant_name(marker, doname), 1439. CONTAINED_SYM, TRUE, cost)); 1440. marker->unpaid = save_unpaid; 1441. } 1442. } 1443. } 1444. } 1445. 1446. putstr(win, 0, ""); 1447. putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost)); 1448. display_nhwindow(win, FALSE); 1449. destroy_nhwindow(win); 1450. } 1451. 1452. 1453. /* query objlist callback: return TRUE if obj type matches "this_type" */ 1454. static int this_type; 1455. 1456. static boolean 1457. this_type_only(obj) 1458. struct obj *obj; 1459. { 1460. return (obj->oclass == this_type); 1461. } 1462. 1463. /* the 'I' command */ 1464. int 1465. dotypeinv() 1466. { 1467. char c = '\0'; 1468. int n, i = 0; 1469. char *extra_types, types[BUFSZ]; 1470. int class_count, oclass, unpaid_count; 1471. boolean billx = *u.ushops && doinvbill(0); 1472. menu_item *pick_list; 1473. boolean traditional = TRUE; 1474. const char *prompt = "What type of object do you want an inventory of?"; 1475. 1476. if (!invent && !u.ugold && !billx) { 1477. You("aren't carrying anything."); 1478. return 0; 1479. } 1480. unpaid_count = count_unpaid(invent); 1481. if (flags.menu_style != MENU_TRADITIONAL) { 1482. if (flags.menu_style == MENU_FULL || 1483. flags.menu_style == MENU_PARTIAL) { 1484. traditional = FALSE; 1485. i = UNPAID_TYPES; 1486. if (billx) i |= BILLED_TYPES; 1487. n = query_category(prompt, invent, i, &pick_list, PICK_ONE); 1488. if (!n) return 0; 1489. this_type = c = pick_list[0].item.a_int; 1490. free((genericptr_t) pick_list); 1491. } 1492. } 1493. if (traditional) { 1494. /* collect a list of classes of objects carried, for use as a prompt */ 1495. types[0] = 0; 1496. class_count = collect_obj_classes(types, invent, 1497. FALSE, (u.ugold != 0), 1498. (boolean FDECL((*),(OBJ_P))) 0); 1499. if (unpaid_count) { 1500. Strcat(types, "u"); 1501. class_count++; 1502. } 1503. if (billx) { 1504. Strcat(types, "x"); 1505. class_count++; 1506. } 1507. /* add everything not already included; user won't see these */ 1508. extra_types = eos(types); 1509. *extra_types++ = '\033'; 1510. if (!unpaid_count) *extra_types++ = 'u'; 1511. if (!billx) *extra_types++ = 'x'; 1512. *extra_types = '\0'; /* for index() */ 1513. for (i = 0; i < MAXOCLASSES; i++) 1514. if (!index(types, def_oc_syms[i])) { 1515. *extra_types++ = def_oc_syms[i]; 1516. *extra_types = '\0'; 1517. } 1518. 1519. if(class_count > 1) { 1520. c = yn_function(prompt, types, '\0'); 1521. #ifdef REDO 1522. savech(c); 1523. #endif 1524. if(c == '\0') { 1525. clear_nhwindow(WIN_MESSAGE); 1526. return 0; 1527. } 1528. } else { 1529. /* only one thing to itemize */ 1530. if (unpaid_count) 1531. c = 'u'; 1532. else if (billx) 1533. c = 'x'; 1534. else 1535. c = types[0]; 1536. } 1537. } 1538. if (c == 'x') { 1539. if (billx) 1540. (void) doinvbill(1); 1541. else 1542. pline("No used-up objects on your shopping bill."); 1543. return 0; 1544. } 1545. if (c == 'u') { 1546. if (unpaid_count) 1547. dounpaid(); 1548. else 1549. You("are not carrying any unpaid objects."); 1550. return 0; 1551. } 1552. if (traditional) { 1553. oclass = def_char_to_objclass(c); /* change to object class */ 1554. if (oclass == GOLD_CLASS) { 1555. return doprgold(); 1556. } else if (index(types, c) > index(types, '\033')) { 1557. You("have no such objects."); 1558. return 0; 1559. } 1560. this_type = oclass; 1561. } 1562. if (query_objlist((char *) 0, invent, 1563. (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT, 1564. &pick_list, PICK_NONE, this_type_only) > 0) 1565. free((genericptr_t)pick_list); 1566. return 0; 1567. } 1568. 1569. /* look at what is here */ 1570. int 1571. dolook() 1572. { 1573. register struct obj *otmp, *otmp0; 1574. struct trap *trap; 1575. const char *verb = Blind ? "feel" : "see"; 1576. const char *dfeature = (char*) 0; 1577. char fbuf[BUFSZ], fbuf2[BUFSZ]; 1578. boolean no_article = FALSE; 1579. winid tmpwin; 1580. 1581. if(u.uswallow) { 1582. You("%s no objects here.", verb); 1583. return(!!Blind); 1584. } 1585. read_engr_at(u.ux, u.uy); /* Eric Backus */ 1586. if ((trap = t_at(u.ux,u.uy)) && trap->tseen) 1587. pline("There is %s here.", 1588. an(defsyms[trap_to_defsym(trap->ttyp)].explanation)); 1589. 1590. otmp0 = level.objects[u.ux][u.uy]; 1591. 1592. if(IS_DOOR(levl[u.ux][u.uy].typ)) { 1593. switch(levl[u.ux][u.uy].doormask) { 1594. case D_NODOOR: 1595. dfeature = "doorway"; break; 1596. case D_ISOPEN: 1597. dfeature = "open door"; break; 1598. case D_BROKEN: 1599. dfeature = "broken door"; break; 1600. default: 1601. dfeature = "closed door"; 1602. } 1603. /* override door description for open drawbridge */ 1604. if (is_drawbridge_wall(u.ux, u.uy) >= 0) 1605. dfeature = "open drawbridge portcullis"; 1606. } else if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) 1607. /* added by GAN 10/30/86 */ 1608. dfeature = "fountain"; 1609. else if(IS_THRONE(levl[u.ux][u.uy].typ)) 1610. dfeature = "opulent throne"; 1611. else if(is_lava(u.ux,u.uy)) 1612. dfeature = "molten lava", no_article = TRUE; 1613. else if(is_ice(u.ux,u.uy)) 1614. dfeature = "ice", no_article = TRUE; 1615. else if(is_pool(u.ux,u.uy) && !Underwater) 1616. dfeature = "pool of water"; 1617. #ifdef SINKS 1618. else if(IS_SINK(levl[u.ux][u.uy].typ)) 1619. dfeature = "kitchen sink"; 1620. #endif 1621. else if(IS_ALTAR(levl[u.ux][u.uy].typ)) { 1622. Sprintf(fbuf2, "altar to %s (%s)", 1623. a_gname(), 1624. align_str(Amask2align(levl[u.ux][u.uy].altarmask 1625. & ~AM_SHRINE))); 1626. dfeature = fbuf2; 1627. } else if(u.ux == xupstair && u.uy == yupstair) 1628. dfeature = "stairway up"; 1629. else if(u.ux == xdnstair && u.uy == ydnstair) 1630. dfeature = "stairway down"; 1631. else if(u.ux == sstairs.sx && u.uy == sstairs.sy) { 1632. if (sstairs.up) 1633. dfeature = "stairway up"; 1634. else 1635. dfeature = "stairway down"; 1636. } else if(u.ux == xupladder && u.uy == yupladder) 1637. dfeature = "ladder up"; 1638. else if(u.ux == xdnladder && u.uy == ydnladder) 1639. dfeature = "ladder down"; 1640. else if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) 1641. dfeature = "lowered drawbridge"; 1642. else if (levl[u.ux][u.uy].typ == DBWALL) 1643. dfeature = "raised drawbridge"; 1644. 1645. if (Blind) { 1646. boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz); 1647. You("try to feel what is %s%s.", 1648. drift ? "floating here" : "lying here on the ", 1649. drift ? "" : surface(u.ux, u.uy)); 1650. if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy))) 1651. dfeature = 0; /* ice already identifed */ 1652. if (!can_reach_floor()) { 1653. pline("But you can't reach it!"); 1654. return(0); 1655. } 1656. } 1657. 1658. if (dfeature) 1659. Sprintf(fbuf, "There is %s%s here.", 1660. no_article ? "" : 1661. index(vowels,dfeature[0]) ? "an " : "a ", 1662. dfeature); 1663. 1664. if(!otmp0 || (is_pool(u.ux,u.uy) && !Underwater)) { 1665. if (dfeature) pline(fbuf); 1666. if (Blind || !dfeature) You("%s no objects here.", verb); 1667. return(!!Blind); 1668. } 1669. /* we know there is something here */ 1670. 1671. if (!otmp0->nexthere) { 1672. /* only one object */ 1673. if (dfeature) pline(fbuf); 1674. You("%s here %s.", verb, doname(otmp0)); 1675. feel_cockatrice(otmp0); 1676. } else { 1677. display_nhwindow(WIN_MESSAGE, FALSE); 1678. tmpwin = create_nhwindow(NHW_MENU); 1679. if(dfeature) { 1680. putstr(tmpwin, 0, fbuf); 1681. putstr(tmpwin, 0, ""); 1682. } 1683. putstr(tmpwin, 0, "Things that are here:"); 1684. for(otmp = otmp0; otmp; otmp = otmp->nexthere) { 1685. putstr(tmpwin, 0, doname(otmp)); 1686. feel_cockatrice(otmp); 1687. } 1688. display_nhwindow(tmpwin, TRUE); 1689. destroy_nhwindow(tmpwin); 1690. } 1691. return(!!Blind); 1692. } 1693. 1694. static void 1695. feel_cockatrice(otmp) 1696. struct obj *otmp; 1697. { 1698. if(Blind && !uarmg && !resists_ston(&youmonst) && 1699. (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) { 1700. if(poly_when_stoned(uasmon)) 1701. You("touched the cockatrice corpse with your bare %s.", 1702. makeplural(body_part(HAND))); 1703. else 1704. pline("Touching the cockatrice corpse is a fatal mistake..."); 1705. instapetrify("cockatrice corpse"); 1706. } 1707. } 1708. 1709. #endif /* OVLB */ 1710. #ifdef OVL1 1711. 1712. void 1713. stackobj(obj) 1714. struct obj *obj; 1715. { 1716. struct obj *otmp; 1717. 1718. for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere) 1719. if(otmp != obj && merged(&obj,&otmp)) 1720. break; 1721. return; 1722. } 1723. 1724. static boolean 1725. mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ 1726. register struct obj *otmp, *obj; 1727. { 1728. if (obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid || 1729. obj->spe != otmp->spe || obj->dknown != otmp->dknown || 1730. (obj->bknown != otmp->bknown && !Role_is('P')) || 1731. obj->cursed != otmp->cursed || obj->blessed != otmp->blessed || 1732. obj->no_charge != otmp->no_charge || 1733. obj->obroken != otmp->obroken || 1734. obj->otrapped != otmp->otrapped || 1735. obj->lamplit != otmp->lamplit || 1736. obj->oeroded != otmp->oeroded) 1737. return(FALSE); 1738. 1739. if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) && 1740. (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown)) 1741. return FALSE; 1742. 1743. if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten || 1744. obj->orotten != otmp->orotten)) 1745. return(FALSE); 1746. 1747. if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) { 1748. if((obj->corpsenm != otmp->corpsenm) || 1749. (ONAME(obj) && strcmp(ONAME(obj), ONAME(otmp)))) 1750. return FALSE; 1751. } 1752. 1753. /* hatching eggs don't merge; ditto for revivable corpses */ 1754. if ((obj->otyp == EGG && (obj->timed || otmp->timed)) || 1755. (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM && 1756. mons[otmp->corpsenm].mlet == S_TROLL)) 1757. return FALSE; 1758. 1759. /* allow candle merging only if their ages are close */ 1760. /* see begin_burn() for a reference for the magic "25" */ 1761. if (Is_candle(obj) && obj->age/25 != otmp->age/25) 1762. return(FALSE); 1763. 1764. /* burning potions of oil never merge */ 1765. if (obj->otyp == POT_OIL && obj->lamplit) 1766. return FALSE; 1767. 1768. /* don't merge surcharged item with base-cost item */ 1769. if (obj->unpaid && !same_price(obj, otmp)) 1770. return FALSE; 1771. 1772. /* if they have names, make sure they're the same */ 1773. if ( (obj->onamelth != otmp->onamelth && 1774. ((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE) 1775. ) || 1776. (obj->onamelth && otmp->onamelth && 1777. strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth))) 1778. return FALSE; 1779. 1780. if(obj->oartifact != otmp->oartifact) return FALSE; 1781. 1782. if(obj->known == otmp->known || 1783. !objects[otmp->otyp].oc_uses_known) { 1784. return((boolean)(objects[obj->otyp].oc_merge)); 1785. } else return(FALSE); 1786. } 1787. 1788. int 1789. doprgold() 1790. { 1791. /* the messages used to refer to "carrying gold", but that didn't 1792. take containers into account */ 1793. if(!u.ugold) 1794. Your("wallet is empty."); 1795. else 1796. Your("wallet contains %ld gold piece%s.", u.ugold, plur(u.ugold)); 1797. shopper_financial_report(); 1798. return 0; 1799. } 1800. 1801. #endif /* OVL1 */ 1802. #ifdef OVLB 1803. 1804. int 1805. doprwep() 1806. { 1807. if(!uwep) You("are empty %s.", body_part(HANDED)); 1808. else prinv((char *)0, uwep, 0L); 1809. return 0; 1810. } 1811. 1812. int 1813. doprarm() 1814. { 1815. if(!wearing_armor()) 1816. You("are not wearing any armor."); 1817. else { 1818. #ifdef TOURIST 1819. char lets[8]; 1820. #else 1821. char lets[7]; 1822. #endif 1823. register int ct = 0; 1824. 1825. #ifdef TOURIST 1826. if(uarmu) lets[ct++] = obj_to_let(uarmu); 1827. #endif 1828. if(uarm) lets[ct++] = obj_to_let(uarm); 1829. if(uarmc) lets[ct++] = obj_to_let(uarmc); 1830. if(uarmh) lets[ct++] = obj_to_let(uarmh); 1831. if(uarms) lets[ct++] = obj_to_let(uarms); 1832. if(uarmg) lets[ct++] = obj_to_let(uarmg); 1833. if(uarmf) lets[ct++] = obj_to_let(uarmf); 1834. lets[ct] = 0; 1835. (void) display_inventory(lets, FALSE); 1836. } 1837. return 0; 1838. } 1839. 1840. int 1841. doprring() 1842. { 1843. if(!uleft && !uright) 1844. You("are not wearing any rings."); 1845. else { 1846. char lets[3]; 1847. register int ct = 0; 1848. 1849. if(uleft) lets[ct++] = obj_to_let(uleft); 1850. if(uright) lets[ct++] = obj_to_let(uright); 1851. lets[ct] = 0; 1852. (void) display_inventory(lets, FALSE); 1853. } 1854. return 0; 1855. } 1856. 1857. int 1858. dopramulet() 1859. { 1860. if (!uamul) 1861. You("are not wearing an amulet."); 1862. else 1863. prinv((char *)0, uamul, 0L); 1864. return 0; 1865. } 1866. 1867. int 1868. doprtool() 1869. { 1870. register struct obj *otmp; 1871. register int ct=0; 1872. char lets[52+1]; 1873. 1874. for(otmp = invent; otmp; otmp = otmp->nobj) { 1875. if ((otmp->owornmask & W_TOOL) || 1876. (otmp->oclass == TOOL_CLASS && 1877. (otmp == uwep || otmp->lamplit)) || 1878. (otmp->otyp == LEASH && otmp->leashmon)) 1879. lets[ct++] = obj_to_let(otmp); 1880. } 1881. lets[ct] = 0; 1882. if (!ct) You("are not using any tools."); 1883. else (void) display_inventory(lets, FALSE); 1884. return 0; 1885. } 1886. 1887. /* 1888. * uses up an object that's on the floor, charging for it as necessary 1889. */ 1890. void 1891. useupf(obj) 1892. register struct obj *obj; 1893. { 1894. register struct obj *otmp; 1895. 1896. /* burn_floor_paper() keeps an object pointer that it tries to 1897. * useupf() multiple times, so obj must survive if plural */ 1898. if(obj->quan > 1L) 1899. otmp = splitobj(obj, obj->quan - 1L); 1900. else 1901. otmp = obj; 1902. if(costly_spot(otmp->ox, otmp->oy)) { 1903. if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0))) 1904. addtobill(otmp, FALSE, FALSE, FALSE); 1905. else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE); 1906. } 1907. delobj(otmp); 1908. } 1909. 1910. #endif /* OVLB */ 1911. 1912. 1913. #ifdef OVL1 1914. 1915. /* 1916. * Conversion from a class to a string for printing. 1917. * This must match the object class order. 1918. */ 1919. STATIC_VAR NEARDATA const char *names[] = { 0, 1920. "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", 1921. "Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks", 1922. "Wands", "Coins", "Gems", "Boulders/Statues", "Iron balls", 1923. "Chains", "Venoms" 1924. }; 1925. 1926. static NEARDATA const char oth_symbols[] = { 1927. CONTAINED_SYM, 1928. '\0' 1929. }; 1930. 1931. static NEARDATA const char *oth_names[] = { 1932. "Bagged/Boxed items" 1933. }; 1934. 1935. char * 1936. let_to_name(let,unpaid) 1937. char let; 1938. boolean unpaid; 1939. { 1940. const char *class_name; 1941. const char *pos; 1942. int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0; 1943. unsigned len; 1944. static NEARDATA char *buf = (char *)0; 1945. static NEARDATA unsigned bufsiz = 0; 1946. 1947. if (oclass) 1948. class_name = names[oclass]; 1949. else if ((pos = index(oth_symbols, let)) != 0) 1950. class_name = oth_names[pos - oth_symbols]; 1951. else 1952. class_name = names[0]; 1953. 1954. len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof ""); 1955. if (len > bufsiz) { 1956. if (buf) free((genericptr_t)buf), buf = (char *)0; 1957. bufsiz = len + 10; /* add slop to reduce incremental realloc */ 1958. buf = (char *) alloc(bufsiz); 1959. } 1960. if (unpaid) 1961. Strcat(strcpy(buf, "Unpaid "), class_name); 1962. else 1963. Strcpy(buf, class_name); 1964. return (buf); 1965. } 1966. 1967. #endif /* OVL1 */ 1968. #ifdef OVLB 1969. 1970. void 1971. reassign() 1972. { 1973. register int i; 1974. register struct obj *obj; 1975. 1976. for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1977. obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1978. lastinvnr = i; 1979. } 1980. 1981. #endif /* OVLB */ 1982. #ifdef OVL1 1983. 1984. int 1985. doorganize() /* inventory organizer by Del Lamb */ 1986. { 1987. struct obj *obj, *otmp; 1988. register int ix, cur; 1989. register char let; 1990. char alphabet[52+1], buf[52+1]; 1991. char qbuf[QBUFSZ]; 1992. char allowall[2]; 1993. const char *adj_type; 1994. 1995. if (!flags.invlet_constant) reassign(); 1996. /* get a pointer to the object the user wants to organize */ 1997. allowall[0] = ALL_CLASSES; allowall[1] = '\0'; 1998. if (!(obj = getobj(allowall,"adjust"))) return(0); 1999. 2000. /* initialize the list with all upper and lower case letters */ 2001. for (let = 'a', ix = 0; let <= 'z';) alphabet[ix++] = let++; 2002. for (let = 'A', ix = 26; let <= 'Z';) alphabet[ix++] = let++; 2003. alphabet[52] = 0; 2004. 2005. /* blank out all the letters currently in use in the inventory */ 2006. /* except those that will be merged with the selected object */ 2007. for (otmp = invent; otmp; otmp = otmp->nobj) 2008. if (otmp != obj && !mergable(otmp,obj)) 2009. if (otmp->invlet <= 'Z') 2010. alphabet[(otmp->invlet) - 'A' + 26] = ' '; 2011. else alphabet[(otmp->invlet) - 'a'] = ' '; 2012. 2013. /* compact the list by removing all the blanks */ 2014. for (ix = cur = 0; ix <= 52; ix++) 2015. if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix]; 2016. 2017. /* and by dashing runs of letters */ 2018. if(cur > 5) compactify(buf); 2019. 2020. /* get new letter to use as inventory letter */ 2021. for (;;) { 2022. Sprintf(qbuf, "Adjust letter to what [%s]?",buf); 2023. let = yn_function(qbuf, (char *)0, '\0'); 2024. if(index(quitchars,let)) { 2025. pline("Never mind."); 2026. return(0); 2027. } 2028. if (let == '@' || !letter(let)) 2029. pline("Select an inventory slot letter."); 2030. else 2031. break; 2032. } 2033. 2034. /* change the inventory and print the resulting item */ 2035. adj_type = "Moving:"; 2036. 2037. /* 2038. * don't use freeinv/addinv to avoid double-touching artifacts, 2039. * dousing lamps, losing luck, cursing loadstone, etc. 2040. */ 2041. extract_nobj(obj, &invent); 2042. 2043. for (otmp = invent; otmp;) 2044. if (merged(&otmp,&obj)) { 2045. adj_type = "Merging:"; 2046. obj = otmp; 2047. otmp = otmp->nobj; 2048. extract_nobj(obj, &invent); 2049. } else { 2050. if (otmp->invlet == let) { 2051. adj_type = "Swapping:"; 2052. otmp->invlet = obj->invlet; 2053. } 2054. otmp = otmp->nobj; 2055. } 2056. 2057. /* inline addinv (assuming flags.invlet_constant and !merged) */ 2058. obj->invlet = let; 2059. obj->nobj = invent; /* insert at beginning */ 2060. obj->where = OBJ_INVENT; 2061. invent = obj; 2062. reorder_invent(); 2063. 2064. prinv(adj_type, obj, 0L); 2065. update_inventory(); 2066. return(0); 2067. } 2068. 2069. /* common to display_minventory and display_cinventory */ 2070. static void 2071. invdisp_nothing(hdr, txt) 2072. const char *hdr, *txt; 2073. { 2074. winid win; 2075. anything any; 2076. menu_item *selected; 2077. 2078. any.a_void = 0; 2079. win = create_nhwindow(NHW_MENU); 2080. start_menu(win); 2081. add_menu(win, NO_GLYPH, &any, 0, ATR_INVERSE, hdr, MENU_UNSELECTED); 2082. add_menu(win, NO_GLYPH, &any, 0, ATR_NONE, "", MENU_UNSELECTED); 2083. add_menu(win, NO_GLYPH, &any, 0, ATR_NONE, txt, MENU_UNSELECTED); 2084. end_menu(win, (char *)0); 2085. if (select_menu(win, PICK_NONE, &selected) > 0) 2086. free((genericptr_t)selected); 2087. destroy_nhwindow(win); 2088. return; 2089. } 2090. 2091. /* query_objlist callback: return things that could possibly be worn/wielded */ 2092. static boolean 2093. worn_wield_only(obj) 2094. struct obj *obj; 2095. { 2096. return (obj->oclass == WEAPON_CLASS 2097. || obj->oclass == ARMOR_CLASS 2098. || obj->oclass == AMULET_CLASS 2099. || obj->oclass == RING_CLASS 2100. || obj->oclass == TOOL_CLASS); 2101. } 2102. 2103. /* 2104. * Display a monster's inventory. 2105. * Returns a pointer to the object from the monster's inventory selected 2106. * or NULL if nothing was selected. 2107. * 2108. * By default, only worn and wielded items are displayed. The caller 2109. * can pick one. Modifier flags are: 2110. * 2111. * MINV_NOLET - nothing selectable 2112. * MINV_ALL - display all inventory 2113. */ 2114. struct obj * 2115. display_minventory(mon, dflags) 2116. register struct monst *mon; 2117. int dflags; 2118. { 2119. struct obj *ret, m_gold; 2120. char tmp[QBUFSZ]; 2121. int n; 2122. menu_item *selected = 0; 2123. int do_all = (dflags & MINV_ALL) != 0, 2124. do_gold = (do_all && mon->mgold); 2125. 2126. Sprintf(tmp,"%s %s:", s_suffix(Monnam(mon)), 2127. do_all ? "possessions" : "armament"); 2128. 2129. if (do_all ? (mon->minvent || mon->mgold) 2130. : (mon->misc_worn_check || MON_WEP(mon))) { 2131. /* Fool the 'weapon in hand' routine into 2132. * displaying 'weapon in claw', etc. properly. 2133. */ 2134. char save_usym = u.usym; 2135. 2136. u.usym = mon->data->mlet; 2137. uasmon = mon->data; 2138. 2139. if (do_gold) { 2140. /* make temporary gold object & insert at head of inventory */ 2141. m_gold = zeroobj; 2142. m_gold.otyp = GOLD_PIECE; m_gold.oclass = GOLD_CLASS; 2143. m_gold.quan = mon->mgold; m_gold.dknown = 1; 2144. m_gold.where = OBJ_FREE; 2145. add_to_minv(mon, &m_gold); 2146. } 2147. 2148. n = query_objlist(tmp, mon->minvent, INVORDER_SORT, &selected, 2149. (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE, 2150. do_all ? allow_all : worn_wield_only); 2151. 2152. if (do_gold) obj_extract_self(&m_gold); 2153. 2154. u.usym = save_usym; 2155. set_uasmon(); 2156. } else { 2157. invdisp_nothing(tmp, "(none)"); 2158. n = 0; 2159. } 2160. 2161. if (n > 0) { 2162. ret = selected[0].item.a_obj; 2163. free((genericptr_t)selected); 2164. /* 2165. * Unfortunately, we can't return a pointer to our temporary 2166. * gold object. We'll have to work out a scheme where this 2167. * can happen. Maybe even put gold in the inventory list... 2168. */ 2169. if (ret == &m_gold) ret = (struct obj *) 0; 2170. } else 2171. ret = (struct obj *) 0; 2172. return ret; 2173. } 2174. 2175. /* 2176. * Display the contents of a container in inventory style. 2177. * Currently, this is only used for statues, via wand of probing. 2178. */ 2179. struct obj * 2180. display_cinventory(obj) 2181. register struct obj *obj; 2182. { 2183. struct obj *ret; 2184. char tmp[QBUFSZ]; 2185. int n; 2186. menu_item *selected = 0; 2187. 2188. Sprintf(tmp,"Contents of %s:", doname(obj)); 2189. 2190. if (obj->cobj) { 2191. n = query_objlist(tmp, obj->cobj, INVORDER_SORT, &selected, 2192. PICK_NONE, allow_all); 2193. } else { 2194. invdisp_nothing(tmp, "(empty)"); 2195. n = 0; 2196. } 2197. if (n > 0) { 2198. ret = selected[0].item.a_obj; 2199. free((genericptr_t)selected); 2200. } else 2201. ret = (struct obj *) 0; 2202. return ret; 2203. } 2204. 2205. /* query objlist callback: return TRUE if obj is at given location */ 2206. static coord only; 2207. 2208. static boolean 2209. only_here(obj) 2210. struct obj *obj; 2211. { 2212. return (obj->ox == only.x && obj->oy == only.y); 2213. } 2214. 2215. /* 2216. * Display a list of buried items in inventory style. Return a non-zero 2217. * value if there were items at that spot. 2218. * 2219. * Currently, this is only used with a wand of probing zapped downwards. 2220. */ 2221. int 2222. display_binventory(x, y, as_if_seen) 2223. int x, y; 2224. boolean as_if_seen; 2225. { 2226. struct obj *obj; 2227. menu_item *selected = 0; 2228. int n; 2229. 2230. /* count # of objects here */ 2231. for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj) 2232. if (obj->ox == x && obj->oy == y) { 2233. if (as_if_seen) obj->dknown = 1; 2234. n++; 2235. } 2236. 2237. if (n) { 2238. only.x = x; 2239. only.y = y; 2240. if (query_objlist("Things that are buried here:", 2241. level.buriedobjlist, INVORDER_SORT, 2242. &selected, PICK_NONE, only_here) > 0) 2243. free((genericptr_t)selected); 2244. only.x = only.y = 0; 2245. } 2246. return n; 2247. } 2248. 2249. #endif /* OVL1 */ 2250. 2251. /*invent.c*/
|