132689Sbostic /*
2*60842Sbostic * Copyright (c) 1988, 1993
3*60842Sbostic * The Regents of the University of California. All rights reserved.
436704Sbostic *
536704Sbostic * This code is derived from software contributed to Berkeley by
636704Sbostic * Timothy C. Stoehr.
736704Sbostic *
842604Sbostic * %sccs.include.redist.c%
936704Sbostic */
1036704Sbostic
1136704Sbostic #ifndef lint
12*60842Sbostic static char sccsid[] = "@(#)zap.c 8.1 (Berkeley) 05/31/93";
1336704Sbostic #endif /* not lint */
1436704Sbostic
1536704Sbostic /*
1632689Sbostic * zap.c
1732689Sbostic *
1832689Sbostic * This source herein may be modified and/or distributed by anybody who
1932689Sbostic * so desires, with the following restrictions:
2032689Sbostic * 1.) No portion of this notice shall be removed.
2132689Sbostic * 2.) Credit shall not be taken for the creation of this source.
2232689Sbostic * 3.) This code is not to be traded, sold, or used for personal
2332689Sbostic * gain or profit.
2432689Sbostic *
2532689Sbostic */
2632689Sbostic
2732689Sbostic #include "rogue.h"
2832689Sbostic
2932689Sbostic boolean wizard = 0;
3032689Sbostic
3132689Sbostic extern boolean being_held, score_only, detect_monster;
3232689Sbostic extern short cur_room;
3332689Sbostic
zapp()3432689Sbostic zapp()
3532689Sbostic {
3632689Sbostic short wch;
3732689Sbostic boolean first_miss = 1;
3832689Sbostic object *wand;
3932689Sbostic short dir, d, row, col;
4032689Sbostic object *monster;
4132689Sbostic
4232689Sbostic while (!is_direction(dir = rgetchar(), &d)) {
4332689Sbostic sound_bell();
4432689Sbostic if (first_miss) {
4532689Sbostic message("direction? ", 0);
4632689Sbostic first_miss = 0;
4732689Sbostic }
4832689Sbostic }
4932689Sbostic check_message();
5032689Sbostic if (dir == CANCEL) {
5132689Sbostic return;
5232689Sbostic }
5332689Sbostic if ((wch = pack_letter("zap with what?", WAND)) == CANCEL) {
5432689Sbostic return;
5532689Sbostic }
5632689Sbostic check_message();
5732689Sbostic
5832689Sbostic if (!(wand = get_letter_object(wch))) {
5932689Sbostic message("no such item.", 0);
6032689Sbostic return;
6132689Sbostic }
6232689Sbostic if (wand->what_is != WAND) {
6332689Sbostic message("you can't zap with that", 0);
6432689Sbostic return;
6532689Sbostic }
6632689Sbostic if (wand->class <= 0) {
6732689Sbostic message("nothing happens", 0);
6832689Sbostic } else {
6932689Sbostic wand->class--;
7032689Sbostic row = rogue.row; col = rogue.col;
7132689Sbostic if ((wand->which_kind == COLD) || (wand->which_kind == FIRE)) {
7232689Sbostic bounce((short) wand->which_kind, d, row, col, 0);
7332689Sbostic } else {
7432689Sbostic monster = get_zapped_monster(d, &row, &col);
7532689Sbostic if (wand->which_kind == DRAIN_LIFE) {
7632689Sbostic wdrain_life(monster);
7732689Sbostic } else if (monster) {
7832689Sbostic wake_up(monster);
7932689Sbostic s_con_mon(monster);
8032689Sbostic zap_monster(monster, wand->which_kind);
8132689Sbostic relight();
8232689Sbostic }
8332689Sbostic }
8432689Sbostic }
8532689Sbostic (void) reg_move();
8632689Sbostic }
8732689Sbostic
8832689Sbostic object *
get_zapped_monster(dir,row,col)8932689Sbostic get_zapped_monster(dir, row, col)
9032689Sbostic short dir;
9132689Sbostic short *row, *col;
9232689Sbostic {
9332689Sbostic short orow, ocol;
9432689Sbostic
9532689Sbostic for (;;) {
9632689Sbostic orow = *row; ocol = *col;
9732689Sbostic get_dir_rc(dir, row, col, 0);
9832689Sbostic if (((*row == orow) && (*col == ocol)) ||
9932689Sbostic (dungeon[*row][*col] & (HORWALL | VERTWALL)) ||
10032689Sbostic (dungeon[*row][*col] == NOTHING)) {
10132689Sbostic return(0);
10232689Sbostic }
10332689Sbostic if (dungeon[*row][*col] & MONSTER) {
10432689Sbostic if (!imitating(*row, *col)) {
10532689Sbostic return(object_at(&level_monsters, *row, *col));
10632689Sbostic }
10732689Sbostic }
10832689Sbostic }
10932689Sbostic }
11032689Sbostic
zap_monster(monster,kind)11132689Sbostic zap_monster(monster, kind)
11232689Sbostic object *monster;
11332689Sbostic unsigned short kind;
11432689Sbostic {
11532689Sbostic short row, col;
11632689Sbostic object *nm;
11732689Sbostic short tc;
11832689Sbostic
11932689Sbostic row = monster->row;
12032689Sbostic col = monster->col;
12132689Sbostic
12232689Sbostic switch(kind) {
12332689Sbostic case SLOW_MONSTER:
12432689Sbostic if (monster->m_flags & HASTED) {
12532689Sbostic monster->m_flags &= (~HASTED);
12632689Sbostic } else {
12732689Sbostic monster->slowed_toggle = 0;
12832689Sbostic monster->m_flags |= SLOWED;
12932689Sbostic }
13032689Sbostic break;
13132689Sbostic case HASTE_MONSTER:
13232689Sbostic if (monster->m_flags & SLOWED) {
13332689Sbostic monster->m_flags &= (~SLOWED);
13432689Sbostic } else {
13532689Sbostic monster->m_flags |= HASTED;
13632689Sbostic }
13732689Sbostic break;
13832689Sbostic case TELE_AWAY:
13932689Sbostic tele_away(monster);
14032689Sbostic break;
14132689Sbostic case INVISIBILITY:
14232689Sbostic monster->m_flags |= INVISIBLE;
14332689Sbostic break;
14432689Sbostic case POLYMORPH:
14532689Sbostic if (monster->m_flags & HOLDS) {
14632689Sbostic being_held = 0;
14732689Sbostic }
14832689Sbostic nm = monster->next_monster;
14932689Sbostic tc = monster->trail_char;
15032689Sbostic (void) gr_monster(monster, get_rand(0, MONSTERS-1));
15132689Sbostic monster->row = row;
15232689Sbostic monster->col = col;
15332689Sbostic monster->next_monster = nm;
15432689Sbostic monster->trail_char = tc;
15532689Sbostic if (!(monster->m_flags & IMITATES)) {
15632689Sbostic wake_up(monster);
15732689Sbostic }
15832689Sbostic break;
15932689Sbostic case MAGIC_MISSILE:
16032689Sbostic rogue_hit(monster, 1);
16132689Sbostic break;
16232689Sbostic case CANCELLATION:
16332689Sbostic if (monster->m_flags & HOLDS) {
16432689Sbostic being_held = 0;
16532689Sbostic }
16632689Sbostic if (monster->m_flags & STEALS_ITEM) {
16732689Sbostic monster->drop_percent = 0;
16832689Sbostic }
16932689Sbostic monster->m_flags &= (~(FLIES | FLITS | SPECIAL_HIT | INVISIBLE |
17032689Sbostic FLAMES | IMITATES | CONFUSES | SEEKS_GOLD | HOLDS));
17132689Sbostic break;
17232689Sbostic case DO_NOTHING:
17332689Sbostic message("nothing happens", 0);
17432689Sbostic break;
17532689Sbostic }
17632689Sbostic }
17732689Sbostic
tele_away(monster)17832689Sbostic tele_away(monster)
17932689Sbostic object *monster;
18032689Sbostic {
18132689Sbostic short row, col;
18232689Sbostic
18332689Sbostic if (monster->m_flags & HOLDS) {
18432689Sbostic being_held = 0;
18532689Sbostic }
18632689Sbostic gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
18732689Sbostic mvaddch(monster->row, monster->col, monster->trail_char);
18832689Sbostic dungeon[monster->row][monster->col] &= ~MONSTER;
18932689Sbostic monster->row = row; monster->col = col;
19032689Sbostic dungeon[row][col] |= MONSTER;
19132689Sbostic monster->trail_char = mvinch(row, col);
19232689Sbostic if (detect_monster || rogue_can_see(row, col)) {
19332689Sbostic mvaddch(row, col, gmc(monster));
19432689Sbostic }
19532689Sbostic }
19632689Sbostic
wizardize()19732689Sbostic wizardize()
19832689Sbostic {
19932689Sbostic char buf[100];
20032689Sbostic
20132689Sbostic if (wizard) {
20232689Sbostic wizard = 0;
20332689Sbostic message("not wizard anymore", 0);
20432689Sbostic } else {
20532689Sbostic if (get_input_line("wizard's password:", "", buf, "", 0, 0)) {
20632689Sbostic (void) xxx(1);
20732689Sbostic xxxx(buf, strlen(buf));
20832689Sbostic if (!strncmp(buf, "\247\104\126\272\115\243\027", 7)) {
20932689Sbostic wizard = 1;
21032689Sbostic score_only = 1;
21132689Sbostic message("Welcome, mighty wizard!", 0);
21232689Sbostic } else {
21332689Sbostic message("sorry", 0);
21432689Sbostic }
21532689Sbostic }
21632689Sbostic }
21732689Sbostic }
21832689Sbostic
wdrain_life(monster)21932689Sbostic wdrain_life(monster)
22032689Sbostic object *monster;
22132689Sbostic {
22232689Sbostic short hp;
22332689Sbostic object *lmon, *nm;
22432689Sbostic
22532689Sbostic hp = rogue.hp_current / 3;
22632689Sbostic rogue.hp_current = (rogue.hp_current + 1) / 2;
22732689Sbostic
22832689Sbostic if (cur_room >= 0) {
22932689Sbostic lmon = level_monsters.next_monster;
23032689Sbostic while (lmon) {
23132689Sbostic nm = lmon->next_monster;
23232689Sbostic if (get_room_number(lmon->row, lmon->col) == cur_room) {
23332689Sbostic wake_up(lmon);
23432689Sbostic (void) mon_damage(lmon, hp);
23532689Sbostic }
23632689Sbostic lmon = nm;
23732689Sbostic }
23832689Sbostic } else {
23932689Sbostic if (monster) {
24032689Sbostic wake_up(monster);
24132689Sbostic (void) mon_damage(monster, hp);
24232689Sbostic }
24332689Sbostic }
24432689Sbostic print_stats(STAT_HP);
24532689Sbostic relight();
24632689Sbostic }
24732689Sbostic
bounce(ball,dir,row,col,r)24832689Sbostic bounce(ball, dir, row, col, r)
24932689Sbostic short ball, dir, row, col, r;
25032689Sbostic {
25132689Sbostic short orow, ocol;
25232689Sbostic char buf[DCOLS], *s;
25332689Sbostic short i, ch, new_dir = -1, damage;
25432689Sbostic static short btime;
25532689Sbostic
25632689Sbostic if (++r == 1) {
25732689Sbostic btime = get_rand(3, 6);
25832689Sbostic } else if (r > btime) {
25932689Sbostic return;
26032689Sbostic }
26132689Sbostic
26232689Sbostic if (ball == FIRE) {
26332689Sbostic s = "fire";
26432689Sbostic } else {
26532689Sbostic s = "ice";
26632689Sbostic }
26732689Sbostic if (r > 1) {
26832689Sbostic sprintf(buf, "the %s bounces", s);
26932689Sbostic message(buf, 0);
27032689Sbostic }
27132689Sbostic orow = row;
27232689Sbostic ocol = col;
27332689Sbostic do {
27432689Sbostic ch = mvinch(orow, ocol);
27532689Sbostic standout();
27632689Sbostic mvaddch(orow, ocol, ch);
27732689Sbostic get_dir_rc(dir, &orow, &ocol, 1);
27832689Sbostic } while (!( (ocol <= 0) ||
27932689Sbostic (ocol >= DCOLS-1) ||
28032689Sbostic (dungeon[orow][ocol] == NOTHING) ||
28132689Sbostic (dungeon[orow][ocol] & MONSTER) ||
28232689Sbostic (dungeon[orow][ocol] & (HORWALL | VERTWALL)) ||
28332689Sbostic ((orow == rogue.row) && (ocol == rogue.col))));
28432689Sbostic standend();
28532689Sbostic refresh();
28632689Sbostic do {
28732689Sbostic orow = row;
28832689Sbostic ocol = col;
28932689Sbostic ch = mvinch(row, col);
29032689Sbostic mvaddch(row, col, ch);
29132689Sbostic get_dir_rc(dir, &row, &col, 1);
29232689Sbostic } while (!( (col <= 0) ||
29332689Sbostic (col >= DCOLS-1) ||
29432689Sbostic (dungeon[row][col] == NOTHING) ||
29532689Sbostic (dungeon[row][col] & MONSTER) ||
29632689Sbostic (dungeon[row][col] & (HORWALL | VERTWALL)) ||
29732689Sbostic ((row == rogue.row) && (col == rogue.col))));
29832689Sbostic
29932689Sbostic if (dungeon[row][col] & MONSTER) {
30032689Sbostic object *monster;
30132689Sbostic
30232689Sbostic monster = object_at(&level_monsters, row, col);
30332689Sbostic
30432689Sbostic wake_up(monster);
30532689Sbostic if (rand_percent(33)) {
30632689Sbostic sprintf(buf, "the %s misses the %s", s, mon_name(monster));
30732689Sbostic message(buf, 0);
30832689Sbostic goto ND;
30932689Sbostic }
31032689Sbostic if (ball == FIRE) {
31132689Sbostic if (!(monster->m_flags & RUSTS)) {
31232689Sbostic if (monster->m_flags & FREEZES) {
31332689Sbostic damage = monster->hp_to_kill;
31432689Sbostic } else if (monster->m_flags & FLAMES) {
31532689Sbostic damage = (monster->hp_to_kill / 10) + 1;
31632689Sbostic } else {
31732689Sbostic damage = get_rand((rogue.hp_current / 3), rogue.hp_max);
31832689Sbostic }
31932689Sbostic } else {
32032689Sbostic damage = (monster->hp_to_kill / 2) + 1;
32132689Sbostic }
32232689Sbostic sprintf(buf, "the %s hits the %s", s, mon_name(monster));
32332689Sbostic message(buf, 0);
32432689Sbostic (void) mon_damage(monster, damage);
32532689Sbostic } else {
32632689Sbostic damage = -1;
32732689Sbostic if (!(monster->m_flags & FREEZES)) {
32832689Sbostic if (rand_percent(33)) {
32932689Sbostic message("the monster is frozen", 0);
33032689Sbostic monster->m_flags |= (ASLEEP | NAPPING);
33132689Sbostic monster->nap_length = get_rand(3, 6);
33232689Sbostic } else {
33332689Sbostic damage = rogue.hp_current / 4;
33432689Sbostic }
33532689Sbostic } else {
33632689Sbostic damage = -2;
33732689Sbostic }
33832689Sbostic if (damage != -1) {
33932689Sbostic sprintf(buf, "the %s hits the %s", s, mon_name(monster));
34032689Sbostic message(buf, 0);
34132689Sbostic (void) mon_damage(monster, damage);
34232689Sbostic }
34332689Sbostic }
34432689Sbostic } else if ((row == rogue.row) && (col == rogue.col)) {
34532689Sbostic if (rand_percent(10 + (3 * get_armor_class(rogue.armor)))) {
34632689Sbostic sprintf(buf, "the %s misses", s);
34732689Sbostic message(buf, 0);
34832689Sbostic goto ND;
34932689Sbostic } else {
35032689Sbostic damage = get_rand(3, (3 * rogue.exp));
35132689Sbostic if (ball == FIRE) {
35232689Sbostic damage = (damage * 3) / 2;
35332689Sbostic damage -= get_armor_class(rogue.armor);
35432689Sbostic }
35532689Sbostic sprintf(buf, "the %s hits", s);
35632689Sbostic rogue_damage(damage, (object *) 0,
35732689Sbostic ((ball == FIRE) ? KFIRE : HYPOTHERMIA));
35832689Sbostic message(buf, 0);
35932689Sbostic }
36032689Sbostic } else {
36132689Sbostic short nrow, ncol;
36232689Sbostic
36332689Sbostic ND: for (i = 0; i < 10; i++) {
36432689Sbostic dir = get_rand(0, DIRS-1);
36532689Sbostic nrow = orow;
36632689Sbostic ncol = ocol;
36732689Sbostic get_dir_rc(dir, &nrow, &ncol, 1);
36832689Sbostic if (((ncol >= 0) && (ncol <= DCOLS-1)) &&
36932689Sbostic (dungeon[nrow][ncol] != NOTHING) &&
37032689Sbostic (!(dungeon[nrow][ncol] & (VERTWALL | HORWALL)))) {
37132689Sbostic new_dir = dir;
37232689Sbostic break;
37332689Sbostic }
37432689Sbostic }
37532689Sbostic if (new_dir != -1) {
37632689Sbostic bounce(ball, new_dir, orow, ocol, r);
37732689Sbostic }
37832689Sbostic }
37932689Sbostic }
380