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