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