diff options
author | B. Watson <yalhcru@gmail.com> | 2015-05-07 16:32:32 -0400 |
---|---|---|
committer | B. Watson <yalhcru@gmail.com> | 2015-05-07 16:32:32 -0400 |
commit | 013ac7742311556022304e8b30ca170d48b3a016 (patch) | |
tree | 53faa33e75991363f1a6dcc7edc83a66b70e6995 /rogue/hit.c | |
download | bsd-games-extra-013ac7742311556022304e8b30ca170d48b3a016.tar.gz |
initial commit
Diffstat (limited to 'rogue/hit.c')
-rw-r--r-- | rogue/hit.c | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/rogue/hit.c b/rogue/hit.c new file mode 100644 index 0000000..9d27c1f --- /dev/null +++ b/rogue/hit.c @@ -0,0 +1,466 @@ +/* $NetBSD: hit.c,v 1.10 2008/01/14 03:50:01 dholland Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Timothy C. Stoehr. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)hit.c 8.1 (Berkeley) 5/31/93"; +#else +__RCSID("$NetBSD: hit.c,v 1.10 2008/01/14 03:50:01 dholland Exp $"); +#endif +#endif /* not lint */ + +/* + * hit.c + * + * This source herein may be modified and/or distributed by anybody who + * so desires, with the following restrictions: + * 1.) No portion of this notice shall be removed. + * 2.) Credit shall not be taken for the creation of this source. + * 3.) This code is not to be traded, sold, or used for personal + * gain or profit. + * + */ + +#include "rogue.h" + +static int damage_for_strength(void); +static int get_w_damage(const object *); +static int to_hit(const object *); + +static object *fight_monster = NULL; +char hit_message[HIT_MESSAGE_SIZE] = ""; + +void +mon_hit(object *monster) +{ + short damage, hit_chance; + const char *mn; + float minus; + + if (fight_monster && (monster != fight_monster)) { + fight_monster = 0; + } + monster->trow = NO_ROOM; + if (cur_level >= (AMULET_LEVEL * 2)) { + hit_chance = 100; + } else { + hit_chance = monster->m_hit_chance; + hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings); + } + if (wizard) { + hit_chance /= 2; + } + if (!fight_monster) { + interrupted = 1; + } + mn = mon_name(monster); + + if (!rand_percent(hit_chance)) { + if (!fight_monster) { + messagef(1, "%sthe %s misses", hit_message, mn); + hit_message[0] = 0; + } + return; + } + if (!fight_monster) { + messagef(1, "%sthe %s hit", hit_message, mn); + hit_message[0] = 0; + } + if (!(monster->m_flags & STATIONARY)) { + damage = get_damage(monster->m_damage, 1); + if (cur_level >= (AMULET_LEVEL * 2)) { + minus = (float)((AMULET_LEVEL * 2) - cur_level); + } else { + minus = (float)get_armor_class(rogue.armor) * 3.00; + minus = minus/100.00 * (float)damage; + } + damage -= (short)minus; + } else { + damage = monster->stationary_damage++; + } + if (wizard) { + damage /= 3; + } + if (damage > 0) { + rogue_damage(damage, monster, 0); + } + if (monster->m_flags & SPECIAL_HIT) { + special_hit(monster); + } +} + +void +rogue_hit(object *monster, boolean force_hit) +{ + short damage, hit_chance; + + if (monster) { + if (check_imitator(monster)) { + return; + } + hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon); + + if (wizard) { + hit_chance *= 2; + } + if (!rand_percent(hit_chance)) { + if (!fight_monster) { + (void)strlcpy(hit_message, "you miss ", + sizeof(hit_message)); + } + goto RET; + } + damage = get_weapon_damage(rogue.weapon); + if (wizard) { + damage *= 3; + } + if (con_mon) { + s_con_mon(monster); + } + if (mon_damage(monster, damage)) { /* still alive? */ + if (!fight_monster) { + (void)strlcpy(hit_message, "you hit ", + sizeof(hit_message)); + } + } +RET: check_gold_seeker(monster); + wake_up(monster); + } +} + +void +rogue_damage(short d, object *monster, short other) +{ + if (d >= rogue.hp_current) { + rogue.hp_current = 0; + print_stats(STAT_HP); + killed_by(monster, other); + } + if (d > 0) { + rogue.hp_current -= d; + print_stats(STAT_HP); + } +} + +int +get_damage(const char *ds, boolean r) +{ + int i = 0, j, n, d, total = 0; + + while (ds[i]) { + n = get_number(ds+i); + while ((ds[i] != 'd') && ds[i]) { + i++; + } + if (ds[i] == 'd') { + i++; + } + + d = get_number(ds+i); + while ((ds[i] != '/') && ds[i]) { + i++; + } + if (ds[i] == '/') { + i++; + } + + for (j = 0; j < n; j++) { + if (r) { + total += get_rand(1, d); + } else { + total += d; + } + } + } + return(total); +} + +static int +get_w_damage(const object *obj) +{ + char new_damage[32]; + int tmp_to_hit, tmp_damage; + int i = 0; + + if ((!obj) || (obj->what_is != WEAPON)) { + return(-1); + } + tmp_to_hit = get_number(obj->damage) + obj->hit_enchant; + while ((obj->damage[i] != 'd') && obj->damage[i]) { + i++; + } + if (obj->damage[i] == 'd') { + i++; + } + tmp_damage = get_number(obj->damage + i) + obj->d_enchant; + + snprintf(new_damage, sizeof(new_damage), "%dd%d", + tmp_to_hit, tmp_damage); + + return(get_damage(new_damage, 1)); +} + +int +get_number(const char *s) +{ + int i = 0; + int total = 0; + + while ((s[i] >= '0') && (s[i] <= '9')) { + total = (10 * total) + (s[i] - '0'); + i++; + } + return(total); +} + +long +lget_number(const char *s) +{ + short i = 0; + long total = 0; + + while ((s[i] >= '0') && (s[i] <= '9')) { + total = (10 * total) + (s[i] - '0'); + i++; + } + return(total); +} + +static int +to_hit(const object *obj) +{ + if (!obj) { + return(1); + } + return(get_number(obj->damage) + obj->hit_enchant); +} + +static int +damage_for_strength(void) +{ + short strength; + + strength = rogue.str_current + add_strength; + + if (strength <= 6) { + return(strength-5); + } + if (strength <= 14) { + return(1); + } + if (strength <= 17) { + return(3); + } + if (strength <= 18) { + return(4); + } + if (strength <= 20) { + return(5); + } + if (strength <= 21) { + return(6); + } + if (strength <= 30) { + return(7); + } + return(8); +} + +int +mon_damage(object *monster, short damage) +{ + const char *mn; + short row, col; + + monster->hp_to_kill -= damage; + + if (monster->hp_to_kill <= 0) { + row = monster->row; + col = monster->col; + dungeon[row][col] &= ~MONSTER; + mvaddch(row, col, get_dungeon_char(row, col)); + + fight_monster = 0; + cough_up(monster); + mn = mon_name(monster); + messagef(1, "%sdefeated the %s", hit_message, mn); + hit_message[0] = 0; + add_exp(monster->kill_exp, 1); + take_from_pack(monster, &level_monsters); + + if (monster->m_flags & HOLDS) { + being_held = 0; + } + free_object(monster); + return(0); + } + return(1); +} + +void +fight(boolean to_the_death) +{ + short ch, c, d; + short row, col; + boolean first_miss = 1; + short possible_damage; + object *monster; + + ch = 0; + while (!is_direction(ch = rgetchar(), &d)) { + sound_bell(); + if (first_miss) { + messagef(0, "direction?"); + first_miss = 0; + } + } + check_message(); + if (ch == CANCEL) { + return; + } + row = rogue.row; col = rogue.col; + get_dir_rc(d, &row, &col, 0); + + c = mvinch(row, col); + if (((c < 'A') || (c > 'Z')) || + (!can_move(rogue.row, rogue.col, row, col))) { + messagef(0, "I see no monster there"); + return; + } + if (!(fight_monster = object_at(&level_monsters, row, col))) { + return; + } + if (!(fight_monster->m_flags & STATIONARY)) { + possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3); + } else { + possible_damage = fight_monster->stationary_damage - 1; + } + while (fight_monster) { + (void)one_move_rogue(ch, 0); + if (((!to_the_death) && (rogue.hp_current <= possible_damage)) || + interrupted || (!(dungeon[row][col] & MONSTER))) { + fight_monster = 0; + } else { + monster = object_at(&level_monsters, row, col); + if (monster != fight_monster) { + fight_monster = 0; + } + } + } +} + +void +get_dir_rc(short dir, short *row, short *col, short allow_off_screen) +{ + switch(dir) { + case LEFT: + if (allow_off_screen || (*col > 0)) { + (*col)--; + } + break; + case DOWN: + if (allow_off_screen || (*row < (DROWS-2))) { + (*row)++; + } + break; + case UPWARD: + if (allow_off_screen || (*row > MIN_ROW)) { + (*row)--; + } + break; + case RIGHT: + if (allow_off_screen || (*col < (DCOLS-1))) { + (*col)++; + } + break; + case UPLEFT: + if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) { + (*row)--; + (*col)--; + } + break; + case UPRIGHT: + if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) { + (*row)--; + (*col)++; + } + break; + case DOWNRIGHT: + if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) { + (*row)++; + (*col)++; + } + break; + case DOWNLEFT: + if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) { + (*row)++; + (*col)--; + } + break; + } +} + +int +get_hit_chance(const object *weapon) +{ + short hit_chance; + + hit_chance = 40; + hit_chance += 3 * to_hit(weapon); + hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings); + return(hit_chance); +} + +int +get_weapon_damage(const object *weapon) +{ + short damage; + + damage = get_w_damage(weapon); + damage += damage_for_strength(); + damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2); + return(damage); +} + +void +s_con_mon(object *monster) +{ + if (con_mon) { + monster->m_flags |= CONFUSED; + monster->moves_confused += get_rand(12, 22); + messagef(0, "the monster appears confused"); + con_mon = 0; + } +} |