1: /* 2: * pack.c 3: * 4: * This source herein may be modified and/or distributed by anybody who 5: * so desires, with the following restrictions: 6: * 1.) No portion of this notice shall be removed. 7: * 2.) Credit shall not be taken for the creation of this source. 8: * 3.) This code is not to be traded, sold, or used for personal 9: * gain or profit. 10: * 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)pack.c 5.1 (Berkeley) 11/25/87"; 15: #endif /* not lint */ 16: 17: #include "rogue.h" 18: 19: char *curse_message = "you can't, it appears to be cursed"; 20: 21: extern short levitate; 22: 23: object * 24: add_to_pack(obj, pack, condense) 25: object *obj, *pack; 26: { 27: object *op; 28: 29: if (condense) { 30: if (op = check_duplicate(obj, pack)) { 31: free_object(obj); 32: return(op); 33: } else { 34: obj->ichar = next_avail_ichar(); 35: } 36: } 37: if (pack->next_object == 0) { 38: pack->next_object = obj; 39: } else { 40: op = pack->next_object; 41: 42: while (op->next_object) { 43: op = op->next_object; 44: } 45: op->next_object = obj; 46: } 47: obj->next_object = 0; 48: return(obj); 49: } 50: 51: take_from_pack(obj, pack) 52: object *obj, *pack; 53: { 54: while (pack->next_object != obj) { 55: pack = pack->next_object; 56: } 57: pack->next_object = pack->next_object->next_object; 58: } 59: 60: /* Note: *status is set to 0 if the rogue attempts to pick up a scroll 61: * of scare-monster and it turns to dust. *status is otherwise set to 1. 62: */ 63: 64: object * 65: pick_up(row, col, status) 66: short *status; 67: { 68: object *obj; 69: 70: *status = 1; 71: 72: if (levitate) { 73: message("you're floating in the air!", 0); 74: return((object *) 0); 75: } 76: obj = object_at(&level_objects, row, col); 77: if (!obj) { 78: message("pick_up(): inconsistent", 1); 79: return(obj); 80: } 81: if ( (obj->what_is == SCROL) && 82: (obj->which_kind == SCARE_MONSTER) && 83: obj->picked_up) { 84: message("the scroll turns to dust as you pick it up", 0); 85: dungeon[row][col] &= (~OBJECT); 86: vanish(obj, 0, &level_objects); 87: *status = 0; 88: if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) { 89: id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED; 90: } 91: return((object *) 0); 92: } 93: if (obj->what_is == GOLD) { 94: rogue.gold += obj->quantity; 95: dungeon[row][col] &= ~(OBJECT); 96: take_from_pack(obj, &level_objects); 97: print_stats(STAT_GOLD); 98: return(obj); /* obj will be free_object()ed in caller */ 99: } 100: if (pack_count(obj) >= MAX_PACK_COUNT) { 101: message("pack too full", 1); 102: return((object *) 0); 103: } 104: dungeon[row][col] &= ~(OBJECT); 105: take_from_pack(obj, &level_objects); 106: obj = add_to_pack(obj, &rogue.pack, 1); 107: obj->picked_up = 1; 108: return(obj); 109: } 110: 111: drop() 112: { 113: object *obj, *new; 114: short ch; 115: char desc[DCOLS]; 116: 117: if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) { 118: message("there's already something there", 0); 119: return; 120: } 121: if (!rogue.pack.next_object) { 122: message("you have nothing to drop", 0); 123: return; 124: } 125: if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) { 126: return; 127: } 128: if (!(obj = get_letter_object(ch))) { 129: message("no such item.", 0); 130: return; 131: } 132: if (obj->in_use_flags & BEING_WIELDED) { 133: if (obj->is_cursed) { 134: message(curse_message, 0); 135: return; 136: } 137: unwield(rogue.weapon); 138: } else if (obj->in_use_flags & BEING_WORN) { 139: if (obj->is_cursed) { 140: message(curse_message, 0); 141: return; 142: } 143: mv_aquatars(); 144: unwear(rogue.armor); 145: print_stats(STAT_ARMOR); 146: } else if (obj->in_use_flags & ON_EITHER_HAND) { 147: if (obj->is_cursed) { 148: message(curse_message, 0); 149: return; 150: } 151: un_put_on(obj); 152: } 153: obj->row = rogue.row; 154: obj->col = rogue.col; 155: 156: if ((obj->quantity > 1) && (obj->what_is != WEAPON)) { 157: obj->quantity--; 158: new = alloc_object(); 159: *new = *obj; 160: new->quantity = 1; 161: obj = new; 162: } else { 163: obj->ichar = 'L'; 164: take_from_pack(obj, &rogue.pack); 165: } 166: place_at(obj, rogue.row, rogue.col); 167: (void) strcpy(desc, "dropped "); 168: get_desc(obj, desc+8); 169: message(desc, 0); 170: (void) reg_move(); 171: } 172: 173: object * 174: check_duplicate(obj, pack) 175: object *obj, *pack; 176: { 177: object *op; 178: 179: if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) { 180: return(0); 181: } 182: if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) { 183: return(0); 184: } 185: op = pack->next_object; 186: 187: while (op) { 188: if ((op->what_is == obj->what_is) && 189: (op->which_kind == obj->which_kind)) { 190: 191: if ((obj->what_is != WEAPON) || 192: ((obj->what_is == WEAPON) && 193: ((obj->which_kind == ARROW) || 194: (obj->which_kind == DAGGER) || 195: (obj->which_kind == DART) || 196: (obj->which_kind == SHURIKEN)) && 197: (obj->quiver == op->quiver))) { 198: op->quantity += obj->quantity; 199: return(op); 200: } 201: } 202: op = op->next_object; 203: } 204: return(0); 205: } 206: 207: next_avail_ichar() 208: { 209: register object *obj; 210: register i; 211: boolean ichars[26]; 212: 213: for (i = 0; i < 26; i++) { 214: ichars[i] = 0; 215: } 216: obj = rogue.pack.next_object; 217: while (obj) { 218: ichars[(obj->ichar - 'a')] = 1; 219: obj = obj->next_object; 220: } 221: for (i = 0; i < 26; i++) { 222: if (!ichars[i]) { 223: return(i + 'a'); 224: } 225: } 226: return('?'); 227: } 228: 229: wait_for_ack() 230: { 231: while (rgetchar() != ' ') ; 232: } 233: 234: pack_letter(prompt, mask) 235: char *prompt; 236: unsigned short mask; 237: { 238: short ch; 239: unsigned short tmask = mask; 240: 241: if (!mask_pack(&rogue.pack, mask)) { 242: message("nothing appropriate", 0); 243: return(CANCEL); 244: } 245: for (;;) { 246: 247: message(prompt, 0); 248: 249: for (;;) { 250: ch = rgetchar(); 251: if (!is_pack_letter(&ch, &mask)) { 252: sound_bell(); 253: } else { 254: break; 255: } 256: } 257: 258: if (ch == LIST) { 259: check_message(); 260: inventory(&rogue.pack, mask); 261: } else { 262: break; 263: } 264: mask = tmask; 265: } 266: check_message(); 267: return(ch); 268: } 269: 270: take_off() 271: { 272: char desc[DCOLS]; 273: object *obj; 274: 275: if (rogue.armor) { 276: if (rogue.armor->is_cursed) { 277: message(curse_message, 0); 278: } else { 279: mv_aquatars(); 280: obj = rogue.armor; 281: unwear(rogue.armor); 282: (void) strcpy(desc, "was wearing "); 283: get_desc(obj, desc+12); 284: message(desc, 0); 285: print_stats(STAT_ARMOR); 286: (void) reg_move(); 287: } 288: } else { 289: message("not wearing any", 0); 290: } 291: } 292: 293: wear() 294: { 295: short ch; 296: register object *obj; 297: char desc[DCOLS]; 298: 299: if (rogue.armor) { 300: message("your already wearing some", 0); 301: return; 302: } 303: ch = pack_letter("wear what?", ARMOR); 304: 305: if (ch == CANCEL) { 306: return; 307: } 308: if (!(obj = get_letter_object(ch))) { 309: message("no such item.", 0); 310: return; 311: } 312: if (obj->what_is != ARMOR) { 313: message("you can't wear that", 0); 314: return; 315: } 316: obj->identified = 1; 317: (void) strcpy(desc, "wearing "); 318: get_desc(obj, desc + 8); 319: message(desc, 0); 320: do_wear(obj); 321: print_stats(STAT_ARMOR); 322: (void) reg_move(); 323: } 324: 325: unwear(obj) 326: object *obj; 327: { 328: if (obj) { 329: obj->in_use_flags &= (~BEING_WORN); 330: } 331: rogue.armor = (object *) 0; 332: } 333: 334: do_wear(obj) 335: object *obj; 336: { 337: rogue.armor = obj; 338: obj->in_use_flags |= BEING_WORN; 339: obj->identified = 1; 340: } 341: 342: wield() 343: { 344: short ch; 345: register object *obj; 346: char desc[DCOLS]; 347: 348: if (rogue.weapon && rogue.weapon->is_cursed) { 349: message(curse_message, 0); 350: return; 351: } 352: ch = pack_letter("wield what?", WEAPON); 353: 354: if (ch == CANCEL) { 355: return; 356: } 357: if (!(obj = get_letter_object(ch))) { 358: message("No such item.", 0); 359: return; 360: } 361: if (obj->what_is & (ARMOR | RING)) { 362: sprintf(desc, "you can't wield %s", 363: ((obj->what_is == ARMOR) ? "armor" : "rings")); 364: message(desc, 0); 365: return; 366: } 367: if (obj->in_use_flags & BEING_WIELDED) { 368: message("in use", 0); 369: } else { 370: unwield(rogue.weapon); 371: (void) strcpy(desc, "wielding "); 372: get_desc(obj, desc + 9); 373: message(desc, 0); 374: do_wield(obj); 375: (void) reg_move(); 376: } 377: } 378: 379: do_wield(obj) 380: object *obj; 381: { 382: rogue.weapon = obj; 383: obj->in_use_flags |= BEING_WIELDED; 384: } 385: 386: unwield(obj) 387: object *obj; 388: { 389: if (obj) { 390: obj->in_use_flags &= (~BEING_WIELDED); 391: } 392: rogue.weapon = (object *) 0; 393: } 394: 395: call_it() 396: { 397: short ch; 398: register object *obj; 399: struct id *id_table; 400: char buf[MAX_TITLE_LENGTH+2]; 401: 402: ch = pack_letter("call what?", (SCROL | POTION | WAND | RING)); 403: 404: if (ch == CANCEL) { 405: return; 406: } 407: if (!(obj = get_letter_object(ch))) { 408: message("no such item.", 0); 409: return; 410: } 411: if (!(obj->what_is & (SCROL | POTION | WAND | RING))) { 412: message("surely you already know what that's called", 0); 413: return; 414: } 415: id_table = get_id_table(obj); 416: 417: if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) { 418: id_table[obj->which_kind].id_status = CALLED; 419: (void) strcpy(id_table[obj->which_kind].title, buf); 420: } 421: } 422: 423: pack_count(new_obj) 424: object *new_obj; 425: { 426: object *obj; 427: short count = 0; 428: 429: obj = rogue.pack.next_object; 430: 431: while (obj) { 432: if (obj->what_is != WEAPON) { 433: count += obj->quantity; 434: } else if (!new_obj) { 435: count++; 436: } else if ((new_obj->what_is != WEAPON) || 437: ((obj->which_kind != ARROW) && 438: (obj->which_kind != DAGGER) && 439: (obj->which_kind != DART) && 440: (obj->which_kind != SHURIKEN)) || 441: (new_obj->which_kind != obj->which_kind) || 442: (obj->quiver != new_obj->quiver)) { 443: count++; 444: } 445: obj = obj->next_object; 446: } 447: return(count); 448: } 449: 450: boolean 451: mask_pack(pack, mask) 452: object *pack; 453: unsigned short mask; 454: { 455: while (pack->next_object) { 456: pack = pack->next_object; 457: if (pack->what_is & mask) { 458: return(1); 459: } 460: } 461: return(0); 462: } 463: 464: is_pack_letter(c, mask) 465: short *c; 466: unsigned short *mask; 467: { 468: if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') || 469: (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) { 470: switch(*c) { 471: case '?': 472: *mask = SCROL; 473: break; 474: case '!': 475: *mask = POTION; 476: break; 477: case ':': 478: *mask = FOOD; 479: break; 480: case ')': 481: *mask = WEAPON; 482: break; 483: case ']': 484: *mask = ARMOR; 485: break; 486: case '/': 487: *mask = WAND; 488: break; 489: case '=': 490: *mask = RING; 491: break; 492: case ',': 493: *mask = AMULET; 494: break; 495: } 496: *c = LIST; 497: return(1); 498: } 499: return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST)); 500: } 501: 502: has_amulet() 503: { 504: return(mask_pack(&rogue.pack, AMULET)); 505: } 506: 507: kick_into_pack() 508: { 509: object *obj; 510: char desc[DCOLS]; 511: short n, stat; 512: 513: if (!(dungeon[rogue.row][rogue.col] & OBJECT)) { 514: message("nothing here", 0); 515: } else { 516: if (obj = pick_up(rogue.row, rogue.col, &stat)) { 517: get_desc(obj, desc); 518: if (obj->what_is == GOLD) { 519: message(desc, 0); 520: free_object(obj); 521: } else { 522: n = strlen(desc); 523: desc[n] = '('; 524: desc[n+1] = obj->ichar; 525: desc[n+2] = ')'; 526: desc[n+3] = 0; 527: message(desc, 0); 528: } 529: } 530: if (obj || (!stat)) { 531: (void) reg_move(); 532: } 533: } 534: }