132689Sbostic /* 236704Sbostic * Copyright (c) 1988 The Regents of the University of California. 336704Sbostic * All rights reserved. 436704Sbostic * 536704Sbostic * This code is derived from software contributed to Berkeley by 636704Sbostic * Timothy C. Stoehr. 736704Sbostic * 842601Sbostic * %sccs.include.redist.c% 936704Sbostic */ 1036704Sbostic 1136704Sbostic #ifndef lint 12*58506Sbostic static char sccsid[] = "@(#)pack.c 5.4 (Berkeley) 03/05/93"; 1336704Sbostic #endif /* not lint */ 1436704Sbostic 1536704Sbostic /* 1632689Sbostic * pack.c 1732689Sbostic * 1832689Sbostic * This source herein may be modified and/or distributed by anybody who 1932689Sbostic * so desires, with the following restrictions: 2032689Sbostic * 1.) No portion of this notice shall be removed. 2132689Sbostic * 2.) Credit shall not be taken for the creation of this source. 2232689Sbostic * 3.) This code is not to be traded, sold, or used for personal 2332689Sbostic * gain or profit. 2432689Sbostic * 2532689Sbostic */ 2632689Sbostic 2732689Sbostic #include "rogue.h" 2832689Sbostic 2932689Sbostic char *curse_message = "you can't, it appears to be cursed"; 3032689Sbostic 3132689Sbostic extern short levitate; 3232689Sbostic 3332689Sbostic object * 3432689Sbostic add_to_pack(obj, pack, condense) 3532689Sbostic object *obj, *pack; 3632689Sbostic { 3732689Sbostic object *op; 3832689Sbostic 3932689Sbostic if (condense) { 4032689Sbostic if (op = check_duplicate(obj, pack)) { 4132689Sbostic free_object(obj); 4232689Sbostic return(op); 4332689Sbostic } else { 4432689Sbostic obj->ichar = next_avail_ichar(); 4532689Sbostic } 4632689Sbostic } 4732689Sbostic if (pack->next_object == 0) { 4832689Sbostic pack->next_object = obj; 4932689Sbostic } else { 5032689Sbostic op = pack->next_object; 5132689Sbostic 5232689Sbostic while (op->next_object) { 5332689Sbostic op = op->next_object; 5432689Sbostic } 5532689Sbostic op->next_object = obj; 5632689Sbostic } 5732689Sbostic obj->next_object = 0; 5832689Sbostic return(obj); 5932689Sbostic } 6032689Sbostic 6132689Sbostic take_from_pack(obj, pack) 6232689Sbostic object *obj, *pack; 6332689Sbostic { 6432689Sbostic while (pack->next_object != obj) { 6532689Sbostic pack = pack->next_object; 6632689Sbostic } 6732689Sbostic pack->next_object = pack->next_object->next_object; 6832689Sbostic } 6932689Sbostic 7032689Sbostic /* Note: *status is set to 0 if the rogue attempts to pick up a scroll 7132689Sbostic * of scare-monster and it turns to dust. *status is otherwise set to 1. 7232689Sbostic */ 7332689Sbostic 7432689Sbostic object * 7532689Sbostic pick_up(row, col, status) 7632689Sbostic short *status; 7732689Sbostic { 7832689Sbostic object *obj; 7932689Sbostic 8032689Sbostic *status = 1; 8132689Sbostic 8232689Sbostic if (levitate) { 8332689Sbostic message("you're floating in the air!", 0); 8432689Sbostic return((object *) 0); 8532689Sbostic } 8632689Sbostic obj = object_at(&level_objects, row, col); 8732689Sbostic if (!obj) { 8832689Sbostic message("pick_up(): inconsistent", 1); 8932689Sbostic return(obj); 9032689Sbostic } 9132689Sbostic if ( (obj->what_is == SCROL) && 9232689Sbostic (obj->which_kind == SCARE_MONSTER) && 9332689Sbostic obj->picked_up) { 9432689Sbostic message("the scroll turns to dust as you pick it up", 0); 9532689Sbostic dungeon[row][col] &= (~OBJECT); 9632689Sbostic vanish(obj, 0, &level_objects); 9732689Sbostic *status = 0; 9832689Sbostic if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) { 9932689Sbostic id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED; 10032689Sbostic } 10132689Sbostic return((object *) 0); 10232689Sbostic } 10332689Sbostic if (obj->what_is == GOLD) { 10432689Sbostic rogue.gold += obj->quantity; 10532689Sbostic dungeon[row][col] &= ~(OBJECT); 10632689Sbostic take_from_pack(obj, &level_objects); 10732689Sbostic print_stats(STAT_GOLD); 10832689Sbostic return(obj); /* obj will be free_object()ed in caller */ 10932689Sbostic } 11032689Sbostic if (pack_count(obj) >= MAX_PACK_COUNT) { 11132689Sbostic message("pack too full", 1); 11232689Sbostic return((object *) 0); 11332689Sbostic } 11432689Sbostic dungeon[row][col] &= ~(OBJECT); 11532689Sbostic take_from_pack(obj, &level_objects); 11632689Sbostic obj = add_to_pack(obj, &rogue.pack, 1); 11732689Sbostic obj->picked_up = 1; 11832689Sbostic return(obj); 11932689Sbostic } 12032689Sbostic 12132689Sbostic drop() 12232689Sbostic { 12332689Sbostic object *obj, *new; 12432689Sbostic short ch; 12532689Sbostic char desc[DCOLS]; 12632689Sbostic 12732689Sbostic if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) { 12832689Sbostic message("there's already something there", 0); 12932689Sbostic return; 13032689Sbostic } 13132689Sbostic if (!rogue.pack.next_object) { 13232689Sbostic message("you have nothing to drop", 0); 13332689Sbostic return; 13432689Sbostic } 13532689Sbostic if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) { 13632689Sbostic return; 13732689Sbostic } 13832689Sbostic if (!(obj = get_letter_object(ch))) { 13932689Sbostic message("no such item.", 0); 14032689Sbostic return; 14132689Sbostic } 14232689Sbostic if (obj->in_use_flags & BEING_WIELDED) { 14332689Sbostic if (obj->is_cursed) { 14432689Sbostic message(curse_message, 0); 14532689Sbostic return; 14632689Sbostic } 14732689Sbostic unwield(rogue.weapon); 14832689Sbostic } else if (obj->in_use_flags & BEING_WORN) { 14932689Sbostic if (obj->is_cursed) { 15032689Sbostic message(curse_message, 0); 15132689Sbostic return; 15232689Sbostic } 15332689Sbostic mv_aquatars(); 15432689Sbostic unwear(rogue.armor); 15532689Sbostic print_stats(STAT_ARMOR); 15632689Sbostic } else if (obj->in_use_flags & ON_EITHER_HAND) { 15732689Sbostic if (obj->is_cursed) { 15832689Sbostic message(curse_message, 0); 15932689Sbostic return; 16032689Sbostic } 16132689Sbostic un_put_on(obj); 16232689Sbostic } 16332689Sbostic obj->row = rogue.row; 16432689Sbostic obj->col = rogue.col; 16532689Sbostic 16632689Sbostic if ((obj->quantity > 1) && (obj->what_is != WEAPON)) { 16732689Sbostic obj->quantity--; 16832689Sbostic new = alloc_object(); 16932689Sbostic *new = *obj; 17032689Sbostic new->quantity = 1; 17132689Sbostic obj = new; 17232689Sbostic } else { 17332689Sbostic obj->ichar = 'L'; 17432689Sbostic take_from_pack(obj, &rogue.pack); 17532689Sbostic } 17632689Sbostic place_at(obj, rogue.row, rogue.col); 17732689Sbostic (void) strcpy(desc, "dropped "); 17832689Sbostic get_desc(obj, desc+8); 17932689Sbostic message(desc, 0); 18032689Sbostic (void) reg_move(); 18132689Sbostic } 18232689Sbostic 18332689Sbostic object * 18432689Sbostic check_duplicate(obj, pack) 18532689Sbostic object *obj, *pack; 18632689Sbostic { 18732689Sbostic object *op; 18832689Sbostic 18932689Sbostic if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) { 19032689Sbostic return(0); 19132689Sbostic } 19232689Sbostic if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) { 19332689Sbostic return(0); 19432689Sbostic } 19532689Sbostic op = pack->next_object; 19632689Sbostic 19732689Sbostic while (op) { 19832689Sbostic if ((op->what_is == obj->what_is) && 19932689Sbostic (op->which_kind == obj->which_kind)) { 20032689Sbostic 20132689Sbostic if ((obj->what_is != WEAPON) || 20232689Sbostic ((obj->what_is == WEAPON) && 20332689Sbostic ((obj->which_kind == ARROW) || 20432689Sbostic (obj->which_kind == DAGGER) || 20532689Sbostic (obj->which_kind == DART) || 20632689Sbostic (obj->which_kind == SHURIKEN)) && 20732689Sbostic (obj->quiver == op->quiver))) { 20832689Sbostic op->quantity += obj->quantity; 20932689Sbostic return(op); 21032689Sbostic } 21132689Sbostic } 21232689Sbostic op = op->next_object; 21332689Sbostic } 21432689Sbostic return(0); 21532689Sbostic } 21632689Sbostic 21732689Sbostic next_avail_ichar() 21832689Sbostic { 21932689Sbostic register object *obj; 22032689Sbostic register i; 22132689Sbostic boolean ichars[26]; 22232689Sbostic 22332689Sbostic for (i = 0; i < 26; i++) { 22432689Sbostic ichars[i] = 0; 22532689Sbostic } 22632689Sbostic obj = rogue.pack.next_object; 22732689Sbostic while (obj) { 22832689Sbostic ichars[(obj->ichar - 'a')] = 1; 22932689Sbostic obj = obj->next_object; 23032689Sbostic } 23132689Sbostic for (i = 0; i < 26; i++) { 23232689Sbostic if (!ichars[i]) { 23332689Sbostic return(i + 'a'); 23432689Sbostic } 23532689Sbostic } 23632689Sbostic return('?'); 23732689Sbostic } 23832689Sbostic 23932689Sbostic wait_for_ack() 24032689Sbostic { 24132689Sbostic while (rgetchar() != ' ') ; 24232689Sbostic } 24332689Sbostic 24432689Sbostic pack_letter(prompt, mask) 24532689Sbostic char *prompt; 24632689Sbostic unsigned short mask; 24732689Sbostic { 24832689Sbostic short ch; 24932689Sbostic unsigned short tmask = mask; 25032689Sbostic 25132689Sbostic if (!mask_pack(&rogue.pack, mask)) { 25232689Sbostic message("nothing appropriate", 0); 25332689Sbostic return(CANCEL); 25432689Sbostic } 25532689Sbostic for (;;) { 25632689Sbostic 25732689Sbostic message(prompt, 0); 25832689Sbostic 25932689Sbostic for (;;) { 26032689Sbostic ch = rgetchar(); 26132689Sbostic if (!is_pack_letter(&ch, &mask)) { 26232689Sbostic sound_bell(); 26332689Sbostic } else { 26432689Sbostic break; 26532689Sbostic } 26632689Sbostic } 26732689Sbostic 26832689Sbostic if (ch == LIST) { 26932689Sbostic check_message(); 270*58506Sbostic mask = tmask; 27132689Sbostic inventory(&rogue.pack, mask); 27232689Sbostic } else { 27332689Sbostic break; 27432689Sbostic } 27532689Sbostic mask = tmask; 27632689Sbostic } 27732689Sbostic check_message(); 27832689Sbostic return(ch); 27932689Sbostic } 28032689Sbostic 28132689Sbostic take_off() 28232689Sbostic { 28332689Sbostic char desc[DCOLS]; 28432689Sbostic object *obj; 28532689Sbostic 28632689Sbostic if (rogue.armor) { 28732689Sbostic if (rogue.armor->is_cursed) { 28832689Sbostic message(curse_message, 0); 28932689Sbostic } else { 29032689Sbostic mv_aquatars(); 29132689Sbostic obj = rogue.armor; 29232689Sbostic unwear(rogue.armor); 29332689Sbostic (void) strcpy(desc, "was wearing "); 29432689Sbostic get_desc(obj, desc+12); 29532689Sbostic message(desc, 0); 29632689Sbostic print_stats(STAT_ARMOR); 29732689Sbostic (void) reg_move(); 29832689Sbostic } 29932689Sbostic } else { 30032689Sbostic message("not wearing any", 0); 30132689Sbostic } 30232689Sbostic } 30332689Sbostic 30432689Sbostic wear() 30532689Sbostic { 30632689Sbostic short ch; 30732689Sbostic register object *obj; 30832689Sbostic char desc[DCOLS]; 30932689Sbostic 31032689Sbostic if (rogue.armor) { 31132689Sbostic message("your already wearing some", 0); 31232689Sbostic return; 31332689Sbostic } 31432689Sbostic ch = pack_letter("wear what?", ARMOR); 31532689Sbostic 31632689Sbostic if (ch == CANCEL) { 31732689Sbostic return; 31832689Sbostic } 31932689Sbostic if (!(obj = get_letter_object(ch))) { 32032689Sbostic message("no such item.", 0); 32132689Sbostic return; 32232689Sbostic } 32332689Sbostic if (obj->what_is != ARMOR) { 32432689Sbostic message("you can't wear that", 0); 32532689Sbostic return; 32632689Sbostic } 32732689Sbostic obj->identified = 1; 32832689Sbostic (void) strcpy(desc, "wearing "); 32932689Sbostic get_desc(obj, desc + 8); 33032689Sbostic message(desc, 0); 33132689Sbostic do_wear(obj); 33232689Sbostic print_stats(STAT_ARMOR); 33332689Sbostic (void) reg_move(); 33432689Sbostic } 33532689Sbostic 33632689Sbostic unwear(obj) 33732689Sbostic object *obj; 33832689Sbostic { 33932689Sbostic if (obj) { 34032689Sbostic obj->in_use_flags &= (~BEING_WORN); 34132689Sbostic } 34232689Sbostic rogue.armor = (object *) 0; 34332689Sbostic } 34432689Sbostic 34532689Sbostic do_wear(obj) 34632689Sbostic object *obj; 34732689Sbostic { 34832689Sbostic rogue.armor = obj; 34932689Sbostic obj->in_use_flags |= BEING_WORN; 35032689Sbostic obj->identified = 1; 35132689Sbostic } 35232689Sbostic 35332689Sbostic wield() 35432689Sbostic { 35532689Sbostic short ch; 35632689Sbostic register object *obj; 35732689Sbostic char desc[DCOLS]; 35832689Sbostic 35932689Sbostic if (rogue.weapon && rogue.weapon->is_cursed) { 36032689Sbostic message(curse_message, 0); 36132689Sbostic return; 36232689Sbostic } 36332689Sbostic ch = pack_letter("wield what?", WEAPON); 36432689Sbostic 36532689Sbostic if (ch == CANCEL) { 36632689Sbostic return; 36732689Sbostic } 36832689Sbostic if (!(obj = get_letter_object(ch))) { 36932689Sbostic message("No such item.", 0); 37032689Sbostic return; 37132689Sbostic } 37232689Sbostic if (obj->what_is & (ARMOR | RING)) { 37332689Sbostic sprintf(desc, "you can't wield %s", 37432689Sbostic ((obj->what_is == ARMOR) ? "armor" : "rings")); 37532689Sbostic message(desc, 0); 37632689Sbostic return; 37732689Sbostic } 37832689Sbostic if (obj->in_use_flags & BEING_WIELDED) { 37932689Sbostic message("in use", 0); 38032689Sbostic } else { 38132689Sbostic unwield(rogue.weapon); 38232689Sbostic (void) strcpy(desc, "wielding "); 38332689Sbostic get_desc(obj, desc + 9); 38432689Sbostic message(desc, 0); 38532689Sbostic do_wield(obj); 38632689Sbostic (void) reg_move(); 38732689Sbostic } 38832689Sbostic } 38932689Sbostic 39032689Sbostic do_wield(obj) 39132689Sbostic object *obj; 39232689Sbostic { 39332689Sbostic rogue.weapon = obj; 39432689Sbostic obj->in_use_flags |= BEING_WIELDED; 39532689Sbostic } 39632689Sbostic 39732689Sbostic unwield(obj) 39832689Sbostic object *obj; 39932689Sbostic { 40032689Sbostic if (obj) { 40132689Sbostic obj->in_use_flags &= (~BEING_WIELDED); 40232689Sbostic } 40332689Sbostic rogue.weapon = (object *) 0; 40432689Sbostic } 40532689Sbostic 40632689Sbostic call_it() 40732689Sbostic { 40832689Sbostic short ch; 40932689Sbostic register object *obj; 41032689Sbostic struct id *id_table; 41132689Sbostic char buf[MAX_TITLE_LENGTH+2]; 41232689Sbostic 41332689Sbostic ch = pack_letter("call what?", (SCROL | POTION | WAND | RING)); 41432689Sbostic 41532689Sbostic if (ch == CANCEL) { 41632689Sbostic return; 41732689Sbostic } 41832689Sbostic if (!(obj = get_letter_object(ch))) { 41932689Sbostic message("no such item.", 0); 42032689Sbostic return; 42132689Sbostic } 42232689Sbostic if (!(obj->what_is & (SCROL | POTION | WAND | RING))) { 42332689Sbostic message("surely you already know what that's called", 0); 42432689Sbostic return; 42532689Sbostic } 42632689Sbostic id_table = get_id_table(obj); 42732689Sbostic 42832689Sbostic if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) { 42932689Sbostic id_table[obj->which_kind].id_status = CALLED; 43032689Sbostic (void) strcpy(id_table[obj->which_kind].title, buf); 43132689Sbostic } 43232689Sbostic } 43332689Sbostic 43432689Sbostic pack_count(new_obj) 43532689Sbostic object *new_obj; 43632689Sbostic { 43732689Sbostic object *obj; 43832689Sbostic short count = 0; 43932689Sbostic 44032689Sbostic obj = rogue.pack.next_object; 44132689Sbostic 44232689Sbostic while (obj) { 44332689Sbostic if (obj->what_is != WEAPON) { 44432689Sbostic count += obj->quantity; 44532689Sbostic } else if (!new_obj) { 44632689Sbostic count++; 44732689Sbostic } else if ((new_obj->what_is != WEAPON) || 44832689Sbostic ((obj->which_kind != ARROW) && 44932689Sbostic (obj->which_kind != DAGGER) && 45032689Sbostic (obj->which_kind != DART) && 45132689Sbostic (obj->which_kind != SHURIKEN)) || 45232689Sbostic (new_obj->which_kind != obj->which_kind) || 45332689Sbostic (obj->quiver != new_obj->quiver)) { 45432689Sbostic count++; 45532689Sbostic } 45632689Sbostic obj = obj->next_object; 45732689Sbostic } 45832689Sbostic return(count); 45932689Sbostic } 46032689Sbostic 46132689Sbostic boolean 46232689Sbostic mask_pack(pack, mask) 46332689Sbostic object *pack; 46432689Sbostic unsigned short mask; 46532689Sbostic { 46632689Sbostic while (pack->next_object) { 46732689Sbostic pack = pack->next_object; 46832689Sbostic if (pack->what_is & mask) { 46932689Sbostic return(1); 47032689Sbostic } 47132689Sbostic } 47232689Sbostic return(0); 47332689Sbostic } 47432689Sbostic 47532689Sbostic is_pack_letter(c, mask) 47632689Sbostic short *c; 47732689Sbostic unsigned short *mask; 47832689Sbostic { 47932689Sbostic if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') || 48032689Sbostic (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) { 48132689Sbostic switch(*c) { 48232689Sbostic case '?': 48332689Sbostic *mask = SCROL; 48432689Sbostic break; 48532689Sbostic case '!': 48632689Sbostic *mask = POTION; 48732689Sbostic break; 48832689Sbostic case ':': 48932689Sbostic *mask = FOOD; 49032689Sbostic break; 49132689Sbostic case ')': 49232689Sbostic *mask = WEAPON; 49332689Sbostic break; 49432689Sbostic case ']': 49532689Sbostic *mask = ARMOR; 49632689Sbostic break; 49732689Sbostic case '/': 49832689Sbostic *mask = WAND; 49932689Sbostic break; 50032689Sbostic case '=': 50132689Sbostic *mask = RING; 50232689Sbostic break; 50332689Sbostic case ',': 50432689Sbostic *mask = AMULET; 50532689Sbostic break; 50632689Sbostic } 50732689Sbostic *c = LIST; 50832689Sbostic return(1); 50932689Sbostic } 51032689Sbostic return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST)); 51132689Sbostic } 51232689Sbostic 51332689Sbostic has_amulet() 51432689Sbostic { 51532689Sbostic return(mask_pack(&rogue.pack, AMULET)); 51632689Sbostic } 51732689Sbostic 51832689Sbostic kick_into_pack() 51932689Sbostic { 52032689Sbostic object *obj; 52132689Sbostic char desc[DCOLS]; 52232689Sbostic short n, stat; 52332689Sbostic 52432689Sbostic if (!(dungeon[rogue.row][rogue.col] & OBJECT)) { 52532689Sbostic message("nothing here", 0); 52632689Sbostic } else { 52732689Sbostic if (obj = pick_up(rogue.row, rogue.col, &stat)) { 52832689Sbostic get_desc(obj, desc); 52932689Sbostic if (obj->what_is == GOLD) { 53032689Sbostic message(desc, 0); 53132689Sbostic free_object(obj); 53232689Sbostic } else { 53332689Sbostic n = strlen(desc); 53432689Sbostic desc[n] = '('; 53532689Sbostic desc[n+1] = obj->ichar; 53632689Sbostic desc[n+2] = ')'; 53732689Sbostic desc[n+3] = 0; 53832689Sbostic message(desc, 0); 53932689Sbostic } 54032689Sbostic } 54132689Sbostic if (obj || (!stat)) { 54232689Sbostic (void) reg_move(); 54332689Sbostic } 54432689Sbostic } 54532689Sbostic } 546