]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - rogue/use.c
don't use char values for functions that can return -1; chars are not always
[bsdgames-darwin.git] / rogue / use.c
1 /* $NetBSD: use.c,v 1.9 2008/01/14 03:50:03 dholland 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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)use.c 8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: use.c,v 1.9 2008/01/14 03:50:03 dholland Exp $");
41 #endif
42 #endif /* not lint */
43
44 /*
45 * use.c
46 *
47 * This source herein may be modified and/or distributed by anybody who
48 * so desires, with the following restrictions:
49 * 1.) No portion of this notice shall be removed.
50 * 2.) Credit shall not be taken for the creation of this source.
51 * 3.) This code is not to be traded, sold, or used for personal
52 * gain or profit.
53 *
54 */
55
56 #include "rogue.h"
57
58 short halluc = 0;
59 short blind = 0;
60 short confused = 0;
61 short levitate = 0;
62 short haste_self = 0;
63 boolean see_invisible = 0;
64 short extra_hp = 0;
65 boolean detect_monster = 0;
66 boolean con_mon = 0;
67
68 static const char strange_feeling[] =
69 "you have a strange feeling for a moment, then it passes";
70
71 void
72 quaff(void)
73 {
74 short ch;
75 object *obj;
76
77 ch = pack_letter("quaff what?", POTION);
78
79 if (ch == CANCEL) {
80 return;
81 }
82 if (!(obj = get_letter_object(ch))) {
83 messagef(0, "no such item.");
84 return;
85 }
86 if (obj->what_is != POTION) {
87 messagef(0, "you can't drink that");
88 return;
89 }
90 switch(obj->which_kind) {
91 case INCREASE_STRENGTH:
92 messagef(0, "you feel stronger now, what bulging muscles!");
93 rogue.str_current++;
94 if (rogue.str_current > rogue.str_max) {
95 rogue.str_max = rogue.str_current;
96 }
97 break;
98 case RESTORE_STRENGTH:
99 rogue.str_current = rogue.str_max;
100 messagef(0, "this tastes great, you feel warm all over");
101 break;
102 case HEALING:
103 messagef(0, "you begin to feel better");
104 potion_heal(0);
105 break;
106 case EXTRA_HEALING:
107 messagef(0, "you begin to feel much better");
108 potion_heal(1);
109 break;
110 case POISON:
111 if (!sustain_strength) {
112 rogue.str_current -= get_rand(1, 3);
113 if (rogue.str_current < 1) {
114 rogue.str_current = 1;
115 }
116 }
117 messagef(0, "you feel very sick now");
118 if (halluc) {
119 unhallucinate();
120 }
121 break;
122 case RAISE_LEVEL:
123 rogue.exp_points = level_points[rogue.exp - 1];
124 messagef(0, "you suddenly feel much more skillful");
125 add_exp(1, 1);
126 break;
127 case BLINDNESS:
128 go_blind();
129 break;
130 case HALLUCINATION:
131 messagef(0, "oh wow, everything seems so cosmic");
132 halluc += get_rand(500, 800);
133 break;
134 case DETECT_MONSTER:
135 show_monsters();
136 if (!(level_monsters.next_monster)) {
137 messagef(0, "%s", strange_feeling);
138 }
139 break;
140 case DETECT_OBJECTS:
141 if (level_objects.next_object) {
142 if (!blind) {
143 show_objects();
144 }
145 } else {
146 messagef(0, "%s", strange_feeling);
147 }
148 break;
149 case CONFUSION:
150 messagef(0, (halluc ? "what a trippy feeling" :
151 "you feel confused"));
152 cnfs();
153 break;
154 case LEVITATION:
155 messagef(0, "you start to float in the air");
156 levitate += get_rand(15, 30);
157 being_held = bear_trap = 0;
158 break;
159 case HASTE_SELF:
160 messagef(0, "you feel yourself moving much faster");
161 haste_self += get_rand(11, 21);
162 if (!(haste_self % 2)) {
163 haste_self++;
164 }
165 break;
166 case SEE_INVISIBLE:
167 messagef(0, "hmm, this potion tastes like %sjuice",
168 fruit);
169 if (blind) {
170 unblind();
171 }
172 see_invisible = 1;
173 relight();
174 break;
175 }
176 print_stats((STAT_STRENGTH | STAT_HP));
177 if (id_potions[obj->which_kind].id_status != CALLED) {
178 id_potions[obj->which_kind].id_status = IDENTIFIED;
179 }
180 vanish(obj, 1, &rogue.pack);
181 }
182
183 void
184 read_scroll(void)
185 {
186 short ch;
187 object *obj;
188
189 ch = pack_letter("read what?", SCROL);
190
191 if (ch == CANCEL) {
192 return;
193 }
194 if (!(obj = get_letter_object(ch))) {
195 messagef(0, "no such item.");
196 return;
197 }
198 if (obj->what_is != SCROL) {
199 messagef(0, "you can't read that");
200 return;
201 }
202 switch(obj->which_kind) {
203 case SCARE_MONSTER:
204 messagef(0, "you hear a maniacal laughter in the distance");
205 break;
206 case HOLD_MONSTER:
207 hold_monster();
208 break;
209 case ENCH_WEAPON:
210 if (rogue.weapon) {
211 if (rogue.weapon->what_is == WEAPON) {
212 messagef(0, "your %sglow%s %sfor a moment",
213 name_of(rogue.weapon),
214 ((rogue.weapon->quantity <= 1) ? "s" : ""),
215 get_ench_color());
216 if (coin_toss()) {
217 rogue.weapon->hit_enchant++;
218 } else {
219 rogue.weapon->d_enchant++;
220 }
221 }
222 rogue.weapon->is_cursed = 0;
223 } else {
224 messagef(0, "your hands tingle");
225 }
226 break;
227 case ENCH_ARMOR:
228 if (rogue.armor) {
229 messagef(0, "your armor glows %sfor a moment",
230 get_ench_color());
231 rogue.armor->d_enchant++;
232 rogue.armor->is_cursed = 0;
233 print_stats(STAT_ARMOR);
234 } else {
235 messagef(0, "your skin crawls");
236 }
237 break;
238 case IDENTIFY:
239 messagef(0, "this is a scroll of identify");
240 obj->identified = 1;
241 id_scrolls[obj->which_kind].id_status = IDENTIFIED;
242 idntfy();
243 break;
244 case TELEPORT:
245 tele();
246 break;
247 case SLEEP:
248 messagef(0, "you fall asleep");
249 take_a_nap();
250 break;
251 case PROTECT_ARMOR:
252 if (rogue.armor) {
253 messagef(0, "your armor is covered by a shimmering gold shield");
254 rogue.armor->is_protected = 1;
255 rogue.armor->is_cursed = 0;
256 } else {
257 messagef(0, "your acne seems to have disappeared");
258 }
259 break;
260 case REMOVE_CURSE:
261 messagef(0, (!halluc) ?
262 "you feel as though someone is watching over you" :
263 "you feel in touch with the universal oneness");
264 uncurse_all();
265 break;
266 case CREATE_MONSTER:
267 create_monster();
268 break;
269 case AGGRAVATE_MONSTER:
270 aggravate();
271 break;
272 case MAGIC_MAPPING:
273 messagef(0, "this scroll seems to have a map on it");
274 draw_magic_map();
275 break;
276 case CON_MON:
277 con_mon = 1;
278 messagef(0, "your hands glow %sfor a moment",
279 get_ench_color());
280 break;
281 }
282 if (id_scrolls[obj->which_kind].id_status != CALLED) {
283 id_scrolls[obj->which_kind].id_status = IDENTIFIED;
284 }
285 vanish(obj, (obj->which_kind != SLEEP), &rogue.pack);
286 }
287
288 /* vanish() does NOT handle a quiver of weapons with more than one
289 * arrow (or whatever) in the quiver. It will only decrement the count.
290 */
291
292 void
293 vanish(object *obj, short rm, object *pack)
294 {
295 if (obj->quantity > 1) {
296 obj->quantity--;
297 } else {
298 if (obj->in_use_flags & BEING_WIELDED) {
299 unwield(obj);
300 } else if (obj->in_use_flags & BEING_WORN) {
301 unwear(obj);
302 } else if (obj->in_use_flags & ON_EITHER_HAND) {
303 un_put_on(obj);
304 }
305 take_from_pack(obj, pack);
306 free_object(obj);
307 }
308 if (rm) {
309 (void)reg_move();
310 }
311 }
312
313 void
314 potion_heal(int extra)
315 {
316 float ratio;
317 short add;
318
319 rogue.hp_current += rogue.exp;
320
321 ratio = ((float)rogue.hp_current) / rogue.hp_max;
322
323 if (ratio >= 1.00) {
324 rogue.hp_max += (extra ? 2 : 1);
325 extra_hp += (extra ? 2 : 1);
326 rogue.hp_current = rogue.hp_max;
327 } else if (ratio >= 0.90) {
328 rogue.hp_max += (extra ? 1 : 0);
329 extra_hp += (extra ? 1 : 0);
330 rogue.hp_current = rogue.hp_max;
331 } else {
332 if (ratio < 0.33) {
333 ratio = 0.33;
334 }
335 if (extra) {
336 ratio += ratio;
337 }
338 add = (short)(ratio * (rogue.hp_max - rogue.hp_current));
339 rogue.hp_current += add;
340 if (rogue.hp_current > rogue.hp_max) {
341 rogue.hp_current = rogue.hp_max;
342 }
343 }
344 if (blind) {
345 unblind();
346 }
347 if (confused && extra) {
348 unconfuse();
349 } else if (confused) {
350 confused = (confused / 2) + 1;
351 }
352 if (halluc && extra) {
353 unhallucinate();
354 } else if (halluc) {
355 halluc = (halluc / 2) + 1;
356 }
357 }
358
359 void
360 idntfy(void)
361 {
362 short ch;
363 object *obj;
364 struct id *id_table;
365 char desc[DCOLS];
366 AGAIN:
367 ch = pack_letter("what would you like to identify?", ALL_OBJECTS);
368
369 if (ch == CANCEL) {
370 return;
371 }
372 if (!(obj = get_letter_object(ch))) {
373 messagef(0, "no such item, try again");
374 messagef(0, "%s", ""); /* gcc objects to just "" */
375 check_message();
376 goto AGAIN;
377 }
378 obj->identified = 1;
379 if (obj->what_is & (SCROL | POTION | WEAPON | ARMOR | WAND | RING)) {
380 id_table = get_id_table(obj);
381 id_table[obj->which_kind].id_status = IDENTIFIED;
382 }
383 get_desc(obj, desc, sizeof(desc));
384 messagef(0, "%s", desc);
385 }
386
387 void
388 eat(void)
389 {
390 short ch;
391 short moves;
392 object *obj;
393
394 ch = pack_letter("eat what?", FOOD);
395
396 if (ch == CANCEL) {
397 return;
398 }
399 if (!(obj = get_letter_object(ch))) {
400 messagef(0, "no such item.");
401 return;
402 }
403 if (obj->what_is != FOOD) {
404 messagef(0, "you can't eat that");
405 return;
406 }
407 if ((obj->which_kind == FRUIT) || rand_percent(60)) {
408 moves = get_rand(950, 1150);
409 if (obj->which_kind == RATION) {
410 messagef(0, "yum, that tasted good");
411 } else {
412 messagef(0, "my, that was a yummy %s", fruit);
413 }
414 } else {
415 moves = get_rand(750, 950);
416 messagef(0, "yuk, that food tasted awful");
417 add_exp(2, 1);
418 }
419 rogue.moves_left /= 3;
420 rogue.moves_left += moves;
421 hunger_str[0] = 0;
422 print_stats(STAT_HUNGER);
423
424 vanish(obj, 1, &rogue.pack);
425 }
426
427 void
428 hold_monster(void)
429 {
430 short i, j;
431 short mcount = 0;
432 object *monster;
433 short row, col;
434
435 for (i = -2; i <= 2; i++) {
436 for (j = -2; j <= 2; j++) {
437 row = rogue.row + i;
438 col = rogue.col + j;
439 if ((row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) ||
440 (col > (DCOLS-1))) {
441 continue;
442 }
443 if (dungeon[row][col] & MONSTER) {
444 monster = object_at(&level_monsters, row, col);
445 monster->m_flags |= ASLEEP;
446 monster->m_flags &= (~WAKENS);
447 mcount++;
448 }
449 }
450 }
451 if (mcount == 0) {
452 messagef(0, "you feel a strange sense of loss");
453 } else if (mcount == 1) {
454 messagef(0, "the monster freezes");
455 } else {
456 messagef(0, "the monsters around you freeze");
457 }
458 }
459
460 void
461 tele(void)
462 {
463 mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
464
465 if (cur_room >= 0) {
466 darken_room(cur_room);
467 }
468 put_player(get_room_number(rogue.row, rogue.col));
469 being_held = 0;
470 bear_trap = 0;
471 }
472
473 void
474 hallucinate(void)
475 {
476 object *obj, *monster;
477 short ch;
478
479 if (blind) return;
480
481 obj = level_objects.next_object;
482
483 while (obj) {
484 ch = mvinch(obj->row, obj->col);
485 if (((ch < 'A') || (ch > 'Z')) &&
486 ((obj->row != rogue.row) || (obj->col != rogue.col)))
487 if ((ch != ' ') && (ch != '.') && (ch != '#') && (ch != '+')) {
488 addch(gr_obj_char());
489 }
490 obj = obj->next_object;
491 }
492 monster = level_monsters.next_monster;
493
494 while (monster) {
495 ch = mvinch(monster->row, monster->col);
496 if ((ch >= 'A') && (ch <= 'Z')) {
497 addch(get_rand('A', 'Z'));
498 }
499 monster = monster->next_monster;
500 }
501 }
502
503 void
504 unhallucinate(void)
505 {
506 halluc = 0;
507 relight();
508 messagef(1, "everything looks SO boring now");
509 }
510
511 void
512 unblind(void)
513 {
514 blind = 0;
515 messagef(1, "the veil of darkness lifts");
516 relight();
517 if (halluc) {
518 hallucinate();
519 }
520 if (detect_monster) {
521 show_monsters();
522 }
523 }
524
525 void
526 relight(void)
527 {
528 if (cur_room == PASSAGE) {
529 light_passage(rogue.row, rogue.col);
530 } else {
531 light_up_room(cur_room);
532 }
533 mvaddch(rogue.row, rogue.col, rogue.fchar);
534 }
535
536 void
537 take_a_nap(void)
538 {
539 short i;
540
541 i = get_rand(2, 5);
542 md_sleep(1);
543
544 while (i--) {
545 mv_mons();
546 }
547 md_sleep(1);
548 messagef(0, "%s", you_can_move_again);
549 }
550
551 void
552 go_blind(void)
553 {
554 short i, j;
555
556 if (!blind) {
557 messagef(0, "a cloak of darkness falls around you");
558 }
559 blind += get_rand(500, 800);
560
561 if (detect_monster) {
562 object *monster;
563
564 monster = level_monsters.next_monster;
565
566 while (monster) {
567 mvaddch(monster->row, monster->col, monster->trail_char);
568 monster = monster->next_monster;
569 }
570 }
571 if (cur_room >= 0) {
572 for (i = rooms[cur_room].top_row + 1;
573 i < rooms[cur_room].bottom_row; i++) {
574 for (j = rooms[cur_room].left_col + 1;
575 j < rooms[cur_room].right_col; j++) {
576 mvaddch(i, j, ' ');
577 }
578 }
579 }
580 mvaddch(rogue.row, rogue.col, rogue.fchar);
581 }
582
583 const char *
584 get_ench_color(void)
585 {
586 if (halluc) {
587 return(id_potions[get_rand(0, POTIONS-1)].title);
588 } else if (con_mon) {
589 return("red ");
590 }
591 return("blue ");
592 }
593
594 void
595 cnfs(void)
596 {
597 confused += get_rand(12, 22);
598 }
599
600 void
601 unconfuse(void)
602 {
603 confused = 0;
604 messagef(1, "you feel less %s now", (halluc ? "trippy" : "confused"));
605 }
606
607 void
608 uncurse_all(void)
609 {
610 object *obj;
611
612 obj = rogue.pack.next_object;
613
614 while (obj) {
615 obj->is_cursed = 0;
616 obj = obj->next_object;
617 }
618 }