Difference between revisions of "Source:NetHack 3.0.0/invent.c"
Jump to navigation
Jump to search
m (Automated source code upload) |
Kernigh bot (talk | contribs) m (NetHack 3.0.0/invent.c moved to Source:NetHack 3.0.0/invent.c: Robot: moved page) |
(No difference)
|
Latest revision as of 04:44, 4 March 2008
Below is the full text to invent.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/invent.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: @(#)invent.c 3.0 88/10/22 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. #ifdef WORM 8. #include "lev.h" 9. #include "wseg.h" 10. #endif 11. 12. #define NOINVSYM '#' 13. 14. static boolean mergable(); 15. 16. int lastinvnr = 51; /* 0 ... 51 */ 17. static char *xprname(); 18. 19. char inv_order[] = { 20. AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM, 21. #ifdef SPELLS 22. SPBOOK_SYM, 23. #endif 24. POTION_SYM, RING_SYM, WAND_SYM, TOOL_SYM, GEM_SYM, 25. ROCK_SYM, BALL_SYM, CHAIN_SYM, 0 }; 26. 27. static void 28. assigninvlet(otmp) 29. register struct obj *otmp; 30. { 31. boolean inuse[52]; 32. register int i; 33. register struct obj *obj; 34. 35. for(i = 0; i < 52; i++) inuse[i] = FALSE; 36. for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 37. i = obj->invlet; 38. if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 39. if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 40. if(i == otmp->invlet) otmp->invlet = 0; 41. } 42. if((i = otmp->invlet) && 43. (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 44. return; 45. for(i = lastinvnr+1; i != lastinvnr; i++) { 46. if(i == 52) { i = -1; continue; } 47. if(!inuse[i]) break; 48. } 49. otmp->invlet = (inuse[i] ? NOINVSYM : 50. (i < 26) ? ('a'+i) : ('A'+i-26)); 51. lastinvnr = i; 52. } 53. 54. /* merge obj with otmp and delete obj if types agree */ 55. static int 56. merged(otmp, obj, lose) 57. register struct obj *otmp, *obj; 58. register int lose; 59. { 60. if(mergable(otmp, obj)) { 61. /* Approximate age: we do it this way because if we were to 62. * do it "accurately" (merge only when ages are identical) 63. * we'd wind up never merging any corpses. 64. * otmp->age = otmp->age*(1-proportion) + obj->age*proportion; 65. */ 66. otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan)) 67. / (otmp->quan + obj->quan); 68. otmp->quan += obj->quan; 69. otmp->owt += obj->owt; 70. if(lose) freeobj(obj); 71. obfree(obj,otmp); /* free(obj), bill->otmp */ 72. return(1); 73. } else return(0); 74. } 75. 76. struct obj * 77. addinv(obj) 78. register struct obj *obj; 79. { 80. register struct obj *otmp; 81. 82. if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) { 83. if (u.uhave_amulet) impossible ("already have amulet?"); 84. u.uhave_amulet = 1; 85. } 86. /* merge or attach to end of chain */ 87. if(!invent) { 88. invent = obj; 89. otmp = 0; 90. } else 91. for(otmp = invent; /* otmp */; otmp = otmp->nobj) { 92. if(merged(otmp, obj, 0)) { 93. obj = otmp; 94. goto added; 95. } 96. if(!otmp->nobj) { 97. otmp->nobj = obj; 98. break; 99. } 100. } 101. obj->nobj = 0; 102. 103. if(flags.invlet_constant) { 104. assigninvlet(obj); 105. /* 106. * The ordering of the chain is nowhere significant 107. * so in case you prefer some other order than the 108. * historical one, change the code below. 109. */ 110. if(otmp) { /* find proper place in chain */ 111. otmp->nobj = 0; 112. if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { 113. obj->nobj = invent; 114. invent = obj; 115. } else 116. for(otmp = invent; ; otmp = otmp->nobj) { 117. if(!otmp->nobj || 118. (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ 119. obj->nobj = otmp->nobj; 120. otmp->nobj = obj; 121. break; 122. } 123. } 124. } 125. } 126. 127. added: 128. if (obj->otyp == LUCKSTONE) { 129. /* new luckstone must be in inventory by this point 130. * for correct calculation */ 131. if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD; 132. else u.moreluck = -LUCKADD; 133. flags.botl = 1; 134. } 135. return(obj); 136. } 137. 138. void 139. useup(obj) 140. register struct obj *obj; 141. { 142. if(obj->quan > 1){ 143. obj->quan--; 144. obj->owt = weight(obj); 145. } else { 146. setnotworn(obj); 147. freeinv(obj); 148. obfree(obj, (struct obj *) 0); 149. } 150. } 151. 152. void 153. freeinv(obj) 154. register struct obj *obj; 155. { 156. register struct obj *otmp; 157. 158. if(obj == invent) 159. invent = invent->nobj; 160. else { 161. for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) 162. if(!otmp->nobj) panic("freeinv"); 163. otmp->nobj = obj->nobj; 164. } 165. if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) { 166. if (!u.uhave_amulet) impossible ("don't have amulet?"); 167. u.uhave_amulet = 0; 168. } 169. if (obj->otyp == LOADSTONE) 170. curse(obj); 171. if (obj->otyp == LUCKSTONE) { 172. if (!carrying(LUCKSTONE)) u.moreluck = 0; 173. else if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD; 174. else u.moreluck = -LUCKADD; 175. flags.botl = 1; 176. } 177. } 178. 179. /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 180. void 181. delobj(obj) 182. register struct obj *obj; 183. { 184. #ifdef WALKIES 185. if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj); 186. #endif 187. freeobj(obj); 188. unpobj(obj); 189. 190. /* if contained in something else, decrease the container weight */ 191. if(obj->cobj) dec_cwt(obj->cobj, obj); 192. 193. obfree(obj, (struct obj *) 0); 194. } 195. 196. /* unlink obj from chain starting with fobj */ 197. void 198. freeobj(obj) 199. register struct obj *obj; 200. { 201. register struct obj *otmp; 202. register int found = 0; 203. register struct rm *lev = &levl[obj->ox][obj->oy]; 204. 205. lev->omask = 0; 206. 207. if(obj == fobj) { 208. fobj = fobj->nobj; 209. found = 1; 210. } 211. for(otmp = fobj; otmp; otmp = otmp->nobj) { 212. if (otmp->nobj == obj) { 213. otmp->nobj = obj->nobj; 214. found = 1; 215. } 216. if (otmp->ox == obj->ox && otmp->oy == obj->oy) { 217. lev->omask = 1; 218. } 219. } 220. if (!found) panic("error in freeobj"); 221. #ifdef POLYSELF 222. if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) { 223. u.uundetected = 0; 224. if (!Invisible) pru(); 225. } 226. #endif 227. } 228. 229. /* Note: freegold throws away its argument! */ 230. void 231. freegold(gold) 232. register struct gold *gold; 233. { 234. register struct gold *gtmp; 235. 236. levl[gold->gx][gold->gy].gmask = 0; 237. 238. if(gold == fgold) fgold = gold->ngold; 239. else { 240. for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) 241. if(!gtmp) panic("error in freegold"); 242. gtmp->ngold = gold->ngold; 243. } 244. free((genericptr_t) gold); 245. #ifdef POLYSELF 246. if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) { 247. u.uundetected = 0; 248. if (!Invisible) pru(); 249. } 250. #endif 251. } 252. 253. struct monst * 254. m_at(x,y) 255. register int x, y; 256. { 257. register struct monst *mtmp; 258. #ifdef WORM 259. register struct wseg *wtmp; 260. m_atseg = 0; 261. #endif 262. 263. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ 264. if(mtmp->mx == x && mtmp->my == y) 265. return(mtmp); 266. #ifdef WORM 267. if(mtmp->wormno){ 268. for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) 269. if(wtmp->wx == x && wtmp->wy == y){ 270. m_atseg = wtmp; 271. return(mtmp); 272. } 273. } 274. #endif 275. } 276. return((struct monst *)0); 277. } 278. 279. struct obj * 280. o_at(x,y) 281. register int x, y; 282. { 283. register struct obj *otmp; 284. 285. for(otmp = fobj; otmp; otmp = otmp->nobj) 286. if(otmp->ox == x && otmp->oy == y) return(otmp); 287. return((struct obj *)0); 288. } 289. 290. struct obj * 291. sobj_at(n,x,y) 292. register int n, x, y; 293. { 294. register struct obj *otmp; 295. 296. if(levl[x][y].omask) 297. for(otmp = fobj; otmp; otmp = otmp->nobj) 298. if(otmp->ox == x && otmp->oy == y && otmp->otyp == n) 299. return(otmp); 300. return((struct obj *)0); 301. } 302. 303. int 304. carried(obj) 305. register struct obj *obj; 306. { 307. register struct obj *otmp; 308. 309. for(otmp = invent; otmp; otmp = otmp->nobj) 310. if(otmp == obj) return(1); 311. return(0); 312. } 313. 314. struct obj * 315. carrying(type) 316. register int type; 317. { 318. register struct obj *otmp; 319. 320. for(otmp = invent; otmp; otmp = otmp->nobj) 321. if(otmp->otyp == type) 322. return(otmp); 323. return((struct obj *) 0); 324. } 325. 326. struct obj * 327. o_on(id, objchn) 328. unsigned int id; 329. register struct obj *objchn; 330. { 331. while(objchn) { 332. if(objchn->o_id == id) return(objchn); 333. objchn = objchn->nobj; 334. } 335. return((struct obj *) 0); 336. } 337. 338. struct gold * 339. g_at(x,y) 340. register int x, y; 341. { 342. register struct gold *gold = fgold; 343. while(gold) { 344. if(gold->gx == x && gold->gy == y) return(gold); 345. gold = gold->ngold; 346. } 347. return((struct gold *)0); 348. } 349. 350. /* make dummy object structure containing gold - for temporary use only */ 351. static 352. struct obj * 353. mkgoldobj(q) 354. register long q; 355. { 356. register struct obj *otmp; 357. 358. otmp = newobj(0); 359. /* should set o_id etc. but otmp will be freed soon */ 360. otmp->olet = GOLD_SYM; 361. u.ugold -= q; 362. OGOLD(otmp) = q; 363. flags.botl = 1; 364. return(otmp); 365. } 366. 367. /* 368. * getobj returns: 369. * struct obj *xxx: object to do something with. 370. * (struct obj *) 0 error return: no object. 371. * &zeroobj explicitly no object (as in w-). 372. */ 373. struct obj * 374. getobj(let,word) 375. register char *let,*word; 376. { 377. register struct obj *otmp; 378. register char ilet,ilet1,ilet2; 379. char buf[BUFSZ]; 380. char lets[BUFSZ]; 381. register int foo = 0, foo2; 382. register char *bp = buf; 383. xchar allowcnt = 0; /* 0, 1 or 2 */ 384. boolean allowgold = FALSE, usegold = FALSE; 385. /* usegold is needed so that they are given a different message 386. * if gold is prohibited because it's inappropriate, or because 387. * it's appropriate if only they had any. 388. */ 389. boolean allowall = FALSE; 390. boolean allownone = FALSE; 391. xchar foox = 0; 392. long cnt; 393. 394. if(*let == '0') let++, allowcnt = 1; 395. if(*let == GOLD_SYM) let++, 396. usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE); 397. if(*let == '#') let++, allowall = TRUE; 398. if(*let == '-') let++, allownone = TRUE; 399. if(allownone) *bp++ = '-'; 400. if(allowgold) *bp++ = GOLD_SYM; 401. if(bp > buf && bp[-1] == '-') *bp++ = ' '; 402. 403. ilet = 'a'; 404. for(otmp = invent; otmp; otmp = otmp->nobj){ 405. if(!*let || index(let, otmp->olet)) { 406. bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; 407. 408. /* ugly check: remove inappropriate things */ 409. if((!strcmp(word, "take off") && 410. (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) 411. || (otmp==uarm && uarmc) 412. #ifdef SHIRT 413. || (otmp==uarmu && (uarm || uarmc)) 414. #endif 415. )) 416. || (!strcmp(word, "wear") && 417. (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) 418. /* already worn */ 419. || (!strcmp(word, "wield") && 420. (otmp->owornmask & W_WEP)) 421. ) { 422. foo--; 423. foox++; 424. } 425. 426. /* Second ugly check; unlike the first it won't trigger an 427. * "else" in "you don't have anything else to ___". 428. */ 429. if ((!strcmp(word, "wear") && 430. (otmp->olet == TOOL_SYM && otmp->otyp != BLINDFOLD)) 431. || (!strcmp(word, "can") && 432. (otmp->otyp != CORPSE)) 433. || (!strcmp(word, "write with") && 434. (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER)) 435. || (!strcmp(word, "rub") && 436. (otmp->olet == TOOL_SYM && 437. otmp->otyp != LAMP && otmp->otyp != MAGIC_LAMP)) 438. ) 439. foo--; 440. } 441. if(ilet == 'z') ilet = 'A'; else ilet++; 442. } 443. bp[foo] = 0; 444. if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 445. Strcpy(lets, bp); /* necessary since we destroy buf */ 446. if(foo > 5) { /* compactify string */ 447. foo = foo2 = 1; 448. ilet2 = bp[0]; 449. ilet1 = bp[1]; 450. while(ilet = bp[++foo2] = bp[++foo]){ 451. if(ilet == ilet1+1){ 452. if(ilet1 == ilet2+1) 453. bp[foo2 - 1] = ilet1 = '-'; 454. else if(ilet2 == '-') { 455. bp[--foo2] = ++ilet1; 456. continue; 457. } 458. } 459. ilet2 = ilet1; 460. ilet1 = ilet; 461. } 462. } 463. if(!foo && !allowall && !allowgold && !allownone) { 464. You("don't have anything %sto %s.", 465. foox ? "else " : "", word); 466. return((struct obj *)0); 467. } 468. for(;;) { 469. if(!buf[0]) { 470. #ifdef REDO 471. if(!in_doagain) 472. #endif 473. pline("What do you want to %s? [*] ", word); 474. } else { 475. #ifdef REDO 476. if(!in_doagain) 477. #endif 478. pline("What do you want to %s? [%s or ?*] ", 479. word, buf); 480. } 481. cnt = 0; 482. ilet = readchar(); 483. while(digit(ilet) && allowcnt) { 484. #ifdef REDO 485. if (ilet != '?' && ilet != '*') savech(ilet); 486. #endif 487. cnt = 10*cnt + (ilet - '0'); 488. allowcnt = 2; /* signal presence of cnt */ 489. ilet = readchar(); 490. } 491. if(digit(ilet)) { 492. pline("No count allowed with this command."); 493. continue; 494. } 495. if(index(quitchars,ilet)) { 496. if(flags.verbose) 497. pline("Never mind."); 498. return((struct obj *)0); 499. } 500. if(ilet == '-') { 501. return(allownone ? &zeroobj : (struct obj *) 0); 502. } 503. if(ilet == GOLD_SYM) { 504. if(!usegold){ 505. You("cannot %s gold.", word); 506. return(struct obj *)0; 507. } else if (!allowgold) { 508. You("are not carrying any gold."); 509. return(struct obj *)0; 510. } 511. if(!(allowcnt == 2 && cnt < u.ugold)) 512. cnt = u.ugold; 513. return(mkgoldobj(cnt)); 514. } 515. if(allowcnt == 2 && !strcmp(word,"throw")) { 516. /* permit counts for throwing gold, but don't accept 517. * counts for other things since the throw code will 518. * split off a single item anyway */ 519. allowcnt = 1; 520. if(cnt != 1) { 521. pline("You can only throw one item at a time."); 522. continue; 523. } 524. } 525. if(ilet == '?') { 526. doinv(lets); 527. if(!(ilet = morc)) continue; 528. /* he typed a letter (not a space) to more() */ 529. } else if(ilet == '*') { 530. doinv(NULL); 531. if(!(ilet = morc)) continue; 532. /* ... */ 533. } 534. #ifdef REDO 535. if (ilet != '?' && ilet != '*') savech(ilet); 536. #endif 537. if(flags.invlet_constant) { 538. for(otmp = invent; otmp; otmp = otmp->nobj) 539. if(otmp->invlet == ilet) break; 540. } else { 541. if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; 542. ilet -= 'a'; 543. for(otmp = invent; otmp && ilet; 544. ilet--, otmp = otmp->nobj) ; 545. } 546. if(!otmp) { 547. You("don't have that object."); 548. continue; 549. } 550. if(cnt < 0 || otmp->quan < cnt) { 551. You("don't have that many! You have only %u." 552. , otmp->quan); 553. continue; 554. } 555. break; 556. } 557. if(!allowall && let && !index(let,otmp->olet)) { 558. pline("That is a silly thing to %s.",word); 559. return((struct obj *)0); 560. } 561. if(allowcnt == 2) { /* cnt given */ 562. if(cnt == 0) return (struct obj *)0; 563. if(cnt != otmp->quan) { 564. register struct obj *obj; 565. #ifdef LINT /*splitobj for (long )cnt > 30000 && sizeof(int) == 2*/ 566. obj = (struct obj *)0; 567. #else 568. if (sizeof(int) == 2) 569. obj = splitobj(otmp, 570. (int )(cnt >30000 ? 30000 : cnt)); 571. else 572. obj = splitobj(otmp, (int) cnt); 573. #endif 574. if(otmp == uwep) setuwep(obj); 575. } 576. } 577. return(otmp); 578. } 579. 580. static int 581. ckunpaid(otmp) 582. register struct obj *otmp; 583. { 584. return((int)(otmp->unpaid)); 585. } 586. 587. static boolean 588. wearing_armor() { 589. return(uarm || uarmc || uarmf || uarmg || uarmh || uarms 590. #ifdef SHIRT 591. || uarmu 592. #endif 593. ); 594. } 595. 596. static boolean 597. is_worn(otmp) 598. register struct obj *otmp; 599. { 600. return(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP))); 601. } 602. 603. static const char removeables[] = 604. { ARMOR_SYM, WEAPON_SYM, RING_SYM, AMULET_SYM, TOOL_SYM, ' ', 0 }; 605. 606. /* interactive version of getobj - used for Drop, Identify and */ 607. /* Takeoff (A). Return the number of times fn was called successfully */ 608. int 609. ggetobj(word, fn, mx) 610. register char *word; 611. register int (*fn)(), mx; 612. { 613. char buf[BUFSZ]; 614. register char *ip; 615. register char sym; 616. register int oletct = 0, iletct = 0; 617. register boolean allflag = FALSE; 618. char olets[20], ilets[20]; 619. int (*ckfn)() = (int (*)()) 0; 620. xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */ 621. register boolean takeoff = !strcmp(word, "take off"); 622. 623. if(takeoff && !wearing_armor() && !uwep && !uamul && 624. !uleft && !uright && !ublindf) { 625. You("are not wearing anything."); 626. return(0); 627. } 628. if(!invent && !allowgold){ 629. You("have nothing to %s.", word); 630. return(0); 631. } else { 632. register struct obj *otmp = invent; 633. register int uflg = 0; 634. 635. if(allowgold) ilets[iletct++] = GOLD_SYM; 636. ilets[iletct] = 0; 637. while(otmp) { 638. if(!index(ilets, otmp->olet)){ 639. if(!takeoff || is_worn(otmp)) 640. ilets[iletct++] = otmp->olet; 641. ilets[iletct] = 0; 642. } 643. if(otmp->unpaid) uflg = 1; 644. otmp = otmp->nobj; 645. } 646. ilets[iletct++] = ' '; 647. if(uflg && !takeoff) ilets[iletct++] = 'u'; 648. if(invent && !takeoff) ilets[iletct++] = 'a'; 649. ilets[iletct] = 0; 650. } 651. pline("What kinds of thing do you want to %s? [%s] ", 652. word, ilets); 653. getlin(buf); 654. if(buf[0] == '\033') { 655. clrlin(); 656. return(0); 657. } 658. ip = buf; 659. olets[0] = 0; 660. while(sym = *ip++){ 661. if(sym == ' ') continue; 662. if(takeoff) { 663. if(!index(removeables,sym)) { 664. pline("Not applicable."); 665. return(0); 666. } else if(sym == ARMOR_SYM && !wearing_armor()) { 667. You("are not wearing any armor."); 668. return(0); 669. } else if(sym == WEAPON_SYM && !uwep) { 670. You("are not wielding anything."); 671. return(0); 672. } else if(sym == RING_SYM && !uright && !uleft) { 673. You("are not wearing rings."); 674. return(0); 675. } else if(sym == AMULET_SYM && !uamul) { 676. You("are not wearing an amulet."); 677. return(0); 678. } else if(sym == TOOL_SYM && !ublindf) { 679. You("are not wearing a blindfold."); 680. return(0); 681. } 682. } 683. if(sym == GOLD_SYM) { 684. if(allowgold == 1) 685. (*fn)(mkgoldobj(u.ugold)); 686. else if(!u.ugold) 687. You("have no gold."); 688. allowgold = 2; 689. } else if(sym == 'a' || sym == 'A') 690. allflag = TRUE; 691. else if(sym == 'u' || sym == 'U') 692. ckfn = ckunpaid; 693. else if(index(inv_order, sym)) { 694. if(!index(olets, sym)) { 695. olets[oletct++] = sym; 696. olets[oletct] = 0; 697. } 698. } else You("don't have any %c's.", sym); 699. } 700. if(allowgold == 2 && !oletct) 701. return(1); /* he dropped gold (or at least tried to) */ 702. else 703. return(askchain(invent, TRUE, olets, allflag, fn, ckfn, mx, word)); 704. } 705. 706. /* 707. * Walk through the chain starting at objchn and ask for all objects 708. * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) 709. * whether the action in question (i.e., fn) has to be performed. 710. * If allflag then no questions are asked. Max gives the max nr of 711. * objects to be treated. Return the number of objects treated. 712. * If ininv is TRUE, the objects are in the player's inventory. 713. */ 714. int 715. askchain(objchn, ininv, olets, allflag, fn, ckfn, mx, word) 716. register struct obj *objchn; 717. register int ininv, allflag, mx; 718. register char *olets, *word; 719. register int (*fn)(), (*ckfn)(); 720. { 721. register struct obj *otmp, *otmp2; 722. register char sym, ilet; 723. register int cnt = 0, dud = 0; 724. register boolean takeoff, nodot; 725. 726. takeoff = !strcmp(word, "take off"); 727. nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || 728. !strcmp(word, "identify") || takeoff); 729. /* changes so the askchain is interrogated in the order specified. 730. * For example, if a person specifies =/ then first all rings will be 731. * asked about followed by all wands -dgk 732. */ 733. nextclass: 734. ilet = 'a'-1; 735. for(otmp = (ininv ? invent : objchn); otmp; otmp = otmp2){ 736. if(ilet == 'z') ilet = 'A'; else ilet++; 737. otmp2 = otmp->nobj; 738. if (olets && *olets && otmp->olet != *olets) continue; 739. if(takeoff && !is_worn(otmp)) continue; 740. if(ckfn && !(*ckfn)(otmp)) continue; 741. if(!allflag) { 742. if(ininv) { 743. if (nodot) 744. pline(xprname(otmp, ilet, FALSE)); 745. else pline(xprname(otmp, ilet, TRUE)); 746. } 747. else 748. pline(doname(otmp)); 749. addtopl("? "); 750. sym = nyaq(); 751. } 752. else sym = 'y'; 753. 754. switch(sym){ 755. case 'a': 756. allflag = 1; 757. case 'y': 758. cnt += (*fn)(otmp); 759. if(--mx == 0) goto ret; 760. case 'n': 761. if(nodot) dud++; 762. default: 763. break; 764. case 'q': 765. goto ret; 766. } 767. } 768. if (olets && *olets && *++olets) 769. goto nextclass; 770. if(!takeoff && (dud || cnt)) pline("That was all."); 771. else if(!dud && !cnt) pline("No applicable objects."); 772. ret: 773. return(cnt); 774. } 775. 776. static char 777. obj_to_let(obj) /* should of course only be called for things in invent */ 778. register struct obj *obj; 779. { 780. register struct obj *otmp; 781. register char ilet; 782. 783. if(flags.invlet_constant) 784. return(obj->invlet); 785. ilet = 'a'; 786. for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) 787. if(++ilet > 'z') ilet = 'A'; 788. return(otmp ? ilet : NOINVSYM); 789. } 790. 791. void 792. prinv(obj) 793. register struct obj *obj; 794. { 795. pline(xprname(obj, obj_to_let(obj), TRUE)); 796. } 797. 798. static char * 799. xprname(obj,let,dot) 800. register struct obj *obj; 801. register char let; 802. register boolean dot; 803. { 804. #ifdef LINT /* handle static char li[BUFSZ]; */ 805. char li[BUFSZ]; 806. #else 807. static char li[BUFSZ]; 808. #endif 809. 810. Sprintf(li, "%c - %s", 811. (flags.invlet_constant ? obj->invlet : let), 812. doname(obj)); 813. if(dot) Sprintf(eos(li),"."); 814. return(li); 815. } 816. 817. int 818. ddoinv() 819. { 820. doinv(NULL); 821. return 0; 822. } 823. 824. /* called with 0 or "": all objects in inventory */ 825. /* otherwise: all objects with (serial) letter in lets */ 826. void 827. doinv(lets) 828. register char *lets; 829. { 830. register struct obj *otmp; 831. register char ilet; 832. int ct = 0; 833. char any[BUFSZ]; 834. char *invlet = inv_order; 835. int classcount = 0; 836. 837. morc = 0; /* just to be sure */ 838. 839. if(!invent){ 840. pline("Not carrying anything."); 841. return; 842. } 843. if (lets != NULL) { 844. for(ct=0; lets[ct]; ct++) { 845. if (ct >= 52) { 846. impossible("bad lets contents"); 847. break; 848. } 849. } 850. if (ct==1) { 851. ilet = 'a'; 852. for(otmp = invent; otmp; otmp = otmp->nobj) { 853. if(flags.invlet_constant) ilet = otmp->invlet; 854. 855. if (ilet == lets[0]) 856. pline(xprname(otmp, lets[0], TRUE)); 857. 858. if(!flags.invlet_constant) 859. if(++ilet > 'z') ilet = 'A'; 860. } 861. return; 862. } 863. } 864. ct = 0; 865. 866. cornline(0, NULL); 867. nextclass: 868. classcount = 0; 869. ilet = 'a'; 870. for(otmp = invent; otmp; otmp = otmp->nobj) { 871. if(flags.invlet_constant) ilet = otmp->invlet; 872. if(!lets || !*lets || index(lets, ilet)) { 873. if (!flags.sortpack || otmp->olet == *invlet) { 874. if (flags.sortpack && !classcount) { 875. cornline(1, let_to_name(*invlet)); 876. classcount++; 877. } 878. cornline(1, xprname(otmp, ilet, TRUE)); 879. any[ct++] = ilet; 880. } 881. } 882. if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 883. } 884. if (flags.sortpack && *++invlet) goto nextclass; 885. any[ct] = 0; 886. cornline(2, any); 887. } 888. 889. int 890. dotypeinv() /* free after Robert Viduya */ 891. /* Changed to one type only, so he doesn't have to type cr */ 892. { 893. char c, ilet; 894. char stuff[BUFSZ]; 895. register int stct; 896. register struct obj *otmp; 897. boolean billx = inshop() && doinvbill(0); 898. boolean unpd = FALSE; 899. 900. if (!invent && !u.ugold && !billx) { 901. You("aren't carrying anything."); 902. return 0; 903. } 904. 905. stct = 0; 906. if(u.ugold) stuff[stct++] = GOLD_SYM; 907. stuff[stct] = 0; 908. for(otmp = invent; otmp; otmp = otmp->nobj) { 909. if (!index (stuff, otmp->olet)) { 910. stuff[stct++] = otmp->olet; 911. stuff[stct] = 0; 912. } 913. if(otmp->unpaid) 914. unpd = TRUE; 915. } 916. if(unpd) stuff[stct++] = 'u'; 917. if(billx) stuff[stct++] = 'x'; 918. stuff[stct] = 0; 919. 920. if(stct > 1) { 921. #ifdef REDO 922. if (!in_doagain) 923. #endif 924. pline ("What type of object do you want an inventory of? [%s] ", 925. stuff); 926. c = readchar(); 927. #ifdef REDO 928. savech(c); 929. #endif 930. if(index(quitchars,c)) { 931. clrlin(); 932. return 0; 933. } 934. } else 935. c = stuff[0]; 936. 937. if(c == GOLD_SYM) 938. return(doprgold()); 939. 940. if(c == 'x' || c == 'X') { 941. if(billx) 942. (void) doinvbill(1); 943. else 944. pline("No used-up objects on the shopping bill."); 945. return(0); 946. } 947. 948. if((c == 'u' || c == 'U') && !unpd) { 949. You("are not carrying any unpaid objects."); 950. return(0); 951. } 952. 953. stct = 0; 954. ilet = 'a'; 955. for (otmp = invent; otmp; otmp = otmp -> nobj) { 956. if(flags.invlet_constant) ilet = otmp->invlet; 957. if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) 958. stuff[stct++] = ilet; 959. if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 960. } 961. stuff[stct] = '\0'; 962. if(stct == 0) 963. You("have no such objects."); 964. else 965. doinv (stuff); 966. 967. return(0); 968. } 969. 970. /* look at what is here */ 971. int 972. dolook() { 973. register struct obj *otmp, *otmp0; 974. register struct gold *gold; 975. char *verb = Blind ? "feel" : "see"; 976. int ct = 0; 977. int fd = 0; 978. 979. read_engr_at(u.ux, u.uy); /* Eric Backus */ 980. if(!u.uswallow) { 981. otmp0 = o_at(u.ux, u.uy); 982. gold = g_at(u.ux, u.uy); 983. } else { 984. You("%s no objects here.", verb); 985. return(!!Blind); 986. } 987. 988. if(IS_DOOR(levl[u.ux][u.uy].typ)) { 989. fd++; 990. switch(levl[u.ux][u.uy].doormask) { 991. case D_NODOOR: 992. pline("There is a doorway here."); break; 993. case D_ISOPEN: 994. pline("There is an open door here."); break; 995. case D_BROKEN: 996. pline("There is a broken door here."); break; 997. default: 998. pline("There is a closed door here."); 999. } 1000. } 1001. /* added by GAN 10/30/86 */ 1002. #ifdef FOUNTAINS 1003. if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 1004. fd++; 1005. pline("There is a fountain here."); 1006. } 1007. #endif 1008. #ifdef THRONES 1009. if(IS_THRONE(levl[u.ux][u.uy].typ)) { 1010. fd++; 1011. pline("There is an opulent throne here."); 1012. } 1013. #endif 1014. #ifdef SINKS 1015. if(IS_SINK(levl[u.ux][u.uy].typ)) { 1016. fd++; 1017. pline("There is a kitchen sink here."); 1018. } 1019. #endif 1020. #ifdef ALTARS 1021. if(IS_ALTAR(levl[u.ux][u.uy].typ)) { 1022. char *al; 1023. 1024. fd++; 1025. switch (levl[u.ux][u.uy].altarmask & ~A_SHRINE) { 1026. case 0: al = "chaotic"; break; 1027. case 1: al = "neutral"; break; 1028. default: al = "lawful"; break; 1029. } 1030. pline("There is an altar to %s here (%s).", a_gname(), al); 1031. } 1032. #endif 1033. 1034. if(u.ux == xupstair && u.uy == yupstair) { 1035. fd++; 1036. pline("There is a stairway up here."); 1037. } 1038. if(u.ux == xdnstair && u.uy == ydnstair) { 1039. fd++; 1040. pline("There is a stairway down here."); 1041. } 1042. #ifdef STRONGHOLD 1043. if(u.ux == xupladder && u.uy == yupladder) { 1044. fd++; 1045. pline("There is a ladder up here."); 1046. } 1047. if(u.ux == xdnladder && u.uy == ydnladder) { 1048. fd++; 1049. pline("There is a ladder down here."); 1050. } 1051. if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) { 1052. fd++; 1053. pline("There is a lowered drawbridge here."); 1054. } 1055. #endif /* STRONGHOLD /**/ 1056. 1057. if(Blind) { 1058. You("try to feel what is lying here on the floor."); 1059. if(Levitation) { 1060. pline("But you can't reach it!"); 1061. return(0); 1062. } 1063. } 1064. 1065. if(!otmp0 && !gold) { 1066. if(Blind || !fd) 1067. You("%s no objects here.", verb); 1068. return(!!Blind); 1069. } 1070. 1071. cornline(0, "Things that are here:"); 1072. for(otmp = otmp0; otmp; otmp = otmp->nobj) { 1073. if(otmp->ox == u.ux && otmp->oy == u.uy) { 1074. ct++; 1075. cornline(1, doname(otmp)); 1076. 1077. if(Blind && !uarmg && 1078. #ifdef POLYSELF 1079. !resists_ston(uasmon) && 1080. #endif 1081. (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) { 1082. pline("Touching the dead cockatrice is a fatal mistake..."); 1083. You("turn to stone..."); 1084. killer = "dead cockatrice"; 1085. done("stoned"); 1086. } 1087. } 1088. } 1089. 1090. if(gold) { 1091. char gbuf[30]; 1092. 1093. Sprintf(gbuf, "%ld gold piece%s", 1094. gold->amount, plur(gold->amount)); 1095. if(!ct++) 1096. You("%s here %s.", verb, gbuf); 1097. else 1098. cornline(1, gbuf); 1099. } 1100. 1101. if(ct == 1 && !gold) { 1102. You("%s here %s.", verb, doname(otmp0)); 1103. cornline(3, NULL); 1104. } 1105. if(ct > 1) 1106. cornline(2, NULL); 1107. return(!!Blind); 1108. } 1109. 1110. void 1111. stackobj(obj) 1112. register struct obj *obj; 1113. { 1114. register struct obj *otmp = fobj; 1115. for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) 1116. if(otmp->ox == obj->ox && otmp->oy == obj->oy && 1117. merged(obj,otmp,1)) 1118. break; 1119. return; 1120. } 1121. 1122. static boolean 1123. mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ 1124. register struct obj *otmp, *obj; 1125. { 1126. if(obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid || 1127. obj->spe != otmp->spe || obj->dknown != otmp->dknown || 1128. (obj->bknown != otmp->bknown && pl_character[0] != 'P') || 1129. obj->cursed != otmp->cursed || obj->blessed != otmp->blessed || 1130. obj->no_charge != otmp->no_charge || 1131. obj->otrapped != otmp->otrapped) 1132. return(FALSE); 1133. 1134. else if((obj->olet==WEAPON_SYM || obj->olet==ARMOR_SYM) && 1135. obj->rustfree != otmp->rustfree) return FALSE; 1136. 1137. else if(obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) 1138. return( (obj->corpsenm == otmp->corpsenm) && 1139. (!ONAME(obj) || !strcmp(ONAME(obj), ONAME(otmp))) ); 1140. 1141. else if(obj->known == otmp->known) { 1142. return(objects[obj->otyp].oc_merge); 1143. } else return(FALSE); 1144. } 1145. 1146. int 1147. doprgold(){ 1148. if(!u.ugold) 1149. You("do not carry any gold."); 1150. else 1151. You("are carrying %ld gold piece%s.", u.ugold, plur(u.ugold)); 1152. return 0; 1153. } 1154. 1155. int 1156. doprwep() 1157. { 1158. if(!uwep) You("are empty %s.", body_part(HANDED)); 1159. else prinv(uwep); 1160. return 0; 1161. } 1162. 1163. int 1164. doprarm(){ 1165. if(!wearing_armor()) 1166. You("are not wearing any armor."); 1167. else { 1168. #ifdef SHIRT 1169. char lets[8]; 1170. #else 1171. char lets[7]; 1172. #endif 1173. register int ct = 0; 1174. 1175. #ifdef SHIRT 1176. if(uarmu) lets[ct++] = obj_to_let(uarmu); 1177. #endif 1178. if(uarm) lets[ct++] = obj_to_let(uarm); 1179. if(uarmc) lets[ct++] = obj_to_let(uarmc); 1180. if(uarmh) lets[ct++] = obj_to_let(uarmh); 1181. if(uarms) lets[ct++] = obj_to_let(uarms); 1182. if(uarmg) lets[ct++] = obj_to_let(uarmg); 1183. if(uarmf) lets[ct++] = obj_to_let(uarmf); 1184. lets[ct] = 0; 1185. doinv(lets); 1186. } 1187. return 0; 1188. } 1189. 1190. int 1191. doprring(){ 1192. if(!uleft && !uright) 1193. You("are not wearing any rings."); 1194. else { 1195. char lets[3]; 1196. register int ct = 0; 1197. 1198. if(uleft) lets[ct++] = obj_to_let(uleft); 1199. if(uright) lets[ct++] = obj_to_let(uright); 1200. lets[ct] = 0; 1201. doinv(lets); 1202. } 1203. return 0; 1204. } 1205. 1206. int 1207. dopramulet(){ 1208. if (!uamul) 1209. You("are not wearing an amulet."); 1210. else 1211. prinv(uamul); 1212. return 0; 1213. } 1214. 1215. int 1216. doprtool(){ 1217. register struct obj *otmp; 1218. register int ct=0; 1219. char lets[3]; /* Maximum: pick-axe, blindfold */ 1220. 1221. for(otmp = invent; otmp; otmp = otmp->nobj) { 1222. if (((otmp->owornmask & W_TOOL) && otmp->olet==TOOL_SYM) 1223. || (otmp==uwep && 1224. (otmp->otyp==PICK_AXE || otmp->otyp==TIN_OPENER))) 1225. lets[ct++] = obj_to_let(otmp); 1226. } 1227. lets[ct] = 0; 1228. if (!ct) You("are not using any tools."); 1229. else doinv(lets); 1230. return 0; 1231. } 1232. 1233. int 1234. digit(c) 1235. char c; 1236. { 1237. return(c >= '0' && c <= '9'); 1238. } 1239. 1240. /* 1241. * useupf(obj) 1242. * uses up an object that's on the floor 1243. */ 1244. void 1245. useupf(obj) 1246. register struct obj *obj; 1247. { 1248. if(obj->quan > 1) { 1249. obj->quan--; 1250. obj->owt = weight(obj); 1251. } else delobj(obj); 1252. } 1253. 1254. /* 1255. * Convert from a symbol to a string for printing object classes 1256. * 1257. * Names from objects.h 1258. * char obj_symbols[] = { 1259. * ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM, 1260. * BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, 1261. * WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 }; 1262. */ 1263. 1264. static const char *names[] = { 1265. "Illegal objects", "Amulets", "Comestibles", "Weapons", 1266. "Tools", "Iron balls", "Chains", "Boulders/Statues", "Armor", 1267. "Potions", "Scrolls", "Wands", 1268. #ifdef SPELLS 1269. "Spellbooks", 1270. #endif 1271. "Rings", "Gems"}; 1272. 1273. char * 1274. let_to_name(let) 1275. char let; 1276. { 1277. char *pos = index(obj_symbols, let); 1278. /* arbitrary buffer size by Tom May (tom@uw-warp) */ 1279. static char *buf = NULL; 1280. 1281. if (buf == NULL) 1282. buf = (char *) alloc ((unsigned)(strlen(HI)+strlen(HE)+15+1)); 1283. 1284. if (pos == NULL) pos = obj_symbols; 1285. if (HI && HE) 1286. Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE); 1287. else 1288. Sprintf(buf, "%s", names[pos - obj_symbols]); 1289. return (buf); 1290. } 1291. 1292. void 1293. reassign() 1294. { 1295. register int i; 1296. register struct obj *obj; 1297. 1298. for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1299. obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1300. lastinvnr = i; 1301. }