132689Sbostic /* 236704Sbostic * Copyright (c) 1988 The Regents of the University of California. 336704Sbostic * All rights reserved. 436704Sbostic * 536704Sbostic * This code is derived from software contributed to Berkeley by 636704Sbostic * Timothy C. Stoehr. 736704Sbostic * 8*42604Sbostic * %sccs.include.redist.c% 936704Sbostic */ 1036704Sbostic 1136704Sbostic #ifndef lint 12*42604Sbostic static char sccsid[] = "@(#)spec_hit.c 5.3 (Berkeley) 06/01/90"; 1336704Sbostic #endif /* not lint */ 1436704Sbostic 1536704Sbostic /* 1632689Sbostic * special_hit.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 short less_hp = 0; 3032689Sbostic boolean being_held; 3132689Sbostic 3232689Sbostic extern short cur_level, max_level, blind, levitate, ring_exp; 3332689Sbostic extern long level_points[]; 3432689Sbostic extern boolean detect_monster, mon_disappeared; 3532689Sbostic extern boolean sustain_strength, maintain_armor; 3632689Sbostic extern char *you_can_move_again; 3732689Sbostic 3832689Sbostic special_hit(monster) 3932689Sbostic object *monster; 4032689Sbostic { 4132689Sbostic if ((monster->m_flags & CONFUSED) && rand_percent(66)) { 4232689Sbostic return; 4332689Sbostic } 4432689Sbostic if (monster->m_flags & RUSTS) { 4532689Sbostic rust(monster); 4632689Sbostic } 4732689Sbostic if ((monster->m_flags & HOLDS) && !levitate) { 4832689Sbostic being_held = 1; 4932689Sbostic } 5032689Sbostic if (monster->m_flags & FREEZES) { 5132689Sbostic freeze(monster); 5232689Sbostic } 5332689Sbostic if (monster->m_flags & STINGS) { 5432689Sbostic sting(monster); 5532689Sbostic } 5632689Sbostic if (monster->m_flags & DRAINS_LIFE) { 5732689Sbostic drain_life(); 5832689Sbostic } 5932689Sbostic if (monster->m_flags & DROPS_LEVEL) { 6032689Sbostic drop_level(); 6132689Sbostic } 6232689Sbostic if (monster->m_flags & STEALS_GOLD) { 6332689Sbostic steal_gold(monster); 6432689Sbostic } else if (monster->m_flags & STEALS_ITEM) { 6532689Sbostic steal_item(monster); 6632689Sbostic } 6732689Sbostic } 6832689Sbostic 6932689Sbostic rust(monster) 7032689Sbostic object *monster; 7132689Sbostic { 7232689Sbostic if ((!rogue.armor) || (get_armor_class(rogue.armor) <= 1) || 7332689Sbostic (rogue.armor->which_kind == LEATHER)) { 7432689Sbostic return; 7532689Sbostic } 7632689Sbostic if ((rogue.armor->is_protected) || maintain_armor) { 7732689Sbostic if (monster && (!(monster->m_flags & RUST_VANISHED))) { 7832689Sbostic message("the rust vanishes instantly", 0); 7932689Sbostic monster->m_flags |= RUST_VANISHED; 8032689Sbostic } 8132689Sbostic } else { 8232689Sbostic rogue.armor->d_enchant--; 8332689Sbostic message("your armor weakens", 0); 8432689Sbostic print_stats(STAT_ARMOR); 8532689Sbostic } 8632689Sbostic } 8732689Sbostic 8832689Sbostic freeze(monster) 8932689Sbostic object *monster; 9032689Sbostic { 9132689Sbostic short freeze_percent = 99; 9232689Sbostic short i, n; 9332689Sbostic 9432689Sbostic if (rand_percent(12)) { 9532689Sbostic return; 9632689Sbostic } 9732689Sbostic freeze_percent -= (rogue.str_current+(rogue.str_current / 2)); 9832689Sbostic freeze_percent -= ((rogue.exp + ring_exp) * 4); 9932689Sbostic freeze_percent -= (get_armor_class(rogue.armor) * 5); 10032689Sbostic freeze_percent -= (rogue.hp_max / 3); 10132689Sbostic 10232689Sbostic if (freeze_percent > 10) { 10332689Sbostic monster->m_flags |= FREEZING_ROGUE; 10432689Sbostic message("you are frozen", 1); 10532689Sbostic 10632689Sbostic n = get_rand(4, 8); 10732689Sbostic for (i = 0; i < n; i++) { 10832689Sbostic mv_mons(); 10932689Sbostic } 11032689Sbostic if (rand_percent(freeze_percent)) { 11132689Sbostic for (i = 0; i < 50; i++) { 11232689Sbostic mv_mons(); 11332689Sbostic } 11432689Sbostic killed_by((object *)0, HYPOTHERMIA); 11532689Sbostic } 11632689Sbostic message(you_can_move_again, 1); 11732689Sbostic monster->m_flags &= (~FREEZING_ROGUE); 11832689Sbostic } 11932689Sbostic } 12032689Sbostic 12132689Sbostic steal_gold(monster) 12232689Sbostic object *monster; 12332689Sbostic { 12432689Sbostic int amount; 12532689Sbostic 12632689Sbostic if ((rogue.gold <= 0) || rand_percent(10)) { 12732689Sbostic return; 12832689Sbostic } 12932689Sbostic 13032689Sbostic amount = get_rand((cur_level * 10), (cur_level * 30)); 13132689Sbostic 13232689Sbostic if (amount > rogue.gold) { 13332689Sbostic amount = rogue.gold; 13432689Sbostic } 13532689Sbostic rogue.gold -= amount; 13632689Sbostic message("your purse feels lighter", 0); 13732689Sbostic print_stats(STAT_GOLD); 13832689Sbostic disappear(monster); 13932689Sbostic } 14032689Sbostic 14132689Sbostic steal_item(monster) 14232689Sbostic object *monster; 14332689Sbostic { 14432689Sbostic object *obj; 14532689Sbostic short i, n, t; 14632689Sbostic char desc[80]; 14732689Sbostic boolean has_something = 0; 14832689Sbostic 14932689Sbostic if (rand_percent(15)) { 15032689Sbostic return; 15132689Sbostic } 15232689Sbostic obj = rogue.pack.next_object; 15332689Sbostic 15432689Sbostic if (!obj) { 15532689Sbostic goto DSPR; 15632689Sbostic } 15732689Sbostic while (obj) { 15832689Sbostic if (!(obj->in_use_flags & BEING_USED)) { 15932689Sbostic has_something = 1; 16032689Sbostic break; 16132689Sbostic } 16232689Sbostic obj = obj->next_object; 16332689Sbostic } 16432689Sbostic if (!has_something) { 16532689Sbostic goto DSPR; 16632689Sbostic } 16732689Sbostic n = get_rand(0, MAX_PACK_COUNT); 16832689Sbostic obj = rogue.pack.next_object; 16932689Sbostic 17032689Sbostic for (i = 0; i <= n; i++) { 17132689Sbostic obj = obj->next_object; 17232689Sbostic while ((!obj) || (obj->in_use_flags & BEING_USED)) { 17332689Sbostic if (!obj) { 17432689Sbostic obj = rogue.pack.next_object; 17532689Sbostic } else { 17632689Sbostic obj = obj->next_object; 17732689Sbostic } 17832689Sbostic } 17932689Sbostic } 18032689Sbostic (void) strcpy(desc, "she stole "); 18132689Sbostic if (obj->what_is != WEAPON) { 18232689Sbostic t = obj->quantity; 18332689Sbostic obj->quantity = 1; 18432689Sbostic } 18532689Sbostic get_desc(obj, desc+10); 18632689Sbostic message(desc, 0); 18732689Sbostic 18832689Sbostic obj->quantity = ((obj->what_is != WEAPON) ? t : 1); 18932689Sbostic 19032689Sbostic vanish(obj, 0, &rogue.pack); 19132689Sbostic DSPR: 19232689Sbostic disappear(monster); 19332689Sbostic } 19432689Sbostic 19532689Sbostic disappear(monster) 19632689Sbostic object *monster; 19732689Sbostic { 19832689Sbostic short row, col; 19932689Sbostic 20032689Sbostic row = monster->row; 20132689Sbostic col = monster->col; 20232689Sbostic 20332689Sbostic dungeon[row][col] &= ~MONSTER; 20432689Sbostic if (rogue_can_see(row, col)) { 20532689Sbostic mvaddch(row, col, get_dungeon_char(row, col)); 20632689Sbostic } 20732689Sbostic take_from_pack(monster, &level_monsters); 20832689Sbostic free_object(monster); 20932689Sbostic mon_disappeared = 1; 21032689Sbostic } 21132689Sbostic 21232689Sbostic cough_up(monster) 21332689Sbostic object *monster; 21432689Sbostic { 21532689Sbostic object *obj; 21632689Sbostic short row, col, i, n; 21732689Sbostic 21832689Sbostic if (cur_level < max_level) { 21932689Sbostic return; 22032689Sbostic } 22132689Sbostic 22232689Sbostic if (monster->m_flags & STEALS_GOLD) { 22332689Sbostic obj = alloc_object(); 22432689Sbostic obj->what_is = GOLD; 22532689Sbostic obj->quantity = get_rand((cur_level * 15), (cur_level * 30)); 22632689Sbostic } else { 22732689Sbostic if (!rand_percent((int) monster->drop_percent)) { 22832689Sbostic return; 22932689Sbostic } 23032689Sbostic obj = gr_object(); 23132689Sbostic } 23232689Sbostic row = monster->row; 23332689Sbostic col = monster->col; 23432689Sbostic 23532689Sbostic for (n = 0; n <= 5; n++) { 23632689Sbostic for (i = -n; i <= n; i++) { 23732689Sbostic if (try_to_cough(row+n, col+i, obj)) { 23832689Sbostic return; 23932689Sbostic } 24032689Sbostic if (try_to_cough(row-n, col+i, obj)) { 24132689Sbostic return; 24232689Sbostic } 24332689Sbostic } 24432689Sbostic for (i = -n; i <= n; i++) { 24532689Sbostic if (try_to_cough(row+i, col-n, obj)) { 24632689Sbostic return; 24732689Sbostic } 24832689Sbostic if (try_to_cough(row+i, col+n, obj)) { 24932689Sbostic return; 25032689Sbostic } 25132689Sbostic } 25232689Sbostic } 25332689Sbostic free_object(obj); 25432689Sbostic } 25532689Sbostic 25632689Sbostic try_to_cough(row, col, obj) 25732689Sbostic short row, col; 25832689Sbostic object *obj; 25932689Sbostic { 26032689Sbostic if ((row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) || (col>(DCOLS-1))) { 26132689Sbostic return(0); 26232689Sbostic } 26332689Sbostic if ((!(dungeon[row][col] & (OBJECT | STAIRS | TRAP))) && 26432689Sbostic (dungeon[row][col] & (TUNNEL | FLOOR | DOOR))) { 26532689Sbostic place_at(obj, row, col); 26632689Sbostic if (((row != rogue.row) || (col != rogue.col)) && 26732689Sbostic (!(dungeon[row][col] & MONSTER))) { 26832689Sbostic mvaddch(row, col, get_dungeon_char(row, col)); 26932689Sbostic } 27032689Sbostic return(1); 27132689Sbostic } 27232689Sbostic return(0); 27332689Sbostic } 27432689Sbostic 27532689Sbostic seek_gold(monster) 27632689Sbostic object *monster; 27732689Sbostic { 27832689Sbostic short i, j, rn, s; 27932689Sbostic 28032689Sbostic if ((rn = get_room_number(monster->row, monster->col)) < 0) { 28132689Sbostic return(0); 28232689Sbostic } 28332689Sbostic for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) { 28432689Sbostic for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) { 28532689Sbostic if ((gold_at(i, j)) && !(dungeon[i][j] & MONSTER)) { 28632689Sbostic monster->m_flags |= CAN_FLIT; 28732689Sbostic s = mon_can_go(monster, i, j); 28832689Sbostic monster->m_flags &= (~CAN_FLIT); 28932689Sbostic if (s) { 29032689Sbostic move_mon_to(monster, i, j); 29132689Sbostic monster->m_flags |= ASLEEP; 29232689Sbostic monster->m_flags &= (~(WAKENS | SEEKS_GOLD)); 29332689Sbostic return(1); 29432689Sbostic } 29532689Sbostic monster->m_flags &= (~SEEKS_GOLD); 29632689Sbostic monster->m_flags |= CAN_FLIT; 29732689Sbostic mv_1_monster(monster, i, j); 29832689Sbostic monster->m_flags &= (~CAN_FLIT); 29932689Sbostic monster->m_flags |= SEEKS_GOLD; 30032689Sbostic return(1); 30132689Sbostic } 30232689Sbostic } 30332689Sbostic } 30432689Sbostic return(0); 30532689Sbostic } 30632689Sbostic 30732689Sbostic gold_at(row, col) 30832689Sbostic short row, col; 30932689Sbostic { 31032689Sbostic if (dungeon[row][col] & OBJECT) { 31132689Sbostic object *obj; 31232689Sbostic 31332689Sbostic if ((obj = object_at(&level_objects, row, col)) && 31432689Sbostic (obj->what_is == GOLD)) { 31532689Sbostic return(1); 31632689Sbostic } 31732689Sbostic } 31832689Sbostic return(0); 31932689Sbostic } 32032689Sbostic 32132689Sbostic check_gold_seeker(monster) 32232689Sbostic object *monster; 32332689Sbostic { 32432689Sbostic monster->m_flags &= (~SEEKS_GOLD); 32532689Sbostic } 32632689Sbostic 32732689Sbostic check_imitator(monster) 32832689Sbostic object *monster; 32932689Sbostic { 33032689Sbostic char msg[80]; 33132689Sbostic 33232689Sbostic if (monster->m_flags & IMITATES) { 33332689Sbostic wake_up(monster); 33432689Sbostic if (!blind) { 33532689Sbostic mvaddch(monster->row, monster->col, 33632689Sbostic get_dungeon_char(monster->row, monster->col)); 33732689Sbostic check_message(); 33832689Sbostic sprintf(msg, "wait, that's a %s!", mon_name(monster)); 33932689Sbostic message(msg, 1); 34032689Sbostic } 34132689Sbostic return(1); 34232689Sbostic } 34332689Sbostic return(0); 34432689Sbostic } 34532689Sbostic 34632689Sbostic imitating(row, col) 34732689Sbostic register short row, col; 34832689Sbostic { 34932689Sbostic if (dungeon[row][col] & MONSTER) { 35032689Sbostic object *object_at(), *monster; 35132689Sbostic 35232689Sbostic if (monster = object_at(&level_monsters, row, col)) { 35332689Sbostic if (monster->m_flags & IMITATES) { 35432689Sbostic return(1); 35532689Sbostic } 35632689Sbostic } 35732689Sbostic } 35832689Sbostic return(0); 35932689Sbostic } 36032689Sbostic 36132689Sbostic sting(monster) 36232689Sbostic object *monster; 36332689Sbostic { 36432689Sbostic short sting_chance = 35; 36532689Sbostic char msg[80]; 36632689Sbostic 36732689Sbostic if ((rogue.str_current <= 3) || sustain_strength) { 36832689Sbostic return; 36932689Sbostic } 37032689Sbostic sting_chance += (6 * (6 - get_armor_class(rogue.armor))); 37132689Sbostic 37232689Sbostic if ((rogue.exp + ring_exp) > 8) { 37332689Sbostic sting_chance -= (6 * ((rogue.exp + ring_exp) - 8)); 37432689Sbostic } 37532689Sbostic if (rand_percent(sting_chance)) { 37632689Sbostic sprintf(msg, "the %s's bite has weakened you", 37732689Sbostic mon_name(monster)); 37832689Sbostic message(msg, 0); 37932689Sbostic rogue.str_current--; 38032689Sbostic print_stats(STAT_STRENGTH); 38132689Sbostic } 38232689Sbostic } 38332689Sbostic 38432689Sbostic drop_level() 38532689Sbostic { 38632689Sbostic int hp; 38732689Sbostic 38832689Sbostic if (rand_percent(80) || (rogue.exp <= 5)) { 38932689Sbostic return; 39032689Sbostic } 39132689Sbostic rogue.exp_points = level_points[rogue.exp-2] - get_rand(9, 29); 39232689Sbostic rogue.exp -= 2; 39332689Sbostic hp = hp_raise(); 39432689Sbostic if ((rogue.hp_current -= hp) <= 0) { 39532689Sbostic rogue.hp_current = 1; 39632689Sbostic } 39732689Sbostic if ((rogue.hp_max -= hp) <= 0) { 39832689Sbostic rogue.hp_max = 1; 39932689Sbostic } 40032689Sbostic add_exp(1, 0); 40132689Sbostic } 40232689Sbostic 40332689Sbostic drain_life() 40432689Sbostic { 40532689Sbostic short n; 40632689Sbostic 40732689Sbostic if (rand_percent(60) || (rogue.hp_max <= 30) || (rogue.hp_current < 10)) { 40832689Sbostic return; 40932689Sbostic } 41032689Sbostic n = get_rand(1, 3); /* 1 Hp, 2 Str, 3 both */ 41132689Sbostic 41232689Sbostic if ((n != 2) || (!sustain_strength)) { 41332689Sbostic message("you feel weaker", 0); 41432689Sbostic } 41532689Sbostic if (n != 2) { 41632689Sbostic rogue.hp_max--; 41732689Sbostic rogue.hp_current--; 41832689Sbostic less_hp++; 41932689Sbostic } 42032689Sbostic if (n != 1) { 42132689Sbostic if ((rogue.str_current > 3) && (!sustain_strength)) { 42232689Sbostic rogue.str_current--; 42332689Sbostic if (coin_toss()) { 42432689Sbostic rogue.str_max--; 42532689Sbostic } 42632689Sbostic } 42732689Sbostic } 42832689Sbostic print_stats((STAT_STRENGTH | STAT_HP)); 42932689Sbostic } 43032689Sbostic 43132689Sbostic m_confuse(monster) 43232689Sbostic object *monster; 43332689Sbostic { 43432689Sbostic char msg[80]; 43532689Sbostic 43632689Sbostic if (!rogue_can_see(monster->row, monster->col)) { 43732689Sbostic return(0); 43832689Sbostic } 43932689Sbostic if (rand_percent(45)) { 44032689Sbostic monster->m_flags &= (~CONFUSES); /* will not confuse the rogue */ 44132689Sbostic return(0); 44232689Sbostic } 44332689Sbostic if (rand_percent(55)) { 44432689Sbostic monster->m_flags &= (~CONFUSES); 44532689Sbostic sprintf(msg, "the gaze of the %s has confused you", mon_name(monster)); 44632689Sbostic message(msg, 1); 44732689Sbostic cnfs(); 44832689Sbostic return(1); 44932689Sbostic } 45032689Sbostic return(0); 45132689Sbostic } 45232689Sbostic 45332689Sbostic flame_broil(monster) 45432689Sbostic object *monster; 45532689Sbostic { 45632689Sbostic short row, col, dir; 45732689Sbostic 45832689Sbostic if ((!mon_sees(monster, rogue.row, rogue.col)) || coin_toss()) { 45932689Sbostic return(0); 46032689Sbostic } 46132689Sbostic row = rogue.row - monster->row; 46232689Sbostic col = rogue.col - monster->col; 46332689Sbostic if (row < 0) { 46432689Sbostic row = -row; 46532689Sbostic } 46632689Sbostic if (col < 0) { 46732689Sbostic col = -col; 46832689Sbostic } 46932689Sbostic if (((row != 0) && (col != 0) && (row != col)) || 47032689Sbostic ((row > 7) || (col > 7))) { 47132689Sbostic return(0); 47232689Sbostic } 47332689Sbostic dir = get_dir(monster->row, monster->col, row, col); 47432689Sbostic bounce(FIRE, dir, monster->row, monster->col, 0); 47532689Sbostic 47632689Sbostic return(1); 47732689Sbostic } 47832689Sbostic 47932689Sbostic get_dir(srow, scol, drow, dcol) 48032689Sbostic short srow, scol, drow, dcol; 48132689Sbostic { 48232689Sbostic if (srow == drow) { 48332689Sbostic if (scol < dcol) { 48432689Sbostic return(RIGHT); 48532689Sbostic } else { 48632689Sbostic return(LEFT); 48732689Sbostic } 48832689Sbostic } 48932689Sbostic if (scol == dcol) { 49032689Sbostic if (srow < drow) { 49132689Sbostic return(DOWN); 49232689Sbostic } else { 49332689Sbostic return(UPWARD); 49432689Sbostic } 49532689Sbostic } 49632689Sbostic if ((srow > drow) && (scol > dcol)) { 49732689Sbostic return(UPLEFT); 49832689Sbostic } 49932689Sbostic if ((srow < drow) && (scol < dcol)) { 50032689Sbostic return(DOWNRIGHT); 50132689Sbostic } 50232689Sbostic if ((srow < drow) && (scol > dcol)) { 50332689Sbostic return(DOWNLEFT); 50432689Sbostic } 50532689Sbostic /*if ((srow > drow) && (scol < dcol)) {*/ 50632689Sbostic return(UPRIGHT); 50732689Sbostic /*}*/ 50832689Sbostic } 509