games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[games.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. 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 }