Merge from vendor branch GCC:
[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  * @(#)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.2 2003/06/17 04:25:25 dillon 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 trap_at(row, col)
82 int row, col;
83 {
84         short i;
85
86         for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
87                 if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
88                         return(traps[i].trap_type);
89                 }
90         }
91         return(NO_TRAP);
92 }
93
94 trap_player(row, col)
95 short row, col;
96 {
97         short t;
98
99         if ((t = trap_at(row, col)) == NO_TRAP) {
100                 return;
101         }
102         dungeon[row][col] &= (~HIDDEN);
103         if (rand_percent(rogue.exp + ring_exp)) {
104                 message("the trap failed", 1);
105                 return;
106         }
107         switch(t) {
108         case TRAP_DOOR:
109                 trap_door = 1;
110                 new_level_message = trap_strings[(t*2)+1];
111                 break;
112         case BEAR_TRAP:
113                 message(trap_strings[(t*2)+1], 1);
114                 bear_trap = get_rand(4, 7);
115                 break;
116         case TELE_TRAP:
117                 mvaddch(rogue.row, rogue.col, '^');
118                 tele();
119                 break;
120         case DART_TRAP:
121                 message(trap_strings[(t*2)+1], 1);
122                 rogue.hp_current -= get_damage("1d6", 1);
123                 if (rogue.hp_current <= 0) {
124                         rogue.hp_current = 0;
125                 }
126                 if ((!sustain_strength) && rand_percent(40) &&
127                         (rogue.str_current >= 3)) {
128                         rogue.str_current--;
129                 }
130                 print_stats(STAT_HP | STAT_STRENGTH);
131                 if (rogue.hp_current <= 0) {
132                         killed_by((object *) 0, POISON_DART);
133                 }
134                 break;
135         case SLEEPING_GAS_TRAP:
136                 message(trap_strings[(t*2)+1], 1);
137                 take_a_nap();
138                 break;
139         case RUST_TRAP:
140                 message(trap_strings[(t*2)+1], 1);
141                 rust((object *) 0);
142                 break;
143         }
144 }
145
146 add_traps()
147 {
148         short i, n, tries = 0;
149         short row, col;
150
151         if (cur_level <= 2) {
152                 n = 0;
153         } else if (cur_level <= 7) {
154                 n = get_rand(0, 2);
155         } else if (cur_level <= 11) {
156                 n = get_rand(1, 2);
157         } else if (cur_level <= 16) {
158                 n = get_rand(2, 3);
159         } else if (cur_level <= 21) {
160                 n = get_rand(2, 4);
161         } else if (cur_level <= (AMULET_LEVEL + 2)) {
162                 n = get_rand(3, 5);
163         } else {
164                 n = get_rand(5, MAX_TRAPS);
165         }
166         for (i = 0; i < n; i++) {
167                 traps[i].trap_type = get_rand(0, (TRAPS - 1));
168
169                 if ((i == 0) && (party_room != NO_ROOM)) {
170                         do {
171                                 row = get_rand((rooms[party_room].top_row+1),
172                                                 (rooms[party_room].bottom_row-1));
173                                 col = get_rand((rooms[party_room].left_col+1),
174                                                 (rooms[party_room].right_col-1));
175                                 tries++;
176                         } while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
177                                         (dungeon[row][col] == NOTHING)) && (tries < 15));
178                         if (tries >= 15) {
179                                 gr_row_col(&row, &col, (FLOOR | MONSTER));
180                         }
181                 } else {
182                         gr_row_col(&row, &col, (FLOOR | MONSTER));
183                 }
184                 traps[i].trap_row = row;
185                 traps[i].trap_col = col;
186                 dungeon[row][col] |= (TRAP | HIDDEN);
187         }
188 }
189
190 id_trap()
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 show_traps()
218 {
219         short i, j;
220
221         for (i = 0; i < DROWS; i++) {
222                 for (j = 0; j < DCOLS; j++) {
223                         if (dungeon[i][j] & TRAP) {
224                                 mvaddch(i, j, '^');
225                         }
226                 }
227         }
228 }
229
230 search(n, is_auto)
231 short n;
232 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                         (void) reg_move();
281                 }
282         }
283 }