xref: /netbsd-src/games/rogue/trap.c (revision edfa83365254b6d7c6cdaa0d30b214319daeee7f)
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, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 /*static char sccsid[] = "from: @(#)trap.c	5.3 (Berkeley) 6/1/90";*/
39 static char rcsid[] = "$Id: trap.c,v 1.2 1993/08/01 18:52:09 mycroft Exp $";
40 #endif /* not lint */
41 
42 /*
43  * trap.c
44  *
45  * This source herein may be modified and/or distributed by anybody who
46  * so desires, with the following restrictions:
47  *    1.)  No portion of this notice shall be removed.
48  *    2.)  Credit shall not be taken for the creation of this source.
49  *    3.)  This code is not to be traded, sold, or used for personal
50  *         gain or profit.
51  *
52  */
53 
54 #include "rogue.h"
55 
56 trap traps[MAX_TRAPS];
57 boolean trap_door = 0;
58 short bear_trap = 0;
59 
60 char *trap_strings[TRAPS * 2] = {
61 	"trap door",
62 			"you fell down a trap",
63 	"bear trap",
64 			"you are caught in a bear trap",
65 	"teleport trap",
66 			"teleport",
67 	"poison dart trap",
68 			"a small dart just hit you in the shoulder",
69 	"sleeping gas trap",
70 			"a strange white mist envelops you and you fall asleep",
71 	"rust trap",
72 			"a gush of water hits you on the head"
73 };
74 
75 extern short cur_level, party_room;
76 extern char *new_level_message;
77 extern boolean interrupted;
78 extern short ring_exp;
79 extern boolean sustain_strength;
80 extern short blind;
81 
82 trap_at(row, col)
83 register row, col;
84 {
85 	short i;
86 
87 	for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
88 		if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
89 			return(traps[i].trap_type);
90 		}
91 	}
92 	return(NO_TRAP);
93 }
94 
95 trap_player(row, col)
96 short row, col;
97 {
98 	short t;
99 
100 	if ((t = trap_at(row, col)) == NO_TRAP) {
101 		return;
102 	}
103 	dungeon[row][col] &= (~HIDDEN);
104 	if (rand_percent(rogue.exp + ring_exp)) {
105 		message("the trap failed", 1);
106 		return;
107 	}
108 	switch(t) {
109 	case TRAP_DOOR:
110 		trap_door = 1;
111 		new_level_message = trap_strings[(t*2)+1];
112 		break;
113 	case BEAR_TRAP:
114 		message(trap_strings[(t*2)+1], 1);
115 		bear_trap = get_rand(4, 7);
116 		break;
117 	case TELE_TRAP:
118 		mvaddch(rogue.row, rogue.col, '^');
119 		tele();
120 		break;
121 	case DART_TRAP:
122 		message(trap_strings[(t*2)+1], 1);
123 		rogue.hp_current -= get_damage("1d6", 1);
124 		if (rogue.hp_current <= 0) {
125 			rogue.hp_current = 0;
126 		}
127 		if ((!sustain_strength) && rand_percent(40) &&
128 			(rogue.str_current >= 3)) {
129 			rogue.str_current--;
130 		}
131 		print_stats(STAT_HP | STAT_STRENGTH);
132 		if (rogue.hp_current <= 0) {
133 			killed_by((object *) 0, POISON_DART);
134 		}
135 		break;
136 	case SLEEPING_GAS_TRAP:
137 		message(trap_strings[(t*2)+1], 1);
138 		take_a_nap();
139 		break;
140 	case RUST_TRAP:
141 		message(trap_strings[(t*2)+1], 1);
142 		rust((object *) 0);
143 		break;
144 	}
145 }
146 
147 add_traps()
148 {
149 	short i, n, tries = 0;
150 	short row, col;
151 
152 	if (cur_level <= 2) {
153 		n = 0;
154 	} else if (cur_level <= 7) {
155 		n = get_rand(0, 2);
156 	} else if (cur_level <= 11) {
157 		n = get_rand(1, 2);
158 	} else if (cur_level <= 16) {
159 		n = get_rand(2, 3);
160 	} else if (cur_level <= 21) {
161 		n = get_rand(2, 4);
162 	} else if (cur_level <= (AMULET_LEVEL + 2)) {
163 		n = get_rand(3, 5);
164 	} else {
165 		n = get_rand(5, MAX_TRAPS);
166 	}
167 	for (i = 0; i < n; i++) {
168 		traps[i].trap_type = get_rand(0, (TRAPS - 1));
169 
170 		if ((i == 0) && (party_room != NO_ROOM)) {
171 			do {
172 				row = get_rand((rooms[party_room].top_row+1),
173 						(rooms[party_room].bottom_row-1));
174 				col = get_rand((rooms[party_room].left_col+1),
175 						(rooms[party_room].right_col-1));
176 				tries++;
177 			} while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
178 					(dungeon[row][col] == NOTHING)) && (tries < 15));
179 			if (tries >= 15) {
180 				gr_row_col(&row, &col, (FLOOR | MONSTER));
181 			}
182 		} else {
183 			gr_row_col(&row, &col, (FLOOR | MONSTER));
184 		}
185 		traps[i].trap_row = row;
186 		traps[i].trap_col = col;
187 		dungeon[row][col] |= (TRAP | HIDDEN);
188 	}
189 }
190 
191 id_trap()
192 {
193 	short dir, row, col, d, t;
194 
195 	message("direction? ", 0);
196 
197 	while (!is_direction(dir = rgetchar(), &d)) {
198 		sound_bell();
199 	}
200 	check_message();
201 
202 	if (dir == CANCEL) {
203 		return;
204 	}
205 	row = rogue.row;
206 	col = rogue.col;
207 
208 	get_dir_rc(d, &row, &col, 0);
209 
210 	if ((dungeon[row][col] & TRAP) && (!(dungeon[row][col] & HIDDEN))) {
211 		t = trap_at(row, col);
212 		message(trap_strings[t*2], 0);
213 	} else {
214 		message("no trap there", 0);
215 	}
216 }
217 
218 show_traps()
219 {
220 	short i, j;
221 
222 	for (i = 0; i < DROWS; i++) {
223 		for (j = 0; j < DCOLS; j++) {
224 			if (dungeon[i][j] & TRAP) {
225 				mvaddch(i, j, '^');
226 			}
227 		}
228 	}
229 }
230 
231 search(n, is_auto)
232 short n;
233 boolean is_auto;
234 {
235 	short s, i, j, row, col, t;
236 	short shown = 0, found = 0;
237 	static boolean reg_search;
238 
239 	for (i = -1; i <= 1; i++) {
240 		for (j = -1; j <= 1; j++) {
241 			row = rogue.row + i;
242 			col = rogue.col + j;
243 			if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
244 					(col < 0) || (col >= DCOLS)) {
245 				continue;
246 			}
247 			if (dungeon[row][col] & HIDDEN) {
248 				found++;
249 			}
250 		}
251 	}
252 	for (s = 0; s < n; s++) {
253 		for (i = -1; i <= 1; i++) {
254 			for (j = -1; j <= 1; j++) {
255 				row = rogue.row + i;
256 				col = rogue.col + j ;
257 				if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
258 						(col < 0) || (col >= DCOLS)) {
259 					continue;
260 				}
261 				if (dungeon[row][col] & HIDDEN) {
262 					if (rand_percent(17 + (rogue.exp + ring_exp))) {
263 						dungeon[row][col] &= (~HIDDEN);
264 						if ((!blind) && ((row != rogue.row) ||
265 								(col != rogue.col))) {
266 							mvaddch(row, col, get_dungeon_char(row, col));
267 						}
268 						shown++;
269 						if (dungeon[row][col] & TRAP) {
270 							t = trap_at(row, col);
271 							message(trap_strings[t*2], 1);
272 						}
273 					}
274 				}
275 				if (((shown == found) && (found > 0)) || interrupted) {
276 					return;
277 				}
278 			}
279 		}
280 		if ((!is_auto) && (reg_search = !reg_search)) {
281 			(void) reg_move();
282 		}
283 	}
284 }
285