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