Annotation of early-roguelike/arogue5/pack.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Routines to deal with the pack
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include "curses.h"
! 16: #include <ctype.h>
! 17: #include "rogue.h"
! 18:
! 19: char outstring[512]; /* ridiculously long string for use with msg */
! 20:
! 21: bool is_type (struct object *obj, int type);
! 22:
! 23: /*
! 24: * add_pack:
! 25: * Pick up an object and add it to the pack. If the argument is non-null
! 26: * use it as the linked_list pointer instead of gettting it off the ground.
! 27: */
! 28: bool
! 29: add_pack(struct linked_list *item, bool silent, struct linked_list **packret)
! 30: {
! 31: register struct linked_list *ip, *lp = NULL, *ap;
! 32: register struct object *obj, *op = NULL;
! 33: register bool exact, from_floor;
! 34:
! 35: if (packret != NULL)
! 36: *packret = NULL;
! 37:
! 38: if (item == NULL)
! 39: {
! 40: from_floor = TRUE;
! 41: if ((item = find_obj(hero.y, hero.x)) == NULL)
! 42: return(FALSE);
! 43: }
! 44: else
! 45: from_floor = FALSE;
! 46: obj = OBJPTR(item);
! 47: /*
! 48: * If it is gold, just add its value to rogue's purse and get rid
! 49: * of it.
! 50: */
! 51: if (obj->o_type == GOLD) {
! 52: register struct linked_list *mitem;
! 53: register struct thing *tp;
! 54:
! 55: if (!silent) {
! 56: if (!terse) addmsg("You found ");
! 57: msg("%d gold pieces.", obj->o_count);
! 58: }
! 59:
! 60: /* First make sure no greedy monster is after this gold.
! 61: * If so, make the monster run after the rogue instead.
! 62: */
! 63: for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
! 64: tp = THINGPTR(mitem);
! 65: if (tp->t_dest == &obj->o_pos) tp->t_dest = &hero;
! 66: }
! 67:
! 68: purse += obj->o_count;
! 69: if (from_floor) {
! 70: detach(lvl_obj, item);
! 71: if ((ap = find_obj(hero.y, hero.x)) == NULL)
! 72: mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
! 73: else
! 74: mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
! 75: }
! 76: o_discard(item);
! 77: return(TRUE);
! 78: }
! 79:
! 80: /*
! 81: * see if he can carry any more weight
! 82: */
! 83: if (itemweight(obj) + pstats.s_pack > pstats.s_carry) {
! 84: msg("Too much for you to carry.");
! 85: return FALSE;
! 86: }
! 87: /*
! 88: * Link it into the pack. Search the pack for a object of similar type
! 89: * if there isn't one, stuff it at the beginning, if there is, look for one
! 90: * that is exactly the same and just increment the count if there is.
! 91: * it that. Food is always put at the beginning for ease of access, but
! 92: * is not ordered so that you can't tell good food from bad. First check
! 93: * to see if there is something in thr same group and if there is then
! 94: * increment the count.
! 95: */
! 96: if (obj->o_group)
! 97: {
! 98: for (ip = pack; ip != NULL; ip = next(ip))
! 99: {
! 100: op = OBJPTR(ip);
! 101: if (op->o_group == obj->o_group)
! 102: {
! 103: /*
! 104: * Put it in the pack and notify the user
! 105: */
! 106: op->o_count += obj->o_count;
! 107: if (from_floor)
! 108: {
! 109: detach(lvl_obj, item);
! 110: if ((ap = find_obj(hero.y, hero.x)) == NULL)
! 111: mvaddch(hero.y,hero.x,
! 112: (roomin(&hero)==NULL ? PASSAGE : FLOOR));
! 113: else
! 114: mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
! 115: }
! 116: o_discard(item);
! 117: item = ip;
! 118: goto picked_up;
! 119: }
! 120: }
! 121: }
! 122:
! 123: /*
! 124: * Check for and deal with scare monster scrolls
! 125: */
! 126: if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
! 127: if (obj->o_flags & ISCURSED)
! 128: {
! 129: msg("The scroll turns to dust as you pick it up.");
! 130: detach(lvl_obj, item);
! 131: if ((ap = find_obj(hero.y, hero.x)) == NULL)
! 132: mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
! 133: else
! 134: mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
! 135: return(TRUE);
! 136: }
! 137:
! 138: /*
! 139: * Search for an object of the same type
! 140: */
! 141: exact = FALSE;
! 142: for (ip = pack; ip != NULL; ip = next(ip))
! 143: {
! 144: op = OBJPTR(ip);
! 145: if (obj->o_type == op->o_type)
! 146: break;
! 147: }
! 148: if (ip == NULL)
! 149: {
! 150: /*
! 151: * Put it at the end of the pack since it is a new type
! 152: */
! 153: for (ip = pack; ip != NULL; ip = next(ip))
! 154: {
! 155: op = OBJPTR(ip);
! 156: if (op->o_type != FOOD)
! 157: break;
! 158: lp = ip;
! 159: }
! 160: }
! 161: else
! 162: {
! 163: /*
! 164: * Search for an object which is exactly the same
! 165: */
! 166: while (ip != NULL && op->o_type == obj->o_type)
! 167: {
! 168: if (op->o_which == obj->o_which)
! 169: {
! 170: exact = TRUE;
! 171: break;
! 172: }
! 173: lp = ip;
! 174: if ((ip = next(ip)) == NULL)
! 175: break;
! 176: op = OBJPTR(ip);
! 177: }
! 178: }
! 179: /*
! 180: * Check if there is room
! 181: */
! 182: if (ip == NULL || !exact || !ISMULT(obj->o_type)) {
! 183: if (inpack == MAXPACK-1) {
! 184: msg(terse ? "No room." : "You can't carry anything else.");
! 185: return(FALSE);
! 186: }
! 187: }
! 188: inpack++;
! 189: if (from_floor)
! 190: {
! 191: detach(lvl_obj, item);
! 192: if ((ap = find_obj(hero.y, hero.x)) == NULL)
! 193: mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
! 194: else
! 195: mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
! 196: }
! 197: if (ip == NULL)
! 198: {
! 199: /*
! 200: * Didn't find an exact match, just stick it here
! 201: */
! 202: if (pack == NULL)
! 203: pack = item;
! 204: else
! 205: {
! 206: lp->l_next = item;
! 207: item->l_prev = lp;
! 208: item->l_next = NULL;
! 209: }
! 210: }
! 211: else
! 212: {
! 213: /*
! 214: * If we found an exact match. If it is food,
! 215: * increase the count, otherwise put it with its clones.
! 216: */
! 217: if (exact && ISMULT(obj->o_type))
! 218: {
! 219: op->o_count += obj->o_count;
! 220: inpack--; /* adjust for previous addition */
! 221: o_discard(item);
! 222: item = ip;
! 223: goto picked_up;
! 224: }
! 225: if ((item->l_prev = prev(ip)) != NULL)
! 226: item->l_prev->l_next = item;
! 227: else
! 228: pack = item;
! 229: item->l_next = ip;
! 230: ip->l_prev = item;
! 231: }
! 232: picked_up:
! 233: /*
! 234: * Notify the user
! 235: */
! 236: obj = OBJPTR(item);
! 237: if (!silent)
! 238: {
! 239: if (!terse)
! 240: addmsg("You now have ");
! 241: sprintf(outstring,"%s (%c)", inv_name(obj, !terse), pack_char(pack, obj));
! 242: msg(outstring);
! 243: }
! 244:
! 245: /* Relics can do strange things when you pick them up */
! 246: if (obj->o_type == RELIC) {
! 247: cur_relic[obj->o_which]++; /* Note that we have it */
! 248: switch (obj->o_which) {
! 249: case HEIL_ANKH:
! 250: msg("The ankh welds itself into your hand.");
! 251:
! 252: /* A cloak must be worn. */
! 253: when EMORI_CLOAK:
! 254: if (cur_armor != NULL || cur_misc[WEAR_CLOAK]) {
! 255: msg("The cloak insists you remove your current garments.");
! 256: if (!dropcheck(cur_armor != NULL ? cur_armor
! 257: : cur_misc[WEAR_CLOAK])) {
! 258: pstats.s_hpt = -1;
! 259: msg("The cloak constricts around you.");
! 260: msg("It draws your life force from you!!! -- More --");
! 261: wait_for(cw,' ');
! 262: death(D_RELIC);
! 263: }
! 264: }
! 265:
! 266: /* The amulet must be worn. */
! 267: when YENDOR_AMULET:
! 268: if (cur_misc[WEAR_JEWEL]) {
! 269: msg("You have an urge to remove your current amulet.");
! 270: if (!dropcheck(cur_misc[WEAR_JEWEL])) {
! 271: pstats.s_hpt = -1;
! 272: msg("The Amulet of Yendor begins pulsing.");
! 273: msg("It fades away.... -- More --");
! 274: wait_for(cw,' ');
! 275: death(D_RELIC);
! 276: }
! 277: }
! 278: msg("The amulet welds itself into your chest.");
! 279:
! 280: /* Weapons will insist on being wielded. */
! 281: when MUSTY_DAGGER:
! 282: case HRUGGEK_MSTAR:
! 283: case YEENOGHU_FLAIL:
! 284: if (cur_weapon != NULL) {
! 285: msg("The artifact insists you release your current weapon.");
! 286: if (!dropcheck(cur_weapon)) {
! 287: pstats.s_hpt = -1;
! 288: msg("The artifact forces your weapon into your heart.");
! 289: msg("It hums with satisfaction. -- More --");
! 290: wait_for(cw,' ');
! 291: death(D_RELIC);
! 292: }
! 293: }
! 294: cur_weapon = obj;
! 295: }
! 296: }
! 297:
! 298: updpack(FALSE);
! 299: if (packret != NULL)
! 300: *packret = item;
! 301: return(TRUE);
! 302: }
! 303:
! 304: /*
! 305: * inventory:
! 306: * list what is in the pack
! 307: */
! 308: bool
! 309: inventory(struct linked_list *list, int type)
! 310: {
! 311: register struct object *obj;
! 312: register char ch;
! 313: register int n_objs;
! 314: register int cnt;
! 315: char inv_temp[LINELEN];
! 316:
! 317: cnt = 0;
! 318: n_objs = 0;
! 319: for (ch = 'a'; list != NULL; ch++, list = next(list)) {
! 320: obj = OBJPTR(list);
! 321: if (!is_type(obj, type))
! 322: continue;
! 323: switch (n_objs++) {
! 324: /*
! 325: * For the first thing in the inventory, just save the string
! 326: * in case there is only one.
! 327: */
! 328: case 0:
! 329: sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
! 330: break;
! 331: /*
! 332: * If there is more than one, clear the screen, print the
! 333: * saved message and fall through to ...
! 334: */
! 335: case 1:
! 336: if (slow_invent)
! 337: msg(inv_temp);
! 338: else
! 339: {
! 340: wclear(hw);
! 341: waddstr(hw, inv_temp);
! 342: waddch(hw, '\n');
! 343: }
! 344: /*
! 345: * Print the line for this object
! 346: */
! 347: default:
! 348: if (ch > 'z')
! 349: ch = 'A';
! 350: if (slow_invent){
! 351: sprintf(outstring,"%c) %s", ch, inv_name(obj, FALSE));
! 352: msg(outstring);
! 353: }
! 354: else {
! 355: if (++cnt >= LINES - 2) { /* if bottom of screen */
! 356: dbotline(hw, morestr);
! 357: cnt = 0;
! 358: wclear(hw);
! 359: }
! 360: wprintw(hw, "%c) %s\n", ch, inv_name(obj, FALSE));
! 361: }
! 362: }
! 363: }
! 364: if (n_objs == 0) {
! 365: if (terse)
! 366: msg(type == 0 ? "Empty handed." :
! 367: "Nothing appropriate");
! 368: else
! 369: msg(type == 0 ? "You are empty handed." :
! 370: "You don't have anything appropriate");
! 371: return FALSE;
! 372: }
! 373: if (n_objs == 1) {
! 374: msg(inv_temp);
! 375: return TRUE;
! 376: }
! 377: if (!slow_invent)
! 378: {
! 379: mvwaddstr(hw, LINES-1, 0, spacemsg);
! 380: draw(hw);
! 381: wait_for(hw,' ');
! 382: clearok(cw, TRUE);
! 383: touchwin(cw);
! 384: }
! 385: return TRUE;
! 386: }
! 387:
! 388: /*
! 389: * pick_up:
! 390: * Add something to characters pack.
! 391: */
! 392: void
! 393: pick_up(char ch)
! 394: {
! 395: switch (ch) {
! 396: default:
! 397: debug("Where did you pick that up???");
! 398: case GOLD:
! 399: case ARMOR:
! 400: case POTION:
! 401: case FOOD:
! 402: case WEAPON:
! 403: case SCROLL:
! 404: case MM:
! 405: case RING:
! 406: case STICK:
! 407: case RELIC:
! 408: while (add_pack(NULL, FALSE, NULL)); /* pick up everything there */
! 409: break;
! 410: }
! 411: }
! 412:
! 413: /*
! 414: * picky_inven:
! 415: * Allow player to inventory a single item
! 416: */
! 417: void
! 418: picky_inven(void)
! 419: {
! 420: register struct linked_list *item;
! 421: register char ch, mch;
! 422:
! 423: if (pack == NULL)
! 424: msg("You aren't carrying anything");
! 425: else if (next(pack) == NULL)
! 426: msg("a) %s", inv_name(OBJPTR(pack), FALSE));
! 427: else
! 428: {
! 429: msg(terse ? "Item: " : "Which item do you wish to inventory: ");
! 430: mpos = 0;
! 431: if ((mch = readchar()) == ESCAPE)
! 432: {
! 433: msg("");
! 434: return;
! 435: }
! 436:
! 437: /* Check for a special character */
! 438: switch (mch) {
! 439: case FOOD:
! 440: case SCROLL:
! 441: case POTION:
! 442: case RING:
! 443: case STICK:
! 444: case RELIC:
! 445: case ARMOR:
! 446: case WEAPON:
! 447: case MM:
! 448: msg("");
! 449: if (get_item(pack, NULL, mch) == NULL) {
! 450: if (terse) msg("None in pack.");
! 451: else msg("You have no %c in your pack.", mch);
! 452: }
! 453: return;
! 454: }
! 455:
! 456: for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
! 457: if (ch == mch)
! 458: {
! 459: sprintf(outstring, "%c) %s",ch ,inv_name(OBJPTR(item), FALSE));
! 460: msg(outstring);
! 461: return;
! 462: }
! 463: if (!terse)
! 464: msg("'%s' not in pack.", unctrl(mch));
! 465: msg("Range is 'a' to '%c'", --ch);
! 466: }
! 467: }
! 468:
! 469:
! 470: /*
! 471: * get_item:
! 472: * pick something out of a pack for a purpose
! 473: * purpose: NULL if we should be silent (no prompts) *
! 474: */
! 475: struct linked_list *
! 476: get_item(struct linked_list *list, char *purpose, int type)
! 477: {
! 478: reg struct linked_list *item;
! 479: reg struct object *obj;
! 480: reg int cnt, ch, och;
! 481: struct linked_list *saveitem = NULL;
! 482:
! 483: cnt = 0;
! 484: if (list == NULL) {
! 485: msg("You aren't carrying anything.");
! 486: return NULL;
! 487: }
! 488: /* see if we have any of the type requested */
! 489: for(ch = 'a',item = list ; item != NULL ; item = next(item), ch++) {
! 490: obj = OBJPTR(item);
! 491: if (is_type(obj, type)) {
! 492: cnt++;
! 493: saveitem = item;
! 494: }
! 495: }
! 496: if (cnt == 0) {
! 497: if (purpose) msg("Nothing to %s",purpose);
! 498: after = FALSE;
! 499: return NULL;
! 500: }
! 501: else if (cnt == 1) { /* only found one of 'em */
! 502: obj = OBJPTR(saveitem);
! 503: for(;;) {
! 504: if (purpose) { /* Should we prompt the player? */
! 505: msg("%s what (* for the item)? ",purpose);
! 506: ch = tolower(readchar());
! 507: }
! 508: else {
! 509: sprintf(outstring, "%c) %s", pack_char(list, obj), inv_name(obj,FALSE));
! 510: msg(outstring);
! 511: }
! 512:
! 513: if (ch == '*') {
! 514: mpos = 0;
! 515: sprintf(outstring, "%c) %s", pack_char(list, obj), inv_name(obj,FALSE));
! 516: msg(outstring);
! 517: continue;
! 518: }
! 519: if (ch == ESCAPE) {
! 520: msg("");
! 521: after = FALSE;
! 522: return NULL;
! 523: }
! 524: for(item = list,och = 'a'; item != NULL; item = next(item),och++) {
! 525: if (ch == och) break;
! 526: if (och == 'z') och = 'A' - 1;
! 527: }
! 528: if (item == NULL) {
! 529: msg("Please specify a letter between 'a' and '%c'",
! 530: och == 'A' ? 'z' : och-1);
! 531: continue;
! 532: }
! 533: if (is_type (OBJPTR(item), type)) {
! 534: if (purpose) mpos = 0;
! 535: return item;
! 536: }
! 537: else
! 538: msg ("You can't %s that!", purpose);
! 539:
! 540: }
! 541: }
! 542: for(;;) {
! 543: if (purpose) {
! 544: msg("%s what? (* for list): ",purpose);
! 545: ch = readchar();
! 546: }
! 547: else ch = '*';
! 548:
! 549: mpos = 0;
! 550: if (ch == ESCAPE) { /* abort if escape hit */
! 551: after = FALSE;
! 552: msg(""); /* clear display */
! 553: return NULL;
! 554: }
! 555: if (ch == '*') {
! 556: wclear(hw);
! 557: cnt = 0;
! 558: for(item = list,ch = 'a'; item != NULL ; item = next(item), ch++) {
! 559: obj = OBJPTR(item);
! 560: if (!is_type(OBJPTR(item), type))
! 561: continue;
! 562: wprintw(hw,"%c) %s\n\r",ch,inv_name(obj,FALSE));
! 563: if (++cnt >= LINES - 2 && next(item) != NULL) {
! 564: cnt = 0;
! 565: dbotline(hw, spacemsg);
! 566: wclear(hw);
! 567: }
! 568: if (ch == 'z') ch = 'A' - 1;
! 569: }
! 570: wmove(hw, LINES - 1,0);
! 571: if (purpose) wprintw(hw,"%s what? ",purpose);
! 572: else waddstr(hw, spacemsg);
! 573:
! 574: draw(hw); /* write screen */
! 575:
! 576: if (purpose) {
! 577: do {
! 578: ch = tolower(wgetch(hw));
! 579: } until (isalpha(ch) || ch == ESCAPE);
! 580: }
! 581: else {
! 582: ch = pack_char(list, OBJPTR(saveitem)); /* Pick a valid item */
! 583: wait_for(hw,' ');
! 584: }
! 585:
! 586: restscr(cw); /* redraw orig screen */
! 587: if(ch == ESCAPE) {
! 588: after = FALSE;
! 589: msg(""); /* clear top line */
! 590: return NULL; /* all done if abort */
! 591: }
! 592: /* ch has item to get from list */
! 593: }
! 594: for(item = list,och = 'a'; item != NULL; item = next(item),och++) {
! 595: if (ch == och) break;
! 596: if (och == 'z') och = 'A' - 1;
! 597: }
! 598: if (item == NULL) {
! 599: msg("Please specify a letter between 'a' and '%c'",
! 600: och == 'A' ? 'z' : och-1);
! 601: continue;
! 602: }
! 603: if (is_type(OBJPTR(item), type))
! 604: return (item);
! 605: else
! 606: msg ("You can't %s that!", purpose);
! 607: }
! 608: }
! 609:
! 610: char
! 611: pack_char(struct linked_list *list, struct object *obj)
! 612: {
! 613: register struct linked_list *item;
! 614: register char c;
! 615:
! 616: c = 'a';
! 617: for (item = list; item != NULL; item = next(item)) {
! 618: if (OBJPTR(item) == obj)
! 619: return c;
! 620: else {
! 621: if (c == 'z') c = 'A';
! 622: else c++;
! 623: }
! 624: }
! 625: return 'z';
! 626: }
! 627:
! 628:
! 629: /*
! 630: * cur_null:
! 631: * This updates cur_weapon etc for dropping things
! 632: */
! 633: void
! 634: cur_null(struct object *op)
! 635: {
! 636: if (op == cur_weapon) cur_weapon = NULL;
! 637: else if (op == cur_armor) cur_armor = NULL;
! 638: else if (op == cur_ring[LEFT_1]) cur_ring[LEFT_1] = NULL;
! 639: else if (op == cur_ring[LEFT_2]) cur_ring[LEFT_2] = NULL;
! 640: else if (op == cur_ring[LEFT_3]) cur_ring[LEFT_3] = NULL;
! 641: else if (op == cur_ring[LEFT_4]) cur_ring[LEFT_4] = NULL;
! 642: else if (op == cur_ring[RIGHT_1]) cur_ring[RIGHT_1] = NULL;
! 643: else if (op == cur_ring[RIGHT_2]) cur_ring[RIGHT_2] = NULL;
! 644: else if (op == cur_ring[RIGHT_3]) cur_ring[RIGHT_3] = NULL;
! 645: else if (op == cur_ring[RIGHT_4]) cur_ring[RIGHT_4] = NULL;
! 646: else if (op == cur_misc[WEAR_BOOTS]) cur_misc[WEAR_BOOTS] = NULL;
! 647: else if (op == cur_misc[WEAR_JEWEL]) cur_misc[WEAR_JEWEL] = NULL;
! 648: else if (op == cur_misc[WEAR_GAUNTLET]) cur_misc[WEAR_GAUNTLET] = NULL;
! 649: else if (op == cur_misc[WEAR_CLOAK]) cur_misc[WEAR_CLOAK] = NULL;
! 650: else if (op == cur_misc[WEAR_BRACERS]) cur_misc[WEAR_BRACERS] = NULL;
! 651: else if (op == cur_misc[WEAR_NECKLACE]) cur_misc[WEAR_NECKLACE] = NULL;
! 652: }
! 653:
! 654: /*
! 655: * idenpack:
! 656: * Identify all the items in the pack
! 657: */
! 658: void
! 659: idenpack(void)
! 660: {
! 661: reg struct linked_list *pc;
! 662:
! 663: for (pc = pack ; pc != NULL ; pc = next(pc))
! 664: whatis(pc);
! 665: }
! 666:
! 667: bool
! 668: is_type (struct object *obj, int type)
! 669: {
! 670: register bool current;
! 671:
! 672: if (type == obj->o_type)
! 673: return (TRUE);
! 674:
! 675: switch (type) {
! 676: case ALL:
! 677: return (TRUE);
! 678: when ZAPPABLE:
! 679: if (obj->o_type == STICK) return (TRUE);
! 680: if (obj->o_type == RELIC)
! 681: switch (obj->o_which) {
! 682: case MING_STAFF:
! 683: case ASMO_ROD:
! 684: case ORCUS_WAND:
! 685: return (TRUE);
! 686: }
! 687: when WEARABLE:
! 688: case REMOVABLE:
! 689: current = is_current(obj);
! 690:
! 691: /*
! 692: * Don't wear thing we are already wearing or remove things
! 693: * we aren't wearing.
! 694: */
! 695: if (type == WEARABLE && current) return (FALSE);
! 696: else if (type == REMOVABLE && !current) return (FALSE);
! 697:
! 698: switch (obj->o_type) {
! 699: case RELIC:
! 700: switch (obj->o_which) {
! 701: case HEIL_ANKH:
! 702: case EMORI_CLOAK:
! 703: return (TRUE);
! 704: }
! 705: when MM:
! 706: switch (obj->o_which) {
! 707: case MM_ELF_BOOTS:
! 708: case MM_DANCE:
! 709: case MM_BRACERS:
! 710: case MM_DISP:
! 711: case MM_PROTECT:
! 712: case MM_G_DEXTERITY:
! 713: case MM_G_OGRE:
! 714: case MM_JEWEL:
! 715: case MM_R_POWERLESS:
! 716: case MM_FUMBLE:
! 717: case MM_STRANGLE:
! 718: case MM_ADAPTION:
! 719: return (TRUE);
! 720: }
! 721: when ARMOR:
! 722: case RING:
! 723: return (TRUE);
! 724: }
! 725: when CALLABLE:
! 726: switch (obj->o_type) {
! 727: case RING:
! 728: case POTION:
! 729: case STICK:
! 730: case SCROLL:
! 731: case MM:
! 732: return(TRUE);
! 733: }
! 734: when WIELDABLE:
! 735: switch (obj->o_type) {
! 736: case STICK:
! 737: case WEAPON:
! 738: return(TRUE);
! 739: when RELIC:
! 740: switch (obj->o_which) {
! 741: case MUSTY_DAGGER:
! 742: case HRUGGEK_MSTAR:
! 743: case YEENOGHU_FLAIL:
! 744: case MING_STAFF:
! 745: case ORCUS_WAND:
! 746: case ASMO_ROD:
! 747: return(TRUE);
! 748: }
! 749: }
! 750: when IDENTABLE:
! 751: if (!(obj->o_flags & ISKNOW) && obj->o_type != FOOD)
! 752: return (TRUE);
! 753: if (obj->o_type == MM) {
! 754: switch (obj->o_which) {
! 755: case MM_JUG:
! 756: /* Can still identify a jug if we don't know the potion */
! 757: if (obj->o_ac != JUG_EMPTY && !p_know[obj->o_ac])
! 758: return (TRUE);
! 759: }
! 760: }
! 761: when USEABLE:
! 762: if (obj->o_type == MM) {
! 763: switch(obj->o_which) {
! 764: case MM_JUG:
! 765: case MM_BEAKER:
! 766: case MM_BOOK:
! 767: case MM_SKILLS:
! 768: case MM_OPEN:
! 769: case MM_HUNGER:
! 770: case MM_DRUMS:
! 771: case MM_DISAPPEAR:
! 772: case MM_CHOKE:
! 773: case MM_KEOGHTOM:
! 774: return (TRUE);
! 775: }
! 776: }
! 777: else if (obj->o_type == RELIC) {
! 778: switch (obj->o_which) {
! 779: case EMORI_CLOAK:
! 780: case BRIAN_MANDOLIN:
! 781: case HEIL_ANKH:
! 782: case YENDOR_AMULET:
! 783: case GERYON_HORN:
! 784: return (TRUE);
! 785: }
! 786: }
! 787: when PROTECTABLE:
! 788: switch (obj->o_type) {
! 789: case WEAPON:
! 790: if ((obj->o_flags & ISMETAL) == 0) return (FALSE);
! 791:
! 792: /* Fall through */
! 793: case ARMOR:
! 794: return (TRUE);
! 795:
! 796: when MM:
! 797: if (obj->o_which == MM_BRACERS) return (TRUE);
! 798: }
! 799: }
! 800: return(FALSE);
! 801: }
! 802:
! 803: void
! 804: del_pack(struct linked_list *item)
! 805: {
! 806: register struct object *obj;
! 807:
! 808: obj = OBJPTR(item);
! 809: if (obj->o_count > 1) {
! 810: obj->o_count--;
! 811: }
! 812: else {
! 813: cur_null(obj);
! 814: detach(pack, item);
! 815: o_discard(item);
! 816: inpack--;
! 817: }
! 818: }
! 819:
! 820: /*
! 821: * carry_obj:
! 822: * Check to see if a monster is carrying something and, if so, give
! 823: * it to him.
! 824: */
! 825:
! 826: void
! 827: carry_obj(struct thing *mp, int chance)
! 828: {
! 829: reg struct linked_list *item;
! 830: reg struct object *obj;
! 831:
! 832: /*
! 833: * If there is no chance, just return.
! 834: * Note that this means there must be a "chance" in order for
! 835: * the creature to carry a relic.
! 836: */
! 837: if (chance <= 0) return;
! 838:
! 839: /*
! 840: * check for the relic/artifacts
! 841: * Do the relics first so they end up last in the pack. Attach()
! 842: * always adds things to the beginning. This way they will be the
! 843: * last things dropped when the creature is killed. This will ensure
! 844: * the relic will be on top if there is a stack of item lying on the
! 845: * floor and so the hero will know where it is if he's trying to
! 846: * avoid it
! 847: */
! 848: if (on(*mp, CARRYDAGGER)) {
! 849: item = spec_item(RELIC, MUSTY_DAGGER, 0, 0);
! 850: obj = OBJPTR(item);
! 851: obj->o_pos = mp->t_pos;
! 852: attach(mp->t_pack, item);
! 853: }
! 854:
! 855: if (on(*mp, CARRYCLOAK)) {
! 856: item = spec_item(RELIC, EMORI_CLOAK, 0, 0);
! 857: obj = OBJPTR(item);
! 858: obj->o_pos = mp->t_pos;
! 859: attach(mp->t_pack, item);
! 860: }
! 861:
! 862: if (on(*mp, CARRYANKH)) {
! 863: item = spec_item(RELIC, HEIL_ANKH, 0, 0);
! 864: obj = OBJPTR(item);
! 865: obj->o_pos = mp->t_pos;
! 866: attach(mp->t_pack, item);
! 867: }
! 868:
! 869: if (on(*mp, CARRYSTAFF)) {
! 870: item = spec_item(RELIC, MING_STAFF, 0, 0);
! 871: obj = OBJPTR(item);
! 872: obj->o_pos = mp->t_pos;
! 873: attach(mp->t_pack, item);
! 874: }
! 875:
! 876: if (on(*mp, CARRYWAND)) {
! 877: item = spec_item(RELIC, ORCUS_WAND, 0, 0);
! 878: obj = OBJPTR(item);
! 879: obj->o_pos = mp->t_pos;
! 880: attach(mp->t_pack, item);
! 881: }
! 882:
! 883: if (on(*mp, CARRYROD)) {
! 884: item = spec_item(RELIC, ASMO_ROD, 0, 0);
! 885: obj = OBJPTR(item);
! 886: obj->o_pos = mp->t_pos;
! 887: attach(mp->t_pack, item);
! 888: }
! 889:
! 890: if (on(*mp, CARRYAMULET)) {
! 891: item = spec_item(RELIC, YENDOR_AMULET, 0, 0);
! 892: obj = OBJPTR(item);
! 893: obj->o_pos = mp->t_pos;
! 894: attach(mp->t_pack, item);
! 895: }
! 896:
! 897: if (on(*mp, CARRYMANDOLIN)) {
! 898: item = spec_item(RELIC, BRIAN_MANDOLIN, 0, 0);
! 899: obj = OBJPTR(item);
! 900: obj->o_pos = mp->t_pos;
! 901: attach(mp->t_pack, item);
! 902: }
! 903: if (on(*mp, CARRYMSTAR)) {
! 904: item = spec_item(RELIC, HRUGGEK_MSTAR, 0, 0);
! 905: obj = OBJPTR(item);
! 906: obj->o_pos = mp->t_pos;
! 907: attach(mp->t_pack, item);
! 908: }
! 909: if (on(*mp, CARRYFLAIL)) {
! 910: item = spec_item(RELIC, YEENOGHU_FLAIL, 0, 0);
! 911: obj = OBJPTR(item);
! 912: obj->o_pos = mp->t_pos;
! 913: attach(mp->t_pack, item);
! 914: }
! 915: if (on(*mp, CARRYHORN)) {
! 916: item = spec_item(RELIC, GERYON_HORN, 0, 0);
! 917: obj = OBJPTR(item);
! 918: obj->o_pos = mp->t_pos;
! 919: attach(mp->t_pack, item);
! 920: }
! 921: /*
! 922: * If it carries gold, give it some
! 923: */
! 924: if (on(*mp, CARRYGOLD) && rnd(100) < chance) {
! 925: item = spec_item(GOLD, 0, 0, 0);
! 926: obj = OBJPTR(item);
! 927: obj->o_count = GOLDCALC + GOLDCALC;
! 928: obj->o_pos = mp->t_pos;
! 929: attach(mp->t_pack, item);
! 930: }
! 931:
! 932: /*
! 933: * If it carries food, give it some
! 934: */
! 935: if (on(*mp, CARRYFOOD) && rnd(100) < chance) {
! 936: item = spec_item(FOOD, 0, 0, 0);
! 937: obj = OBJPTR(item);
! 938: obj->o_weight = things[TYP_FOOD].mi_wght;
! 939: obj->o_pos = mp->t_pos;
! 940: attach(mp->t_pack, item);
! 941: }
! 942:
! 943: /*
! 944: * If it carries a weapon, give it one
! 945: */
! 946: if (on(*mp, CARRYWEAPON) && rnd(100) < chance) {
! 947: int type, hit, dam;
! 948:
! 949: /* Get the "bonuses" */
! 950: hit = rnd(5) - 2;
! 951: dam = rnd(5) - 2;
! 952:
! 953: /* Only choose an appropriate type of weapon */
! 954: switch (rnd(11)) {
! 955: case 0: type = DAGGER;
! 956: when 1: type = BATTLEAXE;
! 957: when 2: type = MACE;
! 958: when 3: type = SWORD;
! 959: when 4: type = PIKE;
! 960: when 5: type = HALBERD;
! 961: when 6: type = SPETUM;
! 962: when 7: type = BARDICHE;
! 963: when 8: type = TRIDENT;
! 964: when 9: type = BASWORD;
! 965: otherwise: type = TWOSWORD;
! 966: }
! 967:
! 968: /* Create the item */
! 969: item = spec_item(WEAPON, type, hit, dam);
! 970: obj = OBJPTR(item);
! 971: obj->o_pos = mp->t_pos;
! 972: attach(mp->t_pack, item);
! 973: }
! 974:
! 975: /*
! 976: * If it carries a scroll, give it one
! 977: */
! 978: if (on(*mp, CARRYSCROLL) && rnd(100) < chance) {
! 979: item = new_thing(TYP_SCROLL);
! 980: obj = OBJPTR(item);
! 981: obj->o_pos = mp->t_pos;
! 982:
! 983: /* Can the monster carry this scroll? */
! 984: if (obj->o_which == S_SCARE && mp->t_stats.s_intel < 16)
! 985: fall(item, FALSE); /* This would scare us! */
! 986: else attach(mp->t_pack, item);
! 987: }
! 988:
! 989: /*
! 990: * If it carries a potion, give it one
! 991: */
! 992: if (on(*mp, CARRYPOTION) && rnd(100) < chance) {
! 993: item = new_thing(TYP_POTION);
! 994: obj = OBJPTR(item);
! 995: obj->o_pos = mp->t_pos;
! 996: attach(mp->t_pack, item);
! 997: }
! 998:
! 999: /*
! 1000: * If it carries a ring, give it one
! 1001: */
! 1002: if (on(*mp, CARRYRING) && rnd(100) < chance) {
! 1003: item = new_thing(TYP_RING);
! 1004: obj = OBJPTR(item);
! 1005: obj->o_pos = mp->t_pos;
! 1006: attach(mp->t_pack, item);
! 1007: }
! 1008:
! 1009: /*
! 1010: * If it carries a wand or staff, give it one
! 1011: */
! 1012: if (on(*mp, CARRYSTICK) && rnd(100) < chance) {
! 1013: item = new_thing(TYP_STICK);
! 1014: obj = OBJPTR(item);
! 1015: obj->o_pos = mp->t_pos;
! 1016: attach(mp->t_pack, item);
! 1017: }
! 1018:
! 1019: /*
! 1020: * If it carries any miscellaneous magic, give it one
! 1021: */
! 1022: if (on(*mp, CARRYMISC) && rnd(100) < chance) {
! 1023: item = new_thing(TYP_MM);
! 1024: obj = OBJPTR(item);
! 1025: obj->o_pos = mp->t_pos;
! 1026: attach(mp->t_pack, item);
! 1027: }
! 1028: }
! 1029:
! 1030:
! 1031: /*
! 1032: * grab():
! 1033: * See what is on the spot where the player is standing. If
! 1034: * nothing is there, do nothing. If there is one thing, pick it
! 1035: * up. If there are multiple things, prompt the player for what
! 1036: * he wants (* means everything).
! 1037: */
! 1038:
! 1039: int
! 1040: grab(int y, int x)
! 1041: {
! 1042: register struct linked_list *next_item, *item;
! 1043: register struct object *obj;
! 1044: register int cnt;
! 1045: int num_there = 0, ch, och;
! 1046:
! 1047: /*
! 1048: * Count how many objects there are and move them to the front
! 1049: * of the level list.
! 1050: */
! 1051: for (item = lvl_obj; item != NULL; item = next_item) {
! 1052: obj = OBJPTR(item);
! 1053: next_item = next(item);
! 1054: if (obj->o_pos.y == y && obj->o_pos.x == x) {
! 1055: num_there++;
! 1056: detach(lvl_obj, item); /* Remove it from the list */
! 1057: attach(lvl_obj, item); /* Place it at the front of the list */
! 1058: }
! 1059: }
! 1060:
! 1061: /* Nothing there. */
! 1062: if (num_there < 1) msg("Nothing %s", terse ? "there." : "to pick up.");
! 1063:
! 1064: /* One thing there */
! 1065: else if (num_there == 1) {
! 1066: add_pack(FALSE, FALSE, NULL);
! 1067: return(1);
! 1068: }
! 1069:
! 1070: /* Multiple things there */
! 1071: else {
! 1072: wclear(hw);
! 1073: cnt = 0;
! 1074: for (item = lvl_obj, ch = 'a'; item != NULL && cnt < num_there;
! 1075: item = next(item), ch++) {
! 1076: obj = OBJPTR(item);
! 1077: wprintw(hw,"%c) %s\n\r", ch, inv_name(obj,FALSE));
! 1078: if (++cnt >= LINES - 2 && next(item) != NULL) {
! 1079: cnt = 0;
! 1080: dbotline(hw, spacemsg);
! 1081: wclear(hw);
! 1082: }
! 1083: if (ch == 'z') ch = 'A' - 1;
! 1084: }
! 1085: wmove(hw, LINES - 1,0);
! 1086: wprintw(hw, "Pick up what? (* for all): ");
! 1087: draw(hw); /* write screen */
! 1088:
! 1089: for (;;) {
! 1090: do {
! 1091: ch = tolower(wgetch(hw));
! 1092: } until (isalpha(ch) || ch == '*' || ch == ESCAPE);
! 1093: restscr(cw); /* redraw orig screen */
! 1094: if (ch == ESCAPE) {
! 1095: after = FALSE;
! 1096: msg(""); /* clear top line */
! 1097: break;
! 1098: }
! 1099: if (ch == '*') {
! 1100: while (add_pack(NULL, TRUE, NULL)); /* pick up everything there */
! 1101: return(num_there);
! 1102: }
! 1103: /* ch has item to get from list */
! 1104:
! 1105: cnt = 0;
! 1106: for (item = lvl_obj, och = 'a'; item != NULL && cnt < num_there;
! 1107: item = next(item), och++, cnt++) {
! 1108: if (ch == och)
! 1109: break;
! 1110: if (och == 'z') och = 'A' - 1;
! 1111: }
! 1112: if (item == NULL || cnt >= num_there) {
! 1113: wmove(hw, LINES - 1, 25);
! 1114: wprintw(hw, " [between 'a' and '%c']:%c ",
! 1115: och == 'A' ? 'z' : och-1, '\007');
! 1116: draw(hw); /* write screen */
! 1117: continue;
! 1118: }
! 1119: else {
! 1120: detach(lvl_obj, item);
! 1121: if (add_pack(item, FALSE, NULL)) {
! 1122: /*
! 1123: * There should always be at least one item left since we
! 1124: * handle the one item case up above. But it never hurts
! 1125: * to make sure we don't have a NULL pointer.
! 1126: */
! 1127: if ((item = find_obj(hero.y, hero.x)) == NULL)
! 1128: mvaddch(y, x, (OBJPTR(item))->o_type);
! 1129: return(1);
! 1130: }
! 1131: else attach(lvl_obj, item); /* Couldn't pick it up! */
! 1132: break;
! 1133: }
! 1134: }
! 1135: }
! 1136:
! 1137: return(0);
! 1138: }
CVSweb