xref: /original-bsd/games/rogue/trap.c (revision 9eb838fd)
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[] = "@(#)trap.c	5.2 (Berkeley) 02/07/89";
23 #endif /* not lint */
24 
25 /*
26  * trap.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 trap traps[MAX_TRAPS];
40 boolean trap_door = 0;
41 short bear_trap = 0;
42 
43 char *trap_strings[TRAPS * 2] = {
44 	"trap door",
45 			"you fell down a trap",
46 	"bear trap",
47 			"you are caught in a bear trap",
48 	"teleport trap",
49 			"teleport",
50 	"poison dart trap",
51 			"a small dart just hit you in the shoulder",
52 	"sleeping gas trap",
53 			"a strange white mist envelops you and you fall asleep",
54 	"rust trap",
55 			"a gush of water hits you on the head"
56 };
57 
58 extern short cur_level, party_room;
59 extern char *new_level_message;
60 extern boolean interrupted;
61 extern short ring_exp;
62 extern boolean sustain_strength;
63 extern short blind;
64 
65 trap_at(row, col)
66 register row, col;
67 {
68 	short i;
69 
70 	for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
71 		if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
72 			return(traps[i].trap_type);
73 		}
74 	}
75 	return(NO_TRAP);
76 }
77 
78 trap_player(row, col)
79 short row, col;
80 {
81 	short t;
82 
83 	if ((t = trap_at(row, col)) == NO_TRAP) {
84 		return;
85 	}
86 	dungeon[row][col] &= (~HIDDEN);
87 	if (rand_percent(rogue.exp + ring_exp)) {
88 		message("the trap failed", 1);
89 		return;
90 	}
91 	switch(t) {
92 	case TRAP_DOOR:
93 		trap_door = 1;
94 		new_level_message = trap_strings[(t*2)+1];
95 		break;
96 	case BEAR_TRAP:
97 		message(trap_strings[(t*2)+1], 1);
98 		bear_trap = get_rand(4, 7);
99 		break;
100 	case TELE_TRAP:
101 		mvaddch(rogue.row, rogue.col, '^');
102 		tele();
103 		break;
104 	case DART_TRAP:
105 		message(trap_strings[(t*2)+1], 1);
106 		rogue.hp_current -= get_damage("1d6", 1);
107 		if (rogue.hp_current <= 0) {
108 			rogue.hp_current = 0;
109 		}
110 		if ((!sustain_strength) && rand_percent(40) &&
111 			(rogue.str_current >= 3)) {
112 			rogue.str_current--;
113 		}
114 		print_stats(STAT_HP | STAT_STRENGTH);
115 		if (rogue.hp_current <= 0) {
116 			killed_by((object *) 0, POISON_DART);
117 		}
118 		break;
119 	case SLEEPING_GAS_TRAP:
120 		message(trap_strings[(t*2)+1], 1);
121 		take_a_nap();
122 		break;
123 	case RUST_TRAP:
124 		message(trap_strings[(t*2)+1], 1);
125 		rust((object *) 0);
126 		break;
127 	}
128 }
129 
130 add_traps()
131 {
132 	short i, n, tries = 0;
133 	short row, col;
134 
135 	if (cur_level <= 2) {
136 		n = 0;
137 	} else if (cur_level <= 7) {
138 		n = get_rand(0, 2);
139 	} else if (cur_level <= 11) {
140 		n = get_rand(1, 2);
141 	} else if (cur_level <= 16) {
142 		n = get_rand(2, 3);
143 	} else if (cur_level <= 21) {
144 		n = get_rand(2, 4);
145 	} else if (cur_level <= (AMULET_LEVEL + 2)) {
146 		n = get_rand(3, 5);
147 	} else {
148 		n = get_rand(5, MAX_TRAPS);
149 	}
150 	for (i = 0; i < n; i++) {
151 		traps[i].trap_type = get_rand(0, (TRAPS - 1));
152 
153 		if ((i == 0) && (party_room != NO_ROOM)) {
154 			do {
155 				row = get_rand((rooms[party_room].top_row+1),
156 						(rooms[party_room].bottom_row-1));
157 				col = get_rand((rooms[party_room].left_col+1),
158 						(rooms[party_room].right_col-1));
159 				tries++;
160 			} while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
161 					(dungeon[row][col] == NOTHING)) && (tries < 15));
162 			if (tries >= 15) {
163 				gr_row_col(&row, &col, (FLOOR | MONSTER));
164 			}
165 		} else {
166 			gr_row_col(&row, &col, (FLOOR | MONSTER));
167 		}
168 		traps[i].trap_row = row;
169 		traps[i].trap_col = col;
170 		dungeon[row][col] |= (TRAP | HIDDEN);
171 	}
172 }
173 
174 id_trap()
175 {
176 	short dir, row, col, d, t;
177 
178 	message("direction? ", 0);
179 
180 	while (!is_direction(dir = rgetchar(), &d)) {
181 		sound_bell();
182 	}
183 	check_message();
184 
185 	if (dir == CANCEL) {
186 		return;
187 	}
188 	row = rogue.row;
189 	col = rogue.col;
190 
191 	get_dir_rc(d, &row, &col, 0);
192 
193 	if ((dungeon[row][col] & TRAP) && (!(dungeon[row][col] & HIDDEN))) {
194 		t = trap_at(row, col);
195 		message(trap_strings[t*2], 0);
196 	} else {
197 		message("no trap there", 0);
198 	}
199 }
200 
201 show_traps()
202 {
203 	short i, j;
204 
205 	for (i = 0; i < DROWS; i++) {
206 		for (j = 0; j < DCOLS; j++) {
207 			if (dungeon[i][j] & TRAP) {
208 				mvaddch(i, j, '^');
209 			}
210 		}
211 	}
212 }
213 
214 search(n, is_auto)
215 short n;
216 boolean is_auto;
217 {
218 	short s, i, j, row, col, t;
219 	short shown = 0, found = 0;
220 	static boolean reg_search;
221 
222 	for (i = -1; i <= 1; i++) {
223 		for (j = -1; j <= 1; j++) {
224 			row = rogue.row + i;
225 			col = rogue.col + j;
226 			if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
227 					(col < 0) || (col >= DCOLS)) {
228 				continue;
229 			}
230 			if (dungeon[row][col] & HIDDEN) {
231 				found++;
232 			}
233 		}
234 	}
235 	for (s = 0; s < n; s++) {
236 		for (i = -1; i <= 1; i++) {
237 			for (j = -1; j <= 1; j++) {
238 				row = rogue.row + i;
239 				col = rogue.col + j ;
240 				if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
241 						(col < 0) || (col >= DCOLS)) {
242 					continue;
243 				}
244 				if (dungeon[row][col] & HIDDEN) {
245 					if (rand_percent(17 + (rogue.exp + ring_exp))) {
246 						dungeon[row][col] &= (~HIDDEN);
247 						if ((!blind) && ((row != rogue.row) ||
248 								(col != rogue.col))) {
249 							mvaddch(row, col, get_dungeon_char(row, col));
250 						}
251 						shown++;
252 						if (dungeon[row][col] & TRAP) {
253 							t = trap_at(row, col);
254 							message(trap_strings[t*2], 1);
255 						}
256 					}
257 				}
258 				if (((shown == found) && (found > 0)) || interrupted) {
259 					return;
260 				}
261 			}
262 		}
263 		if ((!is_auto) && (reg_search = !reg_search)) {
264 			(void) reg_move();
265 		}
266 	}
267 }
268