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