1 /* 2 * Copyright (c) 1988 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)zap.c 5.3 (Berkeley) 06/01/90"; 13 #endif /* not lint */ 14 15 /* 16 * zap.c 17 * 18 * This source herein may be modified and/or distributed by anybody who 19 * so desires, with the following restrictions: 20 * 1.) No portion of this notice shall be removed. 21 * 2.) Credit shall not be taken for the creation of this source. 22 * 3.) This code is not to be traded, sold, or used for personal 23 * gain or profit. 24 * 25 */ 26 27 #include "rogue.h" 28 29 boolean wizard = 0; 30 31 extern boolean being_held, score_only, detect_monster; 32 extern short cur_room; 33 34 zapp() 35 { 36 short wch; 37 boolean first_miss = 1; 38 object *wand; 39 short dir, d, row, col; 40 object *monster; 41 42 while (!is_direction(dir = rgetchar(), &d)) { 43 sound_bell(); 44 if (first_miss) { 45 message("direction? ", 0); 46 first_miss = 0; 47 } 48 } 49 check_message(); 50 if (dir == CANCEL) { 51 return; 52 } 53 if ((wch = pack_letter("zap with what?", WAND)) == CANCEL) { 54 return; 55 } 56 check_message(); 57 58 if (!(wand = get_letter_object(wch))) { 59 message("no such item.", 0); 60 return; 61 } 62 if (wand->what_is != WAND) { 63 message("you can't zap with that", 0); 64 return; 65 } 66 if (wand->class <= 0) { 67 message("nothing happens", 0); 68 } else { 69 wand->class--; 70 row = rogue.row; col = rogue.col; 71 if ((wand->which_kind == COLD) || (wand->which_kind == FIRE)) { 72 bounce((short) wand->which_kind, d, row, col, 0); 73 } else { 74 monster = get_zapped_monster(d, &row, &col); 75 if (wand->which_kind == DRAIN_LIFE) { 76 wdrain_life(monster); 77 } else if (monster) { 78 wake_up(monster); 79 s_con_mon(monster); 80 zap_monster(monster, wand->which_kind); 81 relight(); 82 } 83 } 84 } 85 (void) reg_move(); 86 } 87 88 object * 89 get_zapped_monster(dir, row, col) 90 short dir; 91 short *row, *col; 92 { 93 short orow, ocol; 94 95 for (;;) { 96 orow = *row; ocol = *col; 97 get_dir_rc(dir, row, col, 0); 98 if (((*row == orow) && (*col == ocol)) || 99 (dungeon[*row][*col] & (HORWALL | VERTWALL)) || 100 (dungeon[*row][*col] == NOTHING)) { 101 return(0); 102 } 103 if (dungeon[*row][*col] & MONSTER) { 104 if (!imitating(*row, *col)) { 105 return(object_at(&level_monsters, *row, *col)); 106 } 107 } 108 } 109 } 110 111 zap_monster(monster, kind) 112 object *monster; 113 unsigned short kind; 114 { 115 short row, col; 116 object *nm; 117 short tc; 118 119 row = monster->row; 120 col = monster->col; 121 122 switch(kind) { 123 case SLOW_MONSTER: 124 if (monster->m_flags & HASTED) { 125 monster->m_flags &= (~HASTED); 126 } else { 127 monster->slowed_toggle = 0; 128 monster->m_flags |= SLOWED; 129 } 130 break; 131 case HASTE_MONSTER: 132 if (monster->m_flags & SLOWED) { 133 monster->m_flags &= (~SLOWED); 134 } else { 135 monster->m_flags |= HASTED; 136 } 137 break; 138 case TELE_AWAY: 139 tele_away(monster); 140 break; 141 case INVISIBILITY: 142 monster->m_flags |= INVISIBLE; 143 break; 144 case POLYMORPH: 145 if (monster->m_flags & HOLDS) { 146 being_held = 0; 147 } 148 nm = monster->next_monster; 149 tc = monster->trail_char; 150 (void) gr_monster(monster, get_rand(0, MONSTERS-1)); 151 monster->row = row; 152 monster->col = col; 153 monster->next_monster = nm; 154 monster->trail_char = tc; 155 if (!(monster->m_flags & IMITATES)) { 156 wake_up(monster); 157 } 158 break; 159 case MAGIC_MISSILE: 160 rogue_hit(monster, 1); 161 break; 162 case CANCELLATION: 163 if (monster->m_flags & HOLDS) { 164 being_held = 0; 165 } 166 if (monster->m_flags & STEALS_ITEM) { 167 monster->drop_percent = 0; 168 } 169 monster->m_flags &= (~(FLIES | FLITS | SPECIAL_HIT | INVISIBLE | 170 FLAMES | IMITATES | CONFUSES | SEEKS_GOLD | HOLDS)); 171 break; 172 case DO_NOTHING: 173 message("nothing happens", 0); 174 break; 175 } 176 } 177 178 tele_away(monster) 179 object *monster; 180 { 181 short row, col; 182 183 if (monster->m_flags & HOLDS) { 184 being_held = 0; 185 } 186 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT)); 187 mvaddch(monster->row, monster->col, monster->trail_char); 188 dungeon[monster->row][monster->col] &= ~MONSTER; 189 monster->row = row; monster->col = col; 190 dungeon[row][col] |= MONSTER; 191 monster->trail_char = mvinch(row, col); 192 if (detect_monster || rogue_can_see(row, col)) { 193 mvaddch(row, col, gmc(monster)); 194 } 195 } 196 197 wizardize() 198 { 199 char buf[100]; 200 201 if (wizard) { 202 wizard = 0; 203 message("not wizard anymore", 0); 204 } else { 205 if (get_input_line("wizard's password:", "", buf, "", 0, 0)) { 206 (void) xxx(1); 207 xxxx(buf, strlen(buf)); 208 if (!strncmp(buf, "\247\104\126\272\115\243\027", 7)) { 209 wizard = 1; 210 score_only = 1; 211 message("Welcome, mighty wizard!", 0); 212 } else { 213 message("sorry", 0); 214 } 215 } 216 } 217 } 218 219 wdrain_life(monster) 220 object *monster; 221 { 222 short hp; 223 object *lmon, *nm; 224 225 hp = rogue.hp_current / 3; 226 rogue.hp_current = (rogue.hp_current + 1) / 2; 227 228 if (cur_room >= 0) { 229 lmon = level_monsters.next_monster; 230 while (lmon) { 231 nm = lmon->next_monster; 232 if (get_room_number(lmon->row, lmon->col) == cur_room) { 233 wake_up(lmon); 234 (void) mon_damage(lmon, hp); 235 } 236 lmon = nm; 237 } 238 } else { 239 if (monster) { 240 wake_up(monster); 241 (void) mon_damage(monster, hp); 242 } 243 } 244 print_stats(STAT_HP); 245 relight(); 246 } 247 248 bounce(ball, dir, row, col, r) 249 short ball, dir, row, col, r; 250 { 251 short orow, ocol; 252 char buf[DCOLS], *s; 253 short i, ch, new_dir = -1, damage; 254 static short btime; 255 256 if (++r == 1) { 257 btime = get_rand(3, 6); 258 } else if (r > btime) { 259 return; 260 } 261 262 if (ball == FIRE) { 263 s = "fire"; 264 } else { 265 s = "ice"; 266 } 267 if (r > 1) { 268 sprintf(buf, "the %s bounces", s); 269 message(buf, 0); 270 } 271 orow = row; 272 ocol = col; 273 do { 274 ch = mvinch(orow, ocol); 275 standout(); 276 mvaddch(orow, ocol, ch); 277 get_dir_rc(dir, &orow, &ocol, 1); 278 } while (!( (ocol <= 0) || 279 (ocol >= DCOLS-1) || 280 (dungeon[orow][ocol] == NOTHING) || 281 (dungeon[orow][ocol] & MONSTER) || 282 (dungeon[orow][ocol] & (HORWALL | VERTWALL)) || 283 ((orow == rogue.row) && (ocol == rogue.col)))); 284 standend(); 285 refresh(); 286 do { 287 orow = row; 288 ocol = col; 289 ch = mvinch(row, col); 290 mvaddch(row, col, ch); 291 get_dir_rc(dir, &row, &col, 1); 292 } while (!( (col <= 0) || 293 (col >= DCOLS-1) || 294 (dungeon[row][col] == NOTHING) || 295 (dungeon[row][col] & MONSTER) || 296 (dungeon[row][col] & (HORWALL | VERTWALL)) || 297 ((row == rogue.row) && (col == rogue.col)))); 298 299 if (dungeon[row][col] & MONSTER) { 300 object *monster; 301 302 monster = object_at(&level_monsters, row, col); 303 304 wake_up(monster); 305 if (rand_percent(33)) { 306 sprintf(buf, "the %s misses the %s", s, mon_name(monster)); 307 message(buf, 0); 308 goto ND; 309 } 310 if (ball == FIRE) { 311 if (!(monster->m_flags & RUSTS)) { 312 if (monster->m_flags & FREEZES) { 313 damage = monster->hp_to_kill; 314 } else if (monster->m_flags & FLAMES) { 315 damage = (monster->hp_to_kill / 10) + 1; 316 } else { 317 damage = get_rand((rogue.hp_current / 3), rogue.hp_max); 318 } 319 } else { 320 damage = (monster->hp_to_kill / 2) + 1; 321 } 322 sprintf(buf, "the %s hits the %s", s, mon_name(monster)); 323 message(buf, 0); 324 (void) mon_damage(monster, damage); 325 } else { 326 damage = -1; 327 if (!(monster->m_flags & FREEZES)) { 328 if (rand_percent(33)) { 329 message("the monster is frozen", 0); 330 monster->m_flags |= (ASLEEP | NAPPING); 331 monster->nap_length = get_rand(3, 6); 332 } else { 333 damage = rogue.hp_current / 4; 334 } 335 } else { 336 damage = -2; 337 } 338 if (damage != -1) { 339 sprintf(buf, "the %s hits the %s", s, mon_name(monster)); 340 message(buf, 0); 341 (void) mon_damage(monster, damage); 342 } 343 } 344 } else if ((row == rogue.row) && (col == rogue.col)) { 345 if (rand_percent(10 + (3 * get_armor_class(rogue.armor)))) { 346 sprintf(buf, "the %s misses", s); 347 message(buf, 0); 348 goto ND; 349 } else { 350 damage = get_rand(3, (3 * rogue.exp)); 351 if (ball == FIRE) { 352 damage = (damage * 3) / 2; 353 damage -= get_armor_class(rogue.armor); 354 } 355 sprintf(buf, "the %s hits", s); 356 rogue_damage(damage, (object *) 0, 357 ((ball == FIRE) ? KFIRE : HYPOTHERMIA)); 358 message(buf, 0); 359 } 360 } else { 361 short nrow, ncol; 362 363 ND: for (i = 0; i < 10; i++) { 364 dir = get_rand(0, DIRS-1); 365 nrow = orow; 366 ncol = ocol; 367 get_dir_rc(dir, &nrow, &ncol, 1); 368 if (((ncol >= 0) && (ncol <= DCOLS-1)) && 369 (dungeon[nrow][ncol] != NOTHING) && 370 (!(dungeon[nrow][ncol] & (VERTWALL | HORWALL)))) { 371 new_dir = dir; 372 break; 373 } 374 } 375 if (new_dir != -1) { 376 bounce(ball, new_dir, orow, ocol, r); 377 } 378 } 379 } 380