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