]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/pack.c
mark non-returning functions (PR#6144 by Joseph Myers <jsm28@cam.ac.uk>)
[bsdgames-darwin.git] / rogue / pack.c
1 /* $NetBSD: pack.c,v 1.5 1998/09/11 14:10:39 hubertf Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)pack.c 8.1 (Berkeley) 5/31/93";
43 #else
44 __RCSID("$NetBSD: pack.c,v 1.5 1998/09/11 14:10:39 hubertf Exp $");
45 #endif
46 #endif /* not lint */
47
48 /*
49 * pack.c
50 *
51 * This source herein may be modified and/or distributed by anybody who
52 * so desires, with the following restrictions:
53 * 1.) No portion of this notice shall be removed.
54 * 2.) Credit shall not be taken for the creation of this source.
55 * 3.) This code is not to be traded, sold, or used for personal
56 * gain or profit.
57 *
58 */
59
60 #include "rogue.h"
61
62 char *curse_message = "you can't, it appears to be cursed";
63
64 object *
65 add_to_pack(obj, pack, condense)
66 object *obj, *pack;
67 int condense;
68 {
69 object *op;
70
71 if (condense) {
72 if ((op = check_duplicate(obj, pack)) != NULL) {
73 free_object(obj);
74 return(op);
75 } else {
76 obj->ichar = next_avail_ichar();
77 }
78 }
79 if (pack->next_object == 0) {
80 pack->next_object = obj;
81 } else {
82 op = pack->next_object;
83
84 while (op->next_object) {
85 op = op->next_object;
86 }
87 op->next_object = obj;
88 }
89 obj->next_object = 0;
90 return(obj);
91 }
92
93 void
94 take_from_pack(obj, pack)
95 object *obj, *pack;
96 {
97 while (pack->next_object != obj) {
98 pack = pack->next_object;
99 }
100 pack->next_object = pack->next_object->next_object;
101 }
102
103 /* Note: *status is set to 0 if the rogue attempts to pick up a scroll
104 * of scare-monster and it turns to dust. *status is otherwise set to 1.
105 */
106
107 object *
108 pick_up(row, col, status)
109 short *status;
110 int row, col;
111 {
112 object *obj;
113
114 *status = 1;
115
116 if (levitate) {
117 message("you're floating in the air!", 0);
118 return((object *) 0);
119 }
120 obj = object_at(&level_objects, row, col);
121 if (!obj) {
122 message("pick_up(): inconsistent", 1);
123 return(obj);
124 }
125 if ( (obj->what_is == SCROL) &&
126 (obj->which_kind == SCARE_MONSTER) &&
127 obj->picked_up) {
128 message("the scroll turns to dust as you pick it up", 0);
129 dungeon[row][col] &= (~OBJECT);
130 vanish(obj, 0, &level_objects);
131 *status = 0;
132 if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) {
133 id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED;
134 }
135 return((object *) 0);
136 }
137 if (obj->what_is == GOLD) {
138 rogue.gold += obj->quantity;
139 dungeon[row][col] &= ~(OBJECT);
140 take_from_pack(obj, &level_objects);
141 print_stats(STAT_GOLD);
142 return(obj); /* obj will be free_object()ed in caller */
143 }
144 if (pack_count(obj) >= MAX_PACK_COUNT) {
145 message("pack too full", 1);
146 return((object *) 0);
147 }
148 dungeon[row][col] &= ~(OBJECT);
149 take_from_pack(obj, &level_objects);
150 obj = add_to_pack(obj, &rogue.pack, 1);
151 obj->picked_up = 1;
152 return(obj);
153 }
154
155 void
156 drop()
157 {
158 object *obj, *new;
159 short ch;
160 char desc[DCOLS];
161
162 if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) {
163 message("there's already something there", 0);
164 return;
165 }
166 if (!rogue.pack.next_object) {
167 message("you have nothing to drop", 0);
168 return;
169 }
170 if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) {
171 return;
172 }
173 if (!(obj = get_letter_object(ch))) {
174 message("no such item.", 0);
175 return;
176 }
177 if (obj->in_use_flags & BEING_WIELDED) {
178 if (obj->is_cursed) {
179 message(curse_message, 0);
180 return;
181 }
182 unwield(rogue.weapon);
183 } else if (obj->in_use_flags & BEING_WORN) {
184 if (obj->is_cursed) {
185 message(curse_message, 0);
186 return;
187 }
188 mv_aquatars();
189 unwear(rogue.armor);
190 print_stats(STAT_ARMOR);
191 } else if (obj->in_use_flags & ON_EITHER_HAND) {
192 if (obj->is_cursed) {
193 message(curse_message, 0);
194 return;
195 }
196 un_put_on(obj);
197 }
198 obj->row = rogue.row;
199 obj->col = rogue.col;
200
201 if ((obj->quantity > 1) && (obj->what_is != WEAPON)) {
202 obj->quantity--;
203 new = alloc_object();
204 *new = *obj;
205 new->quantity = 1;
206 obj = new;
207 } else {
208 obj->ichar = 'L';
209 take_from_pack(obj, &rogue.pack);
210 }
211 place_at(obj, rogue.row, rogue.col);
212 (void) strcpy(desc, "dropped ");
213 get_desc(obj, desc+8);
214 message(desc, 0);
215 (void) reg_move();
216 }
217
218 object *
219 check_duplicate(obj, pack)
220 object *obj, *pack;
221 {
222 object *op;
223
224 if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) {
225 return(0);
226 }
227 if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) {
228 return(0);
229 }
230 op = pack->next_object;
231
232 while (op) {
233 if ((op->what_is == obj->what_is) &&
234 (op->which_kind == obj->which_kind)) {
235
236 if ((obj->what_is != WEAPON) ||
237 ((obj->what_is == WEAPON) &&
238 ((obj->which_kind == ARROW) ||
239 (obj->which_kind == DAGGER) ||
240 (obj->which_kind == DART) ||
241 (obj->which_kind == SHURIKEN)) &&
242 (obj->quiver == op->quiver))) {
243 op->quantity += obj->quantity;
244 return(op);
245 }
246 }
247 op = op->next_object;
248 }
249 return(0);
250 }
251
252 short
253 next_avail_ichar()
254 {
255 object *obj;
256 int i;
257 boolean ichars[26];
258
259 for (i = 0; i < 26; i++) {
260 ichars[i] = 0;
261 }
262 obj = rogue.pack.next_object;
263 while (obj) {
264 ichars[(obj->ichar - 'a')] = 1;
265 obj = obj->next_object;
266 }
267 for (i = 0; i < 26; i++) {
268 if (!ichars[i]) {
269 return(i + 'a');
270 }
271 }
272 return('?');
273 }
274
275 void
276 wait_for_ack()
277 {
278 while (rgetchar() != ' ') ;
279 }
280
281 short
282 pack_letter(prompt, mask)
283 char *prompt;
284 unsigned short mask;
285 {
286 short ch;
287 unsigned short tmask = mask;
288
289 if (!mask_pack(&rogue.pack, mask)) {
290 message("nothing appropriate", 0);
291 return(CANCEL);
292 }
293 for (;;) {
294
295 message(prompt, 0);
296
297 for (;;) {
298 ch = rgetchar();
299 if (!is_pack_letter(&ch, &mask)) {
300 sound_bell();
301 } else {
302 break;
303 }
304 }
305
306 if (ch == LIST) {
307 check_message();
308 mask = tmask;
309 inventory(&rogue.pack, mask);
310 } else {
311 break;
312 }
313 mask = tmask;
314 }
315 check_message();
316 return(ch);
317 }
318
319 void
320 take_off()
321 {
322 char desc[DCOLS];
323 object *obj;
324
325 if (rogue.armor) {
326 if (rogue.armor->is_cursed) {
327 message(curse_message, 0);
328 } else {
329 mv_aquatars();
330 obj = rogue.armor;
331 unwear(rogue.armor);
332 (void) strcpy(desc, "was wearing ");
333 get_desc(obj, desc+12);
334 message(desc, 0);
335 print_stats(STAT_ARMOR);
336 (void) reg_move();
337 }
338 } else {
339 message("not wearing any", 0);
340 }
341 }
342
343 void
344 wear()
345 {
346 short ch;
347 object *obj;
348 char desc[DCOLS];
349
350 if (rogue.armor) {
351 message("your already wearing some", 0);
352 return;
353 }
354 ch = pack_letter("wear what?", ARMOR);
355
356 if (ch == CANCEL) {
357 return;
358 }
359 if (!(obj = get_letter_object(ch))) {
360 message("no such item.", 0);
361 return;
362 }
363 if (obj->what_is != ARMOR) {
364 message("you can't wear that", 0);
365 return;
366 }
367 obj->identified = 1;
368 (void) strcpy(desc, "wearing ");
369 get_desc(obj, desc + 8);
370 message(desc, 0);
371 do_wear(obj);
372 print_stats(STAT_ARMOR);
373 (void) reg_move();
374 }
375
376 void
377 unwear(obj)
378 object *obj;
379 {
380 if (obj) {
381 obj->in_use_flags &= (~BEING_WORN);
382 }
383 rogue.armor = (object *) 0;
384 }
385
386 void
387 do_wear(obj)
388 object *obj;
389 {
390 rogue.armor = obj;
391 obj->in_use_flags |= BEING_WORN;
392 obj->identified = 1;
393 }
394
395 void
396 wield()
397 {
398 short ch;
399 object *obj;
400 char desc[DCOLS];
401
402 if (rogue.weapon && rogue.weapon->is_cursed) {
403 message(curse_message, 0);
404 return;
405 }
406 ch = pack_letter("wield what?", WEAPON);
407
408 if (ch == CANCEL) {
409 return;
410 }
411 if (!(obj = get_letter_object(ch))) {
412 message("No such item.", 0);
413 return;
414 }
415 if (obj->what_is & (ARMOR | RING)) {
416 sprintf(desc, "you can't wield %s",
417 ((obj->what_is == ARMOR) ? "armor" : "rings"));
418 message(desc, 0);
419 return;
420 }
421 if (obj->in_use_flags & BEING_WIELDED) {
422 message("in use", 0);
423 } else {
424 unwield(rogue.weapon);
425 (void) strcpy(desc, "wielding ");
426 get_desc(obj, desc + 9);
427 message(desc, 0);
428 do_wield(obj);
429 (void) reg_move();
430 }
431 }
432
433 void
434 do_wield(obj)
435 object *obj;
436 {
437 rogue.weapon = obj;
438 obj->in_use_flags |= BEING_WIELDED;
439 }
440
441 void
442 unwield(obj)
443 object *obj;
444 {
445 if (obj) {
446 obj->in_use_flags &= (~BEING_WIELDED);
447 }
448 rogue.weapon = (object *) 0;
449 }
450
451 void
452 call_it()
453 {
454 short ch;
455 object *obj;
456 struct id *id_table;
457 char buf[MAX_TITLE_LENGTH+2];
458
459 ch = pack_letter("call what?", (SCROL | POTION | WAND | RING));
460
461 if (ch == CANCEL) {
462 return;
463 }
464 if (!(obj = get_letter_object(ch))) {
465 message("no such item.", 0);
466 return;
467 }
468 if (!(obj->what_is & (SCROL | POTION | WAND | RING))) {
469 message("surely you already know what that's called", 0);
470 return;
471 }
472 id_table = get_id_table(obj);
473
474 if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) {
475 id_table[obj->which_kind].id_status = CALLED;
476 (void) strcpy(id_table[obj->which_kind].title, buf);
477 }
478 }
479
480 short
481 pack_count(new_obj)
482 object *new_obj;
483 {
484 object *obj;
485 short count = 0;
486
487 obj = rogue.pack.next_object;
488
489 while (obj) {
490 if (obj->what_is != WEAPON) {
491 count += obj->quantity;
492 } else if (!new_obj) {
493 count++;
494 } else if ((new_obj->what_is != WEAPON) ||
495 ((obj->which_kind != ARROW) &&
496 (obj->which_kind != DAGGER) &&
497 (obj->which_kind != DART) &&
498 (obj->which_kind != SHURIKEN)) ||
499 (new_obj->which_kind != obj->which_kind) ||
500 (obj->quiver != new_obj->quiver)) {
501 count++;
502 }
503 obj = obj->next_object;
504 }
505 return(count);
506 }
507
508 boolean
509 mask_pack(pack, mask)
510 object *pack;
511 unsigned short mask;
512 {
513 while (pack->next_object) {
514 pack = pack->next_object;
515 if (pack->what_is & mask) {
516 return(1);
517 }
518 }
519 return(0);
520 }
521
522 boolean
523 is_pack_letter(c, mask)
524 short *c;
525 unsigned short *mask;
526 {
527 if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') ||
528 (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) {
529 switch(*c) {
530 case '?':
531 *mask = SCROL;
532 break;
533 case '!':
534 *mask = POTION;
535 break;
536 case ':':
537 *mask = FOOD;
538 break;
539 case ')':
540 *mask = WEAPON;
541 break;
542 case ']':
543 *mask = ARMOR;
544 break;
545 case '/':
546 *mask = WAND;
547 break;
548 case '=':
549 *mask = RING;
550 break;
551 case ',':
552 *mask = AMULET;
553 break;
554 }
555 *c = LIST;
556 return(1);
557 }
558 return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST));
559 }
560
561 boolean
562 has_amulet()
563 {
564 return(mask_pack(&rogue.pack, AMULET));
565 }
566
567 void
568 kick_into_pack()
569 {
570 object *obj;
571 char desc[DCOLS];
572 short n, stat;
573
574 if (!(dungeon[rogue.row][rogue.col] & OBJECT)) {
575 message("nothing here", 0);
576 } else {
577 if ((obj = pick_up(rogue.row, rogue.col, &stat)) != NULL) {
578 get_desc(obj, desc);
579 if (obj->what_is == GOLD) {
580 message(desc, 0);
581 free_object(obj);
582 } else {
583 n = strlen(desc);
584 desc[n] = '(';
585 desc[n+1] = obj->ichar;
586 desc[n+2] = ')';
587 desc[n+3] = 0;
588 message(desc, 0);
589 }
590 }
591 if (obj || (!stat)) {
592 (void) reg_move();
593 }
594 }
595 }