1 /*        $NetBSD: trap.c,v 1.10 2009/08/12 08:44:45 dholland Exp $   */
2 
3 /*
4  * Copyright (c) 1988, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Timothy C. Stoehr.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)trap.c      8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: trap.c,v 1.10 2009/08/12 08:44:45 dholland Exp $");
41 #endif
42 #endif /* not lint */
43 
44 /*
45  * trap.c
46  *
47  * This source herein may be modified and/or distributed by anybody who
48  * so desires, with the following restrictions:
49  *    1.)  No portion of this notice shall be removed.
50  *    2.)  Credit shall not be taken for the creation of this source.
51  *    3.)  This code is not to be traded, sold, or used for personal
52  *         gain or profit.
53  *
54  */
55 
56 #include "rogue.h"
57 
58 trap traps[MAX_TRAPS];
59 boolean trap_door = 0;
60 short bear_trap = 0;
61 
62 static const char *const trap_strings[TRAPS * 2] = {
63           "trap door",
64                               "you fell down a trap",
65           "bear trap",
66                               "you are caught in a bear trap",
67           "teleport trap",
68                               "teleport",
69           "poison dart trap",
70                               "a small dart just hit you in the shoulder",
71           "sleeping gas trap",
72                               "a strange white mist envelops you and you fall asleep",
73           "rust trap",
74                               "a gush of water hits you on the head"
75 };
76 
77 static short
trap_at(int row,int col)78 trap_at(int row, int col)
79 {
80           short i;
81 
82           for (i = 0; ((i < MAX_TRAPS) && (traps[i].trap_type != NO_TRAP)); i++) {
83                     if ((traps[i].trap_row == row) && (traps[i].trap_col == col)) {
84                               return(traps[i].trap_type);
85                     }
86           }
87           return(NO_TRAP);
88 }
89 
90 void
trap_player(short row,short col)91 trap_player(short row, short col)
92 {
93           short t;
94 
95           if ((t = trap_at(row, col)) == NO_TRAP) {
96                     return;
97           }
98           dungeon[row][col] &= (~HIDDEN);
99           if (rand_percent(rogue.exp + ring_exp)) {
100                     messagef(1, "the trap failed");
101                     return;
102           }
103           switch(t) {
104           case TRAP_DOOR:
105                     trap_door = 1;
106                     new_level_message = trap_strings[(t*2)+1];
107                     break;
108           case BEAR_TRAP:
109                     messagef(1, "%s", trap_strings[(t*2)+1]);
110                     bear_trap = get_rand(4, 7);
111                     break;
112           case TELE_TRAP:
113                     mvaddch(rogue.row, rogue.col, '^');
114                     tele();
115                     break;
116           case DART_TRAP:
117                     messagef(1, "%s", trap_strings[(t*2)+1]);
118                     rogue.hp_current -= get_damage("1d6", 1);
119                     if (rogue.hp_current <= 0) {
120                               rogue.hp_current = 0;
121                     }
122                     if ((!sustain_strength) && rand_percent(40) &&
123                               (rogue.str_current >= 3)) {
124                               rogue.str_current--;
125                     }
126                     print_stats(STAT_HP | STAT_STRENGTH);
127                     if (rogue.hp_current <= 0) {
128                               killed_by((object *)0, POISON_DART);
129                     }
130                     break;
131           case SLEEPING_GAS_TRAP:
132                     messagef(1, "%s", trap_strings[(t*2)+1]);
133                     take_a_nap();
134                     break;
135           case RUST_TRAP:
136                     messagef(1, "%s", trap_strings[(t*2)+1]);
137                     rust(NULL);
138                     break;
139           }
140 }
141 
142 void
add_traps(void)143 add_traps(void)
144 {
145           short i, n, tries = 0;
146           short row, col;
147 
148           if (cur_level <= 2) {
149                     n = 0;
150           } else if (cur_level <= 7) {
151                     n = get_rand(0, 2);
152           } else if (cur_level <= 11) {
153                     n = get_rand(1, 2);
154           } else if (cur_level <= 16) {
155                     n = get_rand(2, 3);
156           } else if (cur_level <= 21) {
157                     n = get_rand(2, 4);
158           } else if (cur_level <= (AMULET_LEVEL + 2)) {
159                     n = get_rand(3, 5);
160           } else {
161                     n = get_rand(5, MAX_TRAPS);
162           }
163           for (i = 0; i < n; i++) {
164                     traps[i].trap_type = get_rand(0, (TRAPS - 1));
165 
166                     if ((i == 0) && (party_room != NO_ROOM)) {
167                               do {
168                                         row = get_rand((rooms[party_room].top_row+1),
169                                                             (rooms[party_room].bottom_row-1));
170                                         col = get_rand((rooms[party_room].left_col+1),
171                                                             (rooms[party_room].right_col-1));
172                                         tries++;
173                               } while (((dungeon[row][col] & (OBJECT|STAIRS|TRAP|TUNNEL)) ||
174                                                   (dungeon[row][col] == NOTHING)) && (tries < 15));
175                               if (tries >= 15) {
176                                         gr_row_col(&row, &col, (FLOOR | MONSTER));
177                               }
178                     } else {
179                               gr_row_col(&row, &col, (FLOOR | MONSTER));
180                     }
181                     traps[i].trap_row = row;
182                     traps[i].trap_col = col;
183                     dungeon[row][col] |= (TRAP | HIDDEN);
184           }
185 }
186 
187 void
id_trap(void)188 id_trap(void)
189 {
190           short dir, row, col, d, t;
191 
192           messagef(0, "direction? ");
193 
194           while (!is_direction(dir = rgetchar(), &d)) {
195                     sound_bell();
196           }
197           check_message();
198 
199           if (dir == CANCEL) {
200                     return;
201           }
202           row = rogue.row;
203           col = rogue.col;
204 
205           get_dir_rc(d, &row, &col, 0);
206 
207           if ((dungeon[row][col] & TRAP) && (!(dungeon[row][col] & HIDDEN))) {
208                     t = trap_at(row, col);
209                     messagef(0, "%s", trap_strings[t*2]);
210           } else {
211                     messagef(0, "no trap there");
212           }
213 }
214 
215 void
show_traps(void)216 show_traps(void)
217 {
218           short i, j;
219 
220           for (i = 0; i < DROWS; i++) {
221                     for (j = 0; j < DCOLS; j++) {
222                               if (dungeon[i][j] & TRAP) {
223                                         mvaddch(i, j, '^');
224                               }
225                     }
226           }
227 }
228 
229 void
search(short n,boolean is_auto)230 search(short n, boolean is_auto)
231 {
232           short s, i, j, row, col, t;
233           short shown = 0, found = 0;
234           static boolean reg_search;
235 
236           for (i = -1; i <= 1; i++) {
237                     for (j = -1; j <= 1; j++) {
238                               row = rogue.row + i;
239                               col = rogue.col + j;
240                               if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
241                                                   (col < 0) || (col >= DCOLS)) {
242                                         continue;
243                               }
244                               if (dungeon[row][col] & HIDDEN) {
245                                         found++;
246                               }
247                     }
248           }
249           for (s = 0; s < n; s++) {
250                     for (i = -1; i <= 1; i++) {
251                               for (j = -1; j <= 1; j++) {
252                                         row = rogue.row + i;
253                                         col = rogue.col + j ;
254                                         if ((row < MIN_ROW) || (row >= (DROWS-1)) ||
255                                                             (col < 0) || (col >= DCOLS)) {
256                                                   continue;
257                                         }
258                                         if (dungeon[row][col] & HIDDEN) {
259                                                   if (rand_percent(17 + (rogue.exp + ring_exp))) {
260                                                             dungeon[row][col] &= (~HIDDEN);
261                                                             if ((!blind) && ((row != rogue.row) ||
262                                                                                 (col != rogue.col))) {
263                                                                       mvaddch(row, col, get_dungeon_char(row, col));
264                                                             }
265                                                             shown++;
266                                                             if (dungeon[row][col] & TRAP) {
267                                                                       t = trap_at(row, col);
268                                                                       messagef(1, "%s",
269                                                                                  trap_strings[t*2]);
270                                                             }
271                                                   }
272                                         }
273                                         if (((shown == found) && (found > 0)) || interrupted) {
274                                                   return;
275                                         }
276                               }
277                     }
278                     if ((!is_auto) && (reg_search = !reg_search)) {
279                               (void)reg_move();
280                     }
281           }
282 }
283