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