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