summaryrefslogtreecommitdiff
path: root/src/cmd1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd1.c')
-rw-r--r--src/cmd1.c5125
1 files changed, 0 insertions, 5125 deletions
diff --git a/src/cmd1.c b/src/cmd1.c
deleted file mode 100644
index 49c0d38f..00000000
--- a/src/cmd1.c
+++ /dev/null
@@ -1,5125 +0,0 @@
-/* File: cmd1.c */
-
-/* Purpose: Movement commands (part 1) */
-
-/*
- * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
- *
- * This software may be copied and distributed for educational, research, and
- * not for profit purposes provided that this copyright and statement are
- * included in all such copies.
- */
-
-#include "angband.h"
-#define MAX_VAMPIRIC_DRAIN 100
-
-
-/*
- * Determine if the player "hits" a monster (normal combat).
- * Note -- Always miss 5%, always hit 5%, otherwise random.
- */
-bool_ test_hit_fire(int chance, int ac, int vis)
-{
- int k;
-
-
- /* Percentile dice */
- k = rand_int(100);
-
- /* Hack -- Instant miss or hit */
- if (k < 10) return (k < 5);
-
- /* Never hit */
- if (chance <= 0) return (FALSE);
-
- /* Invisible monsters are harder to hit */
- if (!vis) chance = (chance + 1) / 2;
-
- /* Power competes against armor */
- if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE);
-
- /* Assume hit */
- return (TRUE);
-}
-
-
-
-/*
- * Determine if the player "hits" a monster (normal combat).
- *
- * Note -- Always miss 5%, always hit 5%, otherwise random.
- */
-bool_ test_hit_norm(int chance, int ac, int vis)
-{
- int k;
-
-
- /* Percentile dice */
- k = rand_int(100);
-
- /* Hack -- Instant miss or hit */
- if (k < 10) return (k < 5);
-
- /* Wimpy attack never hits */
- if (chance <= 0) return (FALSE);
-
- /* Penalize invisible targets */
- if (!vis) chance = (chance + 1) / 2;
-
- /* Power must defeat armor */
- if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE);
-
- /* Assume hit */
- return (TRUE);
-}
-
-
-
-/*
- * Critical hits (from objects thrown by player)
- * Factor in item weight, total plusses, and player level.
- */
-s16b critical_shot(int weight, int plus, int dam, int skill)
-{
- int i, k;
-
-
- /* Extract "shot" power */
- i = (weight + ((p_ptr->to_h + plus) * 4) +
- get_skill_scale(skill, 100));
- i += 50 * p_ptr->xtra_crit;
- i += luck( -100, 100);
-
- /* Critical hit */
- if (randint(5000) <= i)
- {
- k = weight + randint(500);
-
- if (k < 500)
- {
- msg_print("It was a good hit!");
- dam = 2 * dam + 5;
- }
- else if (k < 1000)
- {
- msg_print("It was a great hit!");
- dam = 2 * dam + 10;
- }
- else
- {
- msg_print("It was a superb hit!");
- dam = 3 * dam + 15;
- }
- }
-
- return (dam);
-}
-
-/*
- * Critical hits (by player)
- *
- * Factor in weapon weight, total plusses, player level.
- */
-s16b critical_norm(int weight, int plus, int dam, int weapon_tval, bool_ *done_crit)
-{
- int i, k, num = randint(5000);
-
- *done_crit = FALSE;
-
- /* Extract "blow" power */
- i = (weight + ((p_ptr->to_h + plus) * 5) +
- get_skill_scale(p_ptr->melee_style, 150));
- i += 50 * p_ptr->xtra_crit;
- if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS))
- {
- i += get_skill_scale(SKILL_CRITS, 40 * 50);
- }
- i += luck( -100, 100);
-
- /* Force good strikes */
- if (p_ptr->tim_deadly)
- {
- set_tim_deadly(p_ptr->tim_deadly - 1);
- msg_print("It was a *GREAT* hit!");
- dam = 3 * dam + 20;
- *done_crit = TRUE;
- }
-
- /* Chance */
- else if (num <= i)
- {
- k = weight + randint(650);
- if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS))
- {
- k += get_skill_scale(SKILL_CRITS, 400);
- }
-
- if (k < 400)
- {
- msg_print("It was a good hit!");
- dam = 2 * dam + 5;
- }
- else if (k < 700)
- {
- msg_print("It was a great hit!");
- dam = 2 * dam + 10;
- }
- else if (k < 900)
- {
- msg_print("It was a superb hit!");
- dam = 3 * dam + 15;
- }
- else if (k < 1300)
- {
- msg_print("It was a *GREAT* hit!");
- dam = 3 * dam + 20;
- }
- else
- {
- msg_print("It was a *SUPERB* hit!");
- dam = ((7 * dam) / 2) + 25;
- }
- *done_crit = TRUE;
- }
-
- return (dam);
-}
-
-
-
-/*
- * Extract the "total damage" from a given object hitting a given monster.
- *
- * Note that "flasks of oil" do NOT do fire damage, although they
- * certainly could be made to do so. XXX XXX
- *
- * Note that most brands and slays are x3, except Slay Animal (x2),
- * Slay Evil (x2), and Kill dragon (x5).
- */
-s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
- s32b *special)
-{
- int mult = 1;
-
- monster_race *r_ptr = race_inf(m_ptr);
-
- u32b f1, f2, f3, f4, f5, esp;
-
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Some "weapons" and "ammo" do extra damage */
- switch (o_ptr->tval)
- {
- case TV_SHOT:
- case TV_ARROW:
- case TV_BOLT:
- case TV_BOOMERANG:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_SWORD:
- case TV_AXE:
- case TV_DIGGING:
- {
- /* Slay Animal */
- if ((f1 & (TR1_SLAY_ANIMAL)) && (r_ptr->flags3 & (RF3_ANIMAL)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_ANIMAL);
- }
-
- if (mult < 2) mult = 2;
- }
-
- /* Slay Evil */
- if ((f1 & (TR1_SLAY_EVIL)) && (r_ptr->flags3 & (RF3_EVIL)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_EVIL);
- }
-
- if (mult < 2) mult = 2;
- }
-
- /* Slay Undead */
- if ((f1 & (TR1_SLAY_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_UNDEAD);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Slay Demon */
- if ((f1 & (TR1_SLAY_DEMON)) && (r_ptr->flags3 & (RF3_DEMON)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_DEMON);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Slay Orc */
- if ((f1 & (TR1_SLAY_ORC)) && (r_ptr->flags3 & (RF3_ORC)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_ORC);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Slay Troll */
- if ((f1 & (TR1_SLAY_TROLL)) && (r_ptr->flags3 & (RF3_TROLL)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_TROLL);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Slay Giant */
- if ((f1 & (TR1_SLAY_GIANT)) && (r_ptr->flags3 & (RF3_GIANT)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_GIANT);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Slay Dragon */
- if ((f1 & (TR1_SLAY_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_DRAGON);
- }
-
- if (mult < 3) mult = 3;
- }
-
- /* Execute Dragon */
- if ((f1 & (TR1_KILL_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_DRAGON);
- }
-
- if (mult < 5) mult = 5;
- }
-
- /* Execute Undead */
- if ((f5 & (TR5_KILL_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_UNDEAD);
- }
-
- if (mult < 5) mult = 5;
- }
-
- /* Execute Demon */
- if ((f5 & (TR5_KILL_DEMON)) && (r_ptr->flags3 & (RF3_DEMON)))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_DEMON);
- }
-
- if (mult < 5) mult = 5;
- }
-
-
- /* Brand (Acid) */
- if (f1 & (TR1_BRAND_ACID))
- {
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_ACID))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_ACID);
- }
- }
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_ACID))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags9 |= (RF9_SUSCEP_ACID);
- }
- if (mult < 6) mult = 6;
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (mult < 3) mult = 3;
- }
- }
-
- /* Brand (Elec) */
- if (f1 & (TR1_BRAND_ELEC))
- {
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_ELEC))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_ELEC);
- }
- }
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_ELEC))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags9 |= (RF9_SUSCEP_ELEC);
- }
- if (mult < 6) mult = 6;
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (mult < 3) mult = 3;
- }
- }
-
- /* Brand (Fire) */
- if (f1 & (TR1_BRAND_FIRE))
- {
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_FIRE))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_FIRE);
- }
- }
-
- /* Notice susceptibility */
- else if (r_ptr->flags3 & (RF3_SUSCEP_FIRE))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_SUSCEP_FIRE);
- }
- if (mult < 6) mult = 6;
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (mult < 3) mult = 3;
- }
- }
-
- /* Brand (Cold) */
- if (f1 & (TR1_BRAND_COLD))
- {
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_COLD))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_COLD);
- }
- }
-
- /* Notice susceptibility */
- else if (r_ptr->flags3 & (RF3_SUSCEP_COLD))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_SUSCEP_COLD);
- }
- if (mult < 6) mult = 6;
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (mult < 3) mult = 3;
- }
- }
-
- /* Brand (Poison) */
- if (f1 & (TR1_BRAND_POIS) || (p_ptr->tim_poison))
- {
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_POIS))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_POIS);
- }
- }
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_POIS))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags9 |= (RF9_SUSCEP_POIS);
- }
- if (mult < 6) mult = 6;
- if (magik(95)) *special |= SPEC_POIS;
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (mult < 3) mult = 3;
- if (magik(50)) *special |= SPEC_POIS;
- }
- }
-
- /* Wounding */
- if (f5 & (TR5_WOUNDING))
- {
- /* Notice immunity */
- if (r_ptr->flags8 & (RF8_NO_CUT))
- {
- if (m_ptr->ml)
- {
- r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT);
- }
- }
-
- /* Otherwise, take the damage */
- else
- {
- if (magik(50)) *special |= SPEC_CUT;
- }
- }
- break;
- }
- }
-
-
- /* Return the total damage */
- return (tdam * mult);
-}
-
-
-/*
- * Search for hidden things
- */
-void search(void)
-{
- int y, x, chance;
-
- s16b this_o_idx, next_o_idx = 0;
-
- cave_type *c_ptr;
-
-
- /* Start with base search ability */
- chance = p_ptr->skill_srh;
-
- /* Penalize various conditions */
- if (p_ptr->blind || no_lite()) chance = chance / 10;
- if (p_ptr->confused || p_ptr->image) chance = chance / 10;
-
- /* Search the nearby grids, which are always in bounds */
- for (y = (p_ptr->py - 1); y <= (p_ptr->py + 1); y++)
- {
- for (x = (p_ptr->px - 1); x <= (p_ptr->px + 1); x++)
- {
- /* Sometimes, notice things */
- if (rand_int(100) < chance)
- {
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Invisible trap */
- if ((c_ptr->t_idx != 0) && !(c_ptr->info & CAVE_TRDT))
- {
- /* Pick a trap */
- pick_trap(y, x);
-
- /* Message */
- msg_print("You have found a trap.");
-
- /* Disturb */
- disturb(0, 0);
- }
-
- /* Secret door */
- if (c_ptr->feat == FEAT_SECRET)
- {
- /* Message */
- msg_print("You have found a secret door.");
-
- /* Pick a door XXX XXX XXX */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
- cave[y][x].mimic = 0;
- lite_spot(y, x);
-
- /* Disturb */
- disturb(0, 0);
- }
-
- /* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx;
- this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Skip non-chests */
- if (o_ptr->tval != TV_CHEST) continue;
-
- /* Skip non-trapped chests */
- if (!o_ptr->pval) continue;
-
- /* Identify once */
- if (!object_known_p(o_ptr))
- {
- /* Message */
- msg_print("You have discovered a trap on the chest!");
-
- /* Know the trap */
- object_known(o_ptr);
-
- /* Notice it */
- disturb(0, 0);
- }
- }
- }
- }
- }
-}
-
-
-
-
-/*
- * Player "wants" to pick up an object or gold.
- * Note that we ONLY handle things that can be picked up.
- * See "move_player()" for handling of other things.
- */
-void carry(int pickup)
-{
- if (!p_ptr->disembodied)
- {
- py_pickup_floor(pickup);
- }
-}
-
-
-/*
- * Handle player hitting a real trap
- */
-static void hit_trap(void)
-{
- bool_ ident = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Disturb the player */
- disturb(0, 0);
-
- /* Get the cave grid */
- c_ptr = &cave[p_ptr->py][p_ptr->px];
- if (c_ptr->t_idx != 0)
- {
- ident = player_activate_trap_type(p_ptr->py, p_ptr->px, NULL, -1);
- if (ident)
- {
- t_info[c_ptr->t_idx].ident = TRUE;
- msg_format("You identified the trap as %s.",
- t_name + t_info[c_ptr->t_idx].name);
- }
- }
-}
-
-
-void touch_zap_player(monster_type *m_ptr)
-{
- int aura_damage = 0;
-
- monster_race *r_ptr = race_inf(m_ptr);
-
-
- if (r_ptr->flags2 & (RF2_AURA_FIRE))
- {
- if (!(p_ptr->immune_fire))
- {
- char aura_dam[80];
-
- aura_damage =
- damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17));
-
- /* Hack -- Get the "died from" name */
- monster_desc(aura_dam, m_ptr, 0x88);
-
- msg_print("You are suddenly very hot!");
-
- if (p_ptr->oppose_fire) aura_damage = (aura_damage + 2) / 3;
- if (p_ptr->resist_fire) aura_damage = (aura_damage + 2) / 3;
- if (p_ptr->sensible_fire) aura_damage = (aura_damage + 2) * 2;
-
- take_hit(aura_damage, aura_dam);
- r_ptr->r_flags2 |= RF2_AURA_FIRE;
- handle_stuff();
- }
- }
-
-
- if (r_ptr->flags2 & (RF2_AURA_ELEC))
- {
- if (!(p_ptr->immune_elec))
- {
- char aura_dam[80];
-
- aura_damage =
- damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17));
-
- /* Hack -- Get the "died from" name */
- monster_desc(aura_dam, m_ptr, 0x88);
-
- if (p_ptr->oppose_elec) aura_damage = (aura_damage + 2) / 3;
- if (p_ptr->resist_elec) aura_damage = (aura_damage + 2) / 3;
-
- msg_print("You get zapped!");
- take_hit(aura_damage, aura_dam);
- r_ptr->r_flags2 |= RF2_AURA_ELEC;
- handle_stuff();
- }
- }
-}
-
-
-/*
- * Carried monster can attack too.
- * Based on monst_attack_monst.
- */
-static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
- int x, int y)
-{
- monster_type *t_ptr = &m_list[m_idx];
-
- monster_race *r_ptr;
-
- monster_race *tr_ptr = race_inf(t_ptr);
-
- int ap_cnt;
-
- int ac, rlev, pt;
-
- char t_name[80];
-
- cptr sym_name = symbiote_name(TRUE);
-
- char temp[80];
-
- bool_ blinked = FALSE, touched = FALSE;
-
- byte y_saver = t_ptr->fy;
-
- byte x_saver = t_ptr->fx;
-
- object_type *o_ptr;
-
-
- /* Get the carried monster */
- o_ptr = &p_ptr->inventory[INVEN_CARRY];
- if (!o_ptr->k_idx) return;
-
- r_ptr = &r_info[o_ptr->pval];
-
- /* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return;
-
- /* Total armor */
- ac = t_ptr->ac;
-
- /* Extract the effective monster level */
- rlev = ((o_ptr->elevel >= 1) ? o_ptr->elevel : 1);
-
- /* Get the monster name (or "it") */
- monster_desc(t_name, t_ptr, 0);
-
- /* Assume no blink */
- blinked = FALSE;
-
- if (!t_ptr->ml)
- {
- msg_print("You hear noise.");
- }
-
- /* Scan through all four blows */
- for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
- {
- bool_ visible = FALSE;
- bool_ obvious = FALSE;
-
- int power = 0;
- int damage = 0;
-
- cptr act = NULL;
-
- /* Extract the attack infomation */
- int effect = r_ptr->blow[ap_cnt].effect;
- int method = r_ptr->blow[ap_cnt].method;
- int d_dice = r_ptr->blow[ap_cnt].d_dice;
- int d_side = r_ptr->blow[ap_cnt].d_side;
-
- /* Stop attacking if the target dies! */
- if (t_ptr->fx != x_saver || t_ptr->fy != y_saver)
- break;
-
- /* Hack -- no more attacks */
- if (!method) break;
-
- if (blinked) /* Stop! */
- {
- /* break; */
- }
-
- /* Extract visibility (before blink) */
- visible = TRUE;
-
- /* Extract the attack "power" */
- power = get_attack_power(effect);
-
- /* Monster hits */
- if (!effect || check_hit2(power, rlev, ac))
- {
- /* Always disturbing */
- disturb(1, 0);
-
- /* Describe the attack method */
- switch (method)
- {
- case RBM_HIT:
- {
- act = "hits %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_TOUCH:
- {
- act = "touches %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_PUNCH:
- {
- act = "punches %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_KICK:
- {
- act = "kicks %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CLAW:
- {
- act = "claws %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_BITE:
- {
- act = "bites %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_STING:
- {
- act = "stings %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_XXX1:
- {
- act = "XXX1's %s.";
- break;
- }
-
- case RBM_BUTT:
- {
- act = "butts %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRUSH:
- {
- act = "crushes %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_ENGULF:
- {
- act = "engulfs %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CHARGE:
- {
- act = "charges %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRAWL:
- {
- act = "crawls on %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_DROOL:
- {
- act = "drools on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPIT:
- {
- act = "spits on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_GAZE:
- {
- act = "gazes at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_WAIL:
- {
- act = "wails at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPORE:
- {
- act = "releases spores at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_XXX4:
- {
- act = "projects XXX4's at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_BEG:
- {
- act = "begs %s for money.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_INSULT:
- {
- act = "insults %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_MOAN:
- {
- act = "moans at %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_SHOW:
- {
- act = "sings to %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
- }
-
- /* Message */
- if (act)
- {
- strfmt(temp, act, t_name);
- if (t_ptr->ml)
- msg_format("%s %s", sym_name, temp);
-
- }
-
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
- /* Roll out the damage */
- damage = damroll(d_dice, d_side);
-
- pt = GF_MISSILE;
-
- /* Apply appropriate damage */
- switch (effect)
- {
- case 0:
- {
- damage = 0;
- pt = 0;
- break;
- }
-
- case RBE_HURT:
- case RBE_SANITY:
- {
- damage -= (damage * ((ac < 150) ? ac : 150) / 250);
- break;
- }
-
- case RBE_POISON:
- case RBE_DISEASE:
- {
- pt = GF_POIS;
- break;
- }
-
- case RBE_UN_BONUS:
- case RBE_UN_POWER:
- case RBE_ABOMINATION:
- {
- pt = GF_DISENCHANT;
- break;
- }
-
- case RBE_EAT_FOOD:
- case RBE_EAT_LITE:
- {
- pt = damage = 0;
- break;
- }
-
- case RBE_EAT_ITEM:
- case RBE_EAT_GOLD:
- {
- pt = damage = 0;
- if (randint(2) == 1) blinked = TRUE;
- break;
- }
-
- case RBE_ACID:
- {
- pt = GF_ACID;
- break;
- }
-
- case RBE_ELEC:
- {
- pt = GF_ELEC;
- break;
- }
-
- case RBE_FIRE:
- {
- pt = GF_FIRE;
- break;
- }
-
- case RBE_COLD:
- {
- pt = GF_COLD;
- break;
- }
-
- case RBE_BLIND:
- {
- break;
- }
-
- case RBE_CONFUSE:
- case RBE_HALLU:
- {
- pt = GF_CONFUSION;
- break;
- }
-
- case RBE_TERRIFY:
- {
- pt = GF_TURN_ALL;
- break;
- }
-
- case RBE_PARALYZE:
- {
- pt = GF_OLD_SLEEP; /* sort of close... */
- break;
- }
-
- case RBE_LOSE_STR:
- case RBE_LOSE_INT:
- case RBE_LOSE_WIS:
- case RBE_LOSE_DEX:
- case RBE_LOSE_CON:
- case RBE_LOSE_CHR:
- case RBE_LOSE_ALL:
- case RBE_PARASITE:
- {
- break;
- }
-
- case RBE_SHATTER:
- {
- if (damage > 23)
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 8);
- }
- break;
- }
-
- case RBE_EXP_10:
- case RBE_EXP_20:
- case RBE_EXP_40:
- case RBE_EXP_80:
- {
- pt = GF_NETHER;
- break;
- }
-
- case RBE_TIME:
- {
- pt = GF_TIME;
- break;
- }
-
- default:
- {
- pt = 0;
- break;
- }
- }
-
- if (pt)
- {
- /* Do damage if not exploding */
- project(0, 0, t_ptr->fy, t_ptr->fx,
- (pt == GF_OLD_SLEEP ? r_ptr->level : damage), pt,
- PROJECT_KILL | PROJECT_STOP);
-
- if (touched)
- {
- /* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
- {
- if (t_ptr->ml)
- {
- blinked = FALSE;
- msg_format("You are suddenly very hot!");
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_FIRE;
- }
- project(m_idx, 0, p_ptr->py, p_ptr->px,
- damroll(1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_FIRE, PROJECT_KILL | PROJECT_STOP);
- }
-
- /* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) &&
- !(r_ptr->flags3 & (RF3_IM_ELEC)))
- {
- if (t_ptr->ml)
- {
- blinked = FALSE;
- msg_format("You get zapped!");
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_ELEC;
- }
- project(m_idx, 0, p_ptr->py, p_ptr->px,
- damroll(1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_ELEC, PROJECT_KILL | PROJECT_STOP);
- }
- }
- }
- }
-
- /* Monster missed player */
- else
- {
- /* Analyze failed attacks */
- switch (method)
- {
- case RBM_HIT:
- case RBM_TOUCH:
- case RBM_PUNCH:
- case RBM_KICK:
- case RBM_CLAW:
- case RBM_BITE:
- case RBM_STING:
- case RBM_XXX1:
- case RBM_BUTT:
- case RBM_CRUSH:
- case RBM_ENGULF:
- case RBM_CHARGE:
- {
- /* Disturb */
- disturb(1, 0);
-
- /* Message */
- msg_format("%s misses %s.", sym_name, t_name);
- break;
- }
- }
- }
-
-
- /* Analyze "visible" monsters only */
- if (visible)
- {
- /* Count "obvious" attacks (and ones that cause damage) */
- if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10))
- {
- /* Count attacks of this type */
- if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR)
- {
- r_ptr->r_blows[ap_cnt]++;
- }
- }
- }
- }
-
- /* Blink away */
- if (blinked)
- {
- msg_format("You and %s flee laughing!", symbiote_name(FALSE));
-
- teleport_player(MAX_SIGHT * 2 + 5);
- }
-}
-
-/*
- * Carried monster can attack too.
- * Based on monst_attack_monst.
- */
-static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
- int x, int y)
-{
- monster_type *t_ptr = &m_list[m_idx];
-
- monster_race *r_ptr;
-
- monster_race *tr_ptr = race_inf(t_ptr);
-
- int ap_cnt;
-
- int ac, rlev, pt;
-
- char t_name[80];
-
- char temp[80];
-
- bool_ blinked = FALSE, touched = FALSE;
-
- byte y_saver = t_ptr->fy;
-
- byte x_saver = t_ptr->fx;
-
-
- if (!p_ptr->body_monster) return;
-
- r_ptr = race_info_idx(p_ptr->body_monster, 0);
-
- /* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return;
-
- /* Total armor */
- ac = t_ptr->ac;
-
- /* Extract the effective monster level */
- rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
-
- /* Get the monster name (or "it") */
- monster_desc(t_name, t_ptr, 0);
-
- /* Assume no blink */
- blinked = FALSE;
-
- if (!t_ptr->ml)
- {
- msg_print("You hear noise.");
- }
-
- /* Scan through all four blows */
- for (ap_cnt = 0; ap_cnt < (p_ptr->num_blow > 4) ? 4 : p_ptr->num_blow;
- ap_cnt++)
- {
- bool_ visible = FALSE;
- bool_ obvious = FALSE;
-
- int power = 0;
- int damage = 0;
-
- cptr act = NULL;
-
- /* Extract the attack infomation */
- int effect = r_ptr->blow[ap_cnt].effect;
- int method = r_ptr->blow[ap_cnt].method;
- int d_dice = r_ptr->blow[ap_cnt].d_dice;
- int d_side = r_ptr->blow[ap_cnt].d_side;
-
- /* Stop attacking if the target dies! */
- if (t_ptr->fx != x_saver || t_ptr->fy != y_saver)
- break;
-
- /* Hack -- no more attacks */
- if (!method) break;
-
- if (blinked) /* Stop! */
- {
- /* break; */
- }
-
- /* Extract visibility (before blink) */
- visible = TRUE;
-
- /* Extract the attack "power" */
- effect = get_attack_power(effect);
-
- /* Monster hits */
- if (!effect || check_hit2(power, rlev, ac))
- {
- /* Always disturbing */
- disturb(1, 0);
-
- /* Describe the attack method */
- switch (method)
- {
- case RBM_HIT:
- {
- act = "hit %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_TOUCH:
- {
- act = "touch %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_PUNCH:
- {
- act = "punch %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_KICK:
- {
- act = "kick %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CLAW:
- {
- act = "claw %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_BITE:
- {
- act = "bite %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_STING:
- {
- act = "sting %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_XXX1:
- {
- act = "XXX1's %s.";
- break;
- }
-
- case RBM_BUTT:
- {
- act = "butt %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRUSH:
- {
- act = "crush %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_ENGULF:
- {
- act = "engulf %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CHARGE:
- {
- act = "charge %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRAWL:
- {
- act = "crawl on %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_DROOL:
- {
- act = "drool on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPIT:
- {
- act = "spit on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_GAZE:
- {
- act = "gaze at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_WAIL:
- {
- act = "wail at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPORE:
- {
- act = "release spores at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_XXX4:
- {
- act = "project XXX4's at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_BEG:
- {
- act = "beg %s for money.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_INSULT:
- {
- act = "insult %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_MOAN:
- {
- act = "moan at %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_SHOW:
- {
- act = "sing to %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
- }
-
- /* Message */
- if (act)
- {
- strfmt(temp, act, t_name);
- if (t_ptr->ml)
- msg_format("You %s", temp);
-
- }
-
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
- /* Roll out the damage */
- damage = damroll(d_dice, d_side) + p_ptr->to_d;
-
- pt = GF_MISSILE;
-
- /* Apply appropriate damage */
- switch (effect)
- {
- case 0:
- {
- damage = 0;
- pt = 0;
- break;
- }
-
- case RBE_HURT:
- case RBE_SANITY:
- {
- damage -= (damage * ((ac < 150) ? ac : 150) / 250);
- break;
- }
-
- case RBE_POISON:
- case RBE_DISEASE:
- {
- pt = GF_POIS;
- break;
- }
-
- case RBE_UN_BONUS:
- case RBE_UN_POWER:
- {
- pt = GF_DISENCHANT;
- break;
- }
-
- case RBE_EAT_FOOD:
- case RBE_EAT_LITE:
- {
- pt = damage = 0;
- break;
- }
-
- case RBE_EAT_ITEM:
- case RBE_EAT_GOLD:
- {
- pt = damage = 0;
- if (randint(2) == 1) blinked = TRUE;
- break;
- }
-
- case RBE_ACID:
- {
- pt = GF_ACID;
- break;
- }
-
- case RBE_ELEC:
- {
- pt = GF_ELEC;
- break;
- }
-
- case RBE_FIRE:
- {
- pt = GF_FIRE;
- break;
- }
-
- case RBE_COLD:
- {
- pt = GF_COLD;
- break;
- }
-
- case RBE_BLIND:
- {
- break;
- }
-
- case RBE_HALLU:
- case RBE_CONFUSE:
- {
- pt = GF_CONFUSION;
- break;
- }
-
- case RBE_TERRIFY:
- {
- pt = GF_TURN_ALL;
- break;
- }
-
- case RBE_PARALYZE:
- {
- pt = GF_OLD_SLEEP; /* sort of close... */
- break;
- }
-
- case RBE_LOSE_STR:
- case RBE_LOSE_INT:
- case RBE_LOSE_WIS:
- case RBE_LOSE_DEX:
- case RBE_LOSE_CON:
- case RBE_LOSE_CHR:
- case RBE_LOSE_ALL:
- case RBE_PARASITE:
- {
- break;
- }
-
- case RBE_SHATTER:
- {
- if (damage > 23)
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 8);
- }
- break;
- }
-
- case RBE_EXP_10:
- case RBE_EXP_20:
- case RBE_EXP_40:
- case RBE_EXP_80:
- {
- pt = GF_NETHER;
- break;
- }
-
- case RBE_TIME:
- {
- pt = GF_TIME;
- break;
- }
-
- default:
- {
- pt = 0;
- break;
- }
- }
-
- if (pt)
- {
- /* Do damage if not exploding */
- project(0, 0, t_ptr->fy, t_ptr->fx,
- (pt == GF_OLD_SLEEP ? p_ptr->lev * 2 : damage), pt,
- PROJECT_KILL | PROJECT_STOP);
-
- if (touched)
- {
- /* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
- {
- if (t_ptr->ml)
- {
- blinked = FALSE;
- msg_format("You are suddenly very hot!");
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_FIRE;
- }
- project(m_idx, 0, p_ptr->py, p_ptr->px,
- damroll(1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_FIRE, PROJECT_KILL | PROJECT_STOP);
- }
-
- /* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) &&
- !(r_ptr->flags3 & (RF3_IM_ELEC)))
- {
- if (t_ptr->ml)
- {
- blinked = FALSE;
- msg_format("You get zapped!");
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_ELEC;
- }
- project(m_idx, 0, p_ptr->py, p_ptr->px,
- damroll(1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_ELEC, PROJECT_KILL | PROJECT_STOP);
- }
-
- }
- }
- }
-
- /* Monster missed player */
- else
- {
- /* Analyze failed attacks */
- switch (method)
- {
- case RBM_HIT:
- case RBM_TOUCH:
- case RBM_PUNCH:
- case RBM_KICK:
- case RBM_CLAW:
- case RBM_BITE:
- case RBM_STING:
- case RBM_XXX1:
- case RBM_BUTT:
- case RBM_CRUSH:
- case RBM_ENGULF:
- case RBM_CHARGE:
- {
- /* Disturb */
- disturb(1, 0);
-
- /* Message */
- msg_format("You miss %s.", t_name);
-
- break;
- }
- }
- }
-
-
- /* Analyze "visible" monsters only */
- if (visible)
- {
- /* Count "obvious" attacks (and ones that cause damage) */
- if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10))
- {
- /* Count attacks of this type */
- if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR)
- {
- r_ptr->r_blows[ap_cnt]++;
- }
- }
- }
- }
-
- /* Blink away */
- if (blinked)
- {
- msg_print("You flee laughing!");
-
- teleport_player(MAX_SIGHT * 2 + 5);
- }
-}
-
-
-/*
- * Fetch an attack description from dam_*.txt files.
- */
-
-static void flavored_attack(int percent, char *output)
-{
- int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane;
- bool_ insane = (rand_int(100) < insanity);
-
- if (percent < 5)
- {
- if (!insane)
- strcpy(output, "You scratch %s.");
- else
- get_rnd_line("dam_none.txt", output);
-
- }
- else if (percent < 30)
- {
- if (!insane)
- strcpy(output, "You hit %s.");
- else
- get_rnd_line("dam_med.txt", output);
- }
- else if (percent < 60)
- {
- if (!insane)
- strcpy(output, "You wound %s.");
- else
- get_rnd_line("dam_lots.txt", output);
- }
- else if (percent < 95)
- {
- if (!insane)
- strcpy(output, "You cripple %s.");
- else
- get_rnd_line("dam_huge.txt", output);
-
- }
- else
- {
- if (!insane)
- strcpy(output, "You demolish %s.");
- else
- get_rnd_line("dam_xxx.txt", output);
- }
-}
-
-
-/*
- * Apply the special effects of an attack
- */
-void attack_special(monster_type *m_ptr, s32b special, int dam)
-{
- char m_name[80];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
-
- /* Extract monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Special - Cut monster */
- if (special & SPEC_CUT)
- {
- /* Cut the monster */
- if (r_ptr->flags8 & (RF8_NO_CUT))
- {
- if (m_ptr->ml)
- {
- r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT);
- }
- }
- else if (rand_int(100) >= r_ptr->level)
- {
- /* Already partially poisoned */
- if (m_ptr->bleeding) msg_format("%^s is bleeding more strongly.",
- m_name);
- /* Was not poisoned */
- else
- msg_format("%^s is bleeding.", m_name);
-
- m_ptr->bleeding += dam * 2;
- }
- }
-
- /* Special - Poison monster */
- if (special & SPEC_POIS)
- {
- /* Poison the monster */
- if (r_ptr->flags3 & (RF3_IM_POIS))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_POIS);
- }
- }
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_POIS))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags9 |= (RF9_SUSCEP_POIS);
- }
- /* Already partially poisoned */
- if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name);
- /* Was not poisoned */
- else
- msg_format("%^s is poisoned.", m_name);
-
- m_ptr->poisoned += dam * 2;
- }
- else if (rand_int(100) >= r_ptr->level)
- {
- /* Already partially poisoned */
- if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name);
- /* Was not poisoned */
- else
- msg_format("%^s is poisoned.", m_name);
-
- m_ptr->poisoned += dam;
- }
- }
-}
-
-
-/*
- * Bare handed attacks
- */
-static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
-{
- s16b special_effect = 0, stun_effect = 0, times = 0;
- martial_arts *ma_ptr, *old_ptr, *blow_table = ma_blows;
- int resist_stun = 0, max = MAX_MA;
- monster_race *r_ptr = race_inf(m_ptr);
- char m_name[80];
- bool_ desc = FALSE;
- bool_ done_crit;
- int plev = p_ptr->lev;
-
- if ((!p_ptr->body_monster) && (p_ptr->mimic_form == resolve_mimic_name("Bear")) &&
- (p_ptr->melee_style == SKILL_BEAR))
- {
- blow_table = bear_blows;
- max = MAX_BEAR;
- plev = get_skill(SKILL_BEAR);
- }
- if (p_ptr->melee_style == SKILL_HAND)
- {
- blow_table = ma_blows;
- max = MAX_MA;
- plev = get_skill(SKILL_HAND);
- }
- ma_ptr = &blow_table[0];
- old_ptr = &blow_table[0];
-
- /* Extract monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- if (r_ptr->flags1 & RF1_UNIQUE) resist_stun += 88;
- if (r_ptr->flags3 & RF3_NO_CONF) resist_stun += 44;
- if (r_ptr->flags3 & RF3_NO_SLEEP) resist_stun += 44;
- if ((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_NONLIVING)) resist_stun += 88;
-
- if (plev)
- {
- for (times = 0; times < (plev < 7 ? 1 : plev / 7); times++)
- {
- do
- {
- ma_ptr = &blow_table[(randint(max)) - 1];
- }
- while ((ma_ptr->min_level > plev) || (randint(plev) < ma_ptr->chance));
-
- /* keep the highest level attack available we found */
- if ((ma_ptr->min_level > old_ptr->min_level) &&
- !(p_ptr->stun || p_ptr->confused))
- {
- old_ptr = ma_ptr;
-
- if (wizard && cheat_xtra)
- {
- msg_print("Attack re-selected.");
- }
- }
- else
- {
- ma_ptr = old_ptr;
- }
- }
- }
-
- *k = damroll(ma_ptr->dd, ma_ptr->ds);
-
- if (ma_ptr->effect & MA_KNEE)
- {
- if (r_ptr->flags1 & RF1_MALE)
- {
- if (!desc) msg_format("You hit %s in the groin with your knee!",
- m_name);
- sound(SOUND_PAIN);
- special_effect = MA_KNEE;
- }
- else if (!desc) msg_format(ma_ptr->desc, m_name);
-
- desc = TRUE;
- }
- if (ma_ptr->effect & MA_FULL_SLOW)
- {
- special_effect = MA_SLOW;
- if (!desc) msg_format(ma_ptr->desc, m_name);
-
- desc = TRUE;
- }
- if (ma_ptr->effect & MA_SLOW)
- {
- if (!
- ((r_ptr->flags1 & RF1_NEVER_MOVE) ||
- strchr("UjmeEv$,DdsbBFIJQSXclnw!=?", r_ptr->d_char)))
- {
- if (!desc) msg_format("You kick %s in the ankle.", m_name);
- special_effect = MA_SLOW;
- }
- else if (!desc) msg_format(ma_ptr->desc, m_name);
-
- desc = TRUE;
- }
- if (ma_ptr->effect & MA_STUN)
- {
- if (ma_ptr->power)
- {
- stun_effect = (ma_ptr->power / 2) + randint(ma_ptr->power / 2);
- }
-
- if (!desc) msg_format(ma_ptr->desc, m_name);
- desc = TRUE;
- }
- if (ma_ptr->effect & MA_WOUND)
- {
- if (magik(ma_ptr->power))
- {
- *special |= SPEC_CUT;
- }
- if (!desc) msg_format(ma_ptr->desc, m_name);
- desc = TRUE;
- }
-
- *k = critical_norm(plev * (randint(10)), ma_ptr->min_level, *k, -1, &done_crit);
-
- if ((special_effect & MA_KNEE) && ((*k + p_ptr->to_d) < m_ptr->hp))
- {
- msg_format("%^s moans in agony!", m_name);
- stun_effect = 7 + randint(13);
- resist_stun /= 3;
- }
- if (((special_effect & MA_FULL_SLOW) || (special_effect & MA_SLOW)) &&
- ((*k + p_ptr->to_d) < m_ptr->hp))
- {
- if (!(r_ptr->flags1 & RF1_UNIQUE) &&
- (randint(plev) > m_ptr->level) && m_ptr->mspeed > 60)
- {
- msg_format("%^s starts limping slower.", m_name);
- m_ptr->mspeed -= 10;
- }
- }
-
- if (stun_effect && ((*k + p_ptr->to_d) < m_ptr->hp))
- {
- if (plev > randint(m_ptr->level + resist_stun + 10))
- {
- if (m_ptr->stunned)
- msg_format("%^s is still stunned.", m_name);
- else
- msg_format("%^s is stunned.", m_name);
-
- m_ptr->stunned += (stun_effect);
- }
- }
-}
-
-
-/*
- * Apply nazgul effects
- */
-void do_nazgul(int *k, int *num, int num_blow, int weap, monster_race *r_ptr,
- object_type *o_ptr)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- bool_ mundane;
- bool_ allow_shatter = TRUE;
-
- /* Extract mundane-ness of the current weapon */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* It should be Slay Evil, Slay Undead, or *Slay Undead* */
- mundane = !(f1 & TR1_SLAY_EVIL) && !(f1 & TR1_SLAY_UNDEAD) &&
- !(f5 & TR5_KILL_UNDEAD);
-
- /* Some blades can resist shattering */
- if (f5 & TR5_RES_MORGUL)
- allow_shatter = FALSE;
-
- /* Mega Hack -- Hitting Nazgul is REALY dangerous (ideas from Akhronath) */
- if (r_ptr->flags7 & RF7_NAZGUL)
- {
- if ((!o_ptr->name2) && (!artifact_p(o_ptr)) && allow_shatter)
- {
- msg_print("Your weapon *DISINTEGRATES*!");
- *k = 0;
-
- inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE);
-
- /* To stop attacking */
- *num = num_blow;
- }
- else if (o_ptr->name2)
- {
- if (mundane)
- {
- msg_print
- ("The Ringwraith is IMPERVIOUS to the mundane weapon.");
- *k = 0;
- }
-
- /* 25% chance of getting destroyed */
- if (magik(25) && allow_shatter)
- {
- msg_print("Your weapon is destroyed!");
-
- inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE);
-
- /* To stop attacking */
- *num = num_blow;
- }
- }
- else if (artifact_p(o_ptr))
- {
- if (mundane)
- {
- msg_print
- ("The Ringwraith is IMPERVIOUS to the mundane weapon.");
- *k = 0;
- }
-
- apply_disenchant(INVEN_WIELD + weap);
-
- /* 1/1000 chance of getting destroyed */
- if (!rand_int(1000) && allow_shatter)
- {
- msg_print("Your weapon is destroyed!");
-
- inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE);
-
- /* To stop attacking */
- *num = num_blow;
- }
- }
-
- /* If any damage is done, then 25% chance of getting the Black Breath */
- if (*k)
- {
- if (magik(25))
- {
- msg_print("Your foe calls upon your soul!");
- msg_print
- ("You feel the Black Breath slowly draining you of life...");
- p_ptr->black_breath = TRUE;
- }
- }
- }
-}
-
-
-/*
- * Player attacks a (poor, defenseless) creature -RAK-
- *
- * If no "weapon" is available, then "punch" the monster one time.
- */
-void py_attack(int y, int x, int max_blow)
-{
- int num = 0, k, bonus, chance;
-
- s32b special = 0;
-
- cave_type *c_ptr = &cave[y][x];
-
- monster_type *m_ptr = &m_list[c_ptr->m_idx];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
- object_type *o_ptr;
-
- char m_name[80];
-
- bool_ fear = FALSE;
-
- bool_ mdeath = FALSE;
-
- bool_ backstab = FALSE;
-
- bool_ vorpal_cut = FALSE;
-
- int chaos_effect = 0;
-
- bool_ stab_fleeing = FALSE;
-
- bool_ do_quake = FALSE;
-
- bool_ done_crit = FALSE;
-
- bool_ drain_msg = TRUE;
-
- int drain_result = 0, drain_heal = 0;
-
- int drain_left = MAX_VAMPIRIC_DRAIN;
-
- /* A massive hack -- life-draining weapons */
- u32b f1, f2, f3, f4, f5, esp;
-
- int weap;
-
- /* Disturb the player */
- disturb(0, 0);
-
- if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW)
- {
- msg_print("You cannot attack in this form!");
- return;
- }
-
- if (get_skill(SKILL_BACKSTAB))
- {
- if ((m_ptr->csleep) && (m_ptr->ml))
- {
- /* Can't backstab creatures that we can't see, right? */
- backstab = TRUE;
- }
- else if ((m_ptr->monfear) && (m_ptr->ml))
- {
- stab_fleeing = TRUE;
- }
- }
-
- /* Disturb the monster */
- m_ptr->csleep = 0;
-
-
- /* Extract monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dont even bother */
- if (r_ptr->flags7 & RF7_IM_MELEE)
- {
- msg_format("%^s is immune to melee attacks.");
- return;
- }
-
- /* Auto-Recall if possible and visible */
- if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego);
-
- /* Track a new monster */
- if (m_ptr->ml) health_track(c_ptr->m_idx);
-
- /* Stop if friendly */
- if ((is_friend(m_ptr) >= 0) &&
- !(p_ptr->stun || p_ptr->confused || p_ptr->image ||
- !(m_ptr->ml)))
- {
- if (!(p_ptr->inventory[INVEN_WIELD].art_name))
- {
- msg_format("You stop to avoid hitting %s.", m_name);
- return;
- }
-
- if (!
- (streq
- (quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'")))
- {
- msg_format("You stop to avoid hitting %s.", m_name);
- return;
- }
-
- msg_format("Your black blade greedily attacks %s!", m_name);
- }
-
- /* Break goi/manashield */
- if (p_ptr->invuln)
- {
- set_invuln(0);
- }
- if (p_ptr->disrupt_shield)
- {
- set_disrupt_shield(0);
- }
-
- /* Handle player fear */
- if (p_ptr->afraid)
- {
- /* Message */
- if (m_ptr->ml)
- msg_format("You are too afraid to attack %s!", m_name);
- else
- msg_format("There is something scary in your way!");
-
- /* Done */
- return;
- }
-
- /* Monsters can use barehanded combat, but not weapon combat */
- if ((p_ptr->body_monster) &&
- (!r_info[p_ptr->body_monster].body_parts[BODY_WEAPON]) &&
- !(p_ptr->melee_style == SKILL_HAND))
- {
- incarnate_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x);
- }
- /* Otherwise use your weapon(s) */
- else
- {
- int weapons;
- if (p_ptr->melee_style == SKILL_MASTERY)
- weapons = r_info[p_ptr->body_monster].body_parts[BODY_WEAPON];
- else /* SKILL_HAND */
- weapons = 1;
-
- /* Attack with ALL the weapons !!!!! -- ooh that's gonna hurt YOU */
- for (weap = 0; weap < weapons; ++weap)
- {
- /* Monster is already dead ? oh :( */
- if (mdeath) break;
-
- /* Reset the blows counter */
- num = 0;
-
- /* Access the weapon */
- o_ptr = &p_ptr->inventory[INVEN_WIELD + weap];
-
- /* Calculate the "attack quality" */
- bonus = p_ptr->to_h + p_ptr->to_h_melee + o_ptr->to_h;
- chance = p_ptr->skill_thn + (bonus * BTH_PLUS_ADJ);
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (!(f4 & TR4_NEVER_BLOW))
- {
- int num_blow = p_ptr->num_blow;
-
- /* Restrict to max_blow(if max_blow >= 0) */
- if ((max_blow >= 0) &&
- (num_blow > max_blow)) num_blow = max_blow;
-
- /* Attack once for each legal blow */
- while (num++ < num_blow)
- {
- /* Test for hit */
- if (test_hit_norm(chance, m_ptr->ac, m_ptr->ml))
- {
- /* Sound */
- sound(SOUND_HIT);
-
- /* Hack -- bare hands do one damage */
- k = 1;
-
- /* Select a chaotic effect (50% chance) */
- if ((f1 & TR1_CHAOTIC) && (rand_int(2) == 0))
- {
- if (randint(5) < 3)
- {
- /* Vampiric (20%) */
- chaos_effect = 1;
- }
- else if (rand_int(250) == 0)
- {
- /* Quake (0.12%) */
- chaos_effect = 2;
- }
- else if (rand_int(10))
- {
- /* Confusion (26.892%) */
- chaos_effect = 3;
- }
- else if (rand_int(2) == 0)
- {
- /* Teleport away (1.494%) */
- chaos_effect = 4;
- }
- else
- {
- /* Polymorph (1.494%) */
- chaos_effect = 5;
- }
- }
-
- /* Vampiric drain */
- if ((f1 & TR1_VAMPIRIC) || (chaos_effect == 1))
- {
- if (!
- ((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_NONLIVING)))
- drain_result = m_ptr->hp;
- else
- drain_result = 0;
- }
-
- if (f1 & TR1_VORPAL && (randint(6) == 1))
- vorpal_cut = TRUE;
- else
- vorpal_cut = FALSE;
-
- /* Should we attack with hands or not ? */
- if (p_ptr->melee_style != SKILL_MASTERY)
- {
- py_attack_hand(&k, m_ptr, &special);
- }
- /* Handle normal weapon */
- else if (o_ptr->k_idx)
- {
- k = damroll(o_ptr->dd, o_ptr->ds);
- k = tot_dam_aux(o_ptr, k, m_ptr, &special);
-
- if (backstab)
- {
- k += (k *
- get_skill_scale(SKILL_BACKSTAB,
- 100)) / 100;
- }
- else if (stab_fleeing)
- {
- k += (k * get_skill_scale(SKILL_BACKSTAB, 70)) /
- 100;
- }
-
- if ((p_ptr->impact && ((k > 50) || randint(7) == 1))
- || (chaos_effect == 2))
- {
- do_quake = TRUE;
- }
-
- k = critical_norm(o_ptr->weight, o_ptr->to_h, k, o_ptr->tval, &done_crit);
-
- /* Stunning blow */
- if (magik(get_skill(SKILL_STUN)) && (o_ptr->tval == TV_HAFTED) && (o_ptr->weight > 50) && done_crit)
- {
- if (!(r_ptr->flags4 & (RF4_BR_SOUN)) && !(r_ptr->flags4 & (RF4_BR_WALL)) && k)
- {
- int tmp;
-
- /* Get stunned */
- if (m_ptr->stunned)
- {
- msg_format("%^s is more dazed.", m_name);
- tmp = m_ptr->stunned + get_skill_scale(SKILL_STUN, 30) + 10;
- }
- else
- {
- msg_format("%^s is dazed.", m_name);
- tmp = get_skill_scale(SKILL_STUN, 60) + 20;
- }
-
- /* Apply stun */
- m_ptr->stunned = (tmp < 200) ? tmp : 200;
- }
- }
-
- if (vorpal_cut)
- {
- int step_k = k;
-
- msg_format("Your weapon cuts deep into %s!",
- m_name);
- do
- {
- k += step_k;
- }
- while (randint(4) == 1);
- }
-
- PRAY_GOD(GOD_TULKAS)
- {
- if (magik(wisdom_scale(130) - m_ptr->level) && (p_ptr->grace > 1000))
- {
- msg_print("You feel the hand of Tulkas helping your blow.");
- k += (o_ptr->to_d + p_ptr->to_d_melee) * 2;
- }
- else k += o_ptr->to_d + p_ptr->to_d_melee;
- }
- else k += o_ptr->to_d;
-
- /* Project some more nasty stuff? */
- if (p_ptr->tim_project)
- {
- project(0, p_ptr->tim_project_rad, y, x, p_ptr->tim_project_dam, p_ptr->tim_project_gf, p_ptr->tim_project_flag | PROJECT_JUMP);
- if (!c_ptr->m_idx)
- {
- mdeath = TRUE;
- break;
- }
- }
-
- do_nazgul(&k, &num, num_blow, weap, r_ptr, o_ptr);
-
- }
-
- /* Melkor can cast curse for you*/
- PRAY_GOD(GOD_MELKOR)
- {
- int lv = exec_lua("return get_level(MELKOR_CURSE, 100)");
-
- if (lv >= 10)
- {
- int chance = (wisdom_scale(30) * lv) / ((m_ptr->level < 1) ? 1 : m_ptr->level);
-
- if (chance < 1) chance = 1;
- if ((p_ptr->grace > 5000) && magik(chance))
- {
- exec_lua(format("do_melkor_curse(%d)", c_ptr->m_idx));
- }
- }
- }
-
- /* May it clone the monster ? */
- if ((f4 & TR4_CLONE) && magik(30))
- {
- msg_format("Oh no! Your weapon clones %^s!",
- m_name);
- multiply_monster(c_ptr->m_idx, FALSE, TRUE);
- }
-
- /* Apply the player damage bonuses */
- k += p_ptr->to_d + p_ptr->to_d_melee;
-
- /* No negative damage */
- if (k < 0) k = 0;
-
- /* Message */
- if (!(backstab || stab_fleeing))
- {
- /* These monsters never have flavoured combat msgs */
- if (strchr("vwjmelX,.*", r_ptr->d_char))
- {
- msg_format("You hit %s.", m_name);
- }
-
- /* Print flavoured messages if requested */
- else
- {
- char buff[255];
-
- flavored_attack((100 * k) / m_ptr->maxhp, buff);
- msg_format(buff, m_name);
- }
- }
- else if (backstab)
- {
- char buf[80];
-
- monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego);
-
- backstab = FALSE;
-
- msg_format
- ("You cruelly stab the helpless, sleeping %s!",
- buf);
- }
- else
- {
- char buf[80];
-
- monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego);
-
- msg_format("You backstab the fleeing %s!", buf);
- }
-
- /* Complex message */
- if (wizard)
- {
- msg_format("You do %d (out of %d) damage.", k,
- m_ptr->hp);
- }
-
- if (special) attack_special(m_ptr, special, k);
-
- /* Damage, check for fear and death */
- if (mon_take_hit(c_ptr->m_idx, k, &fear, NULL))
- {
- /* Hack -- High-level warriors can spread their attacks out
- * among weaker foes.
- */
- if ((has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) &&
- (energy_use))
- {
- energy_use = energy_use * num / num_blow;
- }
- mdeath = TRUE;
- break;
- }
-
- switch (is_friend(m_ptr))
- {
- case 1:
- msg_format("%^s gets angry!", m_name);
- change_side(m_ptr);
- break;
- case 0:
- msg_format("%^s gets angry!", m_name);
- m_ptr->status = MSTATUS_NEUTRAL_M;
- break;
- }
-
- touch_zap_player(m_ptr);
-
- /* Are we draining it? A little note: If the monster is
- dead, the drain does not work... */
-
- if (drain_result)
- {
- drain_result -= m_ptr->hp; /* Calculate the difference */
-
- if (drain_result > 0) /* Did we really hurt it? */
- {
- drain_heal = damroll(4, (drain_result / 6));
-
- if (cheat_xtra)
- {
- msg_format("Draining left: %d", drain_left);
- }
-
- if (drain_left)
- {
- if (drain_heal < drain_left)
- {
- drain_left -= drain_heal;
- }
- else
- {
- drain_heal = drain_left;
- drain_left = 0;
- }
-
- if (drain_msg)
- {
- msg_format
- ("Your weapon drains life from %s!",
- m_name);
- drain_msg = FALSE;
- }
-
- hp_player(drain_heal);
- /* We get to keep some of it! */
- }
- }
- }
-
- /* Confusion attack */
- if ((p_ptr->confusing) || (chaos_effect == 3))
- {
- /* Cancel glowing hands */
- if (p_ptr->confusing)
- {
- p_ptr->confusing = FALSE;
- msg_print("Your hands stop glowing.");
- }
-
- /* Confuse the monster */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
- msg_format("%^s is unaffected.", m_name);
- }
- else if (rand_int(100) < m_ptr->level)
- {
- msg_format("%^s is unaffected.", m_name);
- }
- else
- {
- msg_format("%^s appears confused.", m_name);
- m_ptr->confused +=
- 10 + rand_int(get_skill(SKILL_COMBAT)) / 5;
- }
- }
-
- else if (chaos_effect == 4)
- {
- msg_format("%^s disappears!", m_name);
- teleport_away(c_ptr->m_idx, 50);
- num = num_blow + 1; /* Can't hit it anymore! */
- }
-
- else if ((chaos_effect == 5) && cave_floor_bold(y, x) &&
- (randint(90) > m_ptr->level))
- {
- if (!((r_ptr->flags1 & RF1_UNIQUE) ||
- (r_ptr->flags4 & RF4_BR_CHAO) ||
- (m_ptr->mflag & MFLAG_QUEST)))
- {
- /* Handle polymorph */
- if (do_poly_monster(y, x))
- {
- /* Polymorph succeeded */
- msg_format("%^s changes!", m_name);
-
- /* Hack -- Get new monster */
- m_ptr = &m_list[c_ptr->m_idx];
-
- /* Oops, we need a different name... */
- monster_desc(m_name, m_ptr, 0);
-
- /* Hack -- Get new race */
- r_ptr = race_inf(m_ptr);
-
- fear = FALSE;
- }
- else
- {
- msg_format("%^s resists.", m_name);
- }
- }
- else
- {
- msg_format("%^s is unaffected.", m_name);
- }
- }
- }
-
- /* Player misses */
- else
- {
- /* Sound */
- sound(SOUND_MISS);
-
- backstab = FALSE; /* Clumsy! */
-
- /* Message */
- msg_format("You miss %s.", m_name);
- }
- }
- }
- else
- {
- msg_print("You can't attack with that weapon.");
- }
- }
- }
-
- /* Carried monster can attack too */
- if ((!mdeath) && m_list[c_ptr->m_idx].hp)
- carried_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x);
-
- /* Hack -- delay fear messages */
- if (fear && m_ptr->ml)
- {
- /* Sound */
- sound(SOUND_FLEE);
-
- /* Message */
- msg_format("%^s flees in terror!", m_name);
- }
-
- /* Mega-Hack -- apply earthquake brand */
- if (do_quake)
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 10);
- }
-}
-
-
-
-static bool_ pattern_tile(int y, int x)
-{
- return ((cave[y][x].feat <= FEAT_PATTERN_XTRA2) &&
- (cave[y][x].feat >= FEAT_PATTERN_START));
-}
-
-
-static bool_ pattern_seq(int c_y, int c_x, int n_y, int n_x)
-{
- if (!(pattern_tile(c_y, c_x)) && !(pattern_tile(n_y, n_x)))
- return TRUE;
-
- if (cave[n_y][n_x].feat == FEAT_PATTERN_START)
- {
- if ((!(pattern_tile(c_y, c_x))) &&
- !(p_ptr->confused || p_ptr->stun || p_ptr->image))
- {
- if (get_check
- ("If you start walking the Straight Road, you must walk the whole way. Ok? "))
- return TRUE;
- else
- return FALSE;
- }
- else
- return TRUE;
- }
- else if ((cave[n_y][n_x].feat == FEAT_PATTERN_OLD) ||
- (cave[n_y][n_x].feat == FEAT_PATTERN_END) ||
- (cave[n_y][n_x].feat == FEAT_PATTERN_XTRA2))
- {
- if (pattern_tile(c_y, c_x))
- {
- return TRUE;
- }
- else
- {
- msg_print
- ("You must start walking the Straight Road from the startpoint.");
- return FALSE;
- }
- }
- else if ((cave[n_y][n_x].feat == FEAT_PATTERN_XTRA1) ||
- (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA1))
- {
- return TRUE;
- }
- else if (cave[c_y][c_x].feat == FEAT_PATTERN_START)
- {
- if (pattern_tile(n_y, n_x))
- return TRUE;
- else
- {
- msg_print("You must walk the Straight Road in correct order.");
- return FALSE;
- }
- }
- else if ((cave[c_y][c_x].feat == FEAT_PATTERN_OLD) ||
- (cave[c_y][c_x].feat == FEAT_PATTERN_END) ||
- (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA2))
- {
- if (!pattern_tile(n_y, n_x))
- {
- msg_print("You may not step off from the Straight Road.");
- return FALSE;
- }
- else
- {
- return TRUE;
- }
- }
- else
- {
- if (!pattern_tile(c_y, c_x))
- {
- msg_print
- ("You must start walking the Straight Road from the startpoint.");
- return FALSE;
- }
- else
- {
- byte ok_move = FEAT_PATTERN_START;
- switch (cave[c_y][c_x].feat)
- {
- case FEAT_PATTERN_1:
- ok_move = FEAT_PATTERN_2;
- break;
- case FEAT_PATTERN_2:
- ok_move = FEAT_PATTERN_3;
- break;
- case FEAT_PATTERN_3:
- ok_move = FEAT_PATTERN_4;
- break;
- case FEAT_PATTERN_4:
- ok_move = FEAT_PATTERN_1;
- break;
- default:
- if (wizard)
- msg_format("Funny Straight Road walking, %d.",
- cave[c_y][c_x]);
- return TRUE; /* Goof-up */
- }
-
- if ((cave[n_y][n_x].feat == ok_move) ||
- (cave[n_y][n_x].feat == cave[c_y][c_x].feat))
- return TRUE;
- else
- {
- if (!pattern_tile(n_y, n_x))
- msg_print("You may not step off from the Straight Road.");
- else
- msg_print
- ("You must walk the Straight Road in correct order.");
-
- return FALSE;
- }
- }
- }
-}
-
-
-
-bool_ player_can_enter(byte feature)
-{
- bool_ pass_wall;
-
- bool_ only_wall = FALSE;
-
-
- /* Player can not walk through "walls" unless in Shadow Form */
- if (p_ptr->wraith_form || (PRACE_FLAG(PR1_SEMI_WRAITH)))
- pass_wall = TRUE;
- else
- pass_wall = FALSE;
-
- /* Wall mimicry force the player to stay in walls */
- if (p_ptr->mimic_extra & CLASS_WALL)
- {
- only_wall = TRUE;
- }
-
- /* Don't let the player kill himself with one keystroke */
- if (p_ptr->wild_mode)
- {
- if (feature == FEAT_DEEP_WATER)
- {
- int wt = weight_limit() / 2;
-
- if ((calc_total_weight() >= wt) && !(p_ptr->ffall))
- return (FALSE);
- }
- else if (feature == FEAT_SHAL_LAVA ||
- feature == FEAT_DEEP_LAVA)
- {
- if (!(p_ptr->resist_fire ||
- p_ptr->immune_fire ||
- p_ptr->oppose_fire ||
- p_ptr->ffall))
- return (FALSE);
- }
- }
-
- if (feature == FEAT_TREES)
- {
- if (p_ptr->fly ||
- pass_wall ||
- (has_ability(AB_TREE_WALK)) ||
- (p_ptr->mimic_form == resolve_mimic_name("Ent")) ||
- ((p_ptr->grace >= 9000) && (p_ptr->praying) && (p_ptr->pgod == GOD_YAVANNA)))
- return (TRUE);
- }
-
- if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB))
- return (TRUE);
- if ((p_ptr->fly) &&
- ((f_info[feature].flags1 & FF1_CAN_FLY) ||
- (f_info[feature].flags1 & FF1_CAN_LEVITATE)))
- return (TRUE);
- else if (only_wall && (f_info[feature].flags1 & FF1_FLOOR))
- return (FALSE);
- else if ((p_ptr->ffall) &&
- (f_info[feature].flags1 & FF1_CAN_LEVITATE))
- return (TRUE);
- else if ((pass_wall || only_wall) &&
- (f_info[feature].flags1 & FF1_CAN_PASS))
- return (TRUE);
- else if (f_info[feature].flags1 & FF1_NO_WALK)
- return (FALSE);
- else if ((f_info[feature].flags1 & FF1_WEB) &&
- ((!(r_info[p_ptr->body_monster].flags7 & RF7_SPIDER)) && (p_ptr->mimic_form != resolve_mimic_name("Spider"))))
- return (FALSE);
-
- return (TRUE);
-}
-
-/*
- * Move player in the given direction, with the given "pickup" flag.
- *
- * This routine should (probably) always induce energy expenditure.
- *
- * Note that moving will *always* take a turn, and will *always* hit
- * any monster which might be in the destination grid. Previously,
- * moving into walls was "free" and did NOT hit invisible monsters.
- */
-void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
-{
- int y, x, tmp;
-
- cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px];
-
- monster_type *m_ptr;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster], *mr_ptr;
-
- char m_name[80];
-
- bool_ stormbringer = FALSE;
-
- bool_ old_dtrap, new_dtrap;
-
- bool_ oktomove = TRUE;
-
-
- /* Hack - random movement */
- if (p_ptr->disembodied)
- tmp = dir;
- else if ((r_ptr->flags1 & RF1_RAND_25) && (r_ptr->flags1 & RF1_RAND_50))
- {
- if (randint(100) < 75)
- tmp = randint(9);
- else
- tmp = dir;
- }
- else if (r_ptr->flags1 & RF1_RAND_50)
- {
- if (randint(100) < 50)
- tmp = randint(9);
- else
- tmp = dir;
- }
- else if (r_ptr->flags1 & RF1_RAND_25)
- {
- if (randint(100) < 25)
- tmp = randint(9);
- else
- tmp = dir;
- }
- else
- {
- tmp = dir;
- }
-
- if ((c_ptr->feat == FEAT_ICE) && (!p_ptr->ffall && !p_ptr->fly))
- {
- if (magik(70 - p_ptr->lev))
- {
- tmp = randint(9);
- msg_print("You slip on the icy floor.");
- }
- else
- tmp = dir;
- }
-
- /* Find the result of moving */
- y = p_ptr->py + ddy[tmp];
- x = p_ptr->px + ddx[tmp];
-
- /* Examine the destination */
- c_ptr = &cave[y][x];
-
- /* Change oldpx and oldpy to place the player well when going back to big mode */
- if (p_ptr->wild_mode)
- {
- if (ddy[tmp] > 0) p_ptr->oldpy = 1;
- if (ddy[tmp] < 0) p_ptr->oldpy = MAX_HGT - 2;
- if (ddy[tmp] == 0) p_ptr->oldpy = MAX_HGT / 2;
- if (ddx[tmp] > 0) p_ptr->oldpx = 1;
- if (ddx[tmp] < 0) p_ptr->oldpx = MAX_WID - 2;
- if (ddx[tmp] == 0) p_ptr->oldpx = MAX_WID / 2;
- }
-
- /* Exit the area */
- if (!dun_level && !p_ptr->wild_mode && !is_quest(dun_level) &&
- ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1)))
- {
- /* Can the player enter the grid? */
- if (player_can_enter(c_ptr->mimic))
- {
- /* Hack: move to new area */
- if ((y == 0) && (x == 0))
- {
- p_ptr->wilderness_y--;
- p_ptr->wilderness_x--;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = cur_wid - 2;
- ambush_flag = FALSE;
- }
-
- else if ((y == 0) && (x == MAX_WID - 1))
- {
- p_ptr->wilderness_y--;
- p_ptr->wilderness_x++;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = 1;
- ambush_flag = FALSE;
- }
-
- else if ((y == MAX_HGT - 1) && (x == 0))
- {
- p_ptr->wilderness_y++;
- p_ptr->wilderness_x--;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = cur_wid - 2;
- ambush_flag = FALSE;
- }
-
- else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1))
- {
- p_ptr->wilderness_y++;
- p_ptr->wilderness_x++;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = 1;
- ambush_flag = FALSE;
- }
-
- else if (y == 0)
- {
- p_ptr->wilderness_y--;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = x;
- ambush_flag = FALSE;
- }
-
- else if (y == cur_hgt - 1)
- {
- p_ptr->wilderness_y++;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = x;
- ambush_flag = FALSE;
- }
-
- else if (x == 0)
- {
- p_ptr->wilderness_x--;
- p_ptr->oldpx = cur_wid - 2;
- p_ptr->oldpy = y;
- ambush_flag = FALSE;
- }
-
- else if (x == cur_wid - 1)
- {
- p_ptr->wilderness_x++;
- p_ptr->oldpx = 1;
- p_ptr->oldpy = y;
- ambush_flag = FALSE;
- }
-
- p_ptr->leaving = TRUE;
-
- return;
- }
- }
-
- /* Some hooks */
- if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return;
-
- /* Get the monster */
- m_ptr = &m_list[c_ptr->m_idx];
- mr_ptr = race_inf(m_ptr);
-
- if (p_ptr->inventory[INVEN_WIELD].art_name)
- {
- if (streq(quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'"))
- stormbringer = TRUE;
- }
-
- /* Hack -- attack monsters */
- if (c_ptr->m_idx && (m_ptr->ml || player_can_enter(c_ptr->feat)))
- {
-
- /* Attack -- only if we can see it OR it is not in a wall */
- if ((is_friend(m_ptr) > 0) &&
- !(p_ptr->confused || p_ptr->image || !(m_ptr->ml) || p_ptr->stun) &&
- (pattern_seq(p_ptr->py, p_ptr->px, y, x)) &&
- ((player_can_enter(cave[y][x].feat))))
- {
- m_ptr->csleep = 0;
-
- /* Extract monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Auto-Recall if possible and visible */
- if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego);
-
- /* Track a new monster */
- if (m_ptr->ml) health_track(c_ptr->m_idx);
-
- /* displace? */
- if (stormbringer && (randint(1000) > 666))
- {
- py_attack(y, x, -1);
- }
- else if (cave_floor_bold(p_ptr->py, p_ptr->px) ||
- (mr_ptr->flags2 & RF2_PASS_WALL))
- {
- msg_format("You push past %s.", m_name);
- m_ptr->fy = p_ptr->py;
- m_ptr->fx = p_ptr->px;
- cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
- c_ptr->m_idx = 0;
- update_mon(cave[p_ptr->py][p_ptr->px].m_idx, TRUE);
- }
- else
- {
- msg_format("%^s is in your way!", m_name);
- energy_use = 0;
- oktomove = FALSE;
- }
-
- /* now continue on to 'movement' */
- }
- else
- {
- py_attack(y, x, -1);
- oktomove = FALSE;
- }
- }
-
- else if ((c_ptr->feat == FEAT_DARK_PIT) && !p_ptr->ffall)
- {
- msg_print("You can't cross the chasm.");
- running = 0;
- oktomove = FALSE;
- }
-
- /* Disarm a visible trap */
- else if (easy_disarm && disarm && (c_ptr->info & (CAVE_TRDT)))
- {
- (void)do_cmd_disarm_aux(y, x, tmp, do_pickup);
- return;
- }
-
- /* Don't step on known traps. */
- else if (disarm && (c_ptr->info & (CAVE_TRDT)) && !(p_ptr->confused || p_ptr->stun || p_ptr->image))
- {
- msg_print("You stop to avoid triggering the trap.");
- energy_use = 0;
- oktomove = FALSE;
- }
-
- /* Player can't enter ? soo bad for him/her ... */
- else if (!player_can_enter(c_ptr->feat))
- {
- oktomove = FALSE;
-
- /* Disturb the player */
- disturb(0, 0);
-
- if (p_ptr->prob_travel)
- {
- if (passwall(tmp, TRUE)) return;
- }
-
- /* Notice things in the dark */
- if (!(c_ptr->info & (CAVE_MARK)) && !(c_ptr->info & (CAVE_SEEN)))
- {
- /* Rubble */
- if (c_ptr->feat == FEAT_RUBBLE)
- {
- msg_print("You feel some rubble blocking your way.");
- c_ptr->info |= (CAVE_MARK);
- lite_spot(y, x);
- }
-
- /* Closed door */
- else if (c_ptr->feat < FEAT_SECRET)
- {
- msg_print("You feel a closed door blocking your way.");
- c_ptr->info |= (CAVE_MARK);
- lite_spot(y, x);
- }
-
- /* Wall (or secret door) */
- else
- {
- int feat;
-
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else
- feat = f_info[c_ptr->feat].mimic;
-
- msg_format("You feel %s.", f_text + f_info[feat].block);
- c_ptr->info |= (CAVE_MARK);
- lite_spot(y, x);
- }
- }
-
- /* Notice things */
- else
- {
- /* Rubble */
- if (c_ptr->feat == FEAT_RUBBLE)
- {
- if (!easy_tunnel)
- {
- msg_print("There is rubble blocking your way.");
-
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- energy_use = 0;
- /*
- * Well, it makes sense that you lose time bumping into
- * a wall _if_ you are confused, stunned or blind; but
- * typing mistakes should not cost you a turn...
- */
- }
- else
- {
- do_cmd_tunnel_aux(y, x, dir);
- return;
- }
- }
- /* Closed doors */
- else if ((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL))
- {
- if (easy_open)
- {
- if (easy_open_door(y, x)) return;
- }
- else
- {
- msg_print("There is a closed door blocking your way.");
-
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- energy_use = 0;
- }
- }
-
- /* Wall (or secret door) */
- else
- {
- if (!easy_tunnel)
- {
- int feat;
-
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else
- feat = f_info[c_ptr->feat].mimic;
-
- msg_format("There is %s.", f_text + f_info[feat].block);
-
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- energy_use = 0;
- }
- else
- {
- do_cmd_tunnel_aux(y, x, dir);
- return;
- }
- }
- }
-
- /* Sound */
- sound(SOUND_HITWALL);
- }
-
- /* Normal movement */
- if (!pattern_seq(p_ptr->py, p_ptr->px, y, x))
- {
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- {
- energy_use = 0;
- }
-
- disturb(0, 0); /* To avoid a loop with running */
-
- oktomove = FALSE;
- }
-
-
- /*
- * Check trap detection status -- retrieve them here
- * because they are used by the movement code as well
- */
- old_dtrap = ((cave[p_ptr->py][p_ptr->px].info & CAVE_DETECT) != 0);
- new_dtrap = ((cave[y][x].info & CAVE_DETECT) != 0);
-
- /* Normal movement */
- if (oktomove && running && disturb_detect)
- {
- /*
- * Disturb the player when about to leave the trap detected
- * area
- */
- if (old_dtrap && !new_dtrap)
- {
- /* Disturb player */
- disturb(0, 0);
-
- /* but don't take a turn */
- energy_use = 0;
-
- /* Tell player why */
- cmsg_print(TERM_VIOLET, "You are about to leave a trap detected zone.");
- /* Flush */
- /* msg_print(NULL); */
-
- oktomove = FALSE;
- }
- }
-
- /* Normal movement */
- if (oktomove)
- {
- int oy, ox;
- int feat;
-
- /* Rooted means no move */
- if (p_ptr->tim_roots) return;
-
- /* Save old location */
- oy = p_ptr->py;
- ox = p_ptr->px;
-
- /* Move the player */
- p_ptr->py = y;
- p_ptr->px = x;
-
- if (cave[p_ptr->py][p_ptr->px].mimic) feat = cave[p_ptr->py][p_ptr->px].mimic;
- else
- feat = cave[p_ptr->py][p_ptr->px].feat;
-
- /* Some hooks */
- if (process_hooks(HOOK_MOVED, "(d,d)", oy, ox)) return;
-
- /* Redraw new spot */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Redraw old spot */
- lite_spot(oy, ox);
-
- /* Sound */
- /* sound(SOUND_WALK); */
-
- /* Check for new panel (redraw map) */
- verify_panel();
-
- /* Check detection status */
- if (old_dtrap && !new_dtrap)
- {
- cmsg_print(TERM_VIOLET, "You leave a trap detected zone.");
- if (running) msg_print(NULL);
- p_ptr->redraw |= (PR_DTRAP);
- }
- else if (!old_dtrap && new_dtrap)
- {
- cmsg_print(TERM_L_BLUE, "You enter a trap detected zone.");
- if (running) msg_print(NULL);
- p_ptr->redraw |= (PR_DTRAP);
- }
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Window stuff */
- if (!run) p_ptr->window |= (PW_OVERHEAD);
-
- /* Some feature descs */
- if (f_info[cave[p_ptr->py][p_ptr->px].feat].text > 1)
- {
- /* Mega-hack for dungeon branches */
- if ((feat == FEAT_MORE) && c_ptr->special)
- {
- msg_format("There is %s", d_text + d_info[c_ptr->special].text);
- }
- else
- {
- msg_print(f_text + f_info[feat].text);
- }
-
- /* Flush message while running */
- if (running) msg_print(NULL);
- }
-
- /* Spontaneous Searching */
- if ((p_ptr->skill_fos >= 50) || (0 == rand_int(50 - p_ptr->skill_fos)))
- {
- search();
- }
-
- /* Continuous Searching */
- if (p_ptr->searching)
- {
- search();
- }
-
- /* Handle "objects" */
- carry(do_pickup);
-
- /* Handle "store doors" */
- if (c_ptr->feat == FEAT_SHOP)
- {
- /* Disturb */
- disturb(0, 0);
-
- /* Hack -- Enter store */
- command_new = '_';
- }
-
- else if (cave[y][x].feat >= FEAT_ALTAR_HEAD &&
- cave[y][x].feat <= FEAT_ALTAR_TAIL)
- {
- cptr name = f_name + f_info[cave[y][x].feat].name;
- cptr pref = (is_a_vowel(name[0])) ? "an" : "a";
-
- msg_format("You see %s %s.", pref, name);
-
- /* Flush message while running */
- if (running) msg_print(NULL);
- }
-
- /* Discover invisible traps */
- else if ((c_ptr->t_idx != 0) &&
- !(f_info[cave[y][x].feat].flags1 & FF1_DOOR))
- {
- /* Disturb */
- disturb(0, 0);
-
- if (!(c_ptr->info & (CAVE_TRDT)))
- {
- /* Message */
- msg_print("You found a trap!");
-
- /* Pick a trap */
- pick_trap(p_ptr->py, p_ptr->px);
- }
-
- /* Hit the trap */
- hit_trap();
- }
-
- /* Execute the inscription */
- else if (c_ptr->inscription)
- {
- /* Disturb */
- disturb(0, 0);
-
- msg_format("There is an inscription here: %s",
- inscription_info[c_ptr->inscription].text);
- if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_WALK)
- {
- execute_inscription(c_ptr->inscription, p_ptr->py, p_ptr->px);
- }
- }
- }
-
- /* Update wilderness knowledge */
- if (p_ptr->wild_mode)
- {
- if (wizard) msg_format("y:%d, x:%d", p_ptr->py, p_ptr->px);
-
- /* Update the known wilderness */
- reveal_wilderness_around_player(p_ptr->py, p_ptr->px, 0, WILDERNESS_SEE_RADIUS);
-
- /* Walking the wild isnt meaningfull */
- p_ptr->did_nothing = TRUE;
- }
-}
-
-void move_player(int dir, int do_pickup, bool_ disarm)
-{
- move_player_aux(dir, do_pickup, 0, disarm);
-}
-
-
-/*
- * Hack -- Grid-based version of see_obstacle
- */
-static int see_obstacle_grid(cave_type *c_ptr)
-{
- /*
- * Hack -- Avoid hitting detected traps, because we cannot rely on
- * the CAVE_MARK check below, and traps can be set to nearly
- * everything the player can move on to XXX XXX XXX
- */
- if (c_ptr->info & (CAVE_TRDT)) return (TRUE);
-
-
- /* Hack -- Handle special cases XXX XXX */
- switch (c_ptr->feat)
- {
- /* Require levitation */
- case FEAT_DARK_PIT:
- case FEAT_DEEP_WATER:
- case FEAT_ICE:
- {
- if (p_ptr->ffall || p_ptr->fly) return (FALSE);
- }
-
- /* Require immunity */
- case FEAT_DEEP_LAVA:
- case FEAT_SHAL_LAVA:
- {
- if (p_ptr->invuln || p_ptr->immune_fire) return (FALSE);
- }
- }
-
-
- /* "Safe" floor grids aren't obstacles */
- if (f_info[c_ptr->feat].flags1 & FF1_CAN_RUN) return (FALSE);
-
- /* Must be known to the player */
- if (!(c_ptr->info & (CAVE_MARK))) return (FALSE);
-
- /* Default */
- return (TRUE);
-}
-
-
-/*
- * Hack -- Check for a "known wall" or "dangerous" feature (see below)
- */
-static int see_obstacle(int dir, int y, int x)
-{
- /* Get the new location */
- y += ddy[dir];
- x += ddx[dir];
-
- /* Illegal grids are not known walls */
- if (!in_bounds2(y, x)) return (FALSE);
-
- /* Analyse the grid */
- return (see_obstacle_grid(&cave[y][x]));
-}
-
-
-/*
- * Hack -- Check for an "unknown corner" (see below)
- */
-static int see_nothing(int dir, int y, int x)
-{
- /* Get the new location */
- y += ddy[dir];
- x += ddx[dir];
-
- /* Illegal grids are unknown */
- if (!in_bounds2(y, x)) return (TRUE);
-
- /* Memorized grids are always known */
- if (cave[y][x].info & (CAVE_MARK)) return (FALSE);
-
- /* Non-floor grids are unknown */
- if (!cave_floor_bold(y, x)) return (TRUE);
-
- /* Viewable door/wall grids are known */
- if (player_can_see_bold(y, x)) return (FALSE);
-
- /* Default */
- return (TRUE);
-}
-
-
-
-
-
-/*
- * The running algorithm: -CJS-
- *
- * In the diagrams below, the player has just arrived in the
- * grid marked as '@', and he has just come from a grid marked
- * as 'o', and he is about to enter the grid marked as 'x'.
- *
- * Of course, if the "requested" move was impossible, then you
- * will of course be blocked, and will stop.
- *
- * Overview: You keep moving until something interesting happens.
- * If you are in an enclosed space, you follow corners. This is
- * the usual corridor scheme. If you are in an open space, you go
- * straight, but stop before entering enclosed space. This is
- * analogous to reaching doorways. If you have enclosed space on
- * one side only (that is, running along side a wall) stop if
- * your wall opens out, or your open space closes in. Either case
- * corresponds to a doorway.
- *
- * What happens depends on what you can really SEE. (i.e. if you
- * have no light, then running along a dark corridor is JUST like
- * running in a dark room.) The algorithm works equally well in
- * corridors, rooms, mine tailings, earthquake rubble, etc, etc.
- *
- * These conditions are kept in static memory:
- * find_openarea You are in the open on at least one
- * side.
- * find_breakleft You have a wall on the left, and will
- * stop if it opens
- * find_breakright You have a wall on the right, and will
- * stop if it opens
- *
- * To initialize these conditions, we examine the grids adjacent
- * to the grid marked 'x', two on each side (marked 'L' and 'R').
- * If either one of the two grids on a given side is seen to be
- * closed, then that side is considered to be closed. If both
- * sides are closed, then it is an enclosed (corridor) run.
- *
- * LL L
- * @x LxR
- * RR @R
- *
- * Looking at more than just the immediate squares is
- * significant. Consider the following case. A run along the
- * corridor will stop just before entering the center point,
- * because a choice is clearly established. Running in any of
- * three available directions will be defined as a corridor run.
- * Note that a minor hack is inserted to make the angled corridor
- * entry (with one side blocked near and the other side blocked
- * further away from the runner) work correctly. The runner moves
- * diagonally, but then saves the previous direction as being
- * straight into the gap. Otherwise, the tail end of the other
- * entry would be perceived as an alternative on the next move.
- *
- * #.#
- * ##.##
- * .@x..
- * ##.##
- * #.#
- *
- * Likewise, a run along a wall, and then into a doorway (two
- * runs) will work correctly. A single run rightwards from @ will
- * stop at 1. Another run right and down will enter the corridor
- * and make the corner, stopping at the 2.
- *
- * #@x 1
- * ########### ######
- * 2 #
- * #############
- * #
- *
- * After any move, the function area_affect is called to
- * determine the new surroundings, and the direction of
- * subsequent moves. It examines the current player location
- * (at which the runner has just arrived) and the previous
- * direction (from which the runner is considered to have come).
- *
- * Moving one square in some direction places you adjacent to
- * three or five new squares (for straight and diagonal moves
- * respectively) to which you were not previously adjacent,
- * marked as '!' in the diagrams below.
- *
- * ...! ...
- * .o@! .o.!
- * ...! ..@!
- * !!!
- *
- * You STOP if any of the new squares are interesting in any way:
- * for example, if they contain visible monsters or treasure.
- *
- * You STOP if any of the newly adjacent squares seem to be open,
- * and you are also looking for a break on that side. (that is,
- * find_openarea AND find_break).
- *
- * You STOP if any of the newly adjacent squares do NOT seem to be
- * open and you are in an open area, and that side was previously
- * entirely open.
- *
- * Corners: If you are not in the open (i.e. you are in a corridor)
- * and there is only one way to go in the new squares, then turn in
- * that direction. If there are more than two new ways to go, STOP.
- * If there are two ways to go, and those ways are separated by a
- * square which does not seem to be open, then STOP.
- *
- * Otherwise, we have a potential corner. There are two new open
- * squares, which are also adjacent. One of the new squares is
- * diagonally located, the other is straight on (as in the diagram).
- * We consider two more squares further out (marked below as ?).
- *
- * We assign "option" to the straight-on grid, and "option2" to the
- * diagonal grid, and "check_dir" to the grid marked 's'.
- *
- * .s
- * @x?
- * #?
- *
- * If they are both seen to be closed, then it is seen that no
- * benefit is gained from moving straight. It is a known corner.
- * To cut the corner, go diagonally, otherwise go straight, but
- * pretend you stepped diagonally into that next location for a
- * full view next time. Conversely, if one of the ? squares is
- * not seen to be closed, then there is a potential choice. We check
- * to see whether it is a potential corner or an intersection/room entrance.
- * If the square two spaces straight ahead, and the space marked with 's'
- * are both blank, then it is a potential corner and enter if find_examine
- * is set, otherwise must stop because it is not a corner.
- */
-
-
-
-
-/*
- * Hack -- allow quick "cycling" through the legal directions
- */
-static byte cycle[] = { 1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1 };
-
-/*
- * Hack -- map each direction into the "middle" of the "cycle[]" array
- */
-static byte chome[] = { 0, 8, 9, 10, 7, 0, 11, 6, 5, 4 };
-
-/*
- * The direction we are running
- */
-static byte find_current;
-
-/*
- * The direction we came from
- */
-static byte find_prevdir;
-
-/*
- * We are looking for open area
- */
-static bool_ find_openarea;
-
-/*
- * We are looking for a break
- */
-static bool_ find_breakright;
-static bool_ find_breakleft;
-
-
-
-/*
- * Initialize the running algorithm for a new direction.
- *
- * Diagonal Corridor -- allow diaginal entry into corridors.
- *
- * Blunt Corridor -- If there is a wall two spaces ahead and
- * we seem to be in a corridor, then force a turn into the side
- * corridor, must be moving straight into a corridor here. ???
- *
- * Diagonal Corridor Blunt Corridor (?)
- * # # #
- * #x# @x#
- * @p. p
- */
-static void run_init(int dir)
-{
- int row, col, deepleft, deepright;
-
- int i, shortleft, shortright;
-
-
- /* Save the direction */
- find_current = dir;
-
- /* Assume running straight */
- find_prevdir = dir;
-
- /* Assume looking for open area */
- find_openarea = TRUE;
-
- /* Assume not looking for breaks */
- find_breakright = find_breakleft = FALSE;
-
- /* Assume no nearby walls */
- deepleft = deepright = FALSE;
- shortright = shortleft = FALSE;
-
- /* Find the destination grid */
- row = p_ptr->py + ddy[dir];
- col = p_ptr->px + ddx[dir];
-
- /* Extract cycle index */
- i = chome[dir];
-
- /* Check for walls */
- if (see_obstacle(cycle[i + 1], p_ptr->py, p_ptr->px))
- {
- find_breakleft = TRUE;
- shortleft = TRUE;
- }
- else if (see_obstacle(cycle[i + 1], row, col))
- {
- find_breakleft = TRUE;
- deepleft = TRUE;
- }
-
- /* Check for walls */
- if (see_obstacle(cycle[i - 1], p_ptr->py, p_ptr->px))
- {
- find_breakright = TRUE;
- shortright = TRUE;
- }
- else if (see_obstacle(cycle[i - 1], row, col))
- {
- find_breakright = TRUE;
- deepright = TRUE;
- }
-
- /* Looking for a break */
- if (find_breakleft && find_breakright)
- {
- /* Not looking for open area */
- find_openarea = FALSE;
-
- /* Hack -- allow angled corridor entry */
- if (dir & 0x01)
- {
- if (deepleft && !deepright)
- {
- find_prevdir = cycle[i - 1];
- }
- else if (deepright && !deepleft)
- {
- find_prevdir = cycle[i + 1];
- }
- }
-
- /* Hack -- allow blunt corridor entry */
- else if (see_obstacle(cycle[i], row, col))
- {
- if (shortleft && !shortright)
- {
- find_prevdir = cycle[i - 2];
- }
- else if (shortright && !shortleft)
- {
- find_prevdir = cycle[i + 2];
- }
- }
- }
-}
-
-
-/*
- * Update the current "run" path
- *
- * Return TRUE if the running should be stopped
- */
-static bool_ run_test(void)
-{
- int prev_dir, new_dir, check_dir = 0;
-
- int row, col;
-
- int i, max, inv;
-
- int option = 0, option2 = 0;
-
- cave_type *c_ptr;
-
-
- /* Where we came from */
- prev_dir = find_prevdir;
-
-
- /* Range of newly adjacent grids */
- max = (prev_dir & 0x01) + 1;
-
-
- /* Look at every newly adjacent square. */
- for (i = -max; i <= max; i++)
- {
- s16b this_o_idx, next_o_idx = 0;
-
-
- /* New direction */
- new_dir = cycle[chome[prev_dir] + i];
-
- /* New location */
- row = p_ptr->py + ddy[new_dir];
- col = p_ptr->px + ddx[new_dir];
-
- /* Access grid */
- c_ptr = &cave[row][col];
-
-
- /* Visible monsters abort running */
- if (c_ptr->m_idx)
- {
- monster_type *m_ptr = &m_list[c_ptr->m_idx];
-
- /* Visible monster */
- if (m_ptr->ml) return (TRUE);
- }
-
- /* Visible objects abort running */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Visible object */
- if (o_ptr->marked) return (TRUE);
- }
-
-
- /* Assume unknown */
- inv = TRUE;
-
- /* Check memorized grids */
- if (c_ptr->info & (CAVE_MARK))
- {
- bool_ notice = TRUE;
-
- /*
- * Examine the terrain -- conditional disturbance
- * If we had more flags, we could make these customisable too
- */
- switch (c_ptr->feat)
- {
- case FEAT_DEEP_LAVA:
- case FEAT_SHAL_LAVA:
- {
- /* Ignore */
- if (p_ptr->invuln || p_ptr->immune_fire) notice = FALSE;
-
- /* Done */
- break;
- }
-
- case FEAT_DEEP_WATER:
- case FEAT_ICE:
- {
- /* Ignore */
- if (p_ptr->ffall || p_ptr->fly) notice = FALSE;
-
- /* Done */
- break;
- }
-
- /* Open doors */
- case FEAT_OPEN:
- case FEAT_BROKEN:
- {
- /* Option -- ignore */
- if (find_ignore_doors) notice = FALSE;
-
- /* Done */
- break;
- }
-
- /*
- * Stairs - too many of them, should find better ways to
- * handle them (not scripting!, because it can be called
- * from within the running algo) XXX XXX XXX
- */
- case FEAT_LESS:
- case FEAT_MORE:
- case FEAT_QUEST_ENTER:
- case FEAT_QUEST_EXIT:
- case FEAT_QUEST_DOWN:
- case FEAT_QUEST_UP:
- case FEAT_SHAFT_UP:
- case FEAT_SHAFT_DOWN:
- case FEAT_WAY_LESS:
- case FEAT_WAY_MORE:
- /* XXX */
- case FEAT_BETWEEN:
- case FEAT_BETWEEN2:
- {
- /* Option -- ignore */
- if (find_ignore_stairs) notice = FALSE;
-
- /* Done */
- break;
- }
- }
-
- /* Check the "don't notice running" flag */
- if (f_info[c_ptr->feat].flags1 & FF1_DONT_NOTICE_RUNNING)
- {
- notice = FALSE;
- }
-
- /* A detected trap is interesting */
- if (c_ptr->info & (CAVE_TRDT)) notice = TRUE;
-
- /* Interesting feature */
- if (notice) return (TRUE);
-
- /* The grid is "visible" */
- inv = FALSE;
- }
-
- /* Mega-Hack -- Maze code removes CAVE_MARK XXX XXX XXX */
- if (c_ptr->info & (CAVE_TRDT)) return (TRUE);
-
- /* Analyze unknown grids and floors */
- if (inv || cave_floor_bold(row, col))
- {
- /* Looking for open area */
- if (find_openarea)
- {
- /* Nothing */
- }
-
- /* The first new direction. */
- else if (!option)
- {
- option = new_dir;
- }
-
- /* Three new directions. Stop running. */
- else if (option2)
- {
- return (TRUE);
- }
-
- /* Two non-adjacent new directions. Stop running. */
- else if (option != cycle[chome[prev_dir] + i - 1])
- {
- return (TRUE);
- }
-
- /* Two new (adjacent) directions (case 1) */
- else if (new_dir & 0x01)
- {
- check_dir = cycle[chome[prev_dir] + i - 2];
- option2 = new_dir;
- }
-
- /* Two new (adjacent) directions (case 2) */
- else
- {
- check_dir = cycle[chome[prev_dir] + i + 1];
- option2 = option;
- option = new_dir;
- }
- }
-
- /* Obstacle, while looking for open area */
- else
- {
- if (find_openarea)
- {
- if (i < 0)
- {
- /* Break to the right */
- find_breakright = TRUE;
- }
-
- else if (i > 0)
- {
- /* Break to the left */
- find_breakleft = TRUE;
- }
- }
- }
- }
-
-
- /* Looking for open area */
- if (find_openarea)
- {
- /* Hack -- look again */
- for (i = -max; i < 0; i++)
- {
- new_dir = cycle[chome[prev_dir] + i];
-
- row = p_ptr->py + ddy[new_dir];
- col = p_ptr->px + ddx[new_dir];
-
- /* Access grid */
- c_ptr = &cave[row][col];
-
- /* Unknown grids or non-obstacle */
- if (!see_obstacle_grid(c_ptr))
- {
- /* Looking to break right */
- if (find_breakright)
- {
- return (TRUE);
- }
- }
-
- /* Obstacle */
- else
- {
- /* Looking to break left */
- if (find_breakleft)
- {
- return (TRUE);
- }
- }
- }
-
- /* Hack -- look again */
- for (i = max; i > 0; i--)
- {
- new_dir = cycle[chome[prev_dir] + i];
-
- row = p_ptr->py + ddy[new_dir];
- col = p_ptr->px + ddx[new_dir];
-
- /* Access grid */
- c_ptr = &cave[row][col];
-
- /* Unknown grid or non-obstacle */
- if (!see_obstacle_grid(c_ptr))
- {
- /* Looking to break left */
- if (find_breakleft)
- {
- return (TRUE);
- }
- }
-
- /* Obstacle */
- else
- {
- /* Looking to break right */
- if (find_breakright)
- {
- return (TRUE);
- }
- }
- }
- }
-
-
- /* Not looking for open area */
- else
- {
- /* No options */
- if (!option)
- {
- return (TRUE);
- }
-
- /* One option */
- else if (!option2)
- {
- /* Primary option */
- find_current = option;
-
- /* No other options */
- find_prevdir = option;
- }
-
- /* Two options, examining corners */
- else if (find_examine && !find_cut)
- {
- /* Primary option */
- find_current = option;
-
- /* Hack -- allow curving */
- find_prevdir = option2;
- }
-
- /* Two options, pick one */
- else
- {
- /* Get next location */
- row = p_ptr->py + ddy[option];
- col = p_ptr->px + ddx[option];
-
- /* Don't see that it is closed off. */
- /* This could be a potential corner or an intersection. */
- if (!see_obstacle(option, row, col) || !see_obstacle(check_dir, row, col))
- {
- /* Can not see anything ahead and in the direction we */
- /* are turning, assume that it is a potential corner. */
- if (find_examine &&
- see_nothing(option, row, col) &&
- see_nothing(option2, row, col))
- {
- find_current = option;
- find_prevdir = option2;
- }
-
- /* STOP: we are next to an intersection or a room */
- else
- {
- return (TRUE);
- }
- }
-
- /* This corner is seen to be enclosed; we cut the corner. */
- else if (find_cut)
- {
- find_current = option2;
- find_prevdir = option2;
- }
-
- /* This corner is seen to be enclosed, and we */
- /* deliberately go the long way. */
- else
- {
- find_current = option;
- find_prevdir = option2;
- }
- }
- }
-
-
- /* About to hit a known wall, stop */
- if (see_obstacle(find_current, p_ptr->py, p_ptr->px))
- {
- return (TRUE);
- }
-
-
- /* Failure */
- return (FALSE);
-}
-
-
-
-/*
- * Take one step along the current "run" path
- */
-void run_step(int dir)
-{
- /* Start running */
- if (dir)
- {
- /* Hack -- do not start silly run */
- if (see_obstacle(dir, p_ptr->py, p_ptr->px) &&
- (cave[p_ptr->py + ddy[dir]][p_ptr->px + ddx[dir]].feat != FEAT_TREES))
- {
- /* Message */
- msg_print("You cannot run in that direction.");
-
- /* Disturb */
- disturb(0, 0);
-
- /* Done */
- return;
- }
-
- /* Calculate torch radius */
- p_ptr->update |= (PU_TORCH);
-
- /* Initialize */
- run_init(dir);
- }
-
- /* Keep running */
- else
- {
- /* Update run */
- if (run_test())
- {
- /* Disturb */
- disturb(0, 0);
-
- /* Done */
- return;
- }
- }
-
- /* Decrease the run counter */
- if (--running <= 0) return;
-
- /* Take time */
- energy_use = 100;
-
-
- /* Move the player, using the "pickup" flag */
- move_player_aux(find_current, always_pickup, 1, TRUE);
-}
-
-
-/*
- * Take care of the various things that can happen when you step
- * into a space. (Objects, traps, and stores.)
- */
-void step_effects(int y, int x, int do_pickup)
-{
- /* Handle "objects" */
- py_pickup_floor(do_pickup);
-
- /* Handle "store doors" */
- if (cave[y][x].feat == FEAT_SHOP)
- {
- /* Disturb */
- disturb(0, 0);
-
- /* Hack -- Enter store */
- command_new = KTRL('V');
- }
-
- /* Discover/set off traps */
- else if (cave[y][x].t_idx != 0)
- {
- /* Disturb */
- disturb(0, 0);
-
- if (!(cave[y][x].info & CAVE_TRDT))
- {
- /* Message */
- msg_print("You found a trap!");
-
- /* Pick a trap */
- pick_trap(y, x);
- }
-
- /* Hit the trap */
- hit_trap();
- }
-}
-
-/*
- * Issue a pet command
- */
-void do_cmd_pet(void)
-{
- int i = 0;
-
- int num = 0;
-
- int powers[36];
-
- char power_desc[36][80];
-
- bool_ flag, redraw;
-
- int ask;
-
- char choice;
-
- char out_val[160];
-
- int pets = 0, pet_ctr = 0;
-
- bool_ all_pets = FALSE;
-
- monster_type *m_ptr;
-
-
- for (num = 0; num < 36; num++)
- {
- powers[num] = 0;
- strcpy(power_desc[num], "");
- }
-
- num = 0;
-
- if (p_ptr->confused)
- {
- msg_print("You are too confused to command your pets.");
- energy_use = 0;
- return;
- }
-
- /* Calculate pets */
- /* Process the monsters (backwards) */
- for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--)
- {
- /* Access the monster */
- m_ptr = &m_list[pet_ctr];
-
- if (m_ptr->status >= MSTATUS_FRIEND) pets++;
- }
-
- if (pets == 0)
- {
- msg_print("You have no pets/companions.");
- energy_use = 0;
- return;
- }
- else
- {
- strcpy(power_desc[num], "dismiss pets");
- powers[num++] = 1;
- strcpy(power_desc[num], "dismiss companions");
- powers[num++] = 10;
- strcpy(power_desc[num], "call pets");
- powers[num++] = 2;
- strcpy(power_desc[num], "follow me");
- powers[num++] = 6;
- strcpy(power_desc[num], "seek and destroy");
- powers[num++] = 3;
- if (p_ptr->pet_open_doors)
- strcpy(power_desc[num], "disallow open doors");
- else
- strcpy(power_desc[num], "allow open doors");
- powers[num++] = 4;
- if (p_ptr->pet_pickup_items)
- strcpy(power_desc[num], "disallow pickup items");
- else
- strcpy(power_desc[num], "allow pickup items");
- powers[num++] = 5;
- strcpy(power_desc[num], "give target to a friend");
- powers[num++] = 7;
- strcpy(power_desc[num], "give target to all friends");
- powers[num++] = 8;
- strcpy(power_desc[num], "friend forget target");
- powers[num++] = 9;
- }
-
- /* Nothing chosen yet */
- flag = FALSE;
-
- /* No redraw yet */
- redraw = FALSE;
-
- /* Build a prompt (accept all spells) */
- if (num <= 26)
- {
- /* Build a prompt (accept all spells) */
- strnfmt(out_val, 78,
- "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0),
- I2A(num - 1));
- }
- else
- {
- strnfmt(out_val, 78,
- "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0),
- '0' + num - 27);
- }
-
- /* Get a command from the user */
- while (!flag && get_com(out_val, &choice))
- {
- /* Request redraw */
- if ((choice == ' ') || (choice == '*') || (choice == '?'))
- {
- /* Show the list */
- if (!redraw)
- {
- byte y = 1, x = 0;
- int ctr = 0;
- char dummy[80];
-
- strcpy(dummy, "");
-
- /* Show list */
- redraw = TRUE;
-
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
-
- prt("", y++, x);
-
- while (ctr < num)
- {
- strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]);
- prt(dummy, y + ctr, x);
- ctr++;
- }
-
- if (ctr < 17)
- {
- prt("", y + ctr, x);
- }
- else
- {
- prt("", y + 17, x);
- }
- }
-
- /* Hide the list */
- else
- {
- /* Hide list */
- redraw = FALSE;
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
- }
-
- /* Redo asking */
- continue;
- }
-
- if (choice == '\r' && num == 1)
- {
- choice = 'a';
- }
-
- if (isalpha(choice))
- {
- /* Note verify */
- ask = (isupper(choice));
-
- /* Lowercase */
- if (ask) choice = tolower(choice);
-
- /* Extract request */
- i = (islower(choice) ? A2I(choice) : -1);
- }
- else
- {
- ask = FALSE; /* Can't uppercase digits */
-
- i = choice - '0' + 26;
- }
-
- /* Totally Illegal */
- if ((i < 0) || (i >= num))
- {
- bell();
- continue;
- }
-
- /* Verify it */
- if (ask)
- {
- char tmp_val[160];
-
- /* Prompt */
- strnfmt(tmp_val, 78, "Use %s? ", power_desc[i]);
-
- /* Belay that order */
- if (!get_check(tmp_val)) continue;
- }
-
- /* Stop the loop */
- flag = TRUE;
- }
-
- /* Restore the screen */
- if (redraw)
- {
- Term_load();
- character_icky = FALSE;
- }
-
- /* Abort if needed */
- if (!flag)
- {
- energy_use = 0;
- return;
- }
-
- switch (powers[i])
- {
- /* forget target */
- case 9:
- {
- monster_type *m_ptr;
- int ii, jj;
-
- msg_print("Select the friendly monster:");
- if (!tgt_pt(&ii, &jj)) return;
-
- if (cave[jj][ii].m_idx)
- {
- m_ptr = &m_list[cave[jj][ii].m_idx];
-
- if (m_ptr->status < MSTATUS_PET)
- {
- msg_print("You cannot give orders to this monster.");
- return;
- }
-
- m_ptr->target = -1;
- }
- break;
- }
- /* Give target to all */
- case 8:
- {
- monster_type *m_ptr;
- int ii, jj, i;
-
-
- msg_print("Select the target monster:");
- if (!tgt_pt(&ii, &jj)) return;
-
- if (cave[jj][ii].m_idx)
- {
- msg_print("Target selected.");
-
- for (i = m_max - 1; i >= 1; i--)
- {
- /* Access the monster */
- m_ptr = &m_list[i];
-
- if (!m_ptr->r_idx) continue;
-
- if (m_ptr->status < MSTATUS_PET) continue;
-
- m_ptr->target = cave[jj][ii].m_idx;
- }
- }
- else
- {
- msg_print("This is not a correct target.");
- return;
- }
- break;
- }
- case 1: /* Dismiss pets */
- {
- int Dismissed = 0;
-
- if (get_check("Dismiss all pets? ")) all_pets = TRUE;
-
- /* Process the monsters (backwards) */
- for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--)
- {
- monster_race *r_ptr;
-
- /* Access the monster */
- m_ptr = &m_list[pet_ctr];
- r_ptr = &r_info[m_ptr->r_idx];
-
- if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_PET) || (m_ptr->status == MSTATUS_FRIEND))) /* Get rid of it! */
- {
- bool_ checked = FALSE;
- char command;
- bool_ delete_this = FALSE;
-
- if (all_pets)
- {
- delete_this = TRUE;
- }
- else
- {
- char friend_name[80], check_friend[80];
- monster_desc(friend_name, m_ptr, 0x80);
- strnfmt(check_friend, 80, "Dismiss %s? (Escape to cancel)", friend_name);
-
- while (!checked)
- {
- if (!get_com(check_friend, &command))
- {
- /* get out of loop */
- checked = TRUE;
- pet_ctr = 0;
- }
- else switch (command)
- {
- case 'Y':
- case 'y':
- delete_this = TRUE;
- checked = TRUE;
- break;
- case 'n':
- case 'N':
- checked = TRUE;
- break;
- default:
- bell();
- break;
- }
- }
- }
-
- if (delete_this)
- {
- delete_monster_idx(pet_ctr);
- Dismissed++;
- }
- }
- }
-
- msg_format("You have dismissed %d pet%s.", Dismissed,
- (Dismissed == 1 ? "" : "s"));
- break;
- }
- case 10: /* Dismiss companions */
- {
- int Dismissed = 0;
-
- if (get_check("Dismiss all companions? ")) all_pets = TRUE;
-
- /* Process the monsters (backwards) */
- for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--)
- {
- monster_race *r_ptr;
-
- /* Access the monster */
- m_ptr = &m_list[pet_ctr];
- r_ptr = &r_info[m_ptr->r_idx];
-
- if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_COMPANION))) /* Get rid of it! */
- {
- bool_ delete_this = FALSE;
-
- if (all_pets)
- delete_this = TRUE;
- else
- {
- char friend_name[80], check_friend[80];
- monster_desc(friend_name, m_ptr, 0x80);
- strnfmt(check_friend, 80, "Dismiss %s? ", friend_name);
-
- if (get_check(check_friend))
- delete_this = TRUE;
- }
-
- if (delete_this)
- {
- delete_monster_idx(pet_ctr);
- Dismissed++;
- }
- }
- }
-
- msg_format("You have dismissed %d companion%s.", Dismissed,
- (Dismissed == 1 ? "" : "s"));
- break;
- }
- /* Call pets */
- case 2:
- {
- p_ptr->pet_follow_distance = 1;
- break;
- }
- /* "Seek and destroy" */
- case 3:
- {
- p_ptr->pet_follow_distance = 255;
- break;
- }
- /* flag - allow pets to open doors */
- case 4:
- {
- p_ptr->pet_open_doors = !p_ptr->pet_open_doors;
- break;
- }
- /* flag - allow pets to pickup items */
- case 5:
- {
- p_ptr->pet_pickup_items = !p_ptr->pet_pickup_items;
-
- /* Drop objects being carried by pets */
- if (!p_ptr->pet_pickup_items)
- {
- for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--)
- {
- /* Access the monster */
- m_ptr = &m_list[pet_ctr];
-
- if (m_ptr->status >= MSTATUS_PET)
- {
- monster_drop_carried_objects(m_ptr);
- }
- }
- }
-
- break;
- }
- /* "Follow Me" */
- case 6:
- {
- p_ptr->pet_follow_distance = 6;
- break;
- }
- }
-}
-
-/*
- * Incarnate into a body
- */
-bool_ do_cmd_integrate_body()
-{
- cptr q, s;
-
- int item;
-
- object_type *o_ptr;
-
-
- if (!p_ptr->disembodied)
- {
- msg_print("You are already in a body.");
- return FALSE;
- }
-
- /* Restrict choices to monsters */
- item_tester_tval = TV_CORPSE;
-
- /* Get an item */
- q = "Incarnate in which body? ";
- s = "You have no corpse to incarnate in.";
- if (!get_item(&item, q, s, (USE_FLOOR))) return FALSE;
-
- o_ptr = &o_list[0 - item];
-
- if (o_ptr->sval != SV_CORPSE_CORPSE)
- {
- msg_print("You must select a corpse.");
- return FALSE;
- }
-
- p_ptr->body_monster = o_ptr->pval2;
- p_ptr->chp = o_ptr->pval3;
-
- floor_item_increase(0 - item, -1);
- floor_item_describe(0 - item);
- floor_item_optimize(0 - item);
-
- msg_print("Your spirit is incarnated in your new body.");
- p_ptr->wraith_form = FALSE;
- p_ptr->disembodied = FALSE;
- do_cmd_redraw();
-
- return TRUE;
-}
-
-/*
- * Leave a body
- */
-bool_ do_cmd_leave_body(bool_ drop_body)
-{
- object_type *o_ptr, forge;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
- int i;
-
-
- if (p_ptr->disembodied)
- {
- msg_print("You are already disembodied.");
- return FALSE;
- }
-
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- if (p_ptr->body_parts[i - INVEN_WIELD] && p_ptr->inventory[i].k_idx &&
- cursed_p(&p_ptr->inventory[i]))
- {
- msg_print("A cursed object is preventing you from leaving your body.");
- return FALSE;
- }
- }
-
- if (drop_body)
- {
- if (magik(25 + get_skill_scale(SKILL_POSSESSION, 25) + get_skill(SKILL_PRESERVATION)))
- {
- o_ptr = &forge;
- object_prep(o_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_CORPSE));
- o_ptr->number = 1;
- o_ptr->pval = 0;
- o_ptr->pval2 = p_ptr->body_monster;
- o_ptr->pval3 = p_ptr->chp;
- o_ptr->weight = (r_ptr->weight + rand_int(r_ptr->weight) / 10) + 1;
- object_aware(o_ptr);
- object_known(o_ptr);
- o_ptr->ident |= IDENT_STOREB;
-
- /* Unique corpses are unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
- {
- o_ptr->name1 = 201;
- }
-
- drop_near(o_ptr, -1, p_ptr->py, p_ptr->px);
- }
- else
- msg_print
- ("You do not manage to keep the corpse from rotting away.");
- }
-
- msg_print("Your spirit leaves your body.");
- p_ptr->disembodied = TRUE;
-
- /* Turn into a lost soul(just for the picture) */
- p_ptr->body_monster = test_monster_name("Lost soul");
- do_cmd_redraw();
-
- return (TRUE);
-}
-
-
-bool_ execute_inscription(byte i, byte y, byte x)
-{
- cave_type *c_ptr = &cave[y][x];
-
-
- /* Not enough mana in the current grid */
- if (c_ptr->mana < inscription_info[i].mana) return (TRUE);
-
-
- /* Reduce the grid mana -- note: it can't be restored */
- c_ptr->mana -= inscription_info[i].mana;
-
- /* Analyse inscription type */
- switch (i)
- {
- case INSCRIP_LIGHT:
- {
- msg_print("The inscription shines in a bright light!");
- lite_room(y, x);
-
- break;
- }
-
- case INSCRIP_DARK:
- {
- msg_print("The inscription is enveloped in a dark aura!");
- unlite_room(y, x);
-
- break;
- }
-
- case INSCRIP_STORM:
- {
- msg_print("The inscription releases a powerful storm!");
- project(0, 3, y, x, damroll(10, 10),
- GF_ELEC, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM |
- PROJECT_KILL | PROJECT_JUMP);
-
- break;
- }
-
- case INSCRIP_PROTECTION:
- {
- return (FALSE);
-
- break;
- }
-
- case INSCRIP_DWARF_SUMMON:
- {
- int yy = y, xx = x;
-
- scatter(&yy, &xx, y, x, 3);
- place_monster_one(yy, xx, test_monster_name("Dwarven Warrior"),
- 0, FALSE, MSTATUS_FRIEND);
-
- break;
- }
-
- case INSCRIP_CHASM:
- {
- monster_type *m_ptr;
- monster_race *r_ptr;
- cave_type *c_ptr;
- int ii = x, ij = y;
-
- cave_set_feat(ij, ii, FEAT_DARK_PIT);
- msg_print("A chasm appears in the floor!");
-
- if (cave[ij][ii].m_idx)
- {
- m_ptr = &m_list[cave[ij][ii].m_idx];
- r_ptr = race_inf(m_ptr);
-
- if (r_ptr->flags7 & RF7_CAN_FLY)
- {
- msg_print("The monster simply flies over the chasm.");
- }
- else
- {
- if (!(r_ptr->flags1 & RF1_UNIQUE))
- {
- msg_print("The monster falls in the chasm!");
- delete_monster_idx(cave[ij][ii].m_idx);
- }
- }
- }
-
- if (cave[ij][ii].o_idx)
- {
- s16b this_o_idx, next_o_idx = 0;
-
- c_ptr = &cave[ij][ii];
-
- /* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx;
- this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
- bool_ plural = FALSE;
-
- char o_name[80];
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- if (o_ptr->number > 1) plural = TRUE;
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Effect "observed" */
- if (o_ptr->marked)
- {
- object_desc(o_name, o_ptr, FALSE, 0);
- }
-
- /* Artifacts get to resist */
- if (o_ptr->name1)
- {
- /* Observe the resist */
- if (o_ptr->marked)
- {
- msg_format("The %s %s simply fly over the chasm!",
- o_name, (plural ? "are" : "is"));
- }
- }
-
- /* Kill it */
- else
- {
- /* Delete the object */
- delete_object_idx(this_o_idx);
-
- /* Redraw */
- lite_spot(ij, ii);
- }
- }
- }
-
- break;
- }
-
- case INSCRIP_BLACK_FIRE:
- {
- msg_print("The inscription releases a blast of hellfire!");
- project(0, 3, y, x, 200,
- GF_HELL_FIRE, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM |
- PROJECT_KILL | PROJECT_JUMP);
-
- break;
- }
- }
-
- return (TRUE);
-}
-
-
-/*
- * Choose an inscription and engrave it
- */
-void do_cmd_engrave()
-{
- char buf[41] = "";
-
- byte i;
-
- strnfmt(buf, 41, "%s", inscription_info[cave[p_ptr->py][p_ptr->px].inscription].text);
-
- get_string("Engrave what? ", buf, 40);
-
- /* Silently do nothing when player his escape or enters an empty string */
- if (!buf[0]) return;
-
- for (i = 0; i < MAX_INSCRIPTIONS; i++)
- {
- if (!strcmp(inscription_info[i].text, buf))
- {
- if (inscription_info[i].know)
- {
- /* Save the inscription */
- cave[p_ptr->py][p_ptr->px].inscription = i;
- }
- else
- msg_print("You can't use this inscription for now.");
- }
- }
-
- /* Execute the inscription */
- if (inscription_info[cave[p_ptr->py][p_ptr->px].inscription].when & INSCRIP_EXEC_ENGRAVE)
- {
- execute_inscription(cave[p_ptr->py][p_ptr->px].inscription, p_ptr->py, p_ptr->px);
- }
-
- energy_use += 300;
-}
-
-
-/*
- * Let's do a spinning around attack: -- DG --
- * aDb
- * y@k
- * ooT
- * Ah ... all of those will get hit.
- */
-void do_spin()
-{
- int i, j;
-
-
- msg_print("You start spinning around...");
-
- for (j = p_ptr->py - 1; j <= p_ptr->py + 1; j++)
- {
- for (i = p_ptr->px - 1; i <= p_ptr->px + 1; i++)
- {
- /* Avoid stupid bugs */
- if (in_bounds(j, i) && cave[j][i].m_idx)
- py_attack(j, i, 1);
- }
- }
-}