open the file for writing, not appending; fix from Chris Torek
[unix-history] / usr / src / games / rogue / pack.c
CommitLineData
fc3e88fd
KB
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Timothy C. Stoehr.
7 *
b2e7427f 8 * %sccs.include.redist.c%
fc3e88fd
KB
9 */
10
11#ifndef lint
b2e7427f 12static char sccsid[] = "@(#)pack.c 5.3 (Berkeley) %G%";
fc3e88fd
KB
13#endif /* not lint */
14
b3afadef
KB
15/*
16 * pack.c
17 *
18 * This source herein may be modified and/or distributed by anybody who
19 * so desires, with the following restrictions:
20 * 1.) No portion of this notice shall be removed.
21 * 2.) Credit shall not be taken for the creation of this source.
22 * 3.) This code is not to be traded, sold, or used for personal
23 * gain or profit.
24 *
25 */
26
b3afadef
KB
27#include "rogue.h"
28
29char *curse_message = "you can't, it appears to be cursed";
30
31extern short levitate;
32
33object *
34add_to_pack(obj, pack, condense)
35object *obj, *pack;
36{
37 object *op;
38
39 if (condense) {
40 if (op = check_duplicate(obj, pack)) {
41 free_object(obj);
42 return(op);
43 } else {
44 obj->ichar = next_avail_ichar();
45 }
46 }
47 if (pack->next_object == 0) {
48 pack->next_object = obj;
49 } else {
50 op = pack->next_object;
51
52 while (op->next_object) {
53 op = op->next_object;
54 }
55 op->next_object = obj;
56 }
57 obj->next_object = 0;
58 return(obj);
59}
60
61take_from_pack(obj, pack)
62object *obj, *pack;
63{
64 while (pack->next_object != obj) {
65 pack = pack->next_object;
66 }
67 pack->next_object = pack->next_object->next_object;
68}
69
70/* Note: *status is set to 0 if the rogue attempts to pick up a scroll
71 * of scare-monster and it turns to dust. *status is otherwise set to 1.
72 */
73
74object *
75pick_up(row, col, status)
76short *status;
77{
78 object *obj;
79
80 *status = 1;
81
82 if (levitate) {
83 message("you're floating in the air!", 0);
84 return((object *) 0);
85 }
86 obj = object_at(&level_objects, row, col);
87 if (!obj) {
88 message("pick_up(): inconsistent", 1);
89 return(obj);
90 }
91 if ( (obj->what_is == SCROL) &&
92 (obj->which_kind == SCARE_MONSTER) &&
93 obj->picked_up) {
94 message("the scroll turns to dust as you pick it up", 0);
95 dungeon[row][col] &= (~OBJECT);
96 vanish(obj, 0, &level_objects);
97 *status = 0;
98 if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) {
99 id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED;
100 }
101 return((object *) 0);
102 }
103 if (obj->what_is == GOLD) {
104 rogue.gold += obj->quantity;
105 dungeon[row][col] &= ~(OBJECT);
106 take_from_pack(obj, &level_objects);
107 print_stats(STAT_GOLD);
108 return(obj); /* obj will be free_object()ed in caller */
109 }
110 if (pack_count(obj) >= MAX_PACK_COUNT) {
111 message("pack too full", 1);
112 return((object *) 0);
113 }
114 dungeon[row][col] &= ~(OBJECT);
115 take_from_pack(obj, &level_objects);
116 obj = add_to_pack(obj, &rogue.pack, 1);
117 obj->picked_up = 1;
118 return(obj);
119}
120
121drop()
122{
123 object *obj, *new;
124 short ch;
125 char desc[DCOLS];
126
127 if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) {
128 message("there's already something there", 0);
129 return;
130 }
131 if (!rogue.pack.next_object) {
132 message("you have nothing to drop", 0);
133 return;
134 }
135 if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) {
136 return;
137 }
138 if (!(obj = get_letter_object(ch))) {
139 message("no such item.", 0);
140 return;
141 }
142 if (obj->in_use_flags & BEING_WIELDED) {
143 if (obj->is_cursed) {
144 message(curse_message, 0);
145 return;
146 }
147 unwield(rogue.weapon);
148 } else if (obj->in_use_flags & BEING_WORN) {
149 if (obj->is_cursed) {
150 message(curse_message, 0);
151 return;
152 }
153 mv_aquatars();
154 unwear(rogue.armor);
155 print_stats(STAT_ARMOR);
156 } else if (obj->in_use_flags & ON_EITHER_HAND) {
157 if (obj->is_cursed) {
158 message(curse_message, 0);
159 return;
160 }
161 un_put_on(obj);
162 }
163 obj->row = rogue.row;
164 obj->col = rogue.col;
165
166 if ((obj->quantity > 1) && (obj->what_is != WEAPON)) {
167 obj->quantity--;
168 new = alloc_object();
169 *new = *obj;
170 new->quantity = 1;
171 obj = new;
172 } else {
173 obj->ichar = 'L';
174 take_from_pack(obj, &rogue.pack);
175 }
176 place_at(obj, rogue.row, rogue.col);
177 (void) strcpy(desc, "dropped ");
178 get_desc(obj, desc+8);
179 message(desc, 0);
180 (void) reg_move();
181}
182
183object *
184check_duplicate(obj, pack)
185object *obj, *pack;
186{
187 object *op;
188
189 if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) {
190 return(0);
191 }
192 if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) {
193 return(0);
194 }
195 op = pack->next_object;
196
197 while (op) {
198 if ((op->what_is == obj->what_is) &&
199 (op->which_kind == obj->which_kind)) {
200
201 if ((obj->what_is != WEAPON) ||
202 ((obj->what_is == WEAPON) &&
203 ((obj->which_kind == ARROW) ||
204 (obj->which_kind == DAGGER) ||
205 (obj->which_kind == DART) ||
206 (obj->which_kind == SHURIKEN)) &&
207 (obj->quiver == op->quiver))) {
208 op->quantity += obj->quantity;
209 return(op);
210 }
211 }
212 op = op->next_object;
213 }
214 return(0);
215}
216
217next_avail_ichar()
218{
219 register object *obj;
220 register i;
221 boolean ichars[26];
222
223 for (i = 0; i < 26; i++) {
224 ichars[i] = 0;
225 }
226 obj = rogue.pack.next_object;
227 while (obj) {
228 ichars[(obj->ichar - 'a')] = 1;
229 obj = obj->next_object;
230 }
231 for (i = 0; i < 26; i++) {
232 if (!ichars[i]) {
233 return(i + 'a');
234 }
235 }
236 return('?');
237}
238
239wait_for_ack()
240{
241 while (rgetchar() != ' ') ;
242}
243
244pack_letter(prompt, mask)
245char *prompt;
246unsigned short mask;
247{
248 short ch;
249 unsigned short tmask = mask;
250
251 if (!mask_pack(&rogue.pack, mask)) {
252 message("nothing appropriate", 0);
253 return(CANCEL);
254 }
255 for (;;) {
256
257 message(prompt, 0);
258
259 for (;;) {
260 ch = rgetchar();
261 if (!is_pack_letter(&ch, &mask)) {
262 sound_bell();
263 } else {
264 break;
265 }
266 }
267
268 if (ch == LIST) {
269 check_message();
270 inventory(&rogue.pack, mask);
271 } else {
272 break;
273 }
274 mask = tmask;
275 }
276 check_message();
277 return(ch);
278}
279
280take_off()
281{
282 char desc[DCOLS];
283 object *obj;
284
285 if (rogue.armor) {
286 if (rogue.armor->is_cursed) {
287 message(curse_message, 0);
288 } else {
289 mv_aquatars();
290 obj = rogue.armor;
291 unwear(rogue.armor);
292 (void) strcpy(desc, "was wearing ");
293 get_desc(obj, desc+12);
294 message(desc, 0);
295 print_stats(STAT_ARMOR);
296 (void) reg_move();
297 }
298 } else {
299 message("not wearing any", 0);
300 }
301}
302
303wear()
304{
305 short ch;
306 register object *obj;
307 char desc[DCOLS];
308
309 if (rogue.armor) {
310 message("your already wearing some", 0);
311 return;
312 }
313 ch = pack_letter("wear what?", ARMOR);
314
315 if (ch == CANCEL) {
316 return;
317 }
318 if (!(obj = get_letter_object(ch))) {
319 message("no such item.", 0);
320 return;
321 }
322 if (obj->what_is != ARMOR) {
323 message("you can't wear that", 0);
324 return;
325 }
326 obj->identified = 1;
327 (void) strcpy(desc, "wearing ");
328 get_desc(obj, desc + 8);
329 message(desc, 0);
330 do_wear(obj);
331 print_stats(STAT_ARMOR);
332 (void) reg_move();
333}
334
335unwear(obj)
336object *obj;
337{
338 if (obj) {
339 obj->in_use_flags &= (~BEING_WORN);
340 }
341 rogue.armor = (object *) 0;
342}
343
344do_wear(obj)
345object *obj;
346{
347 rogue.armor = obj;
348 obj->in_use_flags |= BEING_WORN;
349 obj->identified = 1;
350}
351
352wield()
353{
354 short ch;
355 register object *obj;
356 char desc[DCOLS];
357
358 if (rogue.weapon && rogue.weapon->is_cursed) {
359 message(curse_message, 0);
360 return;
361 }
362 ch = pack_letter("wield what?", WEAPON);
363
364 if (ch == CANCEL) {
365 return;
366 }
367 if (!(obj = get_letter_object(ch))) {
368 message("No such item.", 0);
369 return;
370 }
371 if (obj->what_is & (ARMOR | RING)) {
372 sprintf(desc, "you can't wield %s",
373 ((obj->what_is == ARMOR) ? "armor" : "rings"));
374 message(desc, 0);
375 return;
376 }
377 if (obj->in_use_flags & BEING_WIELDED) {
378 message("in use", 0);
379 } else {
380 unwield(rogue.weapon);
381 (void) strcpy(desc, "wielding ");
382 get_desc(obj, desc + 9);
383 message(desc, 0);
384 do_wield(obj);
385 (void) reg_move();
386 }
387}
388
389do_wield(obj)
390object *obj;
391{
392 rogue.weapon = obj;
393 obj->in_use_flags |= BEING_WIELDED;
394}
395
396unwield(obj)
397object *obj;
398{
399 if (obj) {
400 obj->in_use_flags &= (~BEING_WIELDED);
401 }
402 rogue.weapon = (object *) 0;
403}
404
405call_it()
406{
407 short ch;
408 register object *obj;
409 struct id *id_table;
410 char buf[MAX_TITLE_LENGTH+2];
411
412 ch = pack_letter("call what?", (SCROL | POTION | WAND | RING));
413
414 if (ch == CANCEL) {
415 return;
416 }
417 if (!(obj = get_letter_object(ch))) {
418 message("no such item.", 0);
419 return;
420 }
421 if (!(obj->what_is & (SCROL | POTION | WAND | RING))) {
422 message("surely you already know what that's called", 0);
423 return;
424 }
425 id_table = get_id_table(obj);
426
427 if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) {
428 id_table[obj->which_kind].id_status = CALLED;
429 (void) strcpy(id_table[obj->which_kind].title, buf);
430 }
431}
432
433pack_count(new_obj)
434object *new_obj;
435{
436 object *obj;
437 short count = 0;
438
439 obj = rogue.pack.next_object;
440
441 while (obj) {
442 if (obj->what_is != WEAPON) {
443 count += obj->quantity;
444 } else if (!new_obj) {
445 count++;
446 } else if ((new_obj->what_is != WEAPON) ||
447 ((obj->which_kind != ARROW) &&
448 (obj->which_kind != DAGGER) &&
449 (obj->which_kind != DART) &&
450 (obj->which_kind != SHURIKEN)) ||
451 (new_obj->which_kind != obj->which_kind) ||
452 (obj->quiver != new_obj->quiver)) {
453 count++;
454 }
455 obj = obj->next_object;
456 }
457 return(count);
458}
459
460boolean
461mask_pack(pack, mask)
462object *pack;
463unsigned short mask;
464{
465 while (pack->next_object) {
466 pack = pack->next_object;
467 if (pack->what_is & mask) {
468 return(1);
469 }
470 }
471 return(0);
472}
473
474is_pack_letter(c, mask)
475short *c;
476unsigned short *mask;
477{
478 if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') ||
479 (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) {
480 switch(*c) {
481 case '?':
482 *mask = SCROL;
483 break;
484 case '!':
485 *mask = POTION;
486 break;
487 case ':':
488 *mask = FOOD;
489 break;
490 case ')':
491 *mask = WEAPON;
492 break;
493 case ']':
494 *mask = ARMOR;
495 break;
496 case '/':
497 *mask = WAND;
498 break;
499 case '=':
500 *mask = RING;
501 break;
502 case ',':
503 *mask = AMULET;
504 break;
505 }
506 *c = LIST;
507 return(1);
508 }
509 return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST));
510}
511
512has_amulet()
513{
514 return(mask_pack(&rogue.pack, AMULET));
515}
516
517kick_into_pack()
518{
519 object *obj;
520 char desc[DCOLS];
521 short n, stat;
522
523 if (!(dungeon[rogue.row][rogue.col] & OBJECT)) {
524 message("nothing here", 0);
525 } else {
526 if (obj = pick_up(rogue.row, rogue.col, &stat)) {
527 get_desc(obj, desc);
528 if (obj->what_is == GOLD) {
529 message(desc, 0);
530 free_object(obj);
531 } else {
532 n = strlen(desc);
533 desc[n] = '(';
534 desc[n+1] = obj->ichar;
535 desc[n+2] = ')';
536 desc[n+3] = 0;
537 message(desc, 0);
538 }
539 }
540 if (obj || (!stat)) {
541 (void) reg_move();
542 }
543 }
544}