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

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

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

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