Mercurial > hg > early-roguelike
diff rogue3/fight.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | e7aab31362af |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/fight.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,737 @@ +/* + * All the fighting gets done here + * + * @(#)fight.c 3.28 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include "rogue.h" + +int e_levels[] = { + 10,20,40,80,160,320,640,1280,2560,5120,10240,20480, + 40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 }; + +/* + * fight: + * The player attacks the monster. + */ + +int +fight(coord *mp, int mn, struct object *weap, int thrown) +{ + struct thing *tp; + struct linked_list *item; + int did_hit = TRUE; + + /* + * Find the monster we want to fight + */ + if ((item = find_mons(mp->y, mp->x)) == NULL) + { + debug("Fight what @ %d,%d", mp->y, mp->x); + return(0); + } + tp = (struct thing *) ldata(item); + /* + * Since we are fighting, things are not quiet so no healing takes + * place. + */ + quiet = 0; + runto(mp, &hero); + /* + * Let him know it was really a mimic (if it was one). + */ + if (tp->t_type == 'M' && tp->t_disguise != 'M' && off(player, ISBLIND)) + { + msg("Wait! That's a mimic!"); + tp->t_disguise = 'M'; + did_hit = thrown; + } + if (did_hit) + { + char *mname; + + did_hit = FALSE; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mn-'A'].m_name; + if (roll_em(&pstats, &tp->t_stats, weap, thrown)) + { + did_hit = TRUE; + if (thrown) + thunk(weap, mname); + else + hit(NULL, mname); + if (on(player, CANHUH)) + { + msg("Your hands stop glowing red"); + msg("The %s appears confused.", mname); + tp->t_flags |= ISHUH; + player.t_flags &= ~CANHUH; + } + if (tp->t_stats.s_hpt <= 0) + killed(item, TRUE); + } + else + if (thrown) + bounce(weap, mname); + else + miss(NULL, mname); + } + count = 0; + return did_hit; +} + +/* + * attack: + * The monster attacks the player + */ + +int +attack(struct thing *mp) +{ + char *mname; + + /* + * Since this is an attack, stop running and any healing that was + * going on at the time. + */ + running = FALSE; + quiet = 0; + if (mp->t_type == 'M' && off(player, ISBLIND)) + mp->t_disguise = 'M'; + if (on(player, ISBLIND)) + mname = "it"; + else + mname = monsters[mp->t_type-'A'].m_name; + if (roll_em(&mp->t_stats, &pstats, NULL, FALSE)) + { + if (mp->t_type != 'E') + hit(mname, NULL); + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + if (off(*mp, ISCANC)) + switch (mp->t_type) + { + case 'R': + /* + * If a rust monster hits, you lose armor + */ + if (cur_armor != NULL && cur_armor->o_ac < 9) + { + if (!terse) + msg("Your armor appears to be weaker now. Oh my!"); + else + msg("Your armor weakens"); + cur_armor->o_ac++; + } + when 'E': + /* + * The gaze of the floating eye hypnotizes you + */ + if (on(player, ISBLIND)) + break; + if (!no_command) + { + addmsg("You are transfixed"); + if (!terse) + addmsg(" by the gaze of the floating eye."); + endmsg(); + } + no_command += rnd(2)+2; + if (no_command > 100 && food_left <= 0) + death('E'); + when 'A': + /* + * Ants have poisonous bites + */ + if (!save(VS_POISON)) + if (!ISWEARING(R_SUSTSTR)) + { + chg_str(-1); + if (!terse) + msg("You feel a sting in your arm and now feel weaker"); + else + msg("A sting has weakened you"); + } + else + if (!terse) + msg("A sting momentarily weakens you"); + else + msg("Sting has no effect"); + when 'W': + /* + * Wraiths might drain energy levels + */ + if (rnd(100) < 15) + { + int fewer; + + if (pstats.s_exp == 0) + death('W'); /* All levels gone */ + msg("You suddenly feel weaker."); + if (--pstats.s_lvl == 0) + { + pstats.s_exp = 0; + pstats.s_lvl = 1; + } + else + pstats.s_exp = e_levels[pstats.s_lvl-1]+1; + fewer = roll(1, 10); + pstats.s_hpt -= fewer; + max_hp -= fewer; + if (pstats.s_hpt < 1) + pstats.s_hpt = 1; + if (max_hp < 1) + death('W'); + } + when 'F': + /* + * Violet fungi stops the poor guy from moving + */ + player.t_flags |= ISHELD; + sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit); + when 'L': + { + /* + * Leperachaun steals some gold + */ + int lastpurse; + + lastpurse = purse; + purse -= GOLDCALC; + if (!save(VS_MAGIC)) + purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; + if (purse < 0) + purse = 0; + if (purse != lastpurse) + msg("Your purse feels lighter"); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + } + when 'N': + { + struct linked_list *list, *steal; + struct object *obj; + int nobj; + + /* + * Nymph's steal a magic item, look through the pack + * and pick out one we like. + */ + steal = NULL; + for (nobj = 0, list = pack; list != NULL; list = next(list)) + { + obj = (struct object *) ldata(list); + if (obj != cur_armor && + obj != cur_weapon && + obj != cur_ring[LEFT] && + obj != cur_ring[RIGHT] && /* Nymph bug fix */ + is_magic(obj) && + rnd(++nobj) == 0) + steal = list; + } + if (steal != NULL) + { + struct object *sobj; + + sobj = (struct object *) ldata(steal); + remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); + mp = NULL; + if (sobj->o_count > 1 && sobj->o_group == 0) + { + int oc; + + oc = sobj->o_count; + sobj->o_count = 1; + msg("She stole %s!", inv_name(sobj, TRUE)); + sobj->o_count = oc - 1; + } + else + { + msg("She stole %s!", inv_name(sobj, TRUE)); + detach(pack, steal); + discard(steal); + } + inpack--; + } + } + otherwise: + break; + } + } + else if (mp->t_type != 'E') + { + if (mp->t_type == 'F') + { + pstats.s_hpt -= fung_hit; + if (pstats.s_hpt <= 0) + death(mp->t_type); /* Bye bye life ... */ + } + miss(mname, NULL); + } + /* + * Check to see if this is a regenerating monster and let it heal if + * it is. + */ + if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33)) + mp->t_stats.s_hpt++; + if (fight_flush) + { + flush_type(); /* flush typeahead */ + } + count = 0; + status(); + + if (mp == NULL) + return(-1); + else + return(0); +} + +/* + * swing: + * returns true if the swing hits + */ + +int +swing(int at_lvl, int op_arm, int wplus) +{ + int res = rnd(20)+1; + int need = (21-at_lvl)-op_arm; + + return (res+wplus >= need); +} + +/* + * check_level: + * Check to see if the guy has gone up a level. + */ + +void +check_level() +{ + int i, add; + + for (i = 0; e_levels[i] != 0; i++) + if (e_levels[i] > pstats.s_exp) + break; + i++; + if (i > pstats.s_lvl) + { + add = roll(i-pstats.s_lvl,10); + max_hp += add; + if ((pstats.s_hpt += add) > max_hp) + pstats.s_hpt = max_hp; + msg("Welcome to level %d", i); + } + pstats.s_lvl = i; +} + +/* + * roll_em: + * Roll several attacks + */ + +int +roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl) +{ + char *cp; + int ndice, nsides, def_arm; + int did_hit = FALSE; + int prop_hplus, prop_dplus; + + prop_hplus = prop_dplus = 0; + if (weap == NULL) + cp = att->s_dmg; + else if (hurl) + if ((weap->o_flags&ISMISL) && cur_weapon != NULL && + cur_weapon->o_which == weap->o_launch) + { + cp = weap->o_hurldmg; + prop_hplus = cur_weapon->o_hplus; + prop_dplus = cur_weapon->o_dplus; + } + else + cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg); + else + { + cp = weap->o_damage; + /* + * Drain a staff of striking + */ + if (weap->o_type =