Initial import from FreeBSD RELENG_4:
[dragonfly.git] / games / rogue / trap.c
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 }