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