xref: /dragonfly/games/rogue/trap.c (revision 8e1c6f81)
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  * @(#)trap.c	8.1 (Berkeley) 5/31/93
37  * $FreeBSD: src/games/rogue/trap.c,v 1.6 1999/11/30 03:49:28 billf Exp $
38  * $DragonFly: src/games/rogue/trap.c,v 1.3 2006/09/02 19:31:07 pavalos Exp $
39  */
40 
41 /*
42  * trap.c
43  *
44  * This source herein may be modified and/or distributed by anybody who
45  * so desires, with the following restrictions:
46  *    1.)  No portion of this notice shall be removed.
47  *    2.)  Credit shall not be taken for the creation of this source.
48  *    3.)  This code is not to be traded, sold, or used for personal
49  *         gain or profit.
50  *
51  */
52 
53 #include "rogue.h"
54 
55 trap traps[MAX_TRAPS];
56 boolean trap_door = 0;
57 short bear_trap = 0;
58 
59 const char *const trap_strings[TRAPS * 2] = {
60 	"trap door",
61 			"you fell down a trap",
62 	"bear trap",
63 			"you are caught in a bear trap",
64 	"teleport trap",
65 			"teleport",
66 	"poison dart trap",
67 			"a small dart just hit you in the shoulder",
68 	"sleeping gas trap",
69 			"a strange white mist envelops you and you fall asleep",
70 	"rust trap",
71 			"a gush of water hits you on the head"
72 };
73 
74 extern short cur_level, party_room;
75 extern const char *new_level_message;
76 extern boolean interrupted;
77 extern short ring_exp;
78 extern boolean sustain_strength;
79 extern short blind;
80 
81 static short	trap_at(int, int);
82 
83 static short
84 trap_at(int row, int col)
85 {
86 	short i;
87 
88 	for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
89 		if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
90 			return(traps[i].trap_type);
91 		}
92 	}
93 	return(NO_TRAP);
94 }
95 
96 void
97 trap_player(short row, short col)
98 {
99 	short t;
100 
101 	if ((t = trap_at(row, col)) == NO_TRAP) {
102 		return;
103 	}
104 	dungeon[row][col] &= (~HIDDEN);
105 	if (rand_percent(rogue.exp + ring_exp)) {
106 		message("the trap failed", 1);
107 		return;
108 	}
109 	switch(t) {
110 	case TRAP_DOOR:
111 		trap_door = 1;
112 		new_level_message = trap_strings[(t*2)+1];
113 		break;
114 	case BEAR_TRAP:
115 		message(trap_strings[(t*2)+1], 1);
116 		bear_trap = get_rand(4, 7);
117 		break;
118 	case TELE_TRAP:
119 		mvaddch(rogue.row, rogue.col, '^');
120 		tele();
121 		break;
122 	case DART_TRAP:
123 		message(trap_strings[(t*2)+1], 1);
124 		rogue.hp_current -= get_damage("1d6", 1);
125 		if (rogue.hp_current <= 0) {
126 			rogue.hp_current = 0;
127 		}
128 		if ((!sustain_strength) && rand_percent(40) &&
129 			(rogue.str_current >= 3)) {
130 			rogue.str_current--;
131 		}
132 		print_stats(STAT_HP | STAT_STRENGTH);
133 		if (rogue.hp_current <= 0) {
134 			killed_by((object *) 0, POISON_DART);
135 		}
136 		break;
137 	case SLEEPING_GAS_TRAP:
138 		message(trap_strings[(t*2)+1], 1);
139 		take_a_nap();
140 		break;
141 	case RUST_TRAP:
142 		message(trap_strings[(t*2)+1], 1);
143 		rust((object *) 0);
144 		break;
145 	}
146 }
147 
148 void
149 add_traps(void)
150 {
151 	short i, n, tries = 0;
152 	short row, col;
153 
154 	if (cur_level <= 2) {
155 		n = 0;
156 	} else if (cur_level <= 7) {
157 		n = get_rand(0, 2);
158 	} else if (cur_level <= 11) {
159 		n = get_rand(1, 2);
160 	} else if (cur_level <= 16) {
161 		n = get_rand(2, 3);
162 	} else if (cur_level <= 21) {
163 		n = get_rand(2, 4);
164 	} else if (cur_level <= (AMULET_LEVEL + 2)) {
165 		n = get_rand(3, 5);
166 	} else {
167 		n = get_rand(5, MAX_TRAPS);
168 	}
169 	for (i = 0; i < n; i++) {
170 		traps[i].trap_type = get_rand(0, (TRAPS - 1));
171 
172 		if ((i == 0) && (party_room != NO_ROOM)) {
173 			do {
174 				row = get_rand((rooms[party_room].top_row+1),
175 						(rooms[party_room].bottom_row-1));
176 				col = get_rand((rooms[party_room].left_col+1),
177 						(rooms[party_room].right_col-1));
178 				tries++;
179 			} while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
180 					(dungeon[row][col] == NOTHING)) && (tries < 15));
181 			if (tries >= 15) {
182 				gr_row_col(&row, &col, (FLOOR | MONSTER));
183 			}
184 		} else {
185 			gr_row_col(&row, &col, (FLOOR | MONSTER));
186 		}
187 		traps[i].trap_row = row;
188 		traps[i].trap_col = col;
189 		dungeon[row][col] |= (TRAP | HIDDEN);
190 	}
191 }
192 
193 void
194 id_trap(void)
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 void
222 show_traps(void)
223 {
224 	short i, j;
225 
226 	for (i = 0; i < DROWS; i++) {
227 		for (j = 0; j < DCOLS; j++) {
228 			if (dungeon[i][j] & TRAP) {
229 				mvaddch(i, j, '^');
230 			}
231 		}
232 	}
233 }
234 
235 void
236 search(short n, 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 			reg_move();
285 		}
286 	}
287 }
288