Source:NetHack 3.0.0/pickup.c
Jump to navigation
Jump to search
Below is the full text to pickup.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/pickup.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)pickup.c 3.0 88/07/12 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. void explode_bag(); 12. 13. void 14. pickup(all) 15. int all; 16. { 17. register struct gold *gold = g_at(u.ux, u.uy); 18. register struct obj *obj, *obj2; 19. register int wt; 20. char buf[BUFSZ]; 21. register char *ip; 22. register char sym; 23. register int oletct = 0, iletct = 0; 24. boolean all_of_a_type = FALSE, selective = FALSE; 25. char olets[20], ilets[20]; 26. struct obj dummygold; 27. 28. dummygold.ox = u.ux; 29. dummygold.oy = u.uy; 30. dummygold.olet = GOLD_SYM; 31. dummygold.nobj = fobj; 32. dummygold.cobj = 0; 33. 34. if(Levitation) return; 35. if (all && !flags.pickup) { 36. int ct = 0; 37. 38. for (obj = fobj; obj; obj = obj->nobj) 39. if(obj->ox == u.ux && obj->oy == u.uy) 40. if(!obj->cobj) 41. if (obj != uchain) 42. ct++; 43. 44. /* Stop on a zorkmid */ 45. if (gold) ct++; 46. 47. /* If there are objects here, take a look. 48. */ 49. if (ct) { 50. if (flags.run) 51. nomul(0); 52. nscr(); 53. if (ct < 5) 54. (void) dolook(); 55. else { 56. read_engr_at(u.ux,u.uy); 57. pline("There are several objects here."); 58. } 59. } else read_engr_at(u.ux,u.uy); 60. return; 61. } 62. 63. /* check for more than one object */ 64. if(!all) { 65. register int ct = 0; 66. 67. if (gold) ct++; 68. for(obj = fobj; obj; obj = obj->nobj) 69. if(obj->ox == u.ux && obj->oy == u.uy) 70. if(!obj->cobj) ct++; 71. if(ct < 2) 72. all++; 73. else 74. pline("There are several objects here."); 75. } 76. 77. /* added by GAN 10/24/86 to allow selective picking up */ 78. if(!all) { 79. register struct obj *otmp = fobj; 80. 81. ilets[iletct] = 0; 82. if(gold) { 83. ilets[iletct++] = GOLD_SYM; 84. ilets[iletct] = 0; 85. } 86. while(otmp) { 87. if(!index(ilets, otmp->olet) && !otmp->cobj && 88. otmp->ox == u.ux && otmp->oy == u.uy) { 89. ilets[iletct++] = otmp->olet; 90. ilets[iletct] = 0; 91. } 92. otmp = otmp->nobj; 93. } 94. if(iletct == 1) 95. Strcpy(buf,ilets); 96. else { 97. ilets[iletct++] = ' '; 98. ilets[iletct++] = 'a'; 99. ilets[iletct++] = 'A'; 100. ilets[iletct] = 0; 101. 102. pline("What kinds of thing do you want to pick up? [%s] ", ilets); 103. getlin(buf); 104. if(buf[0] == '\033') { 105. clrlin(); 106. return; 107. } 108. else if(!buf[0]) selective = TRUE; 109. } 110. ip = buf; 111. olets[0] = 0; 112. while(sym = *ip++){ 113. /* new A function (selective all) added by 114. * GAN 01/09/87 115. */ 116. if(sym == ' ') continue; 117. if(sym == 'A') selective = TRUE; 118. else if(sym == 'a') all_of_a_type = TRUE; 119. else if(index(ilets, sym)){ 120. if(!index(olets, sym)){ 121. olets[oletct++] = sym; 122. olets[oletct] = 0; 123. } 124. } 125. else pline("There are no %c's here.", sym); 126. } 127. } 128. if(all_of_a_type && !olets[0]) all = TRUE; 129. 130. for(obj = (gold ? &dummygold : fobj); obj; obj = obj2) { 131. obj2 = obj->nobj; /* perhaps obj will be picked up */ 132. if(!obj->cobj && obj->ox == u.ux && obj->oy == u.uy) { 133. if(flags.run) nomul(0); 134. 135. if(!all) { 136. char c; 137. 138. if(!selective && !index(olets,obj->olet)) continue; 139. 140. if (!all_of_a_type) { 141. if (obj == &dummygold) 142. pline("Pick up %ld gold piece%s? ", 143. gold->amount, plur(gold->amount)); 144. else pline("Pick up %s? ", doname(obj)); 145. if((c = ynaq()) == 'q') return; 146. if(c == 'n') continue; 147. if(c == 'a') { 148. all_of_a_type = TRUE; 149. if (selective) { 150. selective = FALSE; 151. olets[0] = obj->olet; 152. olets[1] = 0; 153. /* oletct = 1; */ 154. } 155. } 156. } 157. } 158. 159. if(obj == &dummygold) { 160. int iw = inv_weight(); 161. long gold_capacity; 162. 163. #ifndef lint /* long/int conversion */ 164. iw -= (int)((u.ugold + 500)/1000); 165. #endif 166. gold_capacity = ((-iw) * 1000L) - 500 + 999 - u.ugold; 167. if (gold_capacity <= 0L) { 168. pline("There %s %ld gold piece%s here, but you cannot carry any more.", 169. (gold->amount == 1) ? "is" : "are", 170. gold->amount, plur(gold->amount)); 171. continue; 172. } 173. if (gold_capacity >= gold->amount) { 174. pline("%ld gold piece%s.", 175. gold->amount, plur(gold->amount)); 176. u.ugold += gold->amount; 177. freegold(gold); 178. if(Invisible) newsym(u.ux,u.uy); 179. } else { 180. pline("You can only carry %s of the %ld gold pieces lying here.", 181. gold_capacity == 1L ? "one" : "some", gold->amount); 182. pline("%ld gold piece%s.", 183. gold_capacity, plur(gold_capacity)); 184. u.ugold += gold_capacity; 185. gold->amount -= gold_capacity; 186. } 187. flags.botl = 1; 188. if(flags.run) nomul(0); 189. continue; 190. } 191. 192. if((obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE) && 193. !uarmg 194. #ifdef POLYSELF 195. && !resists_ston(uasmon) 196. #endif 197. ) { 198. pline("Touching the dead cockatrice is a fatal mistake."); 199. You("turn to stone."); 200. You("die..."); 201. killer = "cockatrice cadaver"; 202. done("stoned"); 203. } 204. 205. if(obj->otyp == SCR_SCARE_MONSTER){ 206. if(!obj->spe) obj->spe = 1; 207. else { 208. pline("The scroll turns to dust as you pick it up."); 209. if(!(objects[SCR_SCARE_MONSTER].oc_name_known) && 210. !(objects[SCR_SCARE_MONSTER].oc_uname)) 211. docall(obj); 212. delobj(obj); 213. continue; 214. } 215. } 216. 217. /* do not pick up uchain */ 218. if(obj == uchain) 219. continue; 220. 221. wt = inv_weight() + obj->owt; 222. if (obj->otyp == LOADSTONE) 223. goto lift_some; /* pick it up even if too heavy */ 224. #ifdef POLYSELF 225. if (obj->otyp == BOULDER && throws_rocks(uasmon)) { 226. wt = inv_weight(); 227. goto lift_some; 228. } 229. #endif 230. if(wt > 0) { 231. if(obj->quan > 1) { 232. /* see how many we can lift */ 233. int savequan = obj->quan; 234. int iw = inv_weight(); 235. int qq; 236. for(qq = 1; qq < savequan; qq++){ 237. obj->quan = qq; 238. if(iw + weight(obj) > 0) 239. break; 240. } 241. obj->quan = savequan; 242. qq--; 243. /* we can carry qq of them */ 244. if(!qq) goto too_heavy; 245. You("can only carry %s of the %s lying here.", 246. (qq == 1) ? "one" : "some", 247. doname(obj)); 248. { 249. register struct obj *obj3; 250. 251. obj3 = splitobj(obj, qq); 252. if(obj3->otyp == SCR_SCARE_MONSTER) 253. if(obj3->spe) obj->spe = 0; 254. } 255. goto lift_some; 256. } 257. too_heavy: 258. pline("There %s %s here, but %s.", 259. (obj->quan == 1) ? "is" : "are", 260. doname(obj), 261. !invent ? "it is too heavy for you to lift" 262. : "you cannot carry any more"); 263. if(obj->otyp == SCR_SCARE_MONSTER) 264. if(obj->spe) obj->spe = 0; 265. break; 266. } 267. lift_some: 268. if(inv_cnt() >= 52) { 269. Your("knapsack cannot accommodate any more items."); 270. if(obj->otyp == SCR_SCARE_MONSTER) 271. if(obj->spe) obj->spe = 0; 272. break; 273. } 274. freeobj(obj); 275. if(Invisible) newsym(u.ux,u.uy); 276. addtobill(obj, TRUE); /* sets obj->unpaid if necessary */ 277. if(wt > -5) You("have a little trouble lifting"); 278. { int pickquan = obj->quan; 279. int mergquan; 280. if(!Blind) obj->dknown = 1; 281. obj = addinv(obj); /* might merge it with other objects */ 282. mergquan = obj->quan; 283. obj->quan = pickquan; /* to fool prinv() */ 284. prinv(obj); 285. obj->quan = mergquan; 286. } 287. } 288. } 289. set_omask(u.ux, u.uy); 290. } 291. 292. int 293. doloot() { /* loot a container on the floor. */ 294. 295. register struct obj *cobj; 296. register int c; 297. 298. if (Levitation) { 299. pline("You cannot reach the floor."); 300. return(0); 301. } 302. if(levl[u.ux][u.uy].omask) 303. for(cobj = fobj; cobj; cobj = cobj->nobj) { 304. 305. if(cobj->ox == u.ux && cobj->oy == u.uy) 306. if(Is_container(cobj)) { 307. 308. pline("There is %s here, loot it? ", doname(cobj)); 309. c = ynq(); 310. if(c == 'q') return 0; 311. if(c == 'n') continue; 312. 313. if(cobj->olocked) { 314. 315. pline("Hmmm, it seems to be locked."); 316. continue; 317. } 318. if(cobj->otyp == BAG_OF_TRICKS) { 319. 320. You("carefully open the bag..."); 321. pline("It develops a huge set of teeth and bites you!"); 322. losehp(rnd(10), "carnivorous bag"); 323. makeknown(BAG_OF_TRICKS); 324. continue; 325. } 326. 327. You("carefully open the %s...", xname(cobj)); 328. if(cobj->otrapped) chest_trap(cobj, FINGER); 329. 330. use_container(cobj, 0); 331. } 332. } 333. return 0; 334. } 335. 336. static 337. struct obj *current_container; /* a local variable of use_container, to be 338. used by its local procedures in/ck_container */ 339. #define Icebox (current_container->otyp == ICE_BOX) 340. int baggone; /* used in askchain so bag isn't used after explosion */ 341. 342. void 343. inc_cwt(cobj, obj) 344. register struct obj *cobj, *obj; 345. { 346. if (cobj->otyp == BAG_OF_HOLDING) 347. cobj->owt += (obj->owt/2 + 1); 348. else cobj->owt += obj->owt; 349. } 350. 351. static int 352. in_container(obj) 353. register struct obj *obj; 354. { 355. if(obj == uball || obj == uchain) { 356. You("must be kidding."); 357. return(0); 358. } 359. if(obj == current_container) { 360. pline("That would be an interesting topological exercise."); 361. return(0); 362. } 363. if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) { 364. You("cannot %s something you are wearing.", 365. Icebox ? "refrigerate" : "stash"); 366. return(0); 367. } 368. if((obj->otyp == LOADSTONE) && obj->cursed) { 369. obj->bknown = 1; 370. pline("The stone%s won't leave your person.", 371. obj->quan==1 ? "" : "s"); 372. return(0); 373. } 374. /* Prohibit Amulets in containers; if you allow it, monsters can't 375. * steal them. It also becomes a pain to check to see if someone 376. * has the Amulet. 377. */ 378. if(obj->otyp == AMULET_OF_YENDOR && !obj->spe) { 379. pline("The Amulet of Yendor cannot be confined in such trappings."); 380. return(0); 381. } 382. /* no nested containers - they do not save/restore properly. */ 383. /* magic bag -> magic bag will self destruct later on. */ 384. if(Is_container(obj) && Is_container(current_container) && 385. (!Is_mbag(obj) || !Is_mbag(current_container))) { 386. pline("It won't go in."); 387. return(1); /* be careful! */ 388. } 389. if(obj == uwep) { 390. if(welded(obj)) { 391. weldmsg(obj, FALSE); 392. return(0); 393. } 394. setuwep((struct obj *) 0); 395. if (uwep) return(0); /* unwielded, died, rewielded */ 396. } 397. #ifdef WALKIES 398. if(obj->otyp == LEASH && obj->leashmon != 0) { 399. pline("It is attached to your pet."); 400. return(0); 401. } 402. #endif 403. inc_cwt(current_container, obj); 404. freeinv(obj); 405. 406. obj->cobj = current_container; 407. obj->nobj = fcobj; 408. fcobj = obj; 409. 410. if(Icebox) obj->age = moves - obj->age; /* actual age */ 411. 412. else if(Is_mbag(obj->cobj) && 413. (Is_mbag(obj) || 414. (obj->otyp == WAN_CANCELLATION && (obj->spe > 0)) )) { 415. explode_bag(obj); 416. You("are blasted by a magical explosion!"); 417. losehp(d(6,6),"magical explosion"); 418. baggone = 1; 419. } 420. return(1); 421. } 422. 423. static int 424. ck_container(obj) 425. register struct obj *obj; 426. { 427. return(obj->cobj == current_container); 428. } 429. 430. static int 431. ck_bag() 432. { 433. return(!baggone); 434. } 435. 436. static int 437. out_container(obj) 438. register struct obj *obj; 439. { 440. register struct obj *otmp; 441. 442. if(inv_cnt() >= 52) { 443. pline("You have no room to hold anything else."); 444. return(0); 445. } 446. if(obj == fcobj) fcobj = fcobj->nobj; 447. else { 448. for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj) 449. if(!otmp->nobj) panic("out_container"); 450. otmp->nobj = obj->nobj; 451. } 452. dec_cwt(current_container, obj); 453. obj->cobj = (struct obj *) 0; 454. 455. if (Icebox) 456. obj->age = moves - obj->age; /* simulated point of time */ 457. 458. (void) addinv(obj); 459. return 0; 460. } 461. 462. void 463. get_all_from_box() { 464. register struct obj *otmp, *cobj, *ootmp, *nxobj; 465. 466. for(otmp = invent; otmp; otmp = otmp->nobj) { 467. cobj = otmp; 468. if(Is_container(otmp)) 469. for(ootmp=fcobj,nxobj=(fcobj ? fcobj->nobj : 0); ootmp; 470. ootmp=nxobj,nxobj=(ootmp ? ootmp->nobj : 0) ) 471. if(ootmp->cobj == cobj) 472. (void)out_container(ootmp); 473. } 474. return; 475. } 476. 477. /* for getobj: 0: allow cnt; #: allow all types; %: expect food */ 478. static const char frozen_food[] = { '0', '#', FOOD_SYM, 0 }; 479. 480. void 481. use_container(obj, held) 482. register struct obj *obj; 483. register int held; 484. { 485. register int cnt = 0; 486. register struct obj *otmp; 487. register struct obj *backobj; 488. 489. current_container = obj; /* for use by in/out_container */ 490. if(current_container->olocked) { 491. pline("The %s seems to be locked.", xname(current_container)); 492. return; 493. } 494. for(otmp = fcobj, backobj = (struct obj *) 0; otmp; 495. backobj = otmp, otmp = otmp->nobj) 496. if(otmp->cobj == obj) 497. if(Is_mbag(obj) && obj->cursed && !rn2(13)) { 498. if (otmp->known) 499. pline("The %s to have vanished!", 500. aobjnam(otmp,"seem")); 501. else You("%s %s disappear.", 502. Blind ? "notice" : "see", 503. doname(otmp)); 504. if(!backobj) { 505. fcobj = otmp->nobj; 506. dec_cwt(current_container, otmp); 507. obfree(otmp, (struct obj *) 0); 508. otmp = fcobj; 509. } else { 510. backobj->nobj = otmp->nobj; 511. dec_cwt(current_container, otmp); 512. obfree(otmp, (struct obj *) 0); 513. otmp = backobj->nobj; 514. } 515. if (!otmp) break; 516. if(otmp->cobj == obj) cnt++; 517. } else cnt++; 518. if(!cnt) 519. pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj)); 520. else if (inv_cnt() < 52) { 521. pline("Do you want to take something out of the %s? ", 522. xname(obj)); 523. if(yn() != 'n') 524. if(askchain(fcobj, FALSE, NULL, 0, out_container, ck_container, 0, "nodot")) 525. return; 526. } 527. if(!invent) return; 528. pline("Do you wish to put something in? "); 529. if(yn() != 'y') return; 530. if (Icebox && current_container->dknown) { 531. otmp = getobj(frozen_food, "put in"); 532. if(!otmp || !in_container(otmp)) 533. flags.move = multi = 0; 534. } else { 535. baggone = 0; /* might be set by in_container */ 536. if(askchain(invent, TRUE, NULL, 0, in_container, ck_bag, 0, "nodot")) 537. return; 538. } 539. return; 540. } 541. 542. void 543. delete_contents(obj) 544. register struct obj *obj; 545. { 546. register struct obj *otmp, *notmp; 547. 548. while (fcobj && fcobj->cobj == obj) { 549. otmp = fcobj; 550. fcobj = fcobj->nobj; 551. obfree(otmp,(struct obj *)0); 552. } 553. if (fcobj) { 554. otmp = fcobj; 555. while(otmp->nobj) 556. if (otmp->nobj->cobj == obj) { 557. notmp = otmp->nobj; 558. otmp->nobj = notmp->nobj; 559. obfree(notmp,(struct obj *)0); 560. } else 561. otmp = otmp->nobj; 562. } 563. } 564. 565. void 566. explode_bag(obj) 567. struct obj *obj; 568. { 569. struct obj *otmp, *cobj; 570. 571. cobj = obj->cobj; 572. delete_contents(cobj); 573. 574. for (otmp = invent; otmp; otmp = otmp->nobj) 575. if (otmp == cobj) break; 576. 577. if (otmp) { 578. You("see your %s blow apart!", xname(otmp)); 579. useup(otmp); 580. /*return(0);*/ 581. } else panic("explode_bag: bag not in invent."); 582. } 583. 584. void 585. dec_cwt(cobj, obj) 586. register struct obj *cobj, *obj; 587. { 588. if (Is_mbag(cobj)) 589. cobj->owt -= (obj->owt/2 + 1); 590. else cobj->owt -= obj->owt; 591. 592. if(cobj->owt < objects[cobj->otyp].oc_weight) 593. cobj->owt = objects[cobj->otyp].oc_weight; 594. }