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