xref: /dragonfly/games/rogue/trap.c (revision 9f7604d7)
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. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * @(#)trap.c	8.1 (Berkeley) 5/31/93
33  * $FreeBSD: src/games/rogue/trap.c,v 1.6 1999/11/30 03:49:28 billf Exp $
34  * $DragonFly: src/games/rogue/trap.c,v 1.3 2006/09/02 19:31:07 pavalos Exp $
35  */
36 
37 /*
38  * trap.c
39  *
40  * This source herein may be modified and/or distributed by anybody who
41  * so desires, with the following restrictions:
42  *    1.)  No portion of this notice shall be removed.
43  *    2.)  Credit shall not be taken for the creation of this source.
44  *    3.)  This code is not to be traded, sold, or used for personal
45  *         gain or profit.
46  *
47  */
48 
49 #include "rogue.h"
50 
51 trap traps[MAX_TRAPS];
52 boolean trap_door = 0;
53 short bear_trap = 0;
54 
55 const char *const trap_strings[TRAPS * 2] = {
56 	"trap door",
57 			"you fell down a trap",
58 	"bear trap",
59 			"you are caught in a bear trap",
60 	"teleport trap",
61 			"teleport",
62 	"poison dart trap",
63 			"a small dart just hit you in the shoulder",
64 	"sleeping gas trap",
65 			"a strange white mist envelops you and you fall asleep",
66 	"rust trap",
67 			"a gush of water hits you on the head"
68 };
69 
70 extern short cur_level, party_room;
71 extern const char *new_level_message;
72 extern boolean interrupted;
73 extern short ring_exp;
74 extern boolean sustain_strength;
75 extern short blind;
76 
77 static short trap_at(int, int);
78 
79 static short
80 trap_at(int row, int col)
81 {
82 	short i;
83 
84 	for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
85 		if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
86 			return(traps[i].trap_type);
87 		}
88 	}
89 	return(NO_TRAP);
90 }
91 
92 void
93 trap_player(short row, short 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(NULL, 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(NULL);
140 		break;
141 	}
142 }
143 
144 void
145 add_traps(void)
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(void)
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(void)
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(short n, boolean is_auto)
233 {
234 	short s, i, j, row, col, t;
235 	short shown = 0, found = 0;
236 	static boolean reg_search;
237 
238 	for (i = -1; i <= 1; i++) {
239 		for (j = -1; j <= 1; j++) {
240 			row = rogue.row + i;
241 			col = rogue.col + j;
242 			if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
243 					(col < 0) || (col >= DCOLS)) {
244 				continue;
245 			}
246 			if (dungeon[row][col] & HIDDEN) {
247 				found++;
248 			}
249 		}
250 	}
251 	for (s = 0; s < n; s++) {
252 		for (i = -1; i <= 1; i++) {
253 			for (j = -1; j <= 1; j++) {
254 				row = rogue.row + i;
255 				col = rogue.col + j ;
256 				if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
257 						(col < 0) || (col >= DCOLS)) {
258 					continue;
259 				}
260 				if (dungeon[row][col] & HIDDEN) {
261 					if (rand_percent(17 + (rogue.exp + ring_exp))) {
262 						dungeon[row][col] &= (~HIDDEN);
263 						if ((!blind) && ((row != rogue.row) ||
264 								(col != rogue.col))) {
265 							mvaddch(row, col, get_dungeon_char(row, col));
266 						}
267 						shown++;
268 						if (dungeon[row][col] & TRAP) {
269 							t = trap_at(row, col);
270 							message(trap_strings[t*2], 1);
271 						}
272 					}
273 				}
274 				if (((shown == found) && (found > 0)) || interrupted) {
275 					return;
276 				}
277 			}
278 		}
279 		if ((!is_auto) && (reg_search = !reg_search)) {
280 			reg_move();
281 		}
282 	}
283 }
284