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: }