Home | History | Annotate | Line # | Download | only in rogue
      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
     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
     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
    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
    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
    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
    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