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