summaryrefslogtreecommitdiff
path: root/src/cmd2.c
diff options
context:
space:
mode:
authorManoj Srivastava <srivasta@debian.org>2020-05-22 19:57:41 -0700
committerManoj Srivastava <srivasta@debian.org>2020-05-22 20:02:19 -0700
commitc3d2579ad8d7eb33059aa8fdbaf5b564411a57f2 (patch)
tree1570cda0676fdcf4171a69a7fe313c1b89a52b0c /src/cmd2.c
parent986b7742bf244b4073ecca0723615f70be8a1ab6 (diff)
parent4e9b9c402ed95bf9a17fd6d795bc49bb4128a6fa (diff)
Merge branch 'upstream' into debian-cmake-fixes
Diffstat (limited to 'src/cmd2.c')
-rw-r--r--src/cmd2.c5107
1 files changed, 0 insertions, 5107 deletions
diff --git a/src/cmd2.c b/src/cmd2.c
deleted file mode 100644
index 2d05c125..00000000
--- a/src/cmd2.c
+++ /dev/null
@@ -1,5107 +0,0 @@
-/* File: cmd2.c */
-
-/* Purpose: Movement commands (part 2) */
-
-/*
- * 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"
-
-void do_cmd_immovable_special(void);
-
-/*
- * Try to bash an altar
- */
-static bool_ do_cmd_bash_altar(int y, int x)
-{
- msg_print("Are you mad? You want to anger the gods?");
- return (FALSE);
-}
-
-
-/*
- * Try to bash a fountain
- */
-static bool_ do_cmd_bash_fountain(int y, int x)
-{
- int bash, temp;
-
- bool_ more = TRUE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
- {
- msg_print("You cannot do that.");
-
- return (FALSE);
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("You smash into the fountain!");
-
- /* Hack -- Bash power based on strength */
- /* (Ranges from 3 to 20 to 100 to 200) */
- bash = adj_str_blow[p_ptr->stat_ind[A_STR]];
-
- /* Compare bash power to door power XXX XXX XXX */
- temp = (bash - 50);
-
- /* Hack -- always have a chance */
- if (temp < 1) temp = 1;
-
- /* Hack -- attempt to bash down the door */
- if (rand_int(200) < temp)
- {
- /* Message */
- msg_print("The fountain breaks!");
-
- fire_ball(GF_WATER, 5, damroll(6, 8), 2);
-
- cave_set_feat(y, x, FEAT_DEEP_WATER);
- more = FALSE;
- }
-
- return (more);
-}
-
-
-/*
- * Go up one level
- */
-void do_cmd_go_up(void)
-{
- bool_ go_up = FALSE, go_up_many = FALSE, prob_traveling = FALSE;
-
- cave_type *c_ptr;
-
- int oldl = dun_level;
-
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
-
-
- /* Player grid */
- c_ptr = &cave[p_ptr->py][p_ptr->px];
-
- /* Can we ? */
- if (process_hooks(HOOK_STAIR, "(s)", "up")) return;
-
- /* Normal up stairs */
- if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_WAY_LESS))
- {
- if (!dun_level)
- {
- go_up = TRUE;
- }
- else if ((dungeon_flags2 & DF2_ASK_LEAVE))
- {
- go_up = get_check("Leave this unique level forever? ");
- }
- else if (confirm_stairs)
- {
- go_up = get_check("Really leave the level? ");
- }
- else
- {
- go_up = TRUE;
- }
- }
-
- /* Shaft up */
- else if (c_ptr->feat == FEAT_SHAFT_UP)
- {
- if (dun_level == 1)
- {
- go_up = TRUE;
- }
- else if ((dungeon_flags2 & DF2_ASK_LEAVE))
- {
- go_up = get_check("Leave this unique level forever? ");
- }
- else if (confirm_stairs)
- {
- go_up_many = get_check("Really leave the level? ");
- }
- else
- {
- go_up_many = TRUE;
- }
- }
-
- /* Quest exit */
- else if (c_ptr->feat == FEAT_QUEST_EXIT)
- {
- leaving_quest = p_ptr->inside_quest;
-
- if ((dungeon_flags2 & DF2_ASK_LEAVE) &&
- !get_check("Leave this unique level forever? "))
- return;
-
- p_ptr->inside_quest = c_ptr->special;
- dun_level = 0;
- p_ptr->oldpx = 0;
- p_ptr->oldpy = 0;
- p_ptr->leaving = TRUE;
-
- return;
- }
-
- /* Exits to previous area in flat terrains */
- else if (!(dungeon_flags1 & DF1_FLAT) &&
- p_ptr->prob_travel && !p_ptr->inside_quest)
- {
- if (d_ptr->mindepth == dun_level) return;
-
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
- {
- msg_print("Some powerful force prevents your from teleporting.");
- return;
- }
-
- prob_traveling = TRUE;
-
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_up = TRUE;
- }
- else
- {
- go_up = TRUE;
- }
- }
- else
- {
- msg_print("I see no up staircase here.");
- return;
- }
-
- if (go_up || go_up_many)
- {
-
- energy_use = 0;
-
- /* Success */
- if (c_ptr->feat == FEAT_WAY_LESS)
- msg_print("You enter the previous area.");
- else
- msg_print("You enter a maze of up staircases.");
-
- autosave_checkpoint();
-
- if (p_ptr->inside_quest)
- {
- dun_level = 1;
- leaving_quest = p_ptr->inside_quest;
-
- p_ptr->inside_quest = c_ptr->special;
- }
-
- /* Create a way back */
- if (go_up_many)
- create_down_shaft = TRUE;
- else
- create_down_stair = TRUE;
-
- /* New depth */
- if (go_up)
- dun_level--;
- else
- {
- dun_level -= randint(3) + 1;
- if (dun_level <= 0) dun_level = 0;
- }
-
- if (c_ptr->special && (!prob_traveling))
- {
- dun_level = oldl;
- dun_level = get_flevel();
- dungeon_type = c_ptr->special;
- dun_level += d_info[dungeon_type].mindepth;
- }
-
- /* Leaving */
- p_ptr->leaving = TRUE;
- }
-}
-
-
-/*
- * Returns TRUE if we are in the Between...
- */
-static bool_ between_effect(void)
-{
- byte bx, by;
-
-
- if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN)
- {
-
- bx = cave[p_ptr->py][p_ptr->px].special & 255;
- by = cave[p_ptr->py][p_ptr->px].special >> 8;
-
- msg_print("You fall into the void.");
- msg_print("Brrrr! It's deadly cold.");
-
- swap_position(by, bx);
-
- /* To avoid being teleported back */
- energy_use = 100;
-
- return (TRUE);
- }
-
- else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN2)
- {
- between_exit *be_ptr = &between_exits[cave[p_ptr->py][p_ptr->px].special];
-
- p_ptr->wild_mode = FALSE;
- p_ptr->wilderness_x = be_ptr->wild_x;
- p_ptr->wilderness_y = be_ptr->wild_y;
- p_ptr->oldpx = p_ptr->px = be_ptr->px;
- p_ptr->oldpy = p_ptr->py = be_ptr->py;
- dungeon_type = be_ptr->d_idx;
- dun_level = be_ptr->level;
- p_ptr->leaving = TRUE;
-
- return (TRUE);
- }
- else
- return (FALSE);
-}
-
-/*
- * Go down one level
- */
-void do_cmd_go_down(void)
-{
- cave_type *c_ptr;
-
- bool_ go_down = FALSE, go_down_many = FALSE, prob_traveling = FALSE;
-
- bool_ fall_trap = FALSE;
-
- char i;
-
- int old_dun = dun_level;
-
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
-
-
- /* MUST be actived now */
- if (between_effect()) return;
-
- /* Player grid */
- c_ptr = &cave[p_ptr->py][p_ptr->px];
-
- if (p_ptr->astral && (dun_level == 98)) return;
-
- if (c_ptr->t_idx == TRAP_OF_SINKING) fall_trap = TRUE;
-
- /* test if on special level */
- if ((dungeon_flags2 & DF2_ASK_LEAVE))
- {
- prt("Leave this unique level forever (y/n) ? ", 0, 0);
- flush();
- i = inkey();
- prt("", 0, 0);
- if (i != 'y') return;
- }
-
- /* Can we ? */
- if (process_hooks(HOOK_STAIR, "(s)", "down")) return;
-
- /* Normal up stairs */
- if (c_ptr->feat == FEAT_SHAFT_DOWN)
- {
- if (!dun_level)
- {
- go_down = TRUE;
-
- /* Save old player position */
- p_ptr->oldpx = p_ptr->px;
- p_ptr->oldpy = p_ptr->py;
- }
- else
- {
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down_many = TRUE;
- }
- else
- {
- go_down_many = TRUE;
- }
- }
- }
-
- /* Normal stairs */
- else if ((c_ptr->feat == FEAT_MORE) || (c_ptr->feat == FEAT_WAY_MORE))
- {
- if (p_ptr->prob_travel)
- {
- if (d_ptr->maxdepth == dun_level) return;
- }
- if (!dun_level)
- {
- go_down = TRUE;
-
- /* Save old player position */
- p_ptr->oldpx = p_ptr->px;
- p_ptr->oldpy = p_ptr->py;
- }
- else
- {
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down = TRUE;
- }
- else
- {
- go_down = TRUE;
- }
- }
- }
-
- /* Handle quest areas -KMW- */
- else if (c_ptr->feat == FEAT_QUEST_ENTER)
- {
- /* Enter quest level */
- enter_quest();
-
- return;
- }
-
- else if (!(dungeon_flags1 & DF1_FLAT) &&
- p_ptr->prob_travel && !p_ptr->inside_quest)
- {
- if (d_ptr->maxdepth == dun_level) return;
-
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
- {
- msg_print("Some powerfull force prevents your from teleporting.");
- return;
- }
-
- prob_traveling = TRUE;
-
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down = TRUE;
- }
- else
- {
- go_down = TRUE;
- }
- }
-
- else if (!(fall_trap))
- {
- msg_print("I see no down staircase here.");
- return;
- }
-
- if (go_down || go_down_many)
- {
- energy_use = 0;
-
- if (fall_trap)
- msg_print("You deliberately jump through the trap door.");
- else
- {
- if (c_ptr->feat == FEAT_WAY_MORE)
- msg_print("You enter the next area.");
- else
- msg_print("You enter a maze of down staircases.");
- }
-
- autosave_checkpoint();
-
- /* Go down */
- if (go_down)
- {
- dun_level++;
- }
- else if (go_down_many)
- {
- int i = randint(3) + 1, j;
-
- for (j = 1; j < i; j++)
- {
- dun_level++;
- if (is_quest(dun_level + i - 1)) break;
- if (d_ptr->maxdepth == dun_level) break;
- }
- }
-
- /* We change place */
- if (c_ptr->special && (!prob_traveling))
- {
- if (d_info[c_ptr->special].min_plev <= p_ptr->lev)
- {
- dungeon_info_type *d_ptr = &d_info[c_ptr->special];
-
- /* Do the lua scripts refuse ? ;) */
- if (process_hooks(HOOK_ENTER_DUNGEON, "(d)", c_ptr->special))
- {
- dun_level = old_dun;
- return;
- }
-
- /* Ok go in the new dungeon */
- dungeon_type = c_ptr->special;
- d_ptr = &d_info[dungeon_type];
-
- if ((p_ptr->wilderness_x == d_ptr->ix) &&
- (p_ptr->wilderness_y == d_ptr->iy))
- {
- dun_level = d_ptr->mindepth;
- }
- else if ((p_ptr->wilderness_x == d_ptr->ox) &&
- (p_ptr->wilderness_y == d_ptr->oy))
- {
- dun_level = d_ptr->maxdepth;
- }
- else
- {
- dun_level = d_ptr->mindepth;
- }
-
- msg_format("You go into %s",
- d_text + d_info[dungeon_type].text);
- }
- else
- {
- msg_print
- ("You don't feel yourself experienced enough to go there...");
- dun_level = old_dun;
- return;
- }
- }
-
- /* Leaving */
- p_ptr->leaving = TRUE;
-
- if (!fall_trap)
- {
- /* Create a way back */
- if (go_down_many)
- create_up_shaft = TRUE;
- else
- create_up_stair = TRUE;
- }
- }
-}
-
-
-
-/*
- * Simple command to "search" for one turn
- */
-void do_cmd_search(void)
-{
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Search */
- search();
-}
-
-
-/*
- * Hack -- toggle search mode
- */
-void do_cmd_toggle_search(void)
-{
- /* Stop searching */
- if (p_ptr->searching)
- {
- /* Clear the searching flag */
- p_ptr->searching = FALSE;
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
- }
-
- /* Start searching */
- else
- {
- /* Set the searching flag */
- p_ptr->searching = TRUE;
-
- /* Update stuff */
- p_ptr->update |= (PU_BONUS);
-
- /* Redraw stuff */
- p_ptr->redraw |= (PR_STATE | PR_SPEED);
- }
-}
-
-
-
-/*
- * Determine if a grid contains a chest
- */
-static s16b chest_check(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- s16b this_o_idx, next_o_idx = 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 unknown chests XXX XXX */
- /* if (!o_ptr->marked) continue; */
-
- /* Check for chest */
- if (o_ptr->tval == TV_CHEST) return (this_o_idx);
- }
-
- /* No chest */
- return (0);
-}
-
-
-/*
- * Allocates objects upon opening a chest -BEN-
- *
- * Disperse treasures from the given chest, centered at (x,y).
- *
- * Small chests often contain "gold", while Large chests always contain
- * items. Wooden chests contain 2 items, Iron chests contain 4 items,
- * and Steel chests contain 6 items. The "value" of the items in a
- * chest is based on the "power" of the chest, which is in turn based
- * on the level on which the chest is generated.
- */
-static void chest_death(int y, int x, s16b o_idx)
-{
- int number;
-
- bool_ small;
-
- object_type forge;
- object_type *q_ptr;
-
- object_type *o_ptr = &o_list[o_idx];
-
-
- /* Small chests often hold "gold" */
- small = (o_ptr->sval < SV_CHEST_MIN_LARGE);
-
- /* Determine how much to drop (see above) */
- number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
-
- /* Zero pval means empty chest */
- if (!o_ptr->pval) number = 0;
-
- /* Opening a chest */
- opening_chest = TRUE;
-
- /* Determine the "value" of the items */
- object_level = ABS(o_ptr->pval) + 10;
-
- /* Drop some objects (non-chests) */
- for (; number > 0; --number)
- {
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Small chests often drop gold */
- if (small && (rand_int(100) < 75))
- {
- /* Make some gold */
- if (!make_gold(q_ptr)) continue;
- }
-
- /* Otherwise drop an item */
- else
- {
- /* Make an object */
- if (!make_object(q_ptr, FALSE, FALSE, d_info[dungeon_type].objs))
- continue;
- }
-
- /* Drop it in the dungeon */
- drop_near(q_ptr, -1, y, x);
- }
-
- /* Reset the object level */
- object_level = dun_level;
-
- /* No longer opening a chest */
- opening_chest = FALSE;
-
- /* Empty */
- o_ptr->pval = 0;
- o_ptr->pval2 = 0;
-
- /* Known */
- object_known(o_ptr);
-}
-
-
-/*
- * Chests have traps too.
- *
- * Exploding chest destroys contents (and traps).
- * Note that the chest itself is never destroyed.
- */
-static void chest_trap(int y, int x, s16b o_idx)
-{
- int trap;
-
- object_type *o_ptr = &o_list[o_idx];
-
- bool_ ident = FALSE;
-
-
- /* Ignore disarmed chests */
- if (o_ptr->pval <= 0) return;
-
- /* Obtain the trap */
- trap = o_ptr->pval;
-
- /* Message */
- msg_print("You found a trap!");
-
- /* Set off trap */
- ident = player_activate_trap_type(y, x, o_ptr, o_idx);
- if (ident)
- {
- t_info[o_ptr->pval].ident = TRUE;
- msg_format("You identified the trap as %s.",
- t_name + t_info[trap].name);
- }
-}
-
-
-/*
- * Attempt to open the given chest at the given location
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
-{
- int i, j;
-
- bool_ flag = TRUE;
-
- bool_ more = FALSE;
-
- object_type *o_ptr = &o_list[o_idx];
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
- {
- msg_print("You cannot open chests.");
-
- return (FALSE);
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Attempt to unlock it */
- if (o_ptr->pval > 0)
- {
- /* Assume locked, and thus not open */
- flag = FALSE;
-
- /* Get the "disarm" factor */
- i = p_ptr->skill_dis;
-
- /* Penalize some conditions */
- if (p_ptr->blind || no_lite()) i = i / 10;
- if (p_ptr->confused || p_ptr->image) i = i / 10;
-
- /* Extract the difficulty */
- j = i - o_ptr->pval;
-
- /* Always have a small chance of success */
- if (j < 2) j = 2;
-
- /* Success -- May still have traps */
- if (rand_int(100) < j)
- {
- msg_print("You have picked the lock.");
- gain_exp(1);
- flag = TRUE;
- }
-
- /* Failure -- Keep trying */
- else
- {
- /* We may continue repeating */
- more = TRUE;
-
- if (flush_failure) flush();
-
- msg_print("You failed to pick the lock.");
- }
- }
-
- /* Allowed to open */
- if (flag)
- {
- /* Apply chest traps, if any */
- chest_trap(y, x, o_idx);
-
- /* Let the Chest drop items */
- chest_death(y, x, o_idx);
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Original code by TNB, improvement for Angband 2.9.3 by rr9
- * Slightly modified for ToME because of its trap implementation
- */
-
-/*
- * Return TRUE if the given grid is an open door
- */
-static bool_ is_open(cave_type *c_ptr)
-{
- return (c_ptr->feat == FEAT_OPEN);
-}
-
-
-/*
- * Return TRUE if the given grid is a closed door
- */
-static bool_ is_closed(cave_type *c_ptr)
-{
- byte feat;
-
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else feat = c_ptr->feat;
-
- return ((feat >= FEAT_DOOR_HEAD) && (feat <= FEAT_DOOR_TAIL));
-}
-
-
-/*
- * Return TRUE if the given grid has a trap
- */
-static bool_ is_trap(cave_type *c_ptr)
-{
- return ((c_ptr->info & (CAVE_TRDT)) != 0);
-}
-
-
-/*
- * Return the number of doors/traps around (or under)
- * the character using the filter function 'test'
- */
-static int count_feats(int *y, int *x, bool_ (*test) (cave_type *c_ptr),
- bool_ under)
-{
- int d;
-
- int xx, yy;
-
- int count;
-
-
- /* Clear match counter */
- count = 0;
-
- /* Check around (and under) the character */
- for (d = 0; d < 9; d++)
- {
- /* Ignore current grid if told so -- See tables.c */
- if ((d == 8) && !under) continue;
-
- /* Extract adjacent (legal) location */
- yy = p_ptr->py + ddy_ddd[d];
- xx = p_ptr->px + ddx_ddd[d];
-
- /* Paranoia */
- if (!in_bounds(yy, xx)) continue;
-
- /* Must have knowledge */
- if (!(cave[yy][xx].info & (CAVE_MARK))) continue;
-
- /* Not looking for this feature */
- if (!(*test) (&cave[yy][xx])) continue;
-
- /* Count it */
- count++;
-
- /* Remember the location. Only meaningful if there's
- exactly one match */
- *y = yy;
- *x = xx;
- }
-
- /* All done */
- return (count);
-}
-
-
-/*
- * Return the number of chests around (or under) the character.
- * If requested, count only trapped chests.
- */
-static int count_chests(int *y, int *x, bool_ trapped)
-{
- int d, count, o_idx;
-
- object_type *o_ptr;
-
-
- /* Count how many matches */
- count = 0;
-
- /* Check around (and under) the character */
- for (d = 0; d < 9; d++)
- {
-
- /* Extract adjacent (legal) location */
- int yy = p_ptr->py + ddy_ddd[d];
- int xx = p_ptr->px + ddx_ddd[d];
-
- /* No (visible) chest is there */
- if ((o_idx = chest_check(yy, xx)) == 0) continue;
-
- /* Grab the object */
- o_ptr = &o_list[o_idx];
-
- /* Already open */
- if (o_ptr->pval == 0) continue;
-
- /* No (known) traps here */
- if (trapped && (!object_known_p(o_ptr) || !o_ptr->pval)) continue;
-
- /* OK */
- ++count;
-
- /* Remember the location. Only useful if only one match */
- *y = yy;
- *x = xx;
- }
-
- /* All done */
- return (count);
-}
-
-
-/*
- * Convert an adjacent location to a direction.
- */
-static int coords_to_dir(int y, int x)
-{
- int d[3][3] =
- {
- {7, 4, 1},
- {8, 5, 2},
- {9, 6, 3} };
-
- int dy, dx;
-
-
- dy = y - p_ptr->py;
- dx = x - p_ptr->px;
-
- /* Paranoia */
- if (ABS(dx) > 1 || ABS(dy) > 1) return (0);
-
- return d[dx + 1][dy + 1];
-}
-
-
-/*
- * Perform the basic "open" command on doors
- *
- * Assume destination is a closed/locked/jammed door
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-static bool_ do_cmd_open_aux(int y, int x, int dir)
-{
- int i, j;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
- {
- msg_print("You cannot open doors.");
-
- return (FALSE);
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get requested grid */
- c_ptr = &cave[y][x];
-
- /* Jammed door */
- if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08)
- {
- /* Stuck */
- msg_print("The door appears to be stuck.");
- }
-
- /* Locked door */
- else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01)
- {
- /* Disarm factor */
- i = p_ptr->skill_dis;
-
- /* Penalize some conditions */
- if (p_ptr->blind || no_lite()) i = i / 10;
- if (p_ptr->confused || p_ptr->image) i = i / 10;
-
- /* Extract the lock power */
- j = c_ptr->feat - FEAT_DOOR_HEAD;
-
- /* Extract the difficulty XXX XXX XXX */
- j = i - (j * 4);
-
- /* Always have a small chance of success */
- if (j < 2) j = 2;
-
- /* Success */
- if (rand_int(100) < j)
- {
- /* Message */
- msg_print("You have picked the lock.");
-
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- /* Open the door */
- cave_set_feat(y, x, FEAT_OPEN);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_OPENDOOR);
-
- /* Experience */
- gain_exp(1);
- }
-
- /* Failure */
- else
- {
- /* Failure */
- if (flush_failure) flush();
-
- /* Message */
- msg_print("You failed to pick the lock.");
-
- /* We may keep trying */
- more = TRUE;
- }
- }
-
- /* Closed door */
- else
- {
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- /* Open the door */
- cave_set_feat(y, x, FEAT_OPEN);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_OPENDOOR);
- }
-
- /* Result */
- return (more);
-}
-
-
-
-/*
- * Open a closed/locked/jammed door or a closed/locked chest.
- *
- * Unlocking a locked door/chest is worth one experience point.
- */
-void do_cmd_open(void)
-{
- int y, x, dir;
-
- s16b o_idx;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
- {
- msg_print("You cannot open doors.");
-
- return;
- }
-
- /* Option: Pick a direction */
- if (easy_open)
- {
- int num_doors, num_chests;
-
- /* Count closed doors (locked or jammed) */
- num_doors = count_feats(&y, &x, is_closed, FALSE);
-
- /* Count chests (locked) */
- num_chests = count_chests(&y, &x, FALSE);
-
- /* There is nothing the player can open */
- if ((num_doors + num_chests) == 0)
- {
- /* Message */
- msg_print("You see nothing there to open.");
-
- /* Done */
- return;
- }
-
- /* Set direction if there is only one target */
- else if ((num_doors + num_chests) == 1)
- {
- command_dir = coords_to_dir(y, x);
- }
- }
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Get requested location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get requested grid */
- c_ptr = &cave[y][x];
-
- /* Check for chest */
- o_idx = chest_check(y, x);
-
- /* Nothing useful */
- if (!((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL)) && !o_idx)
- {
- /* Message */
- msg_print("You see nothing there to open.");
- }
-
- /* Monster in the way */
- else if (c_ptr->m_idx)
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Handle chests */
- else if (o_idx)
- {
- /* Open the chest */
- more = do_cmd_open_chest(y, x, o_idx);
- }
-
- /* Handle doors */
- else
- {
- /* Open the door */
- more = do_cmd_open_aux(y, x, dir);
- }
- }
-
- /* Process the appropriate hooks */
- process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level));
-
- /* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
-}
-
-
-
-/*
- * Perform the basic "close" command
- *
- * Assume destination is an open/broken door
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-static bool_ do_cmd_close_aux(int y, int x, int dir)
-{
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
- {
- msg_print("You cannot close doors.");
-
- return (FALSE);
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get grid and contents */
- c_ptr = &cave[y][x];
-
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- /* Broken door */
- if (c_ptr->feat == FEAT_BROKEN)
- {
- /* Message */
- msg_print("The door appears to be broken.");
- }
-
- /* Open door */
- else
- {
- /* Close the door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_SHUTDOOR);
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Close an open door.
- */
-void do_cmd_close(void)
-{
- int y, x, dir;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- /* Option: Pick a direction */
- if (easy_open)
- {
- int num_doors;
-
- /* Count open doors */
- num_doors = count_feats(&y, &x, is_open, FALSE);
-
- /* There are no doors the player can close */
- if (num_doors == 0)
- {
- /* Message */
- msg_print("You see nothing there to close.");
-
- /* Done */
- return;
- }
-
- /* Exactly one closeable door */
- else if (num_doors == 1)
- {
- command_dir = coords_to_dir(y, x);
- }
- }
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Get requested location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid and contents */
- c_ptr = &cave[y][x];
-
- /* Require open/broken door */
- if ((c_ptr->feat != FEAT_OPEN) && (c_ptr->feat != FEAT_BROKEN))
- {
- /* Message */
- msg_print("You see nothing there to close.");
- }
-
- /* Monster in the way */
- else if (c_ptr->m_idx)
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Close the door */
- else
- {
- /* Close the door */
- more = do_cmd_close_aux(y, x, dir);
- }
- }
-
- /* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
-}
-
-
-/*
- * Determine if a given grid may be "tunneled"
- */
-static bool_ do_cmd_tunnel_test(int y, int x)
-{
- /* Must have knowledge(execpt on "forget" levels) */
- if (!(cave[y][x].info & (CAVE_MARK)))
- {
- /* Message */
- msg_print("You see nothing there.");
-
- /* Nope */
- return (FALSE);
- }
-
- /* Must be a wall/door/etc */
- if (cave_floor_bold(y, x))
- {
- /* Message */
- msg_print("You see nothing there to tunnel.");
-
- /* Nope */
- return (FALSE);
- }
-
- /* Must be tunnelable */
- if (!(f_info[cave[y][x].feat].flags1 & FF1_TUNNELABLE))
- {
- /* Message */
- msg_print(f_text + f_info[cave[y][x].feat].tunnel);
-
- /* Nope */
- return (FALSE);
- }
-
- /* Okay */
- return (TRUE);
-}
-
-
-
-/*
- * Tunnel through wall. Assumes valid location.
- *
- * Note that it is impossible to "extend" rooms past their
- * outer walls (which are actually part of the room).
- *
- * This will, however, produce grids which are NOT illuminated
- * (or darkened) along with the rest of the room.
- */
-static bool_ twall(int y, int x, byte feat)
-{
- cave_type *c_ptr = &cave[y][x];
-
-
- /* Paranoia -- Require a wall or door or some such */
- if (cave_floor_bold(y, x)) return (FALSE);
-
- /* Forget the wall */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Remove the feature */
- cave_set_feat(y, x, feat);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE);
-
- /* Result */
- return (TRUE);
-}
-
-
-
-/*
- * Perform the basic "tunnel" command
- *
- * Assumes that the destination is a wall, a vein, a secret
- * door, or rubble.
- *
- * Assumes that no monster is blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-bool_ do_cmd_tunnel_aux(int y, int x, int dir)
-{
- int skill_req = 0, skill_req_1pct = 0;
- cave_type *c_ptr = &cave[y][x];
-
- feature_type *f_ptr = &f_info[c_ptr->feat];
-
- bool_ more = FALSE;
-
-
- /* Must be have something to dig with (except for sandwalls) */
- if ((c_ptr->feat < FEAT_SANDWALL) || (c_ptr->feat > FEAT_SANDWALL_K))
- {
- if (!p_ptr->inventory[INVEN_TOOL].k_idx ||
- (p_ptr->inventory[INVEN_TOOL].tval != TV_DIGGING))
- {
- msg_print("You need to have a shovel or pick in your tool slot.");
-
- return (FALSE);
- }
- }
-
- /* Verify legality */
- if (!do_cmd_tunnel_test(y, x)) return (FALSE);
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get grid */
- c_ptr = &cave[y][x];
-
- /* Sound */
- sound(SOUND_DIG);
-
- /* Titanium */
- if (f_ptr->flags1 & FF1_PERMANENT)
- {
- msg_print(f_text + f_ptr->tunnel);
- }
-
- else if ((c_ptr->feat == FEAT_TREES) || (c_ptr->feat == FEAT_DEAD_TREE))
- {
- /* Chop Down */
- skill_req = 10;
- skill_req_1pct = 14;
- if ((p_ptr->skill_dig > 10 + rand_int(400)) && twall(y, x, FEAT_GRASS))
- {
- msg_print("You have cleared away the trees.");
- }
-
- /* Keep trying */
- else
- {
- /* We may continue chopping */
- msg_print(f_text + f_ptr->tunnel);
- more = TRUE;
-
- /* Occasional Search XXX XXX */
- if (rand_int(100) < 25) search();
- }
- }
-
-
- /* Granite */
- else if ((c_ptr->feat >= FEAT_WALL_EXTRA) &&
- (c_ptr->feat <= FEAT_WALL_SOLID))
- {
- /* Tunnel */
- skill_req = 40;
- skill_req_1pct = 56;
- if ((p_ptr->skill_dig > 40 + rand_int(1600)) && twall(y, x, FEAT_FLOOR))
- {
- msg_print("You have finished the tunnel.");
- }
-
- /* Keep trying */
- else
- {
- /* We may continue tunelling */
- msg_print(f_text + f_ptr->tunnel);
- more = TRUE;
- }
- }
-
-
- /* Quartz / Magma / Sandwall */
- else if (((c_ptr->feat >= FEAT_MAGMA) &&
- (c_ptr->feat <= FEAT_QUARTZ_K)) ||
- ((c_ptr->feat >= FEAT_SANDWALL) &&
- (c_ptr->feat <= FEAT_SANDWALL_K)))
- {
- bool_ okay = FALSE;
- bool_ gold = FALSE;
- bool_ hard = FALSE;
- bool_ soft = FALSE;
-
- /* Found gold */
- if ((c_ptr->feat >= FEAT_MAGMA_H) &&
- (c_ptr->feat <= FEAT_QUARTZ_K)) gold = TRUE;
-
- if ((c_ptr->feat == FEAT_SANDWALL_H) ||
- (c_ptr->feat == FEAT_SANDWALL_K))
- {
- gold = TRUE;
- soft = TRUE;
- }
- else
- /* Extract "quartz" flag XXX XXX XXX */
- if ((c_ptr->feat - FEAT_MAGMA) & 0x01) hard = TRUE;
-
- /* Quartz */
- if (hard)
- {
- skill_req = 20;
- skill_req_1pct = 28;
- okay = (p_ptr->skill_dig > 20 + rand_int(800));
- }
-
- /* Sandwall */
- else if (soft)
- {
- skill_req = 5;
- skill_req_1pct = 8;
- okay = (p_ptr->skill_dig > 5 + rand_int(250));
- }
-
- /* Magma */
- else
- {
- skill_req = 10;
- skill_req_1pct = 14;
- okay = (p_ptr->skill_dig > 10 + rand_int(400));
- }
-
- /* Success */
- if (okay && twall(y, x, FEAT_FLOOR))
- {
- /* Found treasure */
- if (gold)
- {
- /* Place some gold */
- place_gold(y, x);
-
- /* Message */
- msg_print("You have found something!");
- }
-
- /* Found nothing */
- else
- {
- /* Message */
- msg_print("You have finished the tunnel.");
- }
- }
-
- /* Failure */
- else
- {
- /* Message, continue digging */
- msg_print(f_text + f_ptr->tunnel);
- more = TRUE;
- }
- }
-
- /* Rubble */
- else if (c_ptr->feat == FEAT_RUBBLE)
- {
- /* Remove the rubble */
- skill_req = 0;
- skill_req_1pct = 2;
- if ((p_ptr->skill_dig > rand_int(200)) &&
- twall(y, x, d_info[dungeon_type].floor1))
- {
- /* Message */
- msg_print("You have removed the rubble.");
-
- /* Hack -- place an object */
- if (rand_int(100) < 10)
- {
- /* Create a simple object */
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_RUBBLE);
-
- /* Observe new object */
- if (player_can_see_bold(y, x))
- {
- msg_print("You have found something!");
- }
- }
- }
-
- else
- {
- /* Message, keep digging */
- msg_print(f_text + f_ptr->tunnel);
- more = TRUE;
- }
- }
-
- /* Secret doors */
- else if (c_ptr->feat >= FEAT_SECRET)
- {
- /* Tunnel */
- skill_req = 30;
- skill_req_1pct = 42;
- if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR))
- {
- msg_print("You have finished the tunnel.");
- c_ptr->mimic = 0;
- lite_spot(y, x);
-
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
- }
-
- /* Keep trying */
- else
- {
- int feat;
-
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else
- feat = c_ptr->feat;
-
- /* We may continue tunelling */
- msg_print(f_text + f_info[feat].tunnel);
- more = TRUE;
-
- /* Occasional Search XXX XXX */
- if (rand_int(100) < 25) search();
- }
- }
-
- /* Doors */
- else
- {
- /* Tunnel */
- skill_req = 30;
- skill_req_1pct = 42;
- if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR))
- {
- msg_print("You have finished the tunnel.");
- }
-
- /* Keep trying */
- else
- {
- /* We may continue tunelling */
- msg_print(f_text + f_ptr->tunnel);
- more = TRUE;
- }
- }
-
- if (more && magik(2))
- {
- if (p_ptr->skill_dig < skill_req)
- {
- msg_print("You fail to make even the slightest of progress.");
- more = FALSE;
- }
- else if (p_ptr->skill_dig < skill_req_1pct)
- {
- msg_print("This will take some time.");
- }
- }
-
- /* Notice new floor grids */
- if (!cave_floor_bold(y, x))
- {
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE);
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Tunnels through "walls" (including rubble and closed doors)
- *
- * Note that you must tunnel in order to hit invisible monsters
- * in walls, though moving into walls still takes a turn anyway.
- *
- * Digging is very difficult without a "digger" weapon, but can be
- * accomplished by strong players using heavy weapons.
- */
-void do_cmd_tunnel(void)
-{
- int y, x, dir;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- if (p_ptr->wild_mode) return;
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a direction to tunnel, or Abort */
- if (get_rep_dir(&dir))
- {
- /* Get location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid */
- c_ptr = &cave[y][x];
-
- /* No tunnelling through doors */
- if (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL)) || (c_ptr->feat == FEAT_SHOP))
- {
- /* Message */
- msg_print("You cannot tunnel through doors.");
- }
-
- /* No tunnelling through air */
- else if (cave_floor_grid(c_ptr))
- {
- /* Message */
- msg_print("You cannot tunnel through air.");
- }
-
- /* A monster is in the way */
- else if (c_ptr->m_idx)
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Try digging */
- else
- {
- /* Tunnel through walls */
- more = do_cmd_tunnel_aux(y, x, dir);
- }
- }
-
- /* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
-}
-
-
-/*
- * easy_open_door --
- *
- * If there is a jammed/closed/locked door at the given location,
- * then attempt to unlock/open it. Return TRUE if an attempt was
- * made (successful or not), otherwise return FALSE.
- *
- * The code here should be nearly identical to that in
- * do_cmd_open_test() and do_cmd_open_aux().
- */
-
-bool_ easy_open_door(int y, int x)
-{
- int i, j;
-
- cave_type *c_ptr = &cave[y][x];
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
- {
- msg_print("You cannot open doors.");
-
- return (FALSE);
- }
-
- /* Must be a closed door */
- if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL)))
- {
- /* Nope */
- return (FALSE);
- }
-
- /* Jammed door */
- if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08)
- {
- /* Stuck */
- msg_print("The door appears to be stuck.");
- }
-
- /* Locked door */
- else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01)
- {
- /* Disarm factor */
- i = p_ptr->skill_dis;
-
- /* Penalize some conditions */
- if (p_ptr->blind || no_lite()) i = i / 10;
- if (p_ptr->confused || p_ptr->image) i = i / 10;
-
- /* Extract the lock power */
- j = c_ptr->feat - FEAT_DOOR_HEAD;
-
- /* Extract the difficulty XXX XXX XXX */
- j = i - (j * 4);
-
- /* Always have a small chance of success */
- if (j < 2) j = 2;
-
- /* Success */
- if (rand_int(100) < j)
- {
- /* Message */
- msg_print("You have picked the lock.");
-
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- /* Open the door */
- cave_set_feat(y, x, FEAT_OPEN);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_OPENDOOR);
-
- /* Process the appropriate hooks */
- process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level));
-
- /* Experience */
- gain_exp(1);
- }
-
- /* Failure */
- else
- {
- /* Failure */
- if (flush_failure) flush();
-
- /* Message */
- msg_print("You failed to pick the lock.");
- }
- }
-
- /* Closed door */
- else
- {
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- /* Open the door */
- cave_set_feat(y, x, FEAT_OPEN);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_OPENDOOR);
- }
-
- /* Result */
- return (TRUE);
-}
-
-
-/*
- * Perform the basic "disarm" command
- *
- * Assume destination is a visible trap
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-static bool_ do_cmd_disarm_chest(int y, int x, s16b o_idx)
-{
- int i, j;
-
- bool_ more = FALSE;
-
- object_type *o_ptr = &o_list[o_idx];
-
- trap_type *t_ptr = &t_info[o_ptr->pval];
-
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get the "disarm" factor */
- i = p_ptr->skill_dis;
-
- /* Penalize some conditions */
- if (p_ptr->blind || no_lite()) i = i / 10;
- if (p_ptr->confused || p_ptr->image) i = i / 10;
-
- /* Extract the difficulty */
- j = i - t_ptr->difficulty * 3;
-
- /* Always have a small chance of success */
- if (j < 2) j = 2;
-
- /* Must find the trap first. */
- if (!object_known_p(o_ptr))
- {
- msg_print("I don't see any traps.");
- }
-
- /* Already disarmed/unlocked */
- else if (o_ptr->pval <= 0)
- {
- msg_print("The chest is not trapped.");
- }
-
- /* Success (get a lot of experience) */
- else if (rand_int(100) < j)
- {
- msg_print("You have disarmed the chest.");
- gain_exp(t_ptr->difficulty * 3);
- o_ptr->pval = (0 - o_ptr->pval);
- }
-
- /* Failure -- Keep trying */
- else if ((i > 5) && (randint(i) > 5))
- {
- /* We may keep trying */
- more = TRUE;
- if (flush_failure) flush();
- msg_print("You failed to disarm the chest.");
- }
-
- /* Failure -- Set off the trap */
- else
- {
- msg_print("You set off a trap!");
- sound(SOUND_FAIL);
- chest_trap(y, x, o_idx);
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Perform the basic "disarm" command
- *
- * Assume destination is a visible trap
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup)
-{
- int i, j, power;
-
- cave_type *c_ptr;
-
- cptr name;
-
- bool_ more = FALSE;
-
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get grid and contents */
- c_ptr = &cave[y][x];
-
- /* Access trap name */
- if (t_info[c_ptr->t_idx].ident)
- name = (t_name + t_info[c_ptr->t_idx].name);
- else
- name = "unknown trap";
-
- /* Get the "disarm" factor */
- i = p_ptr->skill_dis;
-
- /* Penalize some conditions */
- if (p_ptr->blind || no_lite()) i = i / 10;
- if (p_ptr->confused || p_ptr->image) i = i / 10;
-
- /* XXX XXX XXX Variable power? */
-
- /* Extract trap "power" */
- power = t_info[c_ptr->t_idx].difficulty;
-
- /* Extract the difficulty */
- j = i - power;
-
- /* Always have a small chance of success */
- if (j < 2) j = 2;
-
- /* Success */
- if (rand_int(100) < j)
- {
- /* Message */
- msg_format("You have disarmed the %s.", name);
-
- /* Reward */
- gain_exp(power);
-
- /* Forget the trap */
- c_ptr->info &= ~(CAVE_MARK | CAVE_TRDT);
-
- /* Remove the trap */
- c_ptr->t_idx = 0;
-
- /* Move the player onto the trap */
- if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR))
- move_player_aux(dir, do_pickup, 0, TRUE);
-
- /* Remove trap attr from grid */
- note_spot(y, x);
- lite_spot(y, x);
- }
-
- /* Failure -- Keep trying */
- else if ((i > 5) && (randint(i) > 5))
- {
- /* Failure */
- if (flush_failure) flush();
-
- /* Message */
- msg_format("You failed to disarm the %s.", name);
-
- /* We may keep trying */
- more = TRUE;
- }
-
- /* Failure -- Set off the trap */
- else
- {
- /* Message */
- msg_format("You set off the %s!", name);
-
- /* Move the player onto the trap */
- if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR))
- move_player_aux(dir, do_pickup, 0, FALSE);
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Disamrs the monster traps(no failure)
- */
-void do_cmd_disarm_mon_trap(int y, int x)
-{
- msg_print("You disarm the monster trap.");
-
- place_floor_convert_glass(y, x);
- cave[p_ptr->py][p_ptr->px].special = cave[p_ptr->py][p_ptr->px].special2 = 0;
-}
-
-
-/*
- * Disarms a trap, or chest
- */
-void do_cmd_disarm(void)
-{
- int y, x, dir;
-
- s16b o_idx;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- /* Option: Pick a direction */
- if (easy_disarm)
- {
- int num_traps, num_chests;
-
- /* Count visible traps */
- num_traps = count_feats(&y, &x, is_trap, TRUE);
-
- /* Count chests (trapped) */
- num_chests = count_chests(&y, &x, TRUE);
-
- /* See if only one target */
- if (num_traps || num_chests)
- {
- if (num_traps + num_chests <= 1)
- command_dir = coords_to_dir(y, x);
- }
- }
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a direction (or abort) */
- if (get_rep_dir(&dir))
- {
- /* Get location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid and contents */
- c_ptr = &cave[y][x];
-
- /* Check for chests */
- o_idx = chest_check(y, x);
-
- /* Disarm a trap */
- if (((c_ptr->t_idx == 0) || (!(c_ptr->info & CAVE_TRDT))) &&
- !o_idx && (c_ptr->feat != FEAT_MON_TRAP))
- {
- /* Message */
- msg_print("You see nothing there to disarm.");
- }
-
- /* Monster in the way */
- else if (c_ptr->m_idx)
- {
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Disarm chest */
- else if (o_idx)
- {
- /* Disarm the chest */
- more = do_cmd_disarm_chest(y, x, o_idx);
- }
-
- /* Disarm trap */
- else
- {
- /* Disarm the trap */
- if (c_ptr->feat == FEAT_MON_TRAP)
- {
- do_cmd_disarm_mon_trap(y, x);
- more = FALSE;
- }
- else
- more = do_cmd_disarm_aux(y, x, dir, always_pickup);
- }
- }
-
- /* Cancel repeat unless told not to */
- if (!more) disturb(0, 0);
-}
-
-
-/*
- * Perform the basic "bash" command
- *
- * Assume destination is a closed/locked/jammed door
- *
- * Assume there is no monster blocking the destination
- *
- * Returns TRUE if repeated commands may continue
- */
-static bool_ do_cmd_bash_aux(int y, int x, int dir)
-{
- int bash, temp;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
- {
- msg_print("You cannot do that.");
-
- return (FALSE);
- }
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get grid */
- c_ptr = &cave[y][x];
-
- /* Message */
- msg_print("You smash into the door!");
-
- /* Hack -- Bash power based on strength */
- /* (Ranges from 3 to 20 to 100 to 200) */
- bash = adj_str_blow[p_ptr->stat_ind[A_STR]];
-
- /* Extract door power */
- temp = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07);
-
- /* Compare bash power to door power XXX XXX XXX */
- temp = (bash - (temp * 10));
-
- /* Hack -- always have a chance */
- if (temp < 1) temp = 1;
-
- /* Hack -- attempt to bash down the door */
- if (rand_int(100) < temp)
- {
- /* Message */
- msg_print("The door crashes open!");
-
- /* Break down the door */
- if (rand_int(100) < 50)
- {
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- cave_set_feat(y, x, FEAT_BROKEN);
- }
-
- /* Open the door */
- else
- {
- /* Set off trap */
- if (c_ptr->t_idx != 0) player_activate_door_trap(y, x);
-
- cave_set_feat(y, x, FEAT_OPEN);
- }
-
- /* Sound */
- sound(SOUND_OPENDOOR);
-
- /* Hack -- Fall through the door. Can't disarm while falling. */
- move_player_aux(dir, always_pickup, 0, FALSE);
-
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_MON_LITE);
- p_ptr->update |= (PU_DISTANCE);
- }
-
- /* Saving throw against stun */
- else if (rand_int(100) < adj_dex_safe[p_ptr->stat_ind[A_DEX]] + p_ptr->lev)
- {
- /* Message */
- msg_print("The door holds firm.");
-
- /* Allow repeated bashing */
- more = TRUE;
- }
-
- /* High dexterity yields coolness */
- else
- {
- /* Message */
- msg_print("You are off-balance.");
-
- /* Hack -- Lose balance ala paralysis */
- (void)set_paralyzed(p_ptr->paralyzed + 2 + rand_int(2));
- }
-
- /* Result */
- return (more);
-}
-
-
-/*
- * Bash open a door, success based on character strength
- *
- * For a closed door, pval is positive if locked; negative if stuck.
- *
- * For an open door, pval is positive for a broken door.
- *
- * A closed door can be opened - harder if locked. Any door might be
- * bashed open (and thereby broken). Bashing a door is (potentially)
- * faster! You move into the door way. To open a stuck door, it must
- * be bashed. A closed door can be jammed (see do_cmd_spike()).
- *
- * Creatures can also open or bash doors, see elsewhere.
- */
-void do_cmd_bash(void)
-{
- int y, x, dir;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
-
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
- {
- msg_print("You cannot do that.");
-
- return;
- }
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Bash location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid */
- c_ptr = &cave[y][x];
-
- /* Nothing useful */
- if ((c_ptr->feat < FEAT_DOOR_HEAD ||
- c_ptr->feat > FEAT_DOOR_TAIL) &&
- (c_ptr->feat < FEAT_ALTAR_HEAD ||
- c_ptr->feat > FEAT_ALTAR_TAIL) && (c_ptr->feat != FEAT_FOUNTAIN))
- {
- /* Message */
- msg_print("You see nothing there to bash.");
- }
-
- /* Monster in the way */
- else if (c_ptr->m_idx)
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- else if (c_ptr->feat >= FEAT_ALTAR_HEAD &&
- c_ptr->feat <= FEAT_ALTAR_TAIL)
- {
- more = do_cmd_bash_altar(y, x);
- }
- /* Bash a closed door */
- else if (c_ptr->feat == FEAT_FOUNTAIN)
- {
- more = do_cmd_bash_fountain(y, x);
- }
- else
- {
- /* Bash the door */
- more = do_cmd_bash_aux(y, x, dir);
- }
- }
-
- /* Unless valid action taken, cancel bash */
- if (!more) disturb(0, 0);
-}
-
-
-
-/*
- * Manipulate an adjacent grid in some way
- *
- * Attack monsters, tunnel through walls, disarm traps, open doors.
- *
- * Consider confusion XXX XXX XXX
- *
- * This command must always take a turn, to prevent free detection
- * of invisible monsters.
- */
-void do_cmd_alter(void)
-{
- int y, x, dir;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a direction */
- if (get_rep_dir(&dir))
- {
- /* Get location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid */
- c_ptr = &cave[y][x];
-
- /* Take a turn */
- energy_use = 100;
-
- /* Attack monsters */
- if (c_ptr->m_idx)
- {
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Open closed doors */
- else if ((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL))
- {
- /* Tunnel */
- more = do_cmd_open_aux(y, x, dir);
- }
-
- /* Tunnel through walls */
- else if (f_info[c_ptr->feat].flags1 & FF1_TUNNELABLE)
- {
- /* Tunnel */
- more = do_cmd_tunnel_aux(y, x, dir);
- }
-
- /* Disarm traps */
- else if (c_ptr->t_idx != 0)
- {
- /* Tunnel */
- more = do_cmd_disarm_aux(y, x, dir, always_pickup);
- }
-
- /* Oops */
- else
- {
- /* Oops */
- msg_print("You attack the empty air.");
- }
- }
-
- /* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
-}
-
-
-/*
- * Find the index of some "spikes", if possible.
- *
- * XXX XXX XXX Let user choose a pile of spikes, perhaps?
- */
-static bool_ get_spike(int *ip)
-{
- int i;
-
-
- /* Check every item in the pack */
- for (i = 0; i < INVEN_PACK; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) continue;
-
- /* Check the "tval" code */
- if (o_ptr->tval == TV_SPIKE)
- {
- /* Save the spike index */
- (*ip) = i;
-
- /* Success */
- return (TRUE);
- }
- }
-
- /* Oops */
- return (FALSE);
-}
-
-
-
-/*
- * Jam a closed door with a spike
- *
- * This command may NOT be repeated
- */
-void do_cmd_spike(void)
-{
- int y, x, dir, item;
-
- cave_type *c_ptr;
-
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Get location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get grid and contents */
- c_ptr = &cave[y][x];
-
- /* Require closed door */
- if (!((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL)))
- {
- /* Message */
- msg_print("You see nothing there to spike.");
- }
-
- /* Get a spike */
- else if (!get_spike(&item))
- {
- /* Message */
- msg_print("You have no spikes!");
- }
-
- /* Is a monster in the way? */
- else if (c_ptr->m_idx)
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Message */
- msg_print("There is a monster in the way!");
-
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Go for it */
- else
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Successful jamming */
- msg_print("You jam the door with a spike.");
-
- /* Convert "locked" to "stuck" XXX XXX XXX */
- if (c_ptr->feat < FEAT_DOOR_HEAD + 0x08) c_ptr->feat += 0x08;
-
- /* Add one spike to the door */
- if (c_ptr->feat < FEAT_DOOR_TAIL) c_ptr->feat++;
-
- /* Use up, and describe, a single spike, from the bottom */
- inc_stack_size(item, -1);
- }
- }
-}
-
-
-static void do_cmd_walk_jump(int pickup, bool_ disarm)
-{
- int dir;
-
- bool_ more = FALSE;
-
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Actually move the character */
- move_player(dir, pickup, disarm);
-
- /* Allow more walking */
- more = TRUE;
- }
-
- /* Hack -- In small scale wilderness it takes MUCH more time to move */
- energy_use *= (p_ptr->wild_mode) ? ((MAX_HGT + MAX_WID) / 2) : 1;
-
- /* Hack again -- Is there a special encounter ??? */
- if (p_ptr->wild_mode &&
- magik(wf_info[wild_map[p_ptr->py][p_ptr->px].feat].level - (p_ptr->lev * 2)))
- {
- /* Go into large wilderness view */
- p_ptr->wilderness_x = p_ptr->px;
- p_ptr->wilderness_y = p_ptr->py;
- energy_use = 100;
- change_wild_mode();
-
- /* HACk -- set the encouter flag for the wilderness generation */
- generate_encounter = TRUE;
- p_ptr->oldpx = MAX_WID / 2;
- p_ptr->oldpy = MAX_HGT / 2;
-
- /* Inform the player of his horrible fate :=) */
- msg_print("You are ambushed!");
- }
-
- /* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
-}
-
-
-/*
- * Support code for the "Walk" and "Jump" commands
- */
-void do_cmd_walk(int pickup, bool_ disarm)
-{
- /* Move (usually pickup) */
-
- if (p_ptr->immovable)
- {
- do_cmd_unwalk();
- }
- else
- {
- do_cmd_walk_jump(pickup, disarm);
- }
-}
-
-
-void do_cmd_run_run()
-{
- int dir;
-
-
- /* Hack -- no running when confused */
- if (p_ptr->confused)
- {
- msg_print("You are too confused!");
- return;
- }
-
- /* Get a "repeated" direction */
- if (get_rep_dir(&dir))
- {
- /* Hack -- Set the run counter */
- running = (command_arg ? command_arg : 1000);
-
- /* First step */
- run_step(dir);
- }
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-
-/*
- * Start running.
- */
-void do_cmd_run(void)
-{
- if (p_ptr->immovable)
- {
- return;
- }
- else
- {
- do_cmd_run_run();
- }
-}
-
-
-
-/*
- * Stay still. Search. Enter stores.
- * Pick up treasure if "pickup" is true.
- */
-void do_cmd_stay(int pickup)
-{
- cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px];
-
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
-
- /* Take a turn */
- energy_use = 100;
-
-
- /* 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(pickup);
-
-
- /* Hack -- enter a store if we are on one */
- if (c_ptr->feat == FEAT_SHOP)
- {
- /* Disturb */
- disturb(0, 0);
-
- /* Hack -- enter store */
- command_new = '_';
- }
-}
-
-/*
- * Resting allows a player to safely restore his hp -RAK-
- */
-void do_cmd_rest(void)
-{
- /* Can't rest on a Void Jumpgate -- too dangerous */
- if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN)
- {
- /* 'R&\n' is one of our favourite macros, so we have to do this */
- if (flush_failure) flush();
-
- /* Tell the player why */
- msg_print(format("Resting on a %s is too dangerous!",
- f_name + f_info[cave[p_ptr->py][p_ptr->px].feat].name));
-
- /* Done */
- return;
- }
-
- /* Can't rest while undead, it would mean dying */
- if (p_ptr->necro_extra & CLASS_UNDEAD)
- {
- /* 'R&\n' is one of our favourite macros, so we have to do this */
- if (flush_failure) flush();
-
- /* Tell the player why */
- msg_print("Resting is impossible while undead!");
-
- /* Done */
- return;
- }
-
- /* Prompt for time if needed */
- if (command_arg <= 0)
- {
- cptr p = "Rest (0-9999, '*' for HP/SP, '&' as needed): ";
-
- char out_val[80];
-
- /* Default */
- strcpy(out_val, "&");
-
- /* Ask for duration */
- if (!get_string(p, out_val, 4)) return;
-
- /* Rest until done */
- if (out_val[0] == '&')
- {
- command_arg = ( -2);
- }
-
- /* Rest a lot */
- else if (out_val[0] == '*')
- {
- command_arg = ( -1);
- }
-
- /* Rest some */
- else
- {
- command_arg = atoi(out_val);
- if (command_arg <= 0) return;
- }
- }
-
-
- /* Paranoia */
- if (command_arg > 9999) command_arg = 9999;
-
-
- /* Take a turn XXX XXX XXX (?) */
- energy_use = 100;
-
- /* Save the rest code */
- resting = command_arg;
-
- /* Cancel searching */
- p_ptr->searching = FALSE;
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Handle stuff */
- handle_stuff();
-
- /* Refresh */
- Term_fresh();
-}
-
-
-
-
-
-
-/*
- * Determines the odds of an object breaking when thrown at a monster
- *
- * Note that artifacts never break, see the "drop_near()" function.
- */
-int breakage_chance(object_type *o_ptr)
-{
- int reducer =
- 1 + ((get_skill(SKILL_ARCHERY)) ? (get_skill_scale(SKILL_ARCHERY, 10)) : 0);
-
- /* Examine the item type */
- switch (o_ptr->tval)
- {
- /* Always break */
- case TV_FLASK:
- case TV_POTION:
- case TV_POTION2:
- case TV_BOTTLE:
- case TV_FOOD:
- {
- return (100);
- }
-
- /* Often break */
- case TV_LITE:
- case TV_SCROLL:
- case TV_SKELETON:
- {
- return (50);
- }
-
- case TV_ARROW:
- {
- return (50 / reducer);
- }
-
- /* Sometimes break */
- case TV_WAND:
- case TV_SPIKE:
- {
- return (25);
- }
-
- case TV_SHOT:
- case TV_BOLT:
- {
- return (25 / reducer);
- }
- case TV_BOOMERANG:
- {
- return 1;
- }
- }
-
- /* Rarely break */
- return (10);
-}
-
-/*
- * Return multiplier of an object
- */
-int get_shooter_mult(object_type *o_ptr)
-{
- /* Assume a base multiplier */
- int tmul = 1;
-
- /* Analyze the launcher */
- switch (o_ptr->sval)
- {
- case SV_SLING:
- {
- /* Sling and ammo */
- tmul = 2;
- break;
- }
-
- case SV_SHORT_BOW:
- {
- /* Short Bow and Arrow */
- tmul = 2;
- break;
- }
-
- case SV_LONG_BOW:
- {
- /* Long Bow and Arrow */
- tmul = 3;
- break;
- }
-
- /* Light Crossbow and Bolt */
- case SV_LIGHT_XBOW:
- {
- tmul = 3;
- break;
- }
-
- /* Heavy Crossbow and Bolt */
- case SV_HEAVY_XBOW:
- {
- tmul = 4;
- break;
- }
- }
- return tmul;
-}
-
-
-/*
- * Fire an object from the pack or floor.
- *
- * You may only fire items that "match" your missile launcher.
- *
- * You must use slings + pebbles/shots, bows + arrows, xbows + bolts.
- *
- * See "calc_bonuses()" for more calculations and such.
- *
- * Note that "firing" a missile is MUCH better than "throwing" it.
- *
- * Note: "unseen" monsters are very hard to hit.
- *
- * Objects are more likely to break if they "attempt" to hit a monster.
- *
- * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
- *
- * The "extra shot" code works by decreasing the amount of energy
- * required to make each shot, spreading the shots out over time.
- *
- * Note that when firing missiles, the launcher multiplier is applied
- * after all the bonuses are added in, making multipliers very useful.
- *
- * Note that Bows of "Extra Might" get extra range and an extra bonus
- * for the damage multiplier.
- *
- * Note that Bows of "Extra Shots" give an extra shot.
- */
-void do_cmd_fire(void)
-{
- int dir, item;
-
- int j, y, x, ny, nx, ty, tx, by, bx;
-
- int oldtdam, tdam, tdis, thits, tmul;
-
- int bonus, chance;
-
- int cur_dis, visible;
-
- int breakage = -1, num_pierce = 0;
-
- s32b special = 0;
-
- object_type forge;
-
- object_type *q_ptr;
-
- object_type *o_ptr;
-
- object_type *j_ptr;
-
- bool_ hit_body = FALSE;
-
- byte missile_attr;
-
- char missile_char;
-
- char o_name[80];
-
- cptr q, s;
-
- int msec = delay_factor * delay_factor * delay_factor;
-
-
- /* Get the "bow" (if any) */
- j_ptr = &p_ptr->inventory[INVEN_BOW];
-
- /* Require a launcher */
- if (!j_ptr->tval)
- {
- msg_print("You have nothing with which to fire.");
- return;
- }
-
- /* XXX HACK */
- if (j_ptr->tval == TV_INSTRUMENT)
- {
- msg_print("You cannot fire with an instrument.");
- return;
- }
-
- /* Get the "ammo" (if any) */
- o_ptr = &p_ptr->inventory[INVEN_AMMO];
-
- item = INVEN_AMMO;
-
- /* If nothing correct try to choose from the backpack */
- if ((p_ptr->tval_ammo != o_ptr->tval) || (!o_ptr->k_idx))
- {
- /* Require proper missile */
- item_tester_tval = p_ptr->tval_ammo;
-
- /* Get an item */
- q = "Your quiver is empty. Fire which item? ";
- s = "You have nothing to fire.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
-
-
- /* Access the item */
- o_ptr = get_object(item);
- }
-
-
- /* Get a direction (or cancel) */
- if (!get_aim_dir(&dir)) return;
-
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Obtain a local object */
- object_copy(q_ptr, o_ptr);
-
- /* Single object */
- q_ptr->number = 1;
-
- /* Reduce stack and describe */
- inc_stack_size(item, -1);
-
- /* Break goi/manashield */
- if (p_ptr->invuln)
- {
- set_invuln(0);
- }
- if (p_ptr->disrupt_shield)
- {
- set_disrupt_shield(0);
- }
-
-
- /* Sound */
- sound(SOUND_SHOOT);
-
-
- /* Describe the object */
- object_desc(o_name, q_ptr, FALSE, 3);
-
- /* Find the color and symbol for the object for throwing */
- missile_attr = object_attr(q_ptr);
- missile_char = object_char(q_ptr);
-
-
- /* Use the proper number of shots */
- thits = p_ptr->num_fire;
-
- /* Use a base distance */
- tdis = 10;
-
- /* Base damage from thrown object plus launcher bonus */
- tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + j_ptr->to_d;
-
- /* Actually "fire" the object */
- bonus = (p_ptr->to_h + p_ptr->to_h_ranged + q_ptr->to_h + j_ptr->to_h);
-
- chance = (p_ptr->skill_thb + (bonus * BTH_PLUS_ADJ));
- if (chance < 5) chance = 5;
-
- tmul = get_shooter_mult(j_ptr);
-
- /* Get extra "power" from "extra might" */
- tmul += p_ptr->xtra_might;
-
- /* Boost the damage */
- tdam *= tmul;
-
- /* Add in the player damage */
- tdam += p_ptr->to_d_ranged;
-
- /* Base range */
- tdis = 10 + 5 * tmul;
-
-
- /* Take a (partial) turn */
- energy_use = (100 / thits);
-
- /* piercing shots ? */
- if (p_ptr->use_piercing_shots)
- {
- num_pierce = (get_skill(SKILL_COMBAT) / 10) - 1;
- num_pierce = (num_pierce < 0) ? 0 : num_pierce;
- }
-
- /* Start at the player */
- by = p_ptr->py;
- bx = p_ptr->px;
- y = p_ptr->py;
- x = p_ptr->px;
-
- /* Predict the "target" location */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Check for "target request" */
- if ((dir == 5) && target_okay())
- {
- tx = target_col;
- ty = target_row;
- }
-
-
- /* Hack -- Handle stuff */
- handle_stuff();
-
- oldtdam = tdam;
- while (TRUE)
- {
- /* Reset after a piercing shot */
- tdam = oldtdam;
-
- /* Travel until stopped */
- for (cur_dis = 0; cur_dis <= tdis; )
- {
- /* Hack -- Stop at the target */
- if ((y == ty) && (x == tx)) break;
-
- /* Calculate the new location (see "project()") */
- ny = y;
- nx = x;
- mmove2(&ny, &nx, by, bx, ty, tx);
-
- /* Stopped by walls/doors */
- if (!cave_floor_bold(ny, nx)) break;
-
- /* Advance the distance */
- cur_dis++;
-
- /* Save the new location */
- x = nx;
- y = ny;
-
-
- /* The player can see the (on screen) missile */
- if (panel_contains(y, x) && player_can_see_bold(y, x))
- {
- /* Draw, Hilite, Fresh, Pause, Erase */
- print_rel(missile_char, missile_attr, y, x);
- move_cursor_relative(y, x);
- Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
- lite_spot(y, x);
- Term_fresh();
- }
-
- /* The player cannot see the missile */
- else
- {
- /* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
- }
-
-
- /* Monster here, Try to hit it */
- if (cave[y][x].m_idx)
- {
- 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);
-
- /* Check the visibility */
- visible = m_ptr->ml;
-
- /* Note the collision */
- hit_body = TRUE;
-
- /* Did we hit it (penalize range) */
- if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml))
- {
- bool_ fear = FALSE;
-
- /* Assume a default death */
- cptr note_dies = " dies.";
-
- /* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- /* Special note at death */
- note_dies = " is destroyed.";
- }
-
-
- /* Handle unseen monster */
- if (!visible)
- {
- /* Invisible monster */
- msg_format("The %s finds a mark.", o_name);
- }
-
- /* Handle visible monster */
- else
- {
- char m_name[80];
-
- /* Get "the monster" or "it" */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("The %s hits %s.", o_name, m_name);
-
- /* Hack -- Track this monster race */
- if (m_ptr->ml) monster_race_track(m_ptr->r_idx,
- m_ptr->ego);
-
- /* Hack -- Track this monster */
- if (m_ptr->ml) health_track(c_ptr->m_idx);
-
- /* Anger friends */
- {
- char m_name[80];
- monster_desc(m_name, m_ptr, 0);
- 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;
- }
- }
- }
- }
-
- /* Apply special damage XXX XXX XXX */
- tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special);
- tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY);
-
- /* No negative damage */
- if (tdam < 0) tdam = 0;
-
- /* Complex message */
- if (wizard)
- {
- msg_format("You do %d (out of %d) damage.",
- tdam, m_ptr->hp);
- }
-
- /* Hit the monster, check for death */
- if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies))
- {
- /* Dead monster */
- }
-
- /* No death */
- else
- {
- /* Message */
- message_pain(c_ptr->m_idx, tdam);
-
- if (special) attack_special(m_ptr, special, tdam);
-
- /* Take note */
- if (fear && m_ptr->ml)
- {
- char m_name[80];
-
- /* Sound */
- sound(SOUND_FLEE);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("%^s flees in terror!", m_name);
- }
- }
- }
-
- /* Stop looking */
- break;
- }
- }
-
- /* Exploding arrow ? */
- if (q_ptr->pval2 != 0)
- {
- int rad = 0, dam =
- (damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d) * 2;
- int flag =
- PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL |
- PROJECT_JUMP;
- switch (q_ptr->sval)
- {
- case SV_AMMO_LIGHT:
- rad = 2;
- dam /= 2;
- break;
- case SV_AMMO_NORMAL:
- rad = 3;
- break;
- case SV_AMMO_HEAVY:
- rad = 4;
- dam *= 2;
- break;
- }
-
- project(0, rad, y, x, dam, q_ptr->pval2, flag);
- }
-
- /* Chance of breakage (during attacks) */
- j = (hit_body ? breakage_chance(q_ptr) : 0);
-
- /* Break ? */
- if ((q_ptr->pval2 != 0) || (rand_int(100) < j))
- {
- breakage = 100;
- break;
- }
-
- /* If the ammo doesn't break, it can pierce through */
- if ((num_pierce) && (hit_body) &&
- (magik(45 + get_skill(SKILL_ARCHERY))))
- {
- num_pierce--;
- hit_body = FALSE;
-
- /* If target isn't reached, continue moving to target */
- if ( !((tx < x && x < bx) || (bx < x && x < tx)) &&
- !((ty < y && y < by) || (by < y && y < ty)))
- {
- /* Continue moving in same direction if we reached the target */
- int dx = tx - bx;
- int dy = ty - by;
- tx = x + 99 * dx;
- ty = y + 99 * dy;
-
- /* New base location */
- by = y;
- bx = x;
- }
-
- msg_format("The %s pierces through!", o_name);
- }
- else
- break;
- }
-
- /* Drop (or break) near that location */
- drop_near(q_ptr, breakage, y, x);
-}
-
-
-/*
- * Why is this here? even if it's temporary boost...
- * Moved into player_type, hoping it might be useful in future extensions
- * -- pelpel
- */
-/* int throw_mult = 1; */
-
-/*
- * Throw an object from the pack or floor.
- *
- * Note: "unseen" monsters are very hard to hit.
- *
- * Should throwing a weapon do full damage? Should it allow the magic
- * to hit bonus of the weapon to have an effect? Should it ever cause
- * the item to be destroyed? Should it do any damage at all?
- */
-void do_cmd_throw(void)
-{
- int dir, item;
-
- s32b special = 0;
-
- int j, y, x, ny, nx, ty, tx;
-
- int chance, tdam, tdis;
-
- int mul, div;
-
- int boulder_add = 0;
- int boulder_mult = 0;
-
- int cur_dis, visible;
-
- object_type forge;
-
- object_type *q_ptr;
-
- object_type *o_ptr;
-
- bool_ hit_body = FALSE;
-
- bool_ hit_wall = FALSE;
-
- byte missile_attr;
-
- char missile_char;
-
- char o_name[80];
-
- int msec = delay_factor * delay_factor * delay_factor;
-
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
-
-
- /* Get an item */
- q = "Throw which item? ";
- s = "You have nothing to throw.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
-
- /* Access the item */
- o_ptr = get_object(item);
-
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Hack - Cannot throw away 'no drop' cursed items */
- if (cursed_p(o_ptr) && (f4 & TR4_CURSE_NO_DROP))
- {
- /* Oops */
- msg_print("Hmmm, you seem to be unable to throw it.");
-
- /* Nope */
- return;
- }
-
- /* Boulder throwing */
- if ((o_ptr->tval == TV_JUNK) && (o_ptr->sval == SV_BOULDER) && (get_skill(SKILL_BOULDER)))
- {
- boulder_add = get_skill_scale(SKILL_BOULDER, 80);
- boulder_mult = get_skill_scale(SKILL_BOULDER, 6);
- }
-
- /* Get a direction (or cancel) */
- if (!get_aim_dir(&dir)) return;
-
- /* Break goi/manashield */
- if (p_ptr->invuln)
- {
- set_invuln(0);
- }
- if (p_ptr->disrupt_shield)
- {
- set_disrupt_shield(0);
- }
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Obtain a local object */
- object_copy(q_ptr, o_ptr);
-
- /*
- * Hack -- If rods or wands are thrown, the total maximum timeout or
- * charges need to be allocated between the two stacks.
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval / o_ptr->number;
-
- if (o_ptr->number > 1) o_ptr->pval -= q_ptr->pval;
- }
-
- /* Single object */
- q_ptr->number = 1;
-
- /* Reduce stack and describe */
- inc_stack_size(item, -1);
-
- /* Description */
- object_desc(o_name, q_ptr, FALSE, 3);
-
- /* Find the color and symbol for the object for throwing */
- missile_attr = object_attr(q_ptr);
- missile_char = object_char(q_ptr);
-
- /* Extract a "distance multiplier" */
- /* Changed for 'launcher' corruption */
- mul = 10 + (2 * (p_ptr->throw_mult - 1)) + (2 * boulder_mult);
-
- /* Enforce a minimum "weight" of one pound */
- div = ((q_ptr->weight > 10) ? q_ptr->weight : 10);
-
- /* Hack -- Distance -- Reward strength, penalize weight */
- tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div;
-
- /* Max distance of 10-18 */
- if (tdis > mul) tdis = mul;
-
- /* Hack -- Base damage from thrown object */
- tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + boulder_add;
- tdam *= p_ptr->throw_mult + boulder_mult;
-
- /* Chance of hitting - adjusted for Weaponmasters -- Gumby */
- chance = (p_ptr->skill_tht + (p_ptr->to_h * BTH_PLUS_ADJ));
-
- /* Take a turn */
- energy_use = 100;
-
-
- /* Start at the player */
- y = p_ptr->py;
- x = p_ptr->px;
-
- /* Predict the "target" location */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Check for "target request" */
- if ((dir == 5) && target_okay())
- {
- tx = target_col;
- ty = target_row;
- }
-
-
- /* Hack -- Handle stuff */
- handle_stuff();
-
-
- /* Travel until stopped */
- for (cur_dis = 0; cur_dis <= tdis; )
- {
- /* Hack -- Stop at the target */
- if ((y == ty) && (x == tx)) break;
-
- /* Calculate the new location (see "project()") */
- ny = y;
- nx = x;
- mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx);
-
- /* Stopped by walls/doors */
- if (!cave_floor_bold(ny, nx))
- {
- hit_wall = TRUE;
- break;
- }
-
- /* Advance the distance */
- cur_dis++;
-
- /* Save the new location */
- x = nx;
- y = ny;
-
-
- /* The player can see the (on screen) missile */
- if (panel_contains(y, x) && player_can_see_bold(y, x))
- {
- /* Draw, Hilite, Fresh, Pause, Erase */
- print_rel(missile_char, missile_attr, y, x);
- move_cursor_relative(y, x);
- Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
- lite_spot(y, x);
- Term_fresh();
- }
-
- /* The player cannot see the missile */
- else
- {
- /* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
- }
-
-
- /* Monster here, Try to hit it */
- if (cave[y][x].m_idx)
- {
- 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);
-
- /* Check the visibility */
- visible = m_ptr->ml;
-
- /* Note the collision */
- hit_body = TRUE;
-
- /* Did we hit it (penalize range) */
- if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml))
- {
- bool_ fear = FALSE;
-
- /* Assume a default death */
- cptr note_dies = " dies.";
-
- /* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- /* Special note at death */
- note_dies = " is destroyed.";
- }
-
-
- /* Handle unseen monster */
- if (!visible)
- {
- /* Invisible monster */
- msg_format("The %s finds a mark.", o_name);
- }
-
- /* Handle visible monster */
- else
- {
- char m_name[80];
-
- /* Get "the monster" or "it" */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("The %s hits %s.", o_name, m_name);
-
- /* Hack -- Track this monster race */
- if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego);
-
- /* Hack -- Track this monster */
- if (m_ptr->ml) health_track(c_ptr->m_idx);
- }
-
- /* Apply special damage XXX XXX XXX */
- tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special);
- tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, o_ptr->sval == SV_BOULDER ? SKILL_BOULDER : SKILL_ARCHERY);
-
- /* No negative damage */
- if (tdam < 0) tdam = 0;
-
- /* Complex message */
- if (wizard)
- {
- msg_format("You do %d (out of %d) damage.",
- tdam, m_ptr->hp);
- }
-
- /* Hit the monster, check for death */
- if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies))
- {
- /* Dead monster */
- }
-
- /* No death */
- else
- {
- /* Message */
- message_pain(c_ptr->m_idx, tdam);
-
- if (special) attack_special(m_ptr, special, tdam);
-
- /* Anger friends */
- if (!(k_info[q_ptr->k_idx].tval == TV_POTION))
- {
- char m_name[80];
- monster_desc(m_name, m_ptr, 0);
- 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;
- }
- }
-
- /* Take note */
- if (fear && m_ptr->ml)
- {
- char m_name[80];
-
- /* Sound */
- sound(SOUND_FLEE);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("%^s flees in terror!", m_name);
- }
- }
- }
-
- /* Stop looking */
- break;
- }
- }
-
- /* Chance of breakage (during attacks) */
- j = (hit_body ? breakage_chance(q_ptr) : 0);
-
- /* Potions smash open */
- if (k_info[q_ptr->k_idx].tval == TV_POTION)
- {
- if ((hit_body) || (hit_wall) || (randint(100) < j))
- {
- /* Message */
- msg_format("The %s shatters!", o_name);
-
- if (potion_smash_effect(0, y, x, q_ptr->sval))
- {
- if (cave[y][x].m_idx)
- {
- char m_name[80];
- monster_desc(m_name, &m_list[cave[y][x].m_idx], 0);
- switch (is_friend(&m_list[cave[y][x].m_idx]))
- {
- case 1:
- msg_format("%^s gets angry!", m_name);
- change_side(&m_list[cave[y][x].m_idx]);
- break;
- case 0:
- msg_format("%^s gets angry!", m_name);
- m_list[cave[y][x].m_idx].status = MSTATUS_NEUTRAL_M;
- break;
- }
- }
- }
-
- return;
- }
- else
- {
- j = 0;
- }
- }
-
- /* Drop (or break) near that location */
- drop_near(q_ptr, j, y, x);
-}
-
-
-/*
- * Throw a boomerang object from the equipement(bow).
- *
- * Note: "unseen" monsters are very hard to hit.
- *
- * Should throwing a weapon do full damage? Should it allow the magic
- * to hit bonus of the weapon to have an effect? Should it ever cause
- * the item to be destroyed? Should it do any damage at all?
- */
-void do_cmd_boomerang(void)
-{
- int dir;
-
- int j, y, x, ny, nx, ty, tx;
-
- int chance, tdam, tdis;
-
- int mul, div;
-
- int cur_dis, visible;
-
- object_type forge;
-
- object_type *q_ptr;
-
- object_type *o_ptr;
-
- bool_ hit_body = FALSE;
-
- byte missile_attr;
-
- char missile_char;
-
- char o_name[80];
-
- s32b special = 0;
-
- int msec = delay_factor * delay_factor * delay_factor;
-
-
- /* Get the "bow" (if any) */
- o_ptr = &p_ptr->inventory[INVEN_BOW];
-
-
- /* Get a direction (or cancel) */
- if (!get_aim_dir(&dir)) return;
-
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Obtain a local object */
- object_copy(q_ptr, o_ptr);
-
- /* Single object */
- q_ptr->number = 1;
-
- /* Description */
- object_desc(o_name, q_ptr, FALSE, 3);
-
- /* Find the color and symbol for the object for throwing */
- missile_attr = object_attr(q_ptr);
- missile_char = object_char(q_ptr);
-
- /* Extract a "distance multiplier" */
- /* Changed for 'launcher' corruption */
- mul = 10 + 2 * (p_ptr->throw_mult - 1);
-
- /* Enforce a minimum "weight" of one pound */
- div = ((q_ptr->weight > 10) ? q_ptr->weight : 10);
-
- /* Hack -- Distance -- Reward strength, penalize weight */
- tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div;
-
- /* Max distance of 10-18 */
- if (tdis > mul) tdis = mul;
-
- /* Hack -- Base damage from thrown object */
- tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d;
- tdam *= p_ptr->throw_mult;
-
- /* Chance of hitting */
- chance =
- (p_ptr->skill_tht +
- ((p_ptr->to_h + p_ptr->to_h_ranged) * BTH_PLUS_ADJ));
-
- chance += get_skill(SKILL_BOOMERANG);
-
- /* Take a turn */
- energy_use = 100;
-
-
- /* Start at the player */
- y = p_ptr->py;
- x = p_ptr->px;
-
- /* Predict the "target" location */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Check for "target request" */
- if ((dir == 5) && target_okay())
- {
- tx = target_col;
- ty = target_row;
- }
-
-
- /* Hack -- Handle stuff */
- handle_stuff();
-
-
- /* Travel until stopped */
- for (cur_dis = 0; cur_dis <= tdis; )
- {
- /* Hack -- Stop at the target */
- if ((y == ty) && (x == tx)) break;
-
- /* Calculate the new location (see "project()") */
- ny = y;
- nx = x;
- mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx);
-
- /* Stopped by walls/doors */
- if (!cave_floor_bold(ny, nx))
- {
- break;
- }
-
- /* Advance the distance */
- cur_dis++;
-
- /* Save the new location */
- x = nx;
- y = ny;
-
-
- /* The player can see the (on screen) missile */
- if (panel_contains(y, x) && player_can_see_bold(y, x))
- {
- /* Draw, Hilite, Fresh, Pause, Erase */
- print_rel(missile_char, missile_attr, y, x);
- move_cursor_relative(y, x);
- Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
- lite_spot(y, x);
- Term_fresh();
- }
-
- /* The player cannot see the missile */
- else
- {
- /* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
- }
-
-
- /* Monster here, Try to hit it */
- if (cave[y][x].m_idx)
- {
- 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);
-
- /* Check the visibility */
- visible = m_ptr->ml;
-
- /* Note the collision */
- hit_body = TRUE;
-
- /* Did we hit it (penalize range) */
- if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml))
- {
- bool_ fear = FALSE;
-
- /* Assume a default death */
- cptr note_dies = " dies.";
-
- /* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- /* Special note at death */
- note_dies = " is destroyed.";
- }
-
-
- /* Handle unseen monster */
- if (!visible)
- {
- /* Invisible monster */
- msg_format("The %s finds a mark.", o_name);
- }
-
- /* Handle visible monster */
- else
- {
- char m_name[80];
-
- /* Get "the monster" or "it" */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("The %s hits %s.", o_name, m_name);
-
- /* Hack -- Track this monster race */
- if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego);
-
- /* Hack -- Track this monster */
- if (m_ptr->ml) health_track(c_ptr->m_idx);
- }
-
- /* Apply special damage XXX XXX XXX */
- tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special);
- tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY);
-
- /* No negative damage */
- if (tdam < 0) tdam = 0;
-
- /* Complex message */
- if (wizard)
- {
- msg_format("You do %d (out of %d) damage.",
- tdam, m_ptr->hp);
- }
-
- /* Hit the monster, check for death */
- if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies))
- {
- /* Dead monster */
- }
-
- /* No death */
- else
- {
- /* Message */
- message_pain(c_ptr->m_idx, tdam);
-
- if (special) attack_special(m_ptr, special, tdam);
-
- /* Anger friends */
- if (!(k_info[q_ptr->k_idx].tval == TV_POTION))
- {
- char m_name[80];
- monster_desc(m_name, m_ptr, 0);
- 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;
- }
- }
-
- /* Take note */
- if (fear && m_ptr->ml)
- {
- char m_name[80];
-
- /* Sound */
- sound(SOUND_FLEE);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Message */
- msg_format("%^s flees in terror!", m_name);
- }
- }
-
- /* Chance of breakage (during attacks) */
- j = (hit_body ? breakage_chance(o_ptr) : 0);
-
- /* Break the boomerang */
- if (!(o_ptr->art_name || artifact_p(o_ptr)) &&
- (rand_int(100) < j))
- {
- msg_print(format("Your %s is destroyed.", o_name));
- inc_stack_size_ex(INVEN_BOW, -1, OPTIMIZE, NO_DESCRIBE);
- }
- }
-
- /* Stop looking */
- break;
- }
- }
-
- /* Travel back to the player */
- for (cur_dis = 0; cur_dis <= tdis; )
- {
- /* Hack -- Stop at the target */
- if ((y == p_ptr->py) && (x == p_ptr->px)) break;
-
- /* Calculate the new location (see "project()") */
- ny = y;
- nx = x;
- mmove2(&ny, &nx, ty, tx, p_ptr->py, p_ptr->px);
-
- /* Advance the distance */
- cur_dis++;
-
- /* Save the new location */
- x = nx;
- y = ny;
-
-
- /* The player can see the (on screen) missile */
- if (panel_contains(y, x) && player_can_see_bold(y, x))
- {
- /* Draw, Hilite, Fresh, Pause, Erase */
- print_rel(missile_char, missile_attr, y, x);
- move_cursor_relative(y, x);
- Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
- lite_spot(y, x);
- Term_fresh();
- }
-
- /* The player cannot see the missile */
- else
- {
- /* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
- }
- }
-}
-
-
-/*
- * Try to ``walk'' using phase door.
- */
-void do_cmd_unwalk()
-{
- int dir, y, x, feat;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- if (!get_rep_dir(&dir)) return;
-
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- c_ptr = &cave[y][x];
- feat = c_ptr->feat;
-
- /* Must have knowledge to know feature XXX XXX */
- if (!(c_ptr->info & (CAVE_MARK))) feat = FEAT_NONE;
-
- /* Take a turn */
- energy_use = 100;
- energy_use *= (p_ptr->wild_mode) ? (5 * (MAX_HGT + MAX_WID) / 2) : 1;
-
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
-
- /* Attack monsters */
- if (c_ptr->m_idx > 0)
- {
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Exit the area */
- else if ((!dun_level) && (!p_ptr->wild_mode) &&
- ((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;
- }
- }
-
- /* Hack -- Ignore weird terrain types. */
- else if (!cave_floor_grid(c_ptr))
- {
- teleport_player(10);
- }
-
- /* Enter quests */
- else if (((feat >= FEAT_QUEST_ENTER) && (feat <= FEAT_QUEST_UP)) ||
- ((feat >= FEAT_LESS) && (feat <= FEAT_MORE)))
- {
- move_player(dir, always_pickup, TRUE);
- more = FALSE;
- }
-
- /* Hack -- Ignore wilderness mofe. */
- else if (p_ptr->wild_mode)
- {
- /* Chance to not blink right */
- if (magik(15))
- {
- do
- {
- dir = rand_range(1, 9);
- }
- while (dir == 5);
- }
-
- move_player(dir, always_pickup, TRUE);
- }
-
- /* Walking semantics */
- else
- {
- teleport_player_directed(10, dir);
- }
-
- /* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
-}
-
-
-static bool_ tport_vertically(bool_ how)
-{
- /* arena or quest -KMW- */
- if ((p_ptr->inside_arena) || (p_ptr->inside_quest))
- {
- msg_print("There is no effect.");
- return (FALSE);
- }
-
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
- {
- msg_print("Some powerful force prevents you from teleporting.");
- return FALSE;
- }
-
- /* Go down */
- if (how)
- {
- if (dun_level >= d_info[dungeon_type].maxdepth)
- {
- msg_print("The floor is impermeable.");
- return (FALSE);
- }
-
- msg_print("You sink through the floor.");
- dun_level++;
- p_ptr->leaving = TRUE;
- }
- else
- {
- if (dun_level < d_info[dungeon_type].mindepth)
- {
- msg_print("There is nothing above you but air.");
- return (FALSE);
- }
-
- msg_print("You rise through the ceiling.");
- dun_level--;
- p_ptr->leaving = TRUE;
- }
-
- return (TRUE);
-}
-
-
-/*
- * Do a special ``movement'' action. Meant to be used for ``immovable''
- * characters.
- */
-void do_cmd_immovable_special(void)
-{
- int i, ii, ij, dir;
-
- int foo = p_ptr->immov_cntr;
-
- int lose_sp = 0;
-
- int lose_hp = 0;
-
- bool_ did_act = FALSE;
-
- bool_ did_load = FALSE;
-
-
- if (foo > 1)
- {
- if (p_ptr->csp > foo / 2)
- {
-
- msg_format("This will drain %d mana points!", foo / 2);
- if (!get_check("Proceed? ")) return;
-
- lose_sp = foo / 2;
-
- }
- else if (p_ptr->chp > foo / 2)
- {
-
- msg_format("Warning: This will drain %d hit points!", foo / 2);
- if (!get_check("Proceed? ")) return;
-
- lose_hp = foo / 2;
-
- }
- else
- {
- msg_print("You can't use your powers yet.");
- return;
- }
- }
-
- /* Enter "icky" mode */
- character_icky = TRUE;
-
- /* Save the screen */
- Term_save();
-
-
- /* Interact until done */
- while (1)
- {
- /* Clear screen */
- Term_clear();
-
- /* Ask for a choice */
- prt("Do what special action:", 2, 0);
-
- /* Give some choices */
- prt("(a) Teleport to a specific place.", 4, 5);
- prt("(b) Fetch an item.", 5, 5);
- prt("(c) Go up 50'", 6, 5);
- prt("(d) Go down 50'", 7, 5);
-
- /* Prompt */
- prt("Command: ", 9, 0);
-
- /* Prompt */
- i = inkey();
-
- /* Done */
- if (i == ESCAPE) break;
-
- /* Tele-to */
- if (i == 'a')
- {
- Term_load();
- character_icky = FALSE;
- did_load = TRUE;
-
- if (!tgt_pt(&ii, &ij)) break;
-
- /* Teleport to the target */
- teleport_player_to(ij, ii);
-
- did_act = TRUE;
- break;
- }
-
- /* Fetch item */
- else if (i == 'b')
- {
- Term_load();
- character_icky = FALSE;
- did_load = TRUE;
-
- if (!get_aim_dir(&dir)) return;
- fetch(dir, p_ptr->lev * 15, FALSE);
- py_pickup_floor(always_pickup);
-
- did_act = TRUE;
- break;
- }
-
- /* Move up */
- else if (i == 'c')
- {
- Term_load();
- character_icky = FALSE;
- did_load = TRUE;
-
- if (!tport_vertically(FALSE)) return;
-
- did_act = TRUE;
- break;
- }
-
- /* Move down */
- else if (i == 'd')
- {
- Term_load();
- character_icky = FALSE;
- did_load = TRUE;
-
- if (!tport_vertically(TRUE)) return;
-
- did_act = TRUE;
- break;
- }
-
- /* Unknown option */
- else
- {
- bell();
- }
-
- }
-
- /* Check if screen was restored before */
- if (!did_load)
- {
- /* Restore the screen */
- Term_load();
-
- /* Leave "icky" mode */
- character_icky = FALSE;
- }
-
- /* Apply stat losses if something was done */
- if (did_act)
- {
- p_ptr->immov_cntr += 101 - (p_ptr->lev * 2);
-
- if (lose_sp)
- {
- p_ptr->csp -= lose_sp;
- p_ptr->redraw |= (PR_MANA);
- }
-
- if (lose_hp)
- {
- p_ptr->chp -= lose_hp;
- p_ptr->redraw |= (PR_HP);
- }
-
- energy_use = 100;
- }
-}
-
-/* Can we sacrifice it ? */
-static bool_ item_tester_hook_sacrifiable(object_type *o_ptr)
-{
- GOD(GOD_MELKOR)
- {
- /* Corpses are */
- if (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE_CORPSE)
- return (TRUE);
-
- /* Books without any udun spells */
- if ((o_ptr->tval == TV_BOOK) && (exec_lua(format("return udun_in_book(%d, %d)", o_ptr->sval, o_ptr->pval)) == 0))
- return TRUE;
- }
-
- /* Assume not */
- return (FALSE);
-}
-
-/*
- * Handle sacrifices.
- * Grace is increased by value of sacrifice.
- */
-void do_cmd_sacrifice(void)
-{
- byte on_what = cave[p_ptr->py][p_ptr->px].feat;
-
- /* Check valididty */
- if ((on_what < FEAT_ALTAR_HEAD) || (on_what > FEAT_ALTAR_TAIL))
- {
- show_god_info(FALSE);
- return;
- }
- else
- {
- int agod = on_what - FEAT_ALTAR_HEAD + 1;
-
- /* Not worshipping a god ? ahhhh! */
- GOD(GOD_NONE)
- {
- int i;
-
- for (i = 0; i < 10; i++)
- {
- if (deity_info[agod].desc[i] != NULL)
- msg_print(deity_info[agod].desc[i]);
- }
- if (get_check(format("Do you want to worship %s? ", deity_info[agod].name)))
- {
- follow_god(agod, FALSE);
- p_ptr->grace = -200;
- inc_piety(p_ptr->pgod, 0);
- }
- }
- else if (p_ptr->pgod == agod)
- {
- GOD(GOD_MELKOR)
- {
- /* One can sacrifice some HP for piety or damage */
- if ((p_ptr->mhp > 10) && (p_ptr->chp > 10) && get_check("Do you want to sacrifice a part of yourself? "))
- {
- /* 10 HP = 300 * wis piety */
- if (get_check("Do you want to sacrifice for more piety instead of damage? "))
- {
- int x = wisdom_scale(6);
- if (x < 1) x = 1;
-
- p_ptr->hp_mod -= 10;
- take_hit(10, "self sacrifice to Melkor");
- msg_print("Your life slips away, and Melkor seems happier.");
- inc_piety(GOD_MELKOR, x * 300);
- p_ptr->update |= (PU_HP);
- }
- /* 10 HP = +wis damage */
- else
- {
- take_hit(10, "self sacrifice to Melkor");
- msg_print("Your life slips away, and your arms grow stronger.");
- p_ptr->melkor_sacrifice++;
- p_ptr->update |= (PU_BONUS | PU_HP);
- }
- }
- else
- {
- int item;
- object_type *o_ptr;
-
- /* Restrict choices to food */
- item_tester_hook = item_tester_hook_sacrifiable;
-
- /* Get an item */
- if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return;
- o_ptr = get_object(item);
-
- /* Piety for corpses is based on monster level */
- if (o_ptr->tval == TV_CORPSE)
- {
- inc_piety(GOD_MELKOR, 2 * r_info[o_ptr->pval2].level);
- }
-
- /* In books it depends of the spell levels*/
- if (o_ptr->tval == TV_BOOK)
- {
- int x = exec_lua(format("return levels_in_book(%d, %d)", o_ptr->sval, o_ptr->pval));
-
- inc_piety(GOD_MELKOR, 2 * x);
- }
-
- /* Remove the item */
- inc_stack_size(item, -1);
- }
- }
- else
- {
- process_hooks(HOOK_SACRIFICE_GOD, "()", "");
- }
- }
- }
-}
-
-
-/*
- * scan_monst --
- *
- * Return a list of o_list[] indexes of items of the given monster
- */
-bool_ scan_monst(int *items, int *item_num, int m_idx)
-{
- int this_o_idx, next_o_idx;
-
- int num = 0;
-
-
- (*item_num) = 0;
-
- /* Scan all objects in the grid */
- for (this_o_idx = m_list[m_idx].hold_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;
-
- /* Accept this item */
- items[num++] = this_o_idx;
-
- /* XXX Hack -- Enforce limit */
- if (num == 23) break;
- }
-
- /* Number of items */
- (*item_num) = num;
-
- /* Result */
- return (num != 0);
-}
-
-
-/*
- * Display a list of the items that the given monster carries.
- */
-byte show_monster_inven(int m_idx, int *monst_list)
-{
- int i, j, k, l;
-
- int col, len, lim;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char tmp_val[80];
-
- int out_index[23];
-
- byte out_color[23];
-
- char out_desc[23][80];
-
- int monst_num;
-
-
- /* Default length */
- len = 79 - 50;
-
- /* Maximum space allowed for descriptions */
- lim = 79 - 3;
-
- /* Require space for weight (if needed) */
- if (show_weights) lim -= 9;
-
- /* Scan for objects on the monster */
- (void)scan_monst(monst_list, &monst_num, m_idx);
-
- /* Display the p_ptr->inventory */
- for (k = 0, i = 0; i < monst_num; i++)
- {
- o_ptr = &o_list[monst_list[i]];
-
- /* Describe the object */
- object_desc(o_name, o_ptr, TRUE, 3);
-
- /* Hack -- enforce max length */
- o_name[lim] = '\0';
-
- /* Save the index */
- out_index[k] = i;
-
- /* Acquire p_ptr->inventory color */
- out_color[k] = tval_to_attr[o_ptr->tval & 0x7F];
-
- /* Save the object description */
- strcpy(out_desc[k], o_name);
-
- /* Find the predicted "line length" */
- l = strlen(out_desc[k]) + 5;
-
- /* Be sure to account for the weight */
- if (show_weights) l += 9;
-
- /* Maintain the maximum length */
- if (l > len) len = l;
-
- /* Advance to next "line" */
- k++;
- }
-
- /* Find the column to start in */
- col = (len > 76) ? 0 : (79 - len);
-
- /* Output each entry */
- for (j = 0; j < k; j++)
- {
- /* Get the index */
- i = monst_list[out_index[j]];
-
- /* Get the item */
- o_ptr = &o_list[i];
-
- /* Clear the line */
- prt("", j + 1, col ? col - 2 : col);
-
- /* Prepare an index --(-- */
- strnfmt(tmp_val, 80, "%c)", index_to_label(j));
-
- /* Clear the line with the (possibly indented) index */
- put_str(tmp_val, j + 1, col);
-
- /* Display the entry itself */
- c_put_str(out_color[j], out_desc[j], j + 1, col + 3);
-
- /* Display the weight if needed */
- if (show_weights)
- {
- int wgt = o_ptr->weight * o_ptr->number;
- strnfmt(tmp_val, 80, "%3d.%1d lb", wgt / 10, wgt % 10);
- put_str(tmp_val, j + 1, 71);
- }
- }
-
- /* Make a "shadow" below the list (only if needed) */
- if (j && (j < 23)) prt("", j + 1, col ? col - 2 : col);
-
- return monst_num;
-}
-
-
-/*
- * Steal an object from a monster
- */
-void do_cmd_steal()
-{
- int x, y, dir = 0, item = -1, k = -1;
-
- cave_type *c_ptr;
-
- monster_type *m_ptr;
-
- object_type *o_ptr, forge;
-
- byte num = 0;
-
- bool_ done = FALSE;
-
- int monst_list[23];
-
-
- /* Only works on adjacent monsters */
- if (!get_rep_dir(&dir)) return;
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
- c_ptr = &cave[y][x];
-
- if (!(c_ptr->m_idx))
- {
- msg_print("There is no monster there!");
- return;
- }
-
- m_ptr = &m_list[c_ptr->m_idx];
-
- /* There were no non-gold items */
- if (!m_ptr->hold_o_idx)
- {
- msg_print("That monster has no objects!");
- return;
- }
-
- /* The monster is immune */
- if (r_info[m_ptr->r_idx].flags7 & (RF7_NO_THEFT))
- {
- msg_print("The monster is guarding the treasures.");
- return;
- }
-
- screen_save();
-
- num = show_monster_inven(c_ptr->m_idx, monst_list);
-
- /* Repeat until done */
- while (!done)
- {
- char tmp_val[80];
- char which = ' ';
-
- /* Build the prompt */
- strnfmt(tmp_val, 80, "Choose an item to steal (a-%c) or ESC:",
- 'a' - 1 + num);
-
- /* Show the prompt */
- prt(tmp_val, 0, 0);
-
- /* Get a key */
- which = inkey();
-
- /* Parse it */
- switch (which)
- {
- case ESCAPE:
- {
- done = TRUE;
-
- break;
- }
-
- default:
- {
- int ver;
-
- /* Extract "query" setting */
- ver = isupper(which);
- which = tolower(which);
-
- k = islower(which) ? A2I(which) : -1;
- if (k < 0 || k >= num)
- {
- bell();
-
- break;
- }
-
- /* Verify the item */
- if (ver && !verify("Try", 0 - monst_list[k]))
- {
- done = TRUE;
-
- break;
- }
-
- /* Accept that choice */
- item = monst_list[k];
- done = TRUE;
-
- break;
- }
- }
- }
-
- if (item != -1)
- {
- int chance;
-
- chance = 40 - p_ptr->stat_ind[A_DEX];
- chance +=
- o_list[item].weight / (get_skill_scale(SKILL_STEALING, 19) + 1);
- chance += get_skill_scale(SKILL_STEALING, 29) + 1;
- chance -= (m_ptr->csleep) ? 10 : 0;
- chance += m_ptr->level;
-
- /* Failure check */
- if (rand_int(chance) > 1 + get_skill_scale(SKILL_STEALING, 25))
- {
- /* Take a turn */
- energy_use = 100;
-
- /* Wake up */
- m_ptr->csleep = 0;
-
- /* Speed up because monsters are ANGRY when you try to thief them */
- m_ptr->mspeed += 5;
-
- screen_load();
-
- msg_print("Oops! The monster is now really *ANGRY*!");
-
- return;
- }
-
- /* Reconnect the objects list */
- if (num == 1) m_ptr->hold_o_idx = 0;
- else
- {
- if (k > 0) o_list[monst_list[k - 1]].next_o_idx = monst_list[k + 1];
- if (k + 1 >= num) o_list[monst_list[k - 1]].next_o_idx = 0;
- if (k == 0) m_ptr->hold_o_idx = monst_list[k + 1];
- }
-
- /* Rogues gain some xp */
- if (PRACE_FLAGS(PR1_EASE_STEAL))
- {
- s32b max_point;
-
- /* Max XP gained from stealing */
- max_point = (o_list[item].weight / 2) + (m_ptr->level * 10);
-
- /* Randomise it a bit, with half a max guaranteed */
- gain_exp((max_point / 2) + (randint(max_point) / 2));
-
- /* Allow escape */
- if (get_check("Phase door?")) teleport_player(10);
- }
-
- /* Get the item */
- o_ptr = &forge;
-
- /* Special handling for gold */
- if (o_list[item].tval == TV_GOLD)
- {
- /* Collect the gold */
- p_ptr->au += o_list[item].pval;
-
- /* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
- }
- else
- {
- object_copy(o_ptr, &o_list[item]);
-
- inven_carry(o_ptr, FALSE);
- }
-
- /* Delete it */
- o_list[item].k_idx = 0;
- }
-
- screen_load();
-
- /* Take a turn */
- energy_use = 100;
-}
-
-
-/*
- * Give an item to a monster
- */
-void do_cmd_give()
-{
- int dir, x, y;
-
- cave_type *c_ptr;
-
- cptr q, s;
-
- int item;
-
-
- /* Get a "repeated" direction */
- if (!get_rep_dir(&dir)) return;
-
- /* Get requested location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get requested grid */
- c_ptr = &cave[y][x];
-
- /* No monster in the way */
- if (c_ptr->m_idx == 0)
- {
- msg_print("There is no monster there.");
- return;
- }
-
- /* Get an item */
- q = "What item do you want to offer? ";
- s = "You have nothing to offer.";
- if (!get_item(&item, q, s, USE_INVEN)) return;
-
- /* Process hooks if there are any */
- if (!process_hooks(HOOK_GIVE, "(d,d)", c_ptr->m_idx, item))
- {
- msg_print("The monster does not want your item.");
- }
-
- /* Take a turn, even if the offer is declined */
- energy_use = 100;
-}
-
-
-/*
- * Chat with a monster
- */
-void do_cmd_chat()
-{
- int dir, x, y;
-
- cave_type *c_ptr;
-
-
- /* Get a "repeated" direction */
- if (!get_rep_dir(&dir)) return;
-
- /* Get requested location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- /* Get requested grid */
- c_ptr = &cave[y][x];
-
- /* No monster in the way */
- if (c_ptr->m_idx == 0)
- {
- msg_print("There is no monster there.");
- return;
- }
-
- /* Process hook if there are any */
- if (!process_hooks(HOOK_CHAT, "(d)", c_ptr->m_idx))
- {
- msg_print("The monster does not want to chat.");
- }
-
- /* No energy spent */
-}