132689Sbostic /*
2*60842Sbostic * Copyright (c) 1988, 1993
3*60842Sbostic * The Regents of the University of California. 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*60842Sbostic static char sccsid[] = "@(#)pack.c 8.1 (Berkeley) 05/31/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 *
add_to_pack(obj,pack,condense)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
take_from_pack(obj,pack)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 *
pick_up(row,col,status)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
drop()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 *
check_duplicate(obj,pack)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
next_avail_ichar()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
wait_for_ack()23932689Sbostic wait_for_ack()
24032689Sbostic {
24132689Sbostic while (rgetchar() != ' ') ;
24232689Sbostic }
24332689Sbostic
pack_letter(prompt,mask)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();
27058506Sbostic mask = tmask;
27132689Sbostic inventory(&rogue.pack, mask);
27232689Sbostic } else {
27332689Sbostic break;
27432689Sbostic }
27532689Sbostic mask = tmask;
27632689Sbostic }
27732689Sbostic check_message();
27832689Sbostic return(ch);
27932689Sbostic }
28032689Sbostic
take_off()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
wear()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
unwear(obj)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
do_wear(obj)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
wield()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
do_wield(obj)39032689Sbostic do_wield(obj)
39132689Sbostic object *obj;
39232689Sbostic {
39332689Sbostic rogue.weapon = obj;
39432689Sbostic obj->in_use_flags |= BEING_WIELDED;
39532689Sbostic }
39632689Sbostic
unwield(obj)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
call_it()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
pack_count(new_obj)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
mask_pack(pack,mask)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
is_pack_letter(c,mask)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
has_amulet()51332689Sbostic has_amulet()
51432689Sbostic {
51532689Sbostic return(mask_pack(&rogue.pack, AMULET));
51632689Sbostic }
51732689Sbostic
kick_into_pack()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