Source:NetHack 3.4.0/pickup.c
Revision as of 13:38, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.4.0/pickup.c moved to Source:NetHack 3.4.0/pickup.c: Robot: moved page)
Below is the full text to pickup.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/pickup.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)pickup.c 3.4 2001/03/14 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* 6. * Contains code for picking objects up, and container use. 7. */ 8. 9. #include "hack.h" 10. 11. STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P)); 12. #ifndef GOLDOBJ 13. STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, 14. const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *)); 15. #else 16. STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, 17. const char *,struct obj *,BOOLEAN_P,int *)); 18. #endif 19. STATIC_DCL void FDECL(check_here, (BOOLEAN_P)); 20. STATIC_DCL boolean FDECL(n_or_more, (struct obj *)); 21. STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); 22. #if 0 /* not used */ 23. STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *)); 24. #endif 25. STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **)); 26. STATIC_DCL int FDECL(count_categories, (struct obj *,int)); 27. STATIC_DCL long FDECL(carry_count, 28. (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *)); 29. STATIC_DCL int FDECL(lift_object, (struct obj *,struct obj *,long *,BOOLEAN_P)); 30. STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *,int)); 31. STATIC_PTR int FDECL(in_container,(struct obj *)); 32. STATIC_PTR int FDECL(ck_bag,(struct obj *)); 33. STATIC_PTR int FDECL(out_container,(struct obj *)); 34. STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P)); 35. STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *)); 36. STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P)); 37. STATIC_DCL boolean FDECL(able_to_loot, (int, int)); 38. STATIC_DCL boolean FDECL(mon_beside, (int, int)); 39. 40. /* define for query_objlist() and autopickup() */ 41. #define FOLLOW(curr, flags) \ 42. (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj) 43. 44. /* 45. * How much the weight of the given container will change when the given 46. * object is removed from it. This calculation must match the one used 47. * by weight() in mkobj.c. 48. */ 49. #define DELTA_CWT(cont,obj) \ 50. ((cont)->cursed ? (obj)->owt * 2 : \ 51. 1 + ((obj)->owt / ((cont)->blessed ? 4 : 2))) 52. #define GOLD_WT(n) (((n) + 50L) / 100L) 53. /* if you can figure this out, give yourself a hearty pat on the back... */ 54. #define GOLD_CAPACITY(w,n) (((w) * -100L) - ((n) + 50L) - 1L) 55. 56. static const char moderateloadmsg[] = "You have a little trouble lifting"; 57. static const char nearloadmsg[] = "You have much trouble lifting"; 58. static const char overloadmsg[] = "You have extreme difficulty lifting"; 59. 60. /* BUG: this lets you look at cockatrice corpses while blind without 61. touching them */ 62. /* much simpler version of the look-here code; used by query_classes() */ 63. STATIC_OVL void 64. simple_look(otmp, here) 65. struct obj *otmp; /* list of objects */ 66. boolean here; /* flag for type of obj list linkage */ 67. { 68. /* Neither of the first two cases is expected to happen, since 69. * we're only called after multiple classes of objects have been 70. * detected, hence multiple objects must be present. 71. */ 72. if (!otmp) { 73. impossible("simple_look(null)"); 74. } else if (!(here ? otmp->nexthere : otmp->nobj)) { 75. pline("%s", doname(otmp)); 76. } else { 77. winid tmpwin = create_nhwindow(NHW_MENU); 78. putstr(tmpwin, 0, ""); 79. do { 80. putstr(tmpwin, 0, doname(otmp)); 81. otmp = here ? otmp->nexthere : otmp->nobj; 82. } while (otmp); 83. display_nhwindow(tmpwin, TRUE); 84. destroy_nhwindow(tmpwin); 85. } 86. } 87. 88. #ifndef GOLDOBJ 89. int 90. collect_obj_classes(ilets, otmp, here, incl_gold, filter) 91. char ilets[]; 92. register struct obj *otmp; 93. boolean here, incl_gold; 94. boolean FDECL((*filter),(OBJ_P)); 95. #else 96. int 97. collect_obj_classes(ilets, otmp, here, filter) 98. char ilets[]; 99. register struct obj *otmp; 100. boolean here; 101. boolean FDECL((*filter),(OBJ_P)); 102. #endif 103. { 104. register int iletct = 0; 105. register char c; 106. 107. #ifndef GOLDOBJ 108. if (incl_gold) 109. ilets[iletct++] = def_oc_syms[GOLD_CLASS]; 110. #endif 111. ilets[iletct] = '\0'; /* terminate ilets so that index() will work */ 112. while (otmp) { 113. c = def_oc_syms[(int)otmp->oclass]; 114. if (!index(ilets, c) && (!filter || (*filter)(otmp))) 115. ilets[iletct++] = c, ilets[iletct] = '\0'; 116. otmp = here ? otmp->nexthere : otmp->nobj; 117. } 118. 119. return iletct; 120. } 121. 122. /* 123. * Suppose some '?' and '!' objects are present, but '/' objects aren't: 124. * "a" picks all items without further prompting; 125. * "A" steps through all items, asking one by one; 126. * "?" steps through '?' items, asking, and ignores '!' ones; 127. * "/" becomes 'A', since no '/' present; 128. * "?a" or "a?" picks all '?' without further prompting; 129. * "/a" or "a/" becomes 'A' since there aren't any '/' 130. * (bug fix: 3.1.0 thru 3.1.3 treated it as "a"); 131. * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/' 132. * (ie, treated as if it had just been "?a"). 133. */ 134. #ifndef GOLDOBJ 135. STATIC_OVL boolean 136. query_classes(oclasses, one_at_a_time, everything, action, objs, 137. here, incl_gold, menu_on_demand) 138. char oclasses[]; 139. boolean *one_at_a_time, *everything; 140. const char *action; 141. struct obj *objs; 142. boolean here, incl_gold; 143. int *menu_on_demand; 144. #else 145. STATIC_OVL boolean 146. query_classes(oclasses, one_at_a_time, everything, action, objs, 147. here, menu_on_demand) 148. char oclasses[]; 149. boolean *one_at_a_time, *everything; 150. const char *action; 151. struct obj *objs; 152. boolean here; 153. int *menu_on_demand; 154. #endif 155. { 156. char ilets[20], inbuf[BUFSZ]; 157. int iletct, oclassct; 158. boolean not_everything; 159. char qbuf[QBUFSZ]; 160. boolean m_seen; 161. 162. oclasses[oclassct = 0] = '\0'; 163. *one_at_a_time = *everything = m_seen = FALSE; 164. iletct = collect_obj_classes(ilets, objs, here, 165. #ifndef GOLDOBJ 166. incl_gold, 167. #endif 168. (boolean FDECL((*),(OBJ_P))) 0); 169. if (iletct == 0) { 170. return FALSE; 171. } else if (iletct == 1) { 172. oclasses[0] = def_char_to_objclass(ilets[0]); 173. oclasses[1] = '\0'; 174. } else { /* more than one choice available */ 175. const char *where = 0; 176. register char sym, oc_of_sym, *p; 177. /* additional choices */ 178. ilets[iletct++] = ' '; 179. ilets[iletct++] = 'a'; 180. ilets[iletct++] = 'A'; 181. ilets[iletct++] = (objs == invent ? 'i' : ':'); 182. if (menu_on_demand) { 183. ilets[iletct++] = 'm'; 184. *menu_on_demand = 0; 185. } 186. ilets[iletct] = '\0'; 187. ask_again: 188. oclasses[oclassct = 0] = '\0'; 189. *one_at_a_time = *everything = FALSE; 190. not_everything = FALSE; 191. Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]", 192. action, ilets); 193. getlin(qbuf,inbuf); 194. if (*inbuf == '\033') return FALSE; 195. 196. for (p = inbuf; (sym = *p++); ) { 197. /* new A function (selective all) added by GAN 01/09/87 */ 198. if (sym == ' ') continue; 199. else if (sym == 'A') *one_at_a_time = TRUE; 200. else if (sym == 'a') *everything = TRUE; 201. else if (sym == ':') { 202. simple_look(objs, here); /* dumb if objs==invent */ 203. goto ask_again; 204. } else if (sym == 'i') { 205. (void) display_inventory((char *)0, TRUE); 206. goto ask_again; 207. } else if (sym == 'm') { 208. m_seen = TRUE; 209. } else { 210. oc_of_sym = def_char_to_objclass(sym); 211. if (index(ilets,sym)) { 212. add_valid_menu_class(oc_of_sym); 213. oclasses[oclassct++] = oc_of_sym; 214. oclasses[oclassct] = '\0'; 215. } else { 216. if (!where) 217. where = !strcmp(action,"pick up") ? "here" : 218. !strcmp(action,"take out") ? 219. "inside" : ""; 220. if (*where) 221. There("are no %c's %s.", sym, where); 222. else 223. You("have no %c's.", sym); 224. not_everything = TRUE; 225. } 226. } 227. } 228. if (m_seen && menu_on_demand) { 229. *menu_on_demand = (*everything || !oclassct) ? -2 : -3; 230. return FALSE; 231. } 232. if (!oclassct && (!*everything || not_everything)) { 233. /* didn't pick anything, 234. or tried to pick something that's not present */ 235. *one_at_a_time = TRUE; /* force 'A' */ 236. *everything = FALSE; /* inhibit 'a' */ 237. } 238. } 239. return TRUE; 240. } 241. 242. /* look at the objects at our location, unless there are too many of them */ 243. STATIC_OVL void 244. check_here(picked_some) 245. boolean picked_some; 246. { 247. register struct obj *obj; 248. register int ct = 0; 249. 250. /* count the objects here */ 251. for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) { 252. if (obj != uchain) 253. ct++; 254. } 255. 256. /* If there are objects here, take a look. */ 257. if (ct) { 258. if (flags.run) nomul(0); 259. flush_screen(1); 260. (void) look_here(ct, picked_some); 261. } else { 262. read_engr_at(u.ux,u.uy); 263. } 264. } 265. 266. /* Value set by query_objlist() for n_or_more(). */ 267. static long val_for_n_or_more; 268. 269. /* query_objlist callback: return TRUE if obj's count is >= reference value */ 270. STATIC_OVL boolean 271. n_or_more(obj) 272. struct obj *obj; 273. { 274. if (obj == uchain) return FALSE; 275. return (obj->quan >= val_for_n_or_more); 276. } 277. 278. /* List of valid menu classes for query_objlist() and allow_category callback */ 279. static char valid_menu_classes[MAXOCLASSES + 2]; 280. 281. void 282. add_valid_menu_class(c) 283. int c; 284. { 285. static int vmc_count = 0; 286. 287. if (c == 0) /* reset */ 288. vmc_count = 0; 289. else 290. valid_menu_classes[vmc_count++] = (char)c; 291. valid_menu_classes[vmc_count] = '\0'; 292. } 293. 294. /* query_objlist callback: return TRUE if not uchain */ 295. STATIC_OVL boolean 296. all_but_uchain(obj) 297. struct obj *obj; 298. { 299. return (obj != uchain); 300. } 301. 302. /* query_objlist callback: return TRUE */ 303. /*ARGSUSED*/ 304. boolean 305. allow_all(obj) 306. struct obj *obj; 307. { 308. return TRUE; 309. } 310. 311. boolean 312. allow_category(obj) 313. struct obj *obj; 314. { 315. if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) || 316. (index(valid_menu_classes, obj->oclass) != (char *)0)) 317. return TRUE; 318. else if (((index(valid_menu_classes,'U') != (char *)0) && 319. (obj->oclass != GOLD_CLASS && obj->bknown && !obj->blessed && !obj->cursed))) 320. return TRUE; 321. else if (((index(valid_menu_classes,'B') != (char *)0) && 322. (obj->oclass != GOLD_CLASS && obj->bknown && obj->blessed))) 323. return TRUE; 324. else if (((index(valid_menu_classes,'C') != (char *)0) && 325. (obj->oclass != GOLD_CLASS && obj->bknown && obj->cursed))) 326. return TRUE; 327. else if (((index(valid_menu_classes,'X') != (char *)0) && 328. (obj->oclass != GOLD_CLASS && !obj->bknown))) 329. return TRUE; 330. else 331. return FALSE; 332. } 333. 334. #if 0 /* not used */ 335. /* query_objlist callback: return TRUE if valid category (class), no uchain */ 336. STATIC_OVL boolean 337. allow_cat_no_uchain(obj) 338. struct obj *obj; 339. { 340. if ((obj != uchain) && 341. (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) || 342. (index(valid_menu_classes, obj->oclass) != (char *)0))) 343. return TRUE; 344. else 345. return FALSE; 346. } 347. #endif 348. 349. /* query_objlist callback: return TRUE if valid class and worn */ 350. boolean 351. is_worn_by_type(otmp) 352. register struct obj *otmp; 353. { 354. return((boolean)(!!(otmp->owornmask & 355. (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER))) 356. && (index(valid_menu_classes, otmp->oclass) != (char *)0)); 357. } 358. 359. /* 360. * Have the hero pick things from the ground 361. * or a monster's inventory if swallowed. 362. * 363. * Arg what: 364. * >0 autopickup 365. * =0 interactive 366. * <0 pickup count of something 367. * 368. * Returns 1 if tried to pick something up, whether 369. * or not it succeeded. 370. */ 371. int 372. pickup(what) 373. int what; /* should be a long */ 374. { 375. int i, n, res, count, n_tried = 0, n_picked = 0; 376. menu_item *pick_list = (menu_item *) 0; 377. boolean autopickup = what > 0; 378. struct obj *objchain; 379. int traverse_how; 380. 381. if (what < 0) /* pick N of something */ 382. count = -what; 383. else /* pick anything */ 384. count = 0; 385. 386. if (!u.uswallow) { 387. /* no auto-pick if no-pick move, nothing there, or in a pool */ 388. if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) || 389. (is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) { 390. read_engr_at(u.ux, u.uy); 391. return (0); 392. } 393. 394. /* no pickup if levitating & not on air or water level */ 395. if (!can_reach_floor()) { 396. if ((multi && !flags.run) || (autopickup && !flags.pickup)) 397. read_engr_at(u.ux, u.uy); 398. return (0); 399. } 400. 401. /* multi && !flags.run means they are in the middle of some other 402. * action, or possibly paralyzed, sleeping, etc.... and they just 403. * teleported onto the object. They shouldn't pick it up. 404. */ 405. if ((multi && !flags.run) || (autopickup && !flags.pickup)) { 406. check_here(FALSE); 407. return (0); 408. } 409. if (notake(youmonst.data)) { 410. if (!autopickup) 411. You("are physically incapable of picking anything up."); 412. else 413. check_here(FALSE); 414. return (0); 415. } 416. 417. /* if there's anything here, stop running */ 418. if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0); 419. } 420. 421. add_valid_menu_class(0); /* reset */ 422. if (!u.uswallow) { 423. objchain = level.objects[u.ux][u.uy]; 424. traverse_how = BY_NEXTHERE; 425. } else { 426. objchain = u.ustuck->minvent; 427. traverse_how = 0; /* nobj */ 428. } 429. /* 430. * Start the actual pickup process. This is split into two main 431. * sections, the newer menu and the older "traditional" methods. 432. * Automatic pickup has been split into its own menu-style routine 433. * to make things less confusing. 434. */ 435. if (autopickup) { 436. n = autopick(objchain, traverse_how, &pick_list); 437. goto menu_pickup; 438. } 439. 440. if (flags.menu_style != MENU_TRADITIONAL) { 441. /* use menus exclusively */ 442. 443. if (count) { /* looking for N of something */ 444. char buf[QBUFSZ]; 445. Sprintf(buf, "Pick %d of what?", count); 446. val_for_n_or_more = count; /* set up callback selector */ 447. n = query_objlist(buf, objchain, 448. traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT, 449. &pick_list, PICK_ONE, n_or_more); 450. /* correct counts, if any given */ 451. for (i = 0; i < n; i++) 452. pick_list[i].count = count; 453. } else { 454. n = query_objlist("Pick up what?", objchain, 455. traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT, 456. &pick_list, PICK_ANY, all_but_uchain); 457. } 458. menu_pickup: 459. n_tried = n; 460. for (n_picked = i = 0 ; i < n; i++) { 461. res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count, 462. FALSE); 463. if (res < 0) break; /* can't continue */ 464. n_picked += res; 465. } 466. if (pick_list) free((genericptr_t)pick_list); 467. 468. } else { 469. /* old style interface */ 470. int ct = 0; 471. long lcount; 472. boolean all_of_a_type, selective; 473. char oclasses[MAXOCLASSES]; 474. struct obj *obj, *obj2; 475. 476. oclasses[0] = '\0'; /* types to consider (empty for all) */ 477. all_of_a_type = TRUE; /* take all of considered types */ 478. selective = FALSE; /* ask for each item */ 479. 480. /* check for more than one object */ 481. for (obj = objchain; 482. obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj) 483. ct++; 484. 485. if (ct == 1 && count) { 486. /* if only one thing, then pick it */ 487. obj = objchain; 488. lcount = min(obj->quan, (long)count); 489. n_tried++; 490. if (pickup_object(obj, lcount, FALSE) > 0) 491. n_picked++; /* picked something */ 492. goto end_query; 493. 494. } else if (ct >= 2) { 495. int via_menu = 0; 496. 497. There("are %s objects here.", 498. (ct <= 10) ? "several" : "many"); 499. if (!query_classes(oclasses, &selective, &all_of_a_type, 500. "pick up", objchain, 501. traverse_how == BY_NEXTHERE, 502. #ifndef GOLDOBJ 503. FALSE, 504. #endif 505. &via_menu)) { 506. if (!via_menu) return (0); 507. n = query_objlist("Pick up what?", 508. objchain, 509. traverse_how|(selective ? 0 : INVORDER_SORT), 510. &pick_list, PICK_ANY, 511. via_menu == -2 ? allow_all : allow_category); 512. goto menu_pickup; 513. } 514. } 515. 516. for (obj = objchain; obj; obj = obj2) { 517. if (traverse_how == BY_NEXTHERE) 518. obj2 = obj->nexthere; /* perhaps obj will be picked up */ 519. else 520. obj2 = obj->nobj; 521. lcount = -1L; 522. 523. if (!selective && oclasses[0] && !index(oclasses,obj->oclass)) 524. continue; 525. 526. if (!all_of_a_type) { 527. char qbuf[QBUFSZ]; 528. Sprintf(qbuf, "Pick up %s?", doname(obj)); 529. switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) { 530. case 'q': goto end_query; /* out 2 levels */ 531. case 'n': continue; 532. case 'a': 533. all_of_a_type = TRUE; 534. if (selective) { 535. selective = FALSE; 536. oclasses[0] = obj->oclass; 537. oclasses[1] = '\0'; 538. } 539. break; 540. case '#': /* count was entered */ 541. if (!yn_number) continue; /* 0 count => No */ 542. lcount = (long) yn_number; 543. if (lcount > obj->quan) lcount = obj->quan; 544. /* fall thru */ 545. default: /* 'y' */ 546. break; 547. } 548. } 549. if (lcount == -1L) lcount = obj->quan; 550. 551. n_tried++; 552. if ((res = pickup_object(obj, lcount, FALSE)) < 0) break; 553. n_picked += res; 554. } 555. end_query: 556. ; /* semicolon needed by brain-damaged compilers */ 557. } 558. 559. if (!u.uswallow) { 560. if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0; 561. 562. /* position may need updating (invisible hero) */ 563. if (n_picked) newsym(u.ux,u.uy); 564. 565. /* see whether there's anything else here, after auto-pickup is done */ 566. if (autopickup) check_here(n_picked > 0); 567. } 568. return (n_tried > 0); 569. } 570. 571. /* 572. * Pick from the given list using flags.pickup_types. Return the number 573. * of items picked (not counts). Create an array that returns pointers 574. * and counts of the items to be picked up. If the number of items 575. * picked is zero, the pickup list is left alone. The caller of this 576. * function must free the pickup list. 577. */ 578. STATIC_OVL int 579. autopick(olist, follow, pick_list) 580. struct obj *olist; /* the object list */ 581. int follow; /* how to follow the object list */ 582. menu_item **pick_list; /* list of objects and counts to pick up */ 583. { 584. menu_item *pi; /* pick item */ 585. struct obj *curr; 586. int n; 587. const char *otypes = flags.pickup_types; 588. 589. /* first count the number of eligible items */ 590. for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) 591. if (!*otypes || index(otypes, curr->oclass)) 592. n++; 593. 594. if (n) { 595. *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n); 596. for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) 597. if (!*otypes || index(otypes, curr->oclass)) { 598. pi[n].item.a_obj = curr; 599. pi[n].count = curr->quan; 600. n++; 601. } 602. } 603. return n; 604. } 605. 606. 607. /* 608. * Put up a menu using the given object list. Only those objects on the 609. * list that meet the approval of the allow function are displayed. Return 610. * a count of the number of items selected, as well as an allocated array of 611. * menu_items, containing pointers to the objects selected and counts. The 612. * returned counts are guaranteed to be in bounds and non-zero. 613. * 614. * Query flags: 615. * BY_NEXTHERE - Follow object list via nexthere instead of nobj. 616. * AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just 617. * use it. 618. * USE_INVLET - Use object's invlet. 619. * INVORDER_SORT - Use hero's pack order. 620. * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow". 621. */ 622. int 623. query_objlist(qstr, olist, qflags, pick_list, how, allow) 624. const char *qstr; /* query string */ 625. struct obj *olist; /* the list to pick from */ 626. int qflags; /* options to control the query */ 627. menu_item **pick_list; /* return list of items picked */ 628. int how; /* type of query */ 629. boolean FDECL((*allow), (OBJ_P));/* allow function */ 630. { 631. int n; 632. winid win; 633. struct obj *curr, *last; 634. char *pack; 635. anything any; 636. boolean printed_type_name; 637. 638. *pick_list = (menu_item *) 0; 639. if (!olist) return 0; 640. 641. /* count the number of items allowed */ 642. for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags)) 643. if ((*allow)(curr)) { 644. last = curr; 645. n++; 646. } 647. 648. if (n == 0) /* nothing to pick here */ 649. return (qflags & SIGNAL_NOMENU) ? -1 : 0; 650. 651. if (n == 1 && (qflags & AUTOSELECT_SINGLE)) { 652. *pick_list = (menu_item *) alloc(sizeof(menu_item)); 653. (*pick_list)->item.a_obj = last; 654. (*pick_list)->count = last->quan; 655. return 1; 656. } 657. 658. win = create_nhwindow(NHW_MENU); 659. start_menu(win); 660. any.a_obj = (struct obj *) 0; 661. 662. /* 663. * Run through the list and add the objects to the menu. If 664. * INVORDER_SORT is set, we'll run through the list once for 665. * each type so we can group them. The allow function will only 666. * be called once per object in the list. 667. */ 668. pack = flags.inv_order; 669. do { 670. printed_type_name = FALSE; 671. for (curr = olist; curr; curr = FOLLOW(curr, qflags)) 672. if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack) 673. && (*allow)(curr)) { 674. 675. /* if sorting, print type name (once only) */ 676. if (qflags & INVORDER_SORT && !printed_type_name) { 677. any.a_obj = (struct obj *) 0; 678. add_menu(win, NO_GLYPH, &any, 0, 0, ATR_INVERSE, 679. let_to_name(*pack, FALSE), MENU_UNSELECTED); 680. printed_type_name = TRUE; 681. } 682. 683. any.a_obj = curr; 684. add_menu(win, obj_to_glyph(curr), &any, 685. qflags & USE_INVLET ? curr->invlet : 0, 686. def_oc_syms[(int)objects[curr->otyp].oc_class], 687. ATR_NONE, doname(curr), MENU_UNSELECTED); 688. } 689. pack++; 690. } while (qflags & INVORDER_SORT && *pack); 691. 692. end_menu(win, qstr); 693. n = select_menu(win, how, pick_list); 694. destroy_nhwindow(win); 695. 696. if (n > 0) { 697. menu_item *mi; 698. int i; 699. 700. /* fix up counts: -1 means no count used => pick all */ 701. for (i = 0, mi = *pick_list; i < n; i++, mi++) 702. if (mi->count == -1L || mi->count > mi->item.a_obj->quan) 703. mi->count = mi->item.a_obj->quan; 704. } else if (n < 0) { 705. n = 0; /* caller's don't expect -1 */ 706. } 707. return n; 708. } 709. 710. /* 711. * allow menu-based category (class) selection (for Drop,take off etc.) 712. * 713. */ 714. int 715. query_category(qstr, olist, qflags, pick_list, how) 716. const char *qstr; /* query string */ 717. struct obj *olist; /* the list to pick from */ 718. int qflags; /* behaviour modification flags */ 719. menu_item **pick_list; /* return list of items picked */ 720. int how; /* type of query */ 721. { 722. int n; 723. winid win; 724. struct obj *curr; 725. char *pack; 726. anything any; 727. boolean collected_type_name; 728. char invlet; 729. int ccount; 730. boolean do_unpaid = FALSE; 731. boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE, 732. do_buc_unknown = FALSE; 733. int num_buc_types = 0; 734. 735. *pick_list = (menu_item *) 0; 736. if (!olist) return 0; 737. if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE; 738. if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) { 739. do_blessed = TRUE; 740. num_buc_types++; 741. } 742. if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) { 743. do_cursed = TRUE; 744. num_buc_types++; 745. } 746. if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) { 747. do_uncursed = TRUE; 748. num_buc_types++; 749. } 750. if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) { 751. do_buc_unknown = TRUE; 752. num_buc_types++; 753. } 754. 755. ccount = count_categories(olist, qflags); 756. /* no point in actually showing a menu for a single category */ 757. if (ccount == 1 && !do_unpaid && num_buc_types <= 1 && !(qflags & BILLED_TYPES)) { 758. for (curr = olist; curr; curr = FOLLOW(curr, qflags)) { 759. if ((qflags & WORN_TYPES) && 760. !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER))) 761. continue; 762. break; 763. } 764. if (curr) { 765. *pick_list = (menu_item *) alloc(sizeof(menu_item)); 766. (*pick_list)->item.a_int = curr->oclass; 767. return 1; 768. } else { 769. #ifdef DEBUG 770. impossible("query_category: no single object match"); 771. #endif 772. } 773. return 0; 774. } 775. 776. win = create_nhwindow(NHW_MENU); 777. start_menu(win); 778. pack = flags.inv_order; 779. if ((qflags & ALL_TYPES) && (ccount > 1)) { 780. invlet = 'a'; 781. any.a_void = 0; 782. any.a_int = ALL_TYPES_SELECTED; 783. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 784. (qflags & WORN_TYPES) ? "All worn types" : "All types", 785. MENU_UNSELECTED); 786. invlet = 'b'; 787. } else 788. invlet = 'a'; 789. do { 790. collected_type_name = FALSE; 791. for (curr = olist; curr; curr = FOLLOW(curr, qflags)) { 792. if (curr->oclass == *pack) { 793. if ((qflags & WORN_TYPES) && 794. !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | 795. W_WEP | W_SWAPWEP | W_QUIVER))) 796. continue; 797. if (!collected_type_name) { 798. any.a_void = 0; 799. any.a_int = curr->oclass; 800. add_menu(win, NO_GLYPH, &any, invlet++, 801. def_oc_syms[(int)objects[curr->otyp].oc_class], 802. ATR_NONE, let_to_name(*pack, FALSE), 803. MENU_UNSELECTED); 804. collected_type_name = TRUE; 805. } 806. } 807. } 808. pack++; 809. if (invlet >= 'u') { 810. impossible("query_category: too many categories"); 811. return 0; 812. } 813. } while (*pack); 814. /* unpaid items if there are any */ 815. if (do_unpaid) { 816. invlet = 'u'; 817. any.a_void = 0; 818. any.a_int = 'u'; 819. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 820. "Unpaid items", MENU_UNSELECTED); 821. } 822. /* billed items: checked by caller, so always include if BILLED_TYPES */ 823. if (qflags & BILLED_TYPES) { 824. invlet = 'x'; 825. any.a_void = 0; 826. any.a_int = 'x'; 827. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 828. "Unpaid items already used up", MENU_UNSELECTED); 829. } 830. if (qflags & CHOOSE_ALL) { 831. invlet = 'A'; 832. any.a_void = 0; 833. any.a_int = 'A'; 834. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 835. (qflags & WORN_TYPES) ? 836. "Auto-select every item being worn" : 837. "Auto-select every item", MENU_UNSELECTED); 838. } 839. /* items with b/u/c/unknown if there are any */ 840. if (do_blessed) { 841. invlet = 'B'; 842. any.a_void = 0; 843. any.a_int = 'B'; 844. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 845. "Items known to be Blessed", MENU_UNSELECTED); 846. } 847. if (do_cursed) { 848. invlet = 'C'; 849. any.a_void = 0; 850. any.a_int = 'C'; 851. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 852. "Items known to be Cursed", MENU_UNSELECTED); 853. } 854. if (do_uncursed) { 855. invlet = 'U'; 856. any.a_void = 0; 857. any.a_int = 'U'; 858. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 859. "Items known to be Uncursed", MENU_UNSELECTED); 860. } 861. if (do_buc_unknown) { 862. invlet = 'X'; 863. any.a_void = 0; 864. any.a_int = 'X'; 865. add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, 866. "Items of unknown B/C/U status", 867. MENU_UNSELECTED); 868. } 869. end_menu(win, qstr); 870. n = select_menu(win, how, pick_list); 871. destroy_nhwindow(win); 872. if (n < 0) 873. n = 0; /* caller's don't expect -1 */ 874. return n; 875. } 876. 877. STATIC_OVL int 878. count_categories(olist, qflags) 879. struct obj *olist; 880. int qflags; 881. { 882. char *pack; 883. boolean counted_category; 884. int ccount = 0; 885. struct obj *curr; 886. 887. pack = flags.inv_order; 888. do { 889. counted_category = FALSE; 890. for (curr = olist; curr; curr = FOLLOW(curr, qflags)) { 891. if (curr->oclass == *pack) { 892. if ((qflags & WORN_TYPES) && 893. !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | 894. W_WEP | W_SWAPWEP | W_QUIVER))) 895. continue; 896. if (!counted_category) { 897. ccount++; 898. counted_category = TRUE; 899. } 900. } 901. } 902. pack++; 903. } while (*pack); 904. return ccount; 905. } 906. 907. /* could we carry `obj'? if not, could we carry some of it/them? */ 908. STATIC_OVL 909. long carry_count(obj, container, count, telekinesis, wt_before, wt_after) 910. struct obj *obj, *container; /* object to pick up, bag it's coming out of */ 911. long count; 912. boolean telekinesis; 913. int *wt_before, *wt_after; 914. { 915. boolean adjust_wt = container && carried(container), 916. is_gold = obj->oclass == GOLD_CLASS; 917. int wt, iw, ow, oow; 918. long qq, savequan; 919. #ifdef GOLDOBJ 920. long umoney = money_cnt(invent); 921. #endif 922. unsigned saveowt; 923. const char *verb, *prefx1, *prefx2, *suffx; 924. char obj_nambuf[BUFSZ], where[BUFSZ]; 925. 926. savequan = obj->quan; 927. saveowt = obj->owt; 928. 929. iw = max_capacity(); 930. 931. if (count != savequan) { 932. obj->quan = count; 933. obj->owt = (unsigned)weight(obj); 934. } 935. wt = iw + (int)obj->owt; 936. if (adjust_wt) 937. wt -= (container->otyp == BAG_OF_HOLDING) ? 938. (int)DELTA_CWT(container, obj) : (int)obj->owt; 939. #ifndef GOLDOBJ 940. if (is_gold) /* merged gold might affect cumulative weight */ 941. wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count)); 942. #else 943. /* This will go with silver+copper & new gold weight */ 944. if (is_gold) /* merged gold might affect cumulative weight */ 945. wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count)); 946. #endif 947. if (count != savequan) { 948. obj->quan = savequan; 949. obj->owt = saveowt; 950. } 951. *wt_before = iw; 952. *wt_after = wt; 953. 954. if (wt < 0) 955. return count; 956. 957. /* see how many we can lift */ 958. if (is_gold) { 959. #ifndef GOLDOBJ 960. iw -= (int)GOLD_WT(u.ugold); 961. if (!adjust_wt) { 962. qq = GOLD_CAPACITY((long)iw, u.ugold); 963. } else { 964. oow = 0; 965. qq = 50L - (u.ugold % 100L) - 1L; 966. #else 967. iw -= (int)GOLD_WT(umoney); 968. if (!adjust_wt) { 969. qq = GOLD_CAPACITY((long)iw, umoney); 970. } else { 971. oow = 0; 972. qq = 50L - (umoney % 100L) - 1L; 973. #endif 974. if (qq < 0L) qq += 100L; 975. for ( ; qq <= count; qq += 100L) { 976. obj->quan = qq; 977. obj->owt = (unsigned)GOLD_WT(qq); 978. #ifndef GOLDOBJ 979. ow = (int)GOLD_WT(u.ugold + qq); 980. #else 981. ow = (int)GOLD_WT(umoney + qq); 982. #endif 983. ow -= (container->otyp == BAG_OF_HOLDING) ? 984. (int)DELTA_CWT(container, obj) : (int)obj->owt; 985. if (iw + ow >= 0) break; 986. oow = ow; 987. } 988. iw -= oow; 989. qq -= 100L; 990. } 991. if (qq < 0L) qq = 0L; 992. else if (qq > count) qq = count; 993. #ifndef GOLDOBJ 994. wt = iw + (int)GOLD_WT(u.ugold + qq); 995. #else 996. wt = iw + (int)GOLD_WT(umoney + qq); 997. #endif 998. } else if (count > 1 || count < obj->quan) { 999. /* 1000. * Ugh. Calc num to lift by changing the quan of of the 1001. * object and calling weight. 1002. * 1003. * This works for containers only because containers 1004. * don't merge. -dean 1005. */ 1006. for (qq = 1L; qq <= count; qq++) { 1007. obj->quan = qq; 1008. obj->owt = (unsigned)(ow = weight(obj)); 1009. if (adjust_wt) 1010. ow -= (container->otyp == BAG_OF_HOLDING) ? 1011. (int)DELTA_CWT(container, obj) : (int)obj->owt; 1012. if (iw + ow >= 0) 1013. break; 1014. wt = iw + ow; 1015. } 1016. --qq; 1017. } else { 1018. /* there's only one, and we can't lift it */ 1019. qq = 0L; 1020. } 1021. obj->quan = savequan; 1022. obj->owt = saveowt; 1023. 1024. if (qq < count) { 1025. /* some message will be given */ 1026. Strcpy(obj_nambuf, doname(obj)); 1027. if (container) { 1028. Sprintf(where, "in %s", the(xname(container))); 1029. verb = "carry"; 1030. } else { 1031. Strcpy(where, "lying here"); 1032. verb = telekinesis ? "acquire" : "lift"; 1033. } 1034. } else { 1035. /* lint supppression */ 1036. *obj_nambuf = *where = '\0'; 1037. verb = ""; 1038. } 1039. /* we can carry qq of them */ 1040. if (qq > 0) { 1041. if (qq < count) 1042. You("can only %s %s of the %s %s.", 1043. verb, (qq == 1L) ? "one" : "some", obj_nambuf, where); 1044. *wt_after = wt; 1045. return qq; 1046. } 1047. 1048. if (!container) Strcpy(where, "here"); /* slightly shorter form */ 1049. #ifndef GOLDOBJ 1050. if (invent || u.ugold) { 1051. #else 1052. if (invent || umoney) { 1053. #endif 1054. prefx1 = "you cannot "; 1055. prefx2 = ""; 1056. suffx = " any more"; 1057. } else { 1058. prefx1 = (obj->quan == 1L) ? "it " : "even one "; 1059. prefx2 = "is too heavy for you to "; 1060. suffx = ""; 1061. } 1062. There("%s %s %s, but %s%s%s%s.", 1063. otense(obj, "are"), obj_nambuf, where, 1064. prefx1, prefx2, verb, suffx); 1065. 1066. /* *wt_after = iw; */ 1067. return 0L; 1068. } 1069. 1070. /* determine whether character is able and player is willing to carry `obj' */ 1071. STATIC_OVL 1072. int 1073. lift_object(obj, container, cnt_p, telekinesis) 1074. struct obj *obj, *container; /* object to pick up, bag it's coming out of */ 1075. long *cnt_p; 1076. boolean telekinesis; 1077. { 1078. int result, old_wt, new_wt, prev_encumbr, next_encumbr; 1079. 1080. if (obj->otyp == BOULDER && In_sokoban(&u.uz)) { 1081. You("cannot get your %s around this %s.", 1082. body_part(HAND), xname(obj)); 1083. return -1; 1084. } 1085. if (obj->otyp == LOADSTONE || 1086. (obj->otyp == BOULDER && throws_rocks(youmonst.data))) 1087. return 1; /* lift regardless of current situation */ 1088. 1089. *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt); 1090. if (*cnt_p < 1L) { 1091. result = -1; /* nothing lifted */ 1092. #ifndef GOLDOBJ 1093. } else if (obj->oclass != GOLD_CLASS && inv_cnt() >= 52 && 1094. !merge_choice(invent, obj)) { 1095. #else 1096. } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) { 1097. #endif 1098. Your("knapsack cannot accommodate any more items."); 1099. result = -1; /* nothing lifted */ 1100. } else { 1101. result = 1; 1102. prev_encumbr = near_capacity(); 1103. if (prev_encumbr < flags.pickup_burden) 1104. prev_encumbr = flags.pickup_burden; 1105. next_encumbr = calc_capacity(new_wt - old_wt); 1106. if (next_encumbr > prev_encumbr) { 1107. if (telekinesis) { 1108. result = 0; /* don't lift */ 1109. } else { 1110. char qbuf[QBUFSZ]; 1111. long savequan = obj->quan; 1112. 1113. obj->quan = *cnt_p; 1114. Sprintf(qbuf, "%s %s. Continue?", 1115. (next_encumbr > HVY_ENCUMBER) ? overloadmsg : 1116. (next_encumbr > MOD_ENCUMBER) ? nearloadmsg : 1117. moderateloadmsg, doname(obj)); 1118. obj->quan = savequan; 1119. switch (ynq(qbuf)) { 1120. case 'q': result = -1; break; 1121. case 'n': result = 0; break; 1122. default: break; /* 'y' => result == 1 */ 1123. } 1124. } 1125. } 1126. } 1127. 1128. if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container) 1129. obj->spe = 0; 1130. return result; 1131. } 1132. 1133. /* 1134. * Pick up <count> of obj from the ground and add it to the hero's inventory. 1135. * Returns -1 if caller should break out of its loop, 0 if nothing picked 1136. * up, 1 if otherwise. 1137. */ 1138. int 1139. pickup_object(obj, count, telekinesis) 1140. struct obj *obj; 1141. long count; 1142. boolean telekinesis; /* not picking it up directly by hand */ 1143. { 1144. int res, nearload; 1145. #ifndef GOLDOBJ 1146. const char *where = (obj->ox == u.ux && obj->oy == u.uy) ? 1147. "here" : "there"; 1148. #endif 1149. 1150. if (obj->quan < count) { 1151. impossible("pickup_object: count %ld > quan %ld?", 1152. count, obj->quan); 1153. return 0; 1154. } 1155. 1156. /* In case of auto-pickup, where we haven't had a chance 1157. to look at it yet; affects docall(SCR_SCARE_MONSTER). */ 1158. if (!Blind) 1159. #ifdef INVISIBLE_OBJECTS 1160. if (!obj->oinvis || See_invisible) 1161. #endif 1162. obj->dknown = 1; 1163. 1164. if (obj == uchain) { /* do not pick up attached chain */ 1165. return 0; 1166. } else if (obj->oartifact && !touch_artifact(obj,&youmonst)) { 1167. return 0; 1168. #ifndef GOLDOBJ 1169. } else if (obj->oclass == GOLD_CLASS) { 1170. /* Special consideration for gold pieces... */ 1171. long iw = (long)max_capacity() - GOLD_WT(u.ugold); 1172. long gold_capacity = GOLD_CAPACITY(iw, u.ugold); 1173. 1174. if (gold_capacity <= 0L) { 1175. pline( 1176. "There %s %ld gold piece%s %s, but you cannot carry any more.", 1177. otense(obj, "are"), 1178. obj->quan, plur(obj->quan), where); 1179. return 0; 1180. } else if (gold_capacity < count) { 1181. You("can only %s %s of the %ld gold pieces lying %s.", 1182. telekinesis ? "acquire" : "carry", 1183. gold_capacity == 1L ? "one" : "some", obj->quan, where); 1184. pline("%s %ld gold piece%s.", 1185. nearloadmsg, gold_capacity, plur(gold_capacity)); 1186. u.ugold += gold_capacity; 1187. obj->quan -= gold_capacity; 1188. costly_gold(obj->ox, obj->oy, gold_capacity); 1189. } else { 1190. u.ugold += count; 1191. if ((nearload = near_capacity()) != 0) 1192. pline("%s %ld gold piece%s.", 1193. nearload < MOD_ENCUMBER ? 1194. moderateloadmsg : nearloadmsg, 1195. count, plur(count)); 1196. else 1197. prinv((char *) 0, obj, count); 1198. costly_gold(obj->ox, obj->oy, count); 1199. if (count == obj->quan) 1200. delobj(obj); 1201. else 1202. obj->quan -= count; 1203. } 1204. flags.botl = 1; 1205. if (flags.run) nomul(0); 1206. return 1; 1207. #endif 1208. } else if (obj->otyp == CORPSE) { 1209. if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg 1210. && !Stone_resistance && !telekinesis) { 1211. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 1212. display_nhwindow(WIN_MESSAGE, FALSE); 1213. else { 1214. char kbuf[BUFSZ]; 1215. 1216. Strcpy(kbuf, an(corpse_xname(obj, TRUE))); 1217. pline("Touching %s is a fatal mistake.", kbuf); 1218. instapetrify(kbuf); 1219. return -1; 1220. } 1221. } else if (is_rider(&mons[obj->corpsenm])) { 1222. pline("At your %s, the corpse suddenly moves...", 1223. telekinesis ? "attempted acquisition" : "touch"); 1224. (void) revive_corpse(obj); 1225. exercise(A_WIS, FALSE); 1226. return -1; 1227. } 1228. } else if (obj->otyp == SCR_SCARE_MONSTER) { 1229. if (obj->blessed) obj->blessed = 0; 1230. else if (!obj->spe && !obj->cursed) obj->spe = 1; 1231. else { 1232. pline_The("scroll%s %s to dust as you %s %s up.", 1233. plur(obj->quan), otense(obj, "turn"), 1234. telekinesis ? "raise" : "pick", 1235. (obj->quan == 1L) ? "it" : "them"); 1236. if (!(objects[SCR_SCARE_MONSTER].oc_name_known) && 1237. !(objects[SCR_SCARE_MONSTER].oc_uname)) 1238. docall(obj); 1239. useupf(obj, obj->quan); 1240. return 1; /* tried to pick something up and failed, but 1241. don't want to terminate pickup loop yet */ 1242. } 1243. } 1244. 1245. if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0) 1246. return res; 1247. 1248. #ifdef GOLDOBJ 1249. /* Whats left of the special case for gold :-) */ 1250. if (obj->oclass == GOLD_CLASS) flags.botl = 1; 1251. #endif 1252. if (obj->quan != count && obj->otyp != LOADSTONE) 1253. obj = splitobj(obj, count); 1254. 1255. obj = pick_obj(obj); 1256. 1257. if (uwep && uwep == obj) mrg_to_wielded = TRUE; 1258. nearload = near_capacity(); 1259. prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, 1260. obj, count); 1261. mrg_to_wielded = FALSE; 1262. return 1; 1263. } 1264. 1265. /* 1266. * Do the actual work of picking otmp from the floor and putting 1267. * it in the hero's inventory. Take care of billing. Return a 1268. * pointer to the object where otmp ends up. This may be different 1269. * from otmp because of merging. 1270. * 1271. * Gold never reaches this routine unless GOLDOBJ is defined. 1272. */ 1273. struct obj * 1274. pick_obj(otmp) 1275. struct obj *otmp; 1276. { 1277. obj_extract_self(otmp); 1278. if (otmp->no_charge) { 1279. /* this attribute only applies to objects outside invent */ 1280. otmp->no_charge = 0; 1281. } else if (otmp != uball && costly_spot(otmp->ox, otmp->oy)) { 1282. char saveushops[5], fakeshop[2]; 1283. 1284. /* addtobill cares about your location rather than the object's; 1285. usually they'll be the same, but not when using telekinesis 1286. (if ever implemented) or a grappling hook */ 1287. Strcpy(saveushops, u.ushops); 1288. fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE); 1289. fakeshop[1] = '\0'; 1290. Strcpy(u.ushops, fakeshop); 1291. /* sets obj->unpaid if necessary */ 1292. addtobill(otmp, TRUE, FALSE, FALSE); 1293. Strcpy(u.ushops, saveushops); 1294. /* if you're outside the shop, make shk notice */ 1295. if (!index(u.ushops, *fakeshop)) 1296. remote_burglary(otmp->ox, otmp->oy); 1297. } 1298. if (Invisible) newsym(otmp->ox, otmp->oy); 1299. return addinv(otmp); /* might merge it with other objects */ 1300. } 1301. 1302. /* 1303. * prints a message if encumbrance changed since the last check and 1304. * returns the new encumbrance value (from near_capacity()). 1305. */ 1306. int 1307. encumber_msg() 1308. { 1309. static int oldcap = UNENCUMBERED; 1310. int newcap = near_capacity(); 1311. 1312. if(oldcap < newcap) { 1313. switch(newcap) { 1314. case 1: Your("movements are slowed slightly because of your load."); 1315. break; 1316. case 2: You("rebalance your load. Movement is difficult."); 1317. break; 1318. case 3: You("%s under your heavy load. Movement is very hard.", 1319. stagger(youmonst.data, "stagger")); 1320. break; 1321. default: You("%s move a handspan with this load!", 1322. newcap == 4 ? "can barely" : "can't even"); 1323. break; 1324. } 1325. flags.botl = 1; 1326. } else if(oldcap > newcap) { 1327. switch(newcap) { 1328. case 0: Your("movements are now unencumbered."); 1329. break; 1330. case 1: Your("movements are only slowed slightly by your load."); 1331. break; 1332. case 2: You("rebalance your load. Movement is still difficult."); 1333. break; 1334. case 3: You("%s under your load. Movement is still very hard.", 1335. stagger(youmonst.data, "stagger")); 1336. break; 1337. } 1338. flags.botl = 1; 1339. } 1340. 1341. oldcap = newcap; 1342. return (newcap); 1343. } 1344. 1345. /* Is there a container at x,y. Optional: return count of containers at x,y */ 1346. STATIC_OVL int 1347. container_at(x, y, countem) 1348. int x,y; 1349. boolean countem; 1350. { 1351. struct obj *cobj, *nobj; 1352. int container_count = 0; 1353. 1354. for(cobj = level.objects[x][y]; cobj; cobj = nobj) { 1355. nobj = cobj->nexthere; 1356. if(Is_container(cobj)) { 1357. container_count++; 1358. if (!countem) break; 1359. } 1360. } 1361. return container_count; 1362. } 1363. 1364. STATIC_OVL boolean 1365. able_to_loot(x, y) 1366. int x, y; 1367. { 1368. if (!can_reach_floor()) { 1369. #ifdef STEED 1370. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 1371. You("aren't skilled enough to reach from %s.", 1372. mon_nam(u.usteed)); 1373. else 1374. #endif 1375. You("cannot reach the %s.", surface(x, y)); 1376. return FALSE; 1377. } else if (is_pool(x, y) || is_lava(x, y)) { 1378. /* at present, can't loot in water even when Underwater */ 1379. You("cannot loot things that are deep in the %s.", 1380. is_lava(x, y) ? "lava" : "water"); 1381. return FALSE; 1382. } else if (nolimbs(youmonst.data)) { 1383. pline("Without limbs, you cannot loot anything."); 1384. return FALSE; 1385. } 1386. return TRUE; 1387. } 1388. 1389. STATIC_OVL 1390. boolean mon_beside(x,y) 1391. int x, y; 1392. { 1393. int i,j,nx,ny; 1394. for(i = -1; i <= 1; i++) 1395. for(j = -1; j <= 1; j++) { 1396. nx = x + i; 1397. ny = y + j; 1398. if(isok(nx, ny) && MON_AT(nx, ny)) 1399. return TRUE; 1400. } 1401. return FALSE; 1402. } 1403. 1404. int 1405. doloot() /* loot a container on the floor. */ 1406. { 1407. register struct obj *cobj, *nobj; 1408. register int c = -1; 1409. int timepassed = 0; 1410. int x,y; 1411. boolean underfoot = TRUE; 1412. const char *dont_find_anything = "don't find anything"; 1413. struct monst *mtmp; 1414. char qbuf[QBUFSZ]; 1415. int prev_inquiry = 0; 1416. boolean prev_loot = FALSE; 1417. 1418. if (check_capacity((char *)0)) { 1419. /* "Can't do that while carrying so much stuff." */ 1420. return 0; 1421. } 1422. if (nohands(youmonst.data)) { 1423. You("have no hands!"); /* not `body_part(HAND)' */ 1424. return 0; 1425. } 1426. x = u.ux; y = u.uy; 1427. 1428. lootcont: 1429. 1430. if (container_at(x, y, FALSE)) { 1431. if (!able_to_loot(x, y)) return 0; 1432. for (cobj = level.objects[x][y]; cobj; cobj = nobj) { 1433. nobj = cobj->nexthere; 1434. 1435. if (Is_container(cobj)) { 1436. Sprintf(qbuf, "There is %s here, loot it?", doname(cobj)); 1437. c = ynq(qbuf); 1438. if (c == 'q') return (timepassed); 1439. if (c == 'n') continue; 1440. 1441. if (cobj->olocked) { 1442. pline("Hmmm, it seems to be locked."); 1443. continue; 1444. } 1445. if (cobj->otyp == BAG_OF_TRICKS) { 1446. int tmp; 1447. You("carefully open the bag..."); 1448. pline("It develops a huge set of teeth and bites you!"); 1449. tmp = rnd(10); 1450. if (Half_physical_damage) tmp = (tmp+1) / 2; 1451. losehp(tmp, "carnivorous bag", KILLED_BY_AN); 1452. makeknown(BAG_OF_TRICKS); 1453. timepassed = 1; 1454. continue; 1455. } 1456. 1457. You("carefully open %s...", the(xname(cobj))); 1458. timepassed |= use_container(cobj, 0); 1459. if (multi < 0) return 1; /* chest trap */ 1460. } 1461. } 1462. } else if (Confusion) { 1463. #ifndef GOLDOBJ 1464. if (u.ugold){ 1465. long contribution = rnd((int)min(LARGEST_INT,u.ugold)); 1466. struct obj *goldob = mkgoldobj(contribution); 1467. #else 1468. struct obj *goldob; 1469. /* Find a money object to mess with */ 1470. for (goldob = invent; goldob; goldob = goldob->nobj) { 1471. if (goldob->oclass == GOLD_CLASS) break; 1472. } 1473. if (goldob){ 1474. long contribution = rnd((int)min(LARGEST_INT, goldob->quan)); 1475. if (contribution < goldob->quan) 1476. goldob = splitobj(goldob, contribution); 1477. freeinv(goldob); 1478. #endif 1479. if (IS_THRONE(levl[u.ux][u.uy].typ)){ 1480. struct obj *coffers; 1481. int pass; 1482. /* find the original coffers chest, or any chest */ 1483. for (pass = 2; pass > -1; pass -= 2) 1484. for (coffers = fobj; coffers; coffers = coffers->nobj) 1485. if (coffers->otyp == CHEST && coffers->spe == pass) 1486. goto gotit; /* two level break */ 1487. gotit: 1488. if (coffers) { 1489. verbalize("Thank you for your contribution to reduce the debt."); 1490. (void) add_to_container(coffers, goldob); 1491. coffers->owt = weight(coffers); 1492. } else { 1493. struct monst *mon = makemon(courtmon(), 1494. u.ux, u.uy, NO_MM_FLAGS); 1495. if (mon) { 1496. #ifndef GOLDOBJ 1497. mon->mgold += goldob->quan; 1498. delobj(goldob); 1499. pline("The exchequer accepts your contribution."); 1500. } else { 1501. dropx(goldob); 1502. } 1503. } 1504. } else { 1505. dropx(goldob); 1506. #else 1507. add_to_minv(mon, goldob); 1508. pline("The exchequer accepts your contribution."); 1509. } else { 1510. dropy(goldob); 1511. } 1512. } 1513. } else { 1514. dropy(goldob); 1515. #endif 1516. pline("Ok, now there is loot here."); 1517. } 1518. } 1519. } else if (IS_GRAVE(levl[x][y].typ)) { 1520. You("need to dig up the grave to effectively loot it..."); 1521. } 1522. /* 1523. * 3.3.1 introduced directional looting for some things. 1524. */ 1525. if (c != 'y' && mon_beside(u.ux, u.uy)) { 1526. if (!getdir("Loot in what direction?")) { 1527. pline(Never_mind); 1528. return(0); 1529. } 1530. x = u.ux + u.dx; 1531. y = u.uy + u.dy; 1532. if (x == u.ux && y == u.uy) { 1533. underfoot = TRUE; 1534. if (container_at(x, y, FALSE)) 1535. goto lootcont; 1536. } else 1537. underfoot = FALSE; 1538. if (u.dz < 0) { 1539. You("%s to loot on the %s.", dont_find_anything, 1540. ceiling(x, y)); 1541. timepassed = 1; 1542. return timepassed; 1543. } 1544. mtmp = m_at(x, y); 1545. if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot); 1546. 1547. /* Preserve pre-3.3.1 behaviour for containers. 1548. * Adjust this if-block to allow container looting 1549. * from one square away to change that in the future. 1550. */ 1551. if (!underfoot) { 1552. if (container_at(x, y, FALSE)) { 1553. if (mtmp) { 1554. You_cant("loot anything %sthere with %s in the way.", 1555. prev_inquiry ? "else " : "", mon_nam(mtmp)); 1556. return timepassed; 1557. } else { 1558. You("have to be at a container to loot it."); 1559. } 1560. } else { 1561. You("%s %sthere to loot.", dont_find_anything, 1562. (prev_inquiry || prev_loot) ? "else " : ""); 1563. return timepassed; 1564. } 1565. } 1566. } else if (c != 'y' && c != 'n') { 1567. You("%s %s to loot.", dont_find_anything, 1568. underfoot ? "here" : "there"); 1569. } 1570. return (timepassed); 1571. } 1572. 1573. /* loot_mon() returns amount of time passed. 1574. */ 1575. int 1576. loot_mon(mtmp, passed_info, prev_loot) 1577. struct monst *mtmp; 1578. int *passed_info; 1579. boolean *prev_loot; 1580. { 1581. int c = -1; 1582. int timepassed = 0; 1583. #ifdef STEED 1584. struct obj *otmp; 1585. char qbuf[QBUFSZ]; 1586. 1587. /* 3.3.1 introduced the ability to remove saddle from a steed */ 1588. /* *passed_info is set to TRUE if a loot query was given. */ 1589. /* *prev_loot is set to TRUE if something was actually acquired in here. */ 1590. if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) { 1591. long unwornmask; 1592. if (passed_info) *passed_info = 1; 1593. Sprintf(qbuf, "Do you want to remove the saddle from %s?", 1594. x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE)); 1595. if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { 1596. if (nolimbs(youmonst.data)) { 1597. You_cant("do that without limbs."); /* not body_part(HAND) */ 1598. return (0); 1599. } 1600. if (otmp->cursed) { 1601. You("can't. The saddle seems to be stuck to %s.", 1602. x_monnam(mtmp, ARTICLE_THE, (char *)0, 1603. SUPPRESS_SADDLE, FALSE)); 1604. 1605. /* the attempt costs you time */ 1606. return (1); 1607. } 1608. obj_extract_self(otmp); 1609. if ((unwornmask = otmp->owornmask) != 0L) { 1610. mtmp->misc_worn_check &= ~unwornmask; 1611. otmp->owornmask = 0L; 1612. update_mon_intrinsics(mtmp, otmp, FALSE); 1613. } 1614. otmp = hold_another_object(otmp, "You drop %s!", doname(otmp), 1615. (const char *)0); 1616. timepassed = rnd(3); 1617. if (prev_loot) *prev_loot = TRUE; 1618. } else if (c == 'q') { 1619. return (0); 1620. } 1621. } 1622. #endif /* STEED */ 1623. /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */ 1624. if (u.uswallow) { 1625. int count = passed_info ? *passed_info : 0; 1626. timepassed = pickup(count); 1627. } 1628. return timepassed; 1629. } 1630. 1631. /* 1632. * Decide whether an object being placed into a magic bag will cause 1633. * it to explode. If the object is a bag itself, check recursively. 1634. */ 1635. STATIC_OVL boolean 1636. mbag_explodes(obj, depthin) 1637. struct obj *obj; 1638. int depthin; 1639. { 1640. /* these won't cause an explosion when they're empty */ 1641. if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) && 1642. obj->spe <= 0) 1643. return FALSE; 1644. 1645. /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */ 1646. if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) && 1647. (rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin)) 1648. return TRUE; 1649. else if (Has_contents(obj)) { 1650. struct obj *otmp; 1651. 1652. for (otmp = obj->cobj; otmp; otmp = otmp->nobj) 1653. if (mbag_explodes(otmp, depthin+1)) return TRUE; 1654. } 1655. return FALSE; 1656. } 1657. 1658. /* A variable set in use_container(), to be used by the callback routines */ 1659. /* in_container(), and out_container() from askchain() and use_container(). */ 1660. static NEARDATA struct obj *current_container; 1661. #define Icebox (current_container->otyp == ICE_BOX) 1662. 1663. /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */ 1664. STATIC_PTR int 1665. in_container(obj) 1666. register struct obj *obj; 1667. { 1668. boolean is_gold = (obj->oclass == GOLD_CLASS); 1669. boolean floor_container = !carried(current_container); 1670. char buf[BUFSZ]; 1671. 1672. if (!current_container) { 1673. impossible("<in> no current_container?"); 1674. return 0; 1675. } else if (obj == uball || obj == uchain) { 1676. You("must be kidding."); 1677. return 0; 1678. } else if (obj == current_container) { 1679. pline("That would be an interesting topological exercise."); 1680. return 0; 1681. } else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) { 1682. Norep("You cannot %s %s you are wearing.", 1683. Icebox ? "refrigerate" : "stash", something); 1684. return 0; 1685. } else if ((obj->otyp == LOADSTONE) && obj->cursed) { 1686. obj->bknown = 1; 1687. pline_The("stone%s won't leave your person.", plur(obj->quan)); 1688. return 0; 1689. } else if (obj->otyp == AMULET_OF_YENDOR || 1690. obj->otyp == CANDELABRUM_OF_INVOCATION || 1691. obj->otyp == BELL_OF_OPENING || 1692. obj->otyp == SPE_BOOK_OF_THE_DEAD) { 1693. /* Prohibit Amulets in containers; if you allow it, monsters can't 1694. * steal them. It also becomes a pain to check to see if someone 1695. * has the Amulet. Ditto for the Candelabrum, the Bell and the Book. 1696. */ 1697. pline("%s cannot be confined in such trappings.", The(xname(obj))); 1698. return 0; 1699. } else if (obj->otyp == LEASH && obj->leashmon != 0) { 1700. pline("%s attached to your pet.", Tobjnam(obj, "are")); 1701. return 0; 1702. } else if (obj == uwep) { 1703. if (welded(obj)) { 1704. weldmsg(obj); 1705. return 0; 1706. } 1707. setuwep((struct obj *) 0); 1708. if (uwep) return 0; /* unwielded, died, rewielded */ 1709. } else if (obj == uswapwep) { 1710. setuswapwep((struct obj *) 0); 1711. if (uswapwep) return 0; /* unwielded, died, rewielded */ 1712. } else if (obj == uquiver) { 1713. setuqwep((struct obj *) 0); 1714. if (uquiver) return 0; /* unwielded, died, rewielded */ 1715. } 1716. 1717. if (obj->otyp == CORPSE) { 1718. if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg 1719. && !Stone_resistance) { 1720. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 1721. display_nhwindow(WIN_MESSAGE, FALSE); 1722. else { 1723. char kbuf[BUFSZ]; 1724. 1725. Strcpy(kbuf, an(corpse_xname(obj, TRUE))); 1726. pline("Touching %s is a fatal mistake.", kbuf); 1727. instapetrify(kbuf); 1728. return -1; 1729. } 1730. } 1731. } 1732. 1733. /* boxes, boulders, and big statues can't fit into any container */ 1734. if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER || 1735. (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) { 1736. /* 1737. * xname() uses a static result array. Save obj's name 1738. * before current_container's name is computed. Don't 1739. * use the result of strcpy() within You() --- the order 1740. * of evaluation of the parameters is undefined. 1741. */ 1742. Strcpy(buf, the(xname(obj))); 1743. You("cannot fit %s into %s.", buf, 1744. the(xname(current_container))); 1745. return 0; 1746. } 1747. 1748. freeinv(obj); 1749. 1750. if (obj_is_burning(obj)) /* this used to be part of freeinv() */ 1751. (void) snuff_lit(obj); 1752. 1753. if (floor_container && costly_spot(u.ux, u.uy)) { 1754. sellobj_state(SELL_DELIBERATE); 1755. sellobj(obj, u.ux, u.uy); 1756. sellobj_state(SELL_NORMAL); 1757. } 1758. if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN 1759. && !Is_candle(obj)) { 1760. obj->age = monstermoves - obj->age; /* actual age */ 1761. /* stop any corpse timeouts when frozen */ 1762. if (obj->otyp == CORPSE && obj->timed) { 1763. long rot_alarm = stop_timer(ROT_CORPSE, (genericptr_t)obj); 1764. (void) stop_timer(REVIVE_MON, (genericptr_t)obj); 1765. /* mark a non-reviving corpse as such */ 1766. if (rot_alarm) obj->norevive = 1; 1767. } 1768. } 1769. 1770. else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) { 1771. You("are blasted by a magical explosion!"); 1772. 1773. /* the !floor_container case is taken care of */ 1774. if(*u.ushops && costly_spot(u.ux, u.uy) && floor_container) { 1775. register struct monst *shkp; 1776. 1777. if ((shkp = shop_keeper(*u.ushops)) != 0) 1778. (void)stolen_value(current_container, u.ux, u.uy, 1779. (boolean)shkp->mpeaceful, FALSE); 1780. } 1781. /* did not actually insert obj yet */ 1782. obfree(obj, (struct obj *)0); 1783. delete_contents(current_container); 1784. if (!floor_container) 1785. useup(current_container); 1786. else if (obj_here(current_container, u.ux, u.uy)) 1787. useupf(current_container, obj->quan); 1788. else 1789. panic("in_container: bag not found."); 1790. 1791. losehp(d(6,6),"magical explosion", KILLED_BY_AN); 1792. current_container = 0; /* baggone = TRUE; */ 1793. } 1794. 1795. if (current_container) { 1796. Strcpy(buf, the(xname(current_container))); 1797. You("put %s into %s.", doname(obj), buf); 1798. 1799. (void) add_to_container(current_container, obj); 1800. current_container->owt = weight(current_container); 1801. } 1802. if (is_gold) bot(); /* update gold piece count immediately */ 1803. 1804. return(current_container ? 1 : -1); 1805. } 1806. 1807. STATIC_PTR int 1808. ck_bag(obj) 1809. struct obj *obj; 1810. { 1811. return current_container && obj != current_container; 1812. } 1813. 1814. /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */ 1815. STATIC_PTR int 1816. out_container(obj) 1817. register struct obj *obj; 1818. { 1819. register struct obj *otmp; 1820. boolean is_gold = (obj->oclass == GOLD_CLASS); 1821. int res, loadlev; 1822. long count; 1823. 1824. if (!current_container) { 1825. impossible("<out> no current_container?"); 1826. return -1; 1827. } else if (is_gold) { 1828. obj->owt = weight(obj); 1829. } 1830. 1831. if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0; 1832. 1833. if (obj->otyp == CORPSE) { 1834. if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg 1835. && !Stone_resistance) { 1836. if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 1837. display_nhwindow(WIN_MESSAGE, FALSE); 1838. else { 1839. char kbuf[BUFSZ]; 1840. 1841. Strcpy(kbuf, an(corpse_xname(obj, TRUE))); 1842. pline("Touching %s is a fatal mistake.", kbuf); 1843. instapetrify(kbuf); 1844. return -1; 1845. } 1846. } 1847. } 1848. 1849. count = obj->quan; 1850. if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0) 1851. return res; 1852. 1853. if (obj->quan != count && obj->otyp != LOADSTONE) 1854. obj = splitobj(obj, count); 1855. 1856. /* Remove the object from the list. */ 1857. obj_extract_self(obj); 1858. current_container->owt = weight(current_container); 1859. 1860. if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN 1861. && !Is_candle(obj)) { 1862. obj->age = monstermoves - obj->age; /* actual age */ 1863. if (obj->otyp == CORPSE) 1864. start_corpse_timeout(obj); 1865. } 1866. /* simulated point of time */ 1867. 1868. if (is_pick(obj) && !obj->unpaid && *u.ushops && shop_keeper(*u.ushops)) 1869. verbalize("You sneaky cad! Get out of here with that pick!"); 1870. if(!obj->unpaid && !carried(current_container) && 1871. costly_spot(current_container->ox, current_container->oy)) { 1872. 1873. obj->ox = current_container->ox; 1874. obj->oy = current_container->oy; 1875. addtobill(obj, FALSE, FALSE, FALSE); 1876. } 1877. 1878. otmp = addinv(obj); 1879. loadlev = near_capacity(); 1880. prinv(loadlev ? 1881. (loadlev < MOD_ENCUMBER ? 1882. "You have a little trouble removing" : 1883. "You have much trouble removing") : (char *)0, 1884. otmp, count); 1885. 1886. if (is_gold) { 1887. #ifndef GOLDOBJ 1888. dealloc_obj(obj); 1889. #endif 1890. bot(); /* update character's gold piece count immediately */ 1891. } 1892. return 1; 1893. } 1894. 1895. #undef Icebox 1896. 1897. int 1898. use_container(obj, held) 1899. register struct obj *obj; 1900. register int held; 1901. { 1902. struct obj *curr, *otmp; 1903. #ifndef GOLDOBJ 1904. struct obj *u_gold = (struct obj *)0; 1905. #endif 1906. struct monst *shkp; 1907. boolean one_by_one, allflag, loot_out = FALSE, loot_in = FALSE; 1908. char select[MAXOCLASSES+1]; 1909. char qbuf[QBUFSZ]; 1910. long loss = 0L; 1911. int cnt = 0, used = 0, lcnt = 0, 1912. menu_on_request; 1913. 1914. if (obj->olocked) { 1915. pline("%s to be locked.", Tobjnam(obj, "seem")); 1916. if (held) You("must put it down to unlock."); 1917. return 0; 1918. } else if (obj->otrapped) { 1919. if (held) You("open %s...", the(xname(obj))); 1920. (void) chest_trap(obj, HAND, FALSE); 1921. /* even if the trap fails, you've used up this turn */ 1922. if (multi >= 0) { /* in case we didn't become paralyzed */ 1923. nomul(-1); 1924. nomovemsg = ""; 1925. } 1926. return 1; 1927. } 1928. current_container = obj; /* for use by in/out_container */ 1929. 1930. if (obj->spe == 1) { 1931. static NEARDATA const char sc[] = "Schroedinger's Cat"; 1932. struct obj *ocat; 1933. struct monst *cat; 1934. 1935. obj->spe = 0; /* obj->owt will be updated below */ 1936. /* this isn't really right, since any form of observation 1937. (telepathic or monster/object/food detection) ought to 1938. force the determination of alive vs dead state; but basing 1939. it just on opening the box is much simpler to cope with */ 1940. cat = rn2(2) ? makemon(&mons[PM_HOUSECAT], 1941. obj->ox, obj->oy, NO_MINVENT) : 0; 1942. if (cat) { 1943. cat->mpeaceful = 1; 1944. set_malign(cat); 1945. if (Blind) 1946. You("think %s brushed your %s.", something, 1947. body_part(FOOT)); 1948. else 1949. pline("%s inside the box is still alive!", Monnam(cat)); 1950. (void) christen_monst(cat, sc); 1951. } else { 1952. ocat = mk_named_object(CORPSE, &mons[PM_HOUSECAT], 1953. obj->ox, obj->oy, sc); 1954. if (ocat) { 1955. obj_extract_self(ocat); 1956. (void) add_to_container(obj, ocat); 1957. /* weight handled below */ 1958. } 1959. pline_The("%s inside the box is dead!", 1960. Hallucination ? rndmonnam() : "housecat"); 1961. } 1962. used = 1; 1963. } 1964. /* Count the number of contained objects. Sometimes toss objects if */ 1965. /* a cursed magic bag. */ 1966. for (curr = obj->cobj; curr; curr = otmp) { 1967. otmp = curr->nobj; 1968. if (Is_mbag(obj) && obj->cursed && !rn2(13)) { 1969. if (curr->dknown) 1970. pline("%s to have vanished!", The(aobjnam(curr,"seem"))); 1971. else 1972. You("%s %s disappear.", Blind ? "notice" : "see", 1973. doname(curr)); 1974. obj_extract_self(curr); 1975. if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) { 1976. if(held) { 1977. if(curr->unpaid) 1978. loss += stolen_value(curr, u.ux, u.uy, 1979. (boolean)shkp->mpeaceful, TRUE); 1980. lcnt++; 1981. } else if(costly_spot(u.ux, u.uy)) { 1982. loss += stolen_value(curr, u.ux, u.uy, 1983. (boolean)shkp->mpeaceful, TRUE); 1984. lcnt++; 1985. } 1986. } 1987. /* obfree() will free all contained objects */ 1988. obfree(curr, (struct obj *) 0); 1989. used = 1; 1990. } else { 1991. cnt++; 1992. } 1993. } 1994. 1995. if (cnt && loss) 1996. You("owe %ld %s for lost item%s.", 1997. loss, currency(loss), lcnt > 1 ? "s" : ""); 1998. 1999. obj->owt = weight(obj); 2000. 2001. if (!cnt) { 2002. pline("%s %s empty.", Yname2(obj), otense(obj, "are")); 2003. } else { 2004. Sprintf(qbuf, "Do you want to take %s out of %s?", 2005. something, yname(obj)); 2006. if (flags.menu_style != MENU_TRADITIONAL) { 2007. if (flags.menu_style == MENU_FULL) { 2008. int t = in_or_out_menu("Do what?", current_container); 2009. if (t <= 0) return 0; 2010. loot_out = (t & 0x01) != 0; 2011. loot_in = (t & 0x02) != 0; 2012. } else { /* MENU_COMBINATION or MENU_PARTIAL */ 2013. loot_out = (yn_function(qbuf, "ynq", 'n') == 'y'); 2014. } 2015. if (loot_out) { 2016. add_valid_menu_class(0); /* reset */ 2017. used |= menu_loot(0, current_container, FALSE) > 0; 2018. } 2019. } else { 2020. /* traditional code */ 2021. ask_again2: 2022. menu_on_request = 0; 2023. add_valid_menu_class(0); /* reset */ 2024. switch (yn_function(qbuf, ":ynq", 'n')) { 2025. case ':': 2026. container_contents(current_container, FALSE, FALSE); 2027. goto ask_again2; 2028. case 'y': 2029. if (query_classes(select, &one_by_one, &allflag, 2030. "take out", current_container->cobj, 2031. FALSE, 2032. #ifndef GOLDOBJ 2033. FALSE, 2034. #endif 2035. &menu_on_request)) { 2036. if (askchain((struct obj **)¤t_container->cobj, 2037. (one_by_one ? (char *)0 : select), 2038. allflag, out_container, 2039. (int FDECL((*),(OBJ_P)))0, 2040. 0, "nodot")) 2041. used = 1; 2042. } else if (menu_on_request < 0) { 2043. used |= menu_loot(menu_on_request, 2044. current_container, FALSE) > 0; 2045. } 2046. /*FALLTHRU*/ 2047. case 'n': 2048. break; 2049. case 'q': 2050. default: 2051. return used; 2052. } 2053. } 2054. } 2055. 2056. #ifndef GOLDOBJ 2057. if (!invent && u.ugold == 0) { 2058. #else 2059. if (!invent) { 2060. #endif 2061. /* nothing to put in, but some feedback is necessary */ 2062. You("don't have anything to put in."); 2063. return used; 2064. } 2065. if (flags.menu_style != MENU_FULL || !cnt) { 2066. loot_in = (yn_function("Do you wish to put something in?", 2067. ynqchars, 'n') == 'y'); 2068. } 2069. /* 2070. * Gone: being nice about only selecting food if we know we are 2071. * putting things in an ice chest. 2072. */ 2073. if (loot_in) { 2074. #ifndef GOLDOBJ 2075. if (u.ugold) { 2076. /* 2077. * Hack: gold is not in the inventory, so make a gold object 2078. * and put it at the head of the inventory list. 2079. */ 2080. u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */ 2081. u.ugold = u_gold->quan; /* put the gold back */ 2082. assigninvlet(u_gold); /* might end up as NOINVSYM */ 2083. u_gold->nobj = invent; 2084. invent = u_gold; 2085. } 2086. #endif 2087. add_valid_menu_class(0); /* reset */ 2088. if (flags.menu_style != MENU_TRADITIONAL) { 2089. used |= menu_loot(0, current_container, TRUE) > 0; 2090. } else { 2091. /* traditional code */ 2092. menu_on_request = 0; 2093. if (query_classes(select, &one_by_one, &allflag, "put in", 2094. invent, FALSE, 2095. #ifndef GOLDOBJ 2096. (u.ugold != 0L), 2097. #endif 2098. &menu_on_request)) { 2099. (void) askchain((struct obj **)&invent, 2100. (one_by_one ? (char *)0 : select), allflag, 2101. in_container, ck_bag, 0, "nodot"); 2102. used = 1; 2103. } else if (menu_on_request < 0) { 2104. used |= menu_loot(menu_on_request, 2105. current_container, TRUE) > 0; 2106. } 2107. } 2108. } 2109. 2110. #ifndef GOLDOBJ 2111. if (u_gold && invent && invent->oclass == GOLD_CLASS) { 2112. /* didn't stash [all of] it */ 2113. u_gold = invent; 2114. invent = u_gold->nobj; 2115. dealloc_obj(u_gold); 2116. } 2117. #endif 2118. return used; 2119. } 2120. 2121. /* Loot a container (take things out, put things in), using a menu. */ 2122. STATIC_OVL int 2123. menu_loot(retry, container, put_in) 2124. int retry; 2125. struct obj *container; 2126. boolean put_in; 2127. { 2128. int n, i, n_looted = 0; 2129. boolean all_categories = TRUE, loot_everything = FALSE; 2130. char buf[BUFSZ]; 2131. const char *takeout = "Take out", *putin = "Put in"; 2132. struct obj *otmp, *otmp2; 2133. menu_item *pick_list; 2134. int mflags, res; 2135. long count; 2136. 2137. if (retry) { 2138. all_categories = (retry == -2); 2139. } else if (flags.menu_style == MENU_FULL) { 2140. all_categories = FALSE; 2141. Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout); 2142. mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN : 2143. ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN; 2144. n = query_category(buf, put_in ? invent : container->cobj, 2145. mflags, &pick_list, PICK_ANY); 2146. if (!n) return 0; 2147. for (i = 0; i < n; i++) { 2148. if (pick_list[i].item.a_int == 'A') 2149. loot_everything = TRUE; 2150. else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) 2151. all_categories = TRUE; 2152. else 2153. add_valid_menu_class(pick_list[i].item.a_int); 2154. } 2155. free((genericptr_t) pick_list); 2156. } 2157. 2158. if (loot_everything) { 2159. for (otmp = container->cobj; otmp; otmp = otmp2) { 2160. otmp2 = otmp->nobj; 2161. res = out_container(otmp); 2162. if (res < 0) break; 2163. } 2164. } else { 2165. mflags = INVORDER_SORT; 2166. if (put_in && flags.invlet_constant) mflags |= USE_INVLET; 2167. Sprintf(buf,"%s what?", put_in ? putin : takeout); 2168. n = query_objlist(buf, put_in ? invent : container->cobj, 2169. mflags, &pick_list, PICK_ANY, 2170. all_categories ? allow_all : allow_category); 2171. if (n) { 2172. n_looted = n; 2173. for (i = 0; i < n; i++) { 2174. otmp = pick_list[i].item.a_obj; 2175. count = pick_list[i].count; 2176. if (count > 0 && count < otmp->quan) { 2177. otmp = splitobj(otmp, count); 2178. /* special split case also handled by askchain() */ 2179. } 2180. res = put_in ? in_container(otmp) : out_container(otmp); 2181. if (res < 0) 2182. break; 2183. } 2184. free((genericptr_t)pick_list); 2185. } 2186. } 2187. return n_looted; 2188. } 2189. 2190. STATIC_OVL int 2191. in_or_out_menu(prompt, obj) 2192. const char *prompt; 2193. struct obj *obj; 2194. { 2195. winid win; 2196. anything any; 2197. menu_item *pick_list; 2198. char buf[BUFSZ]; 2199. int n; 2200. 2201. any.a_void = 0; 2202. win = create_nhwindow(NHW_MENU); 2203. start_menu(win); 2204. any.a_int = 1; 2205. Sprintf(buf,"Take %s out of %s", something, the(xname(obj))); 2206. add_menu(win, NO_GLYPH, &any, 'o', 0, ATR_NONE, buf, MENU_UNSELECTED); 2207. any.a_int = 2; 2208. Sprintf(buf,"Put %s into %s", something, the(xname(obj))); 2209. add_menu(win, NO_GLYPH, &any, 'i', 0, ATR_NONE, buf, MENU_UNSELECTED); 2210. any.a_int = 3; 2211. add_menu(win, NO_GLYPH, &any, 'b', 0, ATR_NONE, 2212. "Both of the above", MENU_UNSELECTED); 2213. end_menu(win, prompt); 2214. n = select_menu(win, PICK_ONE, &pick_list); 2215. destroy_nhwindow(win); 2216. if (n > 0) { 2217. n = pick_list[0].item.a_int; 2218. free((genericptr_t) pick_list); 2219. } 2220. return n; 2221. } 2222. 2223. /*pickup.c*/