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 * 8*42601Sbostic * %sccs.include.redist.c% 936704Sbostic */ 1036704Sbostic 1136704Sbostic #ifndef lint 12*42601Sbostic static char sccsid[] = "@(#)pack.c 5.3 (Berkeley) 06/01/90"; 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(); 27032689Sbostic inventory(&rogue.pack, mask); 27132689Sbostic } else { 27232689Sbostic break; 27332689Sbostic } 27432689Sbostic mask = tmask; 27532689Sbostic } 27632689Sbostic check_message(); 27732689Sbostic return(ch); 27832689Sbostic } 27932689Sbostic 28032689Sbostic take_off() 28132689Sbostic { 28232689Sbostic char desc[DCOLS]; 28332689Sbostic object *obj; 28432689Sbostic 28532689Sbostic if (rogue.armor) { 28632689Sbostic if (rogue.armor->is_cursed) { 28732689Sbostic message(curse_message, 0); 28832689Sbostic } else { 28932689Sbostic mv_aquatars(); 29032689Sbostic obj = rogue.armor; 29132689Sbostic unwear(rogue.armor); 29232689Sbostic (void) strcpy(desc, "was wearing "); 29332689Sbostic get_desc(obj, desc+12); 29432689Sbostic message(desc, 0); 29532689Sbostic print_stats(STAT_ARMOR); 29632689Sbostic (void) reg_move(); 29732689Sbostic } 29832689Sbostic } else { 29932689Sbostic message("not wearing any", 0); 30032689Sbostic } 30132689Sbostic } 30232689Sbostic 30332689Sbostic wear() 30432689Sbostic { 30532689Sbostic short ch; 30632689Sbostic register object *obj; 30732689Sbostic char desc[DCOLS]; 30832689Sbostic 30932689Sbostic if (rogue.armor) { 31032689Sbostic message("your already wearing some", 0); 31132689Sbostic return; 31232689Sbostic } 31332689Sbostic ch = pack_letter("wear what?", ARMOR); 31432689Sbostic 31532689Sbostic if (ch == CANCEL) { 31632689Sbostic return; 31732689Sbostic } 31832689Sbostic if (!(obj = get_letter_object(ch))) { 31932689Sbostic message("no such item.", 0); 32032689Sbostic return; 32132689Sbostic } 32232689Sbostic if (obj->what_is != ARMOR) { 32332689Sbostic message("you can't wear that", 0); 32432689Sbostic return; 32532689Sbostic } 32632689Sbostic obj->identified = 1; 32732689Sbostic (void) strcpy(desc, "wearing "); 32832689Sbostic get_desc(obj, desc + 8); 32932689Sbostic message(desc, 0); 33032689Sbostic do_wear(obj); 33132689Sbostic print_stats(STAT_ARMOR); 33232689Sbostic (void) reg_move(); 33332689Sbostic } 33432689Sbostic 33532689Sbostic unwear(obj) 33632689Sbostic object *obj; 33732689Sbostic { 33832689Sbostic if (obj) { 33932689Sbostic obj->in_use_flags &= (~BEING_WORN); 34032689Sbostic } 34132689Sbostic rogue.armor = (object *) 0; 34232689Sbostic } 34332689Sbostic 34432689Sbostic do_wear(obj) 34532689Sbostic object *obj; 34632689Sbostic { 34732689Sbostic rogue.armor = obj; 34832689Sbostic obj->in_use_flags |= BEING_WORN; 34932689Sbostic obj->identified = 1; 35032689Sbostic } 35132689Sbostic 35232689Sbostic wield() 35332689Sbostic { 35432689Sbostic short ch; 35532689Sbostic register object *obj; 35632689Sbostic char desc[DCOLS]; 35732689Sbostic 35832689Sbostic if (rogue.weapon && rogue.weapon->is_cursed) { 35932689Sbostic message(curse_message, 0); 36032689Sbostic return; 36132689Sbostic } 36232689Sbostic ch = pack_letter("wield what?", WEAPON); 36332689Sbostic 36432689Sbostic if (ch == CANCEL) { 36532689Sbostic return; 36632689Sbostic } 36732689Sbostic if (!(obj = get_letter_object(ch))) { 36832689Sbostic message("No such item.", 0); 36932689Sbostic return; 37032689Sbostic } 37132689Sbostic if (obj->what_is & (ARMOR | RING)) { 37232689Sbostic sprintf(desc, "you can't wield %s", 37332689Sbostic ((obj->what_is == ARMOR) ? "armor" : "rings")); 37432689Sbostic message(desc, 0); 37532689Sbostic return; 37632689Sbostic } 37732689Sbostic if (obj->in_use_flags & BEING_WIELDED) { 37832689Sbostic message("in use", 0); 37932689Sbostic } else { 38032689Sbostic unwield(rogue.weapon); 38132689Sbostic (void) strcpy(desc, "wielding "); 38232689Sbostic get_desc(obj, desc + 9); 38332689Sbostic message(desc, 0); 38432689Sbostic do_wield(obj); 38532689Sbostic (void) reg_move(); 38632689Sbostic } 38732689Sbostic } 38832689Sbostic 38932689Sbostic do_wield(obj) 39032689Sbostic object *obj; 39132689Sbostic { 39232689Sbostic rogue.weapon = obj; 39332689Sbostic obj->in_use_flags |= BEING_WIELDED; 39432689Sbostic } 39532689Sbostic 39632689Sbostic unwield(obj) 39732689Sbostic object *obj; 39832689Sbostic { 39932689Sbostic if (obj) { 40032689Sbostic obj->in_use_flags &= (~BEING_WIELDED); 40132689Sbostic } 40232689Sbostic rogue.weapon = (object *) 0; 40332689Sbostic } 40432689Sbostic 40532689Sbostic call_it() 40632689Sbostic { 40732689Sbostic short ch; 40832689Sbostic register object *obj; 40932689Sbostic struct id *id_table; 41032689Sbostic char buf[MAX_TITLE_LENGTH+2]; 41132689Sbostic 41232689Sbostic ch = pack_letter("call what?", (SCROL | POTION | WAND | RING)); 41332689Sbostic 41432689Sbostic if (ch == CANCEL) { 41532689Sbostic return; 41632689Sbostic } 41732689Sbostic if (!(obj = get_letter_object(ch))) { 41832689Sbostic message("no such item.", 0); 41932689Sbostic return; 42032689Sbostic } 42132689Sbostic if (!(obj->what_is & (SCROL | POTION | WAND | RING))) { 42232689Sbostic message("surely you already know what that's called", 0); 42332689Sbostic return; 42432689Sbostic } 42532689Sbostic id_table = get_id_table(obj); 42632689Sbostic 42732689Sbostic if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) { 42832689Sbostic id_table[obj->which_kind].id_status = CALLED; 42932689Sbostic (void) strcpy(id_table[obj->which_kind].title, buf); 43032689Sbostic } 43132689Sbostic } 43232689Sbostic 43332689Sbostic pack_count(new_obj) 43432689Sbostic object *new_obj; 43532689Sbostic { 43632689Sbostic object *obj; 43732689Sbostic short count = 0; 43832689Sbostic 43932689Sbostic obj = rogue.pack.next_object; 44032689Sbostic 44132689Sbostic while (obj) { 44232689Sbostic if (obj->what_is != WEAPON) { 44332689Sbostic count += obj->quantity; 44432689Sbostic } else if (!new_obj) { 44532689Sbostic count++; 44632689Sbostic } else if ((new_obj->what_is != WEAPON) || 44732689Sbostic ((obj->which_kind != ARROW) && 44832689Sbostic (obj->which_kind != DAGGER) && 44932689Sbostic (obj->which_kind != DART) && 45032689Sbostic (obj->which_kind != SHURIKEN)) || 45132689Sbostic (new_obj->which_kind != obj->which_kind) || 45232689Sbostic (obj->quiver != new_obj->quiver)) { 45332689Sbostic count++; 45432689Sbostic } 45532689Sbostic obj = obj->next_object; 45632689Sbostic } 45732689Sbostic return(count); 45832689Sbostic } 45932689Sbostic 46032689Sbostic boolean 46132689Sbostic mask_pack(pack, mask) 46232689Sbostic object *pack; 46332689Sbostic unsigned short mask; 46432689Sbostic { 46532689Sbostic while (pack->next_object) { 46632689Sbostic pack = pack->next_object; 46732689Sbostic if (pack->what_is & mask) { 46832689Sbostic return(1); 46932689Sbostic } 47032689Sbostic } 47132689Sbostic return(0); 47232689Sbostic } 47332689Sbostic 47432689Sbostic is_pack_letter(c, mask) 47532689Sbostic short *c; 47632689Sbostic unsigned short *mask; 47732689Sbostic { 47832689Sbostic if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') || 47932689Sbostic (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) { 48032689Sbostic switch(*c) { 48132689Sbostic case '?': 48232689Sbostic *mask = SCROL; 48332689Sbostic break; 48432689Sbostic case '!': 48532689Sbostic *mask = POTION; 48632689Sbostic break; 48732689Sbostic case ':': 48832689Sbostic *mask = FOOD; 48932689Sbostic break; 49032689Sbostic case ')': 49132689Sbostic *mask = WEAPON; 49232689Sbostic break; 49332689Sbostic case ']': 49432689Sbostic *mask = ARMOR; 49532689Sbostic break; 49632689Sbostic case '/': 49732689Sbostic *mask = WAND; 49832689Sbostic break; 49932689Sbostic case '=': 50032689Sbostic *mask = RING; 50132689Sbostic break; 50232689Sbostic case ',': 50332689Sbostic *mask = AMULET; 50432689Sbostic break; 50532689Sbostic } 50632689Sbostic *c = LIST; 50732689Sbostic return(1); 50832689Sbostic } 50932689Sbostic return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST)); 51032689Sbostic } 51132689Sbostic 51232689Sbostic has_amulet() 51332689Sbostic { 51432689Sbostic return(mask_pack(&rogue.pack, AMULET)); 51532689Sbostic } 51632689Sbostic 51732689Sbostic kick_into_pack() 51832689Sbostic { 51932689Sbostic object *obj; 52032689Sbostic char desc[DCOLS]; 52132689Sbostic short n, stat; 52232689Sbostic 52332689Sbostic if (!(dungeon[rogue.row][rogue.col] & OBJECT)) { 52432689Sbostic message("nothing here", 0); 52532689Sbostic } else { 52632689Sbostic if (obj = pick_up(rogue.row, rogue.col, &stat)) { 52732689Sbostic get_desc(obj, desc); 52832689Sbostic if (obj->what_is == GOLD) { 52932689Sbostic message(desc, 0); 53032689Sbostic free_object(obj); 53132689Sbostic } else { 53232689Sbostic n = strlen(desc); 53332689Sbostic desc[n] = '('; 53432689Sbostic desc[n+1] = obj->ichar; 53532689Sbostic desc[n+2] = ')'; 53632689Sbostic desc[n+3] = 0; 53732689Sbostic message(desc, 0); 53832689Sbostic } 53932689Sbostic } 54032689Sbostic if (obj || (!stat)) { 54132689Sbostic (void) reg_move(); 54232689Sbostic } 54332689Sbostic } 54432689Sbostic } 545