date and time created 88/10/19 15:51:23 by bostic
[unix-history] / usr / src / games / rogue / pack.c
CommitLineData
b3afadef
KB
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
14static char sccsid[] = "@(#)pack.c 5.1 (Berkeley) %G%";
15#endif /* not lint */
16
17#include "rogue.h"
18
19char *curse_message = "you can't, it appears to be cursed";
20
21extern short levitate;
22
23object *
24add_to_pack(obj, pack, condense)
25object *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
51take_from_pack(obj, pack)
52object *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
64object *
65pick_up(row, col, status)
66short *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
111drop()
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
173object *
174check_duplicate(obj, pack)
175object *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
207next_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
229wait_for_ack()
230{
231 while (rgetchar() != ' ') ;
232}
233
234pack_letter(prompt, mask)
235char *prompt;
236unsigned 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
270take_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
293wear()
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
325unwear(obj)
326object *obj;
327{
328 if (obj) {
329 obj->in_use_flags &= (~BEING_WORN);
330 }
331 rogue.armor = (object *) 0;
332}
333
334do_wear(obj)
335object *obj;
336{
337 rogue.armor = obj;
338 obj->in_use_flags |= BEING_WORN;
339 obj->identified = 1;
340}
341
342wield()
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
379do_wield(obj)
380object *obj;
381{
382 rogue.weapon = obj;
383 obj->in_use_flags |= BEING_WIELDED;
384}
385
386unwield(obj)
387object *obj;
388{
389 if (obj) {
390 obj->in_use_flags &= (~BEING_WIELDED);
391 }
392 rogue.weapon = (object *) 0;
393}
394
395call_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
423pack_count(new_obj)
424object *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
450boolean
451mask_pack(pack, mask)
452object *pack;
453unsigned 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
464is_pack_letter(c, mask)
465short *c;
466unsigned 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
502has_amulet()
503{
504 return(mask_pack(&rogue.pack, AMULET));
505}
506
507kick_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}