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