*/
#include "angband.h"
+#include "floor.h"
+#include "grid.h"
+#include "object-boost.h"
#include "object-hook.h"
#include "object-curse.h"
+#include "objectkind-hook.h"
#include "artifact.h"
#include "player-status.h"
#include "feature.h"
#include "player-move.h"
-
-static void one_sustain(object_type *o_ptr);
-
-/*!
- * @brief 対象のオブジェクトにランダムな能力維持を一つ付加する。/ Choose one random sustain
- * @details 重複の抑止はない。
- * @param o_ptr 対象のオブジェクト構造体ポインタ
- * @return なし
- */
-static void one_sustain(object_type *o_ptr)
-{
- switch (randint0(A_MAX))
- {
- case 0: add_flag(o_ptr->art_flags, TR_SUST_STR); break;
- case 1: add_flag(o_ptr->art_flags, TR_SUST_INT); break;
- case 2: add_flag(o_ptr->art_flags, TR_SUST_WIS); break;
- case 3: add_flag(o_ptr->art_flags, TR_SUST_DEX); break;
- case 4: add_flag(o_ptr->art_flags, TR_SUST_CON); break;
- case 5: add_flag(o_ptr->art_flags, TR_SUST_CHR); break;
- }
-}
+#include "monster.h"
+#include "monsterrace-hook.h"
/*!
* @brief 床上、モンスター所持でスタックされたアイテムを削除しスタックを補完する / Excise a dungeon object from any stacks
if (!(j_ptr->held_m_idx))
{
POSITION y, x;
-
y = j_ptr->iy;
x = j_ptr->ix;
-
- /* Visual update */
lite_spot(y, x);
}
object_wipe(j_ptr);
/* Objects are gone */
g_ptr->o_idx = 0;
- /* Visual update */
lite_spot(y, x);
}
/* Default */
table[i].prob3 = 0;
- /* Access the index */
k_idx = table[i].index;
/* Access the actual kind */
-/*!
- * @brief 破壊可能なアイテムかを返す /
- * Determines whether an object can be destroyed, and makes fake inscription.
- * @param o_ptr 破壊可能かを確認したいオブジェクトの構造体参照ポインタ
- * @return オブジェクトが破壊可能ならばTRUEを返す
- */
-bool can_player_destroy_object(object_type *o_ptr)
-{
- /* Artifacts cannot be destroyed */
- if (!object_is_artifact(o_ptr)) return TRUE;
-
- /* If object is unidentified, makes fake inscription */
- if (!object_is_known(o_ptr))
- {
- byte feel = FEEL_SPECIAL;
-
- /* Hack -- Handle icky artifacts */
- if (object_is_cursed(o_ptr) || object_is_broken(o_ptr)) feel = FEEL_TERRIBLE;
-
- /* Hack -- inscribe the artifact */
- o_ptr->feeling = feel;
-
- /* We have "felt" it (again) */
- o_ptr->ident |= (IDENT_SENSE);
- p_ptr->update |= (PU_COMBINE);
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
-
- return FALSE;
- }
-
- /* Identified artifact -- Nothing to do */
- return FALSE;
-}
-
/*!
* @brief 魔法棒やロッドのスロット分割時に使用回数を分配する /
/*!
- * @brief 上質以上のオブジェクトに与えるための各種ボーナスを正規乱数も加えて算出する。
- * Help determine an "enchantment bonus" for an object.
- * @param max ボーナス値の限度
- * @param level ボーナス値に加味する基準生成階
- * @return 算出されたボーナス値
- * @details
- * To avoid floating point but still provide a smooth distribution of bonuses,\n
- * we simply round the results of division in such a way as to "average" the\n
- * correct floating point value.\n
- *\n
- * This function has been changed. It uses "randnor()" to choose values from\n
- * a normal distribution, whose mean moves from zero towards the max as the\n
- * level increases, and whose standard deviation is equal to 1/4 of the max,\n
- * and whose values are forced to lie between zero and the max, inclusive.\n
- *\n
- * Since the "level" rarely passes 100 before Morgoth is dead, it is very\n
- * rare to get the "full" enchantment on an object, even a deep levels.\n
- *\n
- * It is always possible (albeit unlikely) to get the "full" enchantment.\n
- *\n
- * A sample distribution of values from "m_bonus(10, N)" is shown below:\n
- *\n
- * N 0 1 2 3 4 5 6 7 8 9 10\n
- * --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n
- * 0 66.37 13.01 9.73 5.47 2.89 1.31 0.72 0.26 0.12 0.09 0.03\n
- * 8 46.85 24.66 12.13 8.13 4.20 2.30 1.05 0.36 0.19 0.08 0.05\n
- * 16 30.12 27.62 18.52 10.52 6.34 3.52 1.95 0.90 0.31 0.15 0.05\n
- * 24 22.44 15.62 30.14 12.92 8.55 5.30 2.39 1.63 0.62 0.28 0.11\n
- * 32 16.23 11.43 23.01 22.31 11.19 7.18 4.46 2.13 1.20 0.45 0.41\n
- * 40 10.76 8.91 12.80 29.51 16.00 9.69 5.90 3.43 1.47 0.88 0.65\n
- * 48 7.28 6.81 10.51 18.27 27.57 11.76 7.85 4.99 2.80 1.22 0.94\n
- * 56 4.41 4.73 8.52 11.96 24.94 19.78 11.06 7.18 3.68 1.96 1.78\n
- * 64 2.81 3.07 5.65 9.17 13.01 31.57 13.70 9.30 6.04 3.04 2.64\n
- * 72 1.87 1.99 3.68 7.15 10.56 20.24 25.78 12.17 7.52 4.42 4.62\n
- * 80 1.02 1.23 2.78 4.75 8.37 12.04 27.61 18.07 10.28 6.52 7.33\n
- * 88 0.70 0.57 1.56 3.12 6.34 10.06 15.76 30.46 12.58 8.47 10.38\n
- * 96 0.27 0.60 1.25 2.28 4.30 7.60 10.77 22.52 22.51 11.37 16.53\n
- * 104 0.22 0.42 0.77 1.36 2.62 5.33 8.93 13.05 29.54 15.23 22.53\n
- * 112 0.15 0.20 0.56 0.87 2.00 3.83 6.86 10.06 17.89 27.31 30.27\n
- * 120 0.03 0.11 0.31 0.46 1.31 2.48 4.60 7.78 11.67 25.53 45.72\n
- * 128 0.02 0.01 0.13 0.33 0.83 1.41 3.24 6.17 9.57 14.22 64.07\n
- */
-int m_bonus(int max, DEPTH level)
-{
- int bonus, stand, extra, value;
-
-
- /* Paranoia -- enforce maximal "level" */
- if (level > MAX_DEPTH - 1) level = MAX_DEPTH - 1;
-
-
- /* The "bonus" moves towards the max */
- bonus = ((max * level) / MAX_DEPTH);
-
- /* Hack -- determine fraction of error */
- extra = ((max * level) % MAX_DEPTH);
-
- /* Hack -- simulate floating point computations */
- if (randint0(MAX_DEPTH) < extra) bonus++;
-
-
- /* The "stand" is equal to one quarter of the max */
- stand = (max / 4);
-
- /* Hack -- determine fraction of error */
- extra = (max % 4);
-
- /* Hack -- simulate floating point computations */
- if (randint0(4) < extra) stand++;
-
-
- /* Choose an "interesting" value */
- value = randnor(bonus, stand);
-
- /* Enforce the minimum value */
- if (value < 0) return (0);
-
- /* Enforce the maximum value */
- if (value > max) return (max);
- return (value);
-}
-
-
-/*!
* @brief デバッグ時にアイテム生成情報をメッセージに出力する / Cheat -- describe a created object for the user
* @param o_ptr デバッグ出力するオブジェクトの構造体参照ポインタ
* @return なし
* Hack -- note special base damage dice boosting\n
* Hack -- note special processing for weapon/digger\n
*/
-static void a_m_aux_1(object_type *o_ptr, DEPTH level, int power)
+void apply_magic_weapon(object_type *o_ptr, DEPTH level, int power)
{
HIT_PROB tohit1 = randint1(5) + (HIT_PROB)m_bonus(5, level);
HIT_POINT todam1 = randint1(5) + (HIT_POINT)m_bonus(5, level);
if ((o_ptr->tval == TV_BOLT) || (o_ptr->tval == TV_ARROW) || (o_ptr->tval == TV_SHOT))
{
- tohit2 = (tohit2+1)/2;
- todam2 = (todam2+1)/2;
+ tohit2 = (tohit2 + 1) / 2;
+ todam2 = (todam2 + 1) / 2;
}
/* Good */
if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DIAMOND_EDGE)) return;
- /* Analyze type */
switch (o_ptr->tval)
{
case TV_DIGGING:
break;
}
-
case TV_HAFTED:
case TV_POLEARM:
case TV_SWORD:
do
{
o_ptr->dd++;
- }
- while (one_in_(o_ptr->dd));
-
+ } while (one_in_(o_ptr->dd));
+
do
{
o_ptr->ds++;
- }
- while (one_in_(o_ptr->ds));
+ } while (one_in_(o_ptr->ds));
}
-
+
if (one_in_(5))
{
add_flag(o_ptr->art_flags, TR_BRAND_POIS);
add_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
break;
case EGO_DEMON:
-
- if(one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
- one_in_(3) ?
+
+ if (one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
+ one_in_(3) ?
add_flag(o_ptr->art_flags, TR_DRAIN_EXP) :
one_in_(2) ?
- add_flag(o_ptr->art_flags, TR_DRAIN_HP) :
- add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
-
-
+ add_flag(o_ptr->art_flags, TR_DRAIN_HP) :
+ add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
+
+
if (one_in_(3)) add_flag(o_ptr->art_flags, TR_CHAOTIC);
if (one_in_(4)) add_flag(o_ptr->art_flags, TR_BLOWS);
if (one_in_(5)) add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
/* Roll for ego-item */
if (randint0(MAX_DEPTH) < level)
{
- while(1)
+ while (1)
{
o_ptr->name2 = get_random_ego(INVEN_RARM, FALSE);
if (o_ptr->name2 == EGO_WEIRD && o_ptr->tval != TV_SWORD)
}
switch (o_ptr->name2)
{
- case EGO_MORGUL:
- if (one_in_(6)) add_flag(o_ptr->art_flags, TR_TY_CURSE);
- if (one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
- case EGO_WEIRD:
- if (one_in_(4)) add_flag(o_ptr->art_flags, TR_BRAND_POIS);
- if (one_in_(4)) add_flag(o_ptr->art_flags, TR_RES_NETHER);
- if (one_in_(3)) add_flag(o_ptr->art_flags, TR_NO_MAGIC);
- if (one_in_(6)) add_flag(o_ptr->art_flags, TR_NO_TELE);
- if (one_in_(6)) add_flag(o_ptr->art_flags, TR_TY_CURSE);
- if (one_in_(6)) add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
+ case EGO_MORGUL:
+ if (one_in_(6)) add_flag(o_ptr->art_flags, TR_TY_CURSE);
+ if (one_in_(3)) o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
+ break;
+ case EGO_WEIRD:
+ if (one_in_(4)) add_flag(o_ptr->art_flags, TR_BRAND_POIS);
+ if (one_in_(4)) add_flag(o_ptr->art_flags, TR_RES_NETHER);
+ if (one_in_(3)) add_flag(o_ptr->art_flags, TR_NO_MAGIC);
+ if (one_in_(6)) add_flag(o_ptr->art_flags, TR_NO_TELE);
+ if (one_in_(6)) add_flag(o_ptr->art_flags, TR_TY_CURSE);
+ if (one_in_(6)) add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
+ break;
}
}
}
}
/*!
- * @brief ドラゴン装備にランダムな耐性を与える
- * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
- * @return なし
- */
-static void dragon_resist(object_type * o_ptr)
-{
- do
- {
- if (one_in_(4))
- one_dragon_ele_resistance(o_ptr);
- else
- one_high_resistance(o_ptr);
- }
- while (one_in_(2));
-}
-
-/*!
- * @brief オブジェクトにランダムな強いESPを与える
- * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
- * @return なし
- */
-static bool add_esp_strong(object_type *o_ptr)
-{
- bool nonliv = FALSE;
-
- switch (randint1(3))
- {
- case 1: add_flag(o_ptr->art_flags, TR_ESP_EVIL); break;
- case 2: add_flag(o_ptr->art_flags, TR_TELEPATHY); break;
- case 3: add_flag(o_ptr->art_flags, TR_ESP_NONLIVING); nonliv = TRUE; break;
- }
-
- return nonliv;
-}
-
-/*!
- * @brief オブジェクトにランダムな弱いESPを与える
- * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
- * @param extra TRUEならばESPの最大付与数が増える(TRUE -> 3+1d6 / FALSE -> 1d3)
- * @return なし
- */
-static void add_esp_weak(object_type *o_ptr, bool extra)
-{
- int i;
- u32b weak_esp_list[] = {
- TR_ESP_ANIMAL,
- TR_ESP_UNDEAD,
- TR_ESP_DEMON,
- TR_ESP_ORC,
- TR_ESP_TROLL,
- TR_ESP_GIANT,
- TR_ESP_DRAGON,
- TR_ESP_HUMAN,
- TR_ESP_GOOD,
- TR_ESP_UNIQUE,
- };
- const int MAX_ESP_WEAK = sizeof(weak_esp_list) / sizeof(weak_esp_list[0]);
- const int add_count = MIN(MAX_ESP_WEAK, (extra) ? (3 + randint1(randint1(6))) : randint1(3));
-
- /* Add unduplicated weak esp flags randomly */
- for (i = 0; i < add_count; ++ i)
- {
- int choice = rand_range(i, MAX_ESP_WEAK - 1);
-
- add_flag(o_ptr->art_flags, weak_esp_list[choice]);
- weak_esp_list[choice] = weak_esp_list[i];
- }
-}
-
-
-/*!
* @brief 防具系オブジェクトに生成ランクごとの強化を与えるサブルーチン
* Apply magic to an item known to be "armor"
* @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
if (o_ptr->to_a < 0) o_ptr->curse_flags |= TRC_CURSED;
}
-
- /* Analyze type */
switch (o_ptr->tval)
{
case TV_DRAG_ARMOR:
}
}
-/*!
- * @brief モンスターが人形のベースにできるかを返す
- * @param r_idx チェックしたいモンスター種族のID
- * @return 人形にできるならTRUEを返す
- */
-static bool item_monster_okay(MONRACE_IDX r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* No uniques */
- if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
- if (r_ptr->flags7 & RF7_KAGE) return (FALSE);
- if (r_ptr->flagsr & RFR_RES_ALL) return (FALSE);
- if (r_ptr->flags7 & RF7_NAZGUL) return (FALSE);
- if (r_ptr->flags1 & RF1_FORCE_DEPTH) return (FALSE);
- if (r_ptr->flags7 & RF7_UNIQUE2) return (FALSE);
-
- return (TRUE);
-}
-
/*!
* @brief その他雑多のオブジェクトに生成ランクごとの強化を与えるサブルーチン
case TV_ARROW:
case TV_BOLT:
{
- if (power) a_m_aux_1(o_ptr, lev, power);
+ if (power) apply_magic_weapon(o_ptr, lev, power);
break;
}
case TV_POLEARM:
{
- if (power && !(o_ptr->sval == SV_DEATH_SCYTHE)) a_m_aux_1(o_ptr, lev, power);
+ if (power && !(o_ptr->sval == SV_DEATH_SCYTHE)) apply_magic_weapon(o_ptr, lev, power);
break;
}
case TV_SWORD:
{
- if (power && !(o_ptr->sval == SV_DOKUBARI)) a_m_aux_1(o_ptr, lev, power);
+ if (power && !(o_ptr->sval == SV_DOKUBARI)) apply_magic_weapon(o_ptr, lev, power);
break;
}
/*!
- * @brief ベースアイテムが上質として扱われるかどうかを返す。
- * Hack -- determine if a template is "good"
- * @param k_idx 判定したいベースアイテムのID
- * @return ベースアイテムが上質ならばTRUEを返す。
- */
-static bool kind_is_good(KIND_OBJECT_IDX k_idx)
-{
- object_kind *k_ptr = &k_info[k_idx];
-
- /* Analyze the item type */
- switch (k_ptr->tval)
- {
- /* Armor -- Good unless damaged */
- case TV_HARD_ARMOR:
- case TV_SOFT_ARMOR:
- case TV_DRAG_ARMOR:
- case TV_SHIELD:
- case TV_CLOAK:
- case TV_BOOTS:
- case TV_GLOVES:
- case TV_HELM:
- case TV_CROWN:
- {
- if (k_ptr->to_a < 0) return (FALSE);
- return (TRUE);
- }
-
- /* Weapons -- Good unless damaged */
- case TV_BOW:
- case TV_SWORD:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_DIGGING:
- {
- if (k_ptr->to_h < 0) return (FALSE);
- if (k_ptr->to_d < 0) return (FALSE);
- return (TRUE);
- }
-
- /* Ammo -- Arrows/Bolts are good */
- case TV_BOLT:
- case TV_ARROW:
- {
- return (TRUE);
- }
-
- /* Books -- High level books are good (except Arcane books) */
- case TV_LIFE_BOOK:
- case TV_SORCERY_BOOK:
- case TV_NATURE_BOOK:
- case TV_CHAOS_BOOK:
- case TV_DEATH_BOOK:
- case TV_TRUMP_BOOK:
- case TV_CRAFT_BOOK:
- case TV_DAEMON_BOOK:
- case TV_CRUSADE_BOOK:
- case TV_MUSIC_BOOK:
- case TV_HISSATSU_BOOK:
- case TV_HEX_BOOK:
- {
- if (k_ptr->sval >= SV_BOOK_MIN_GOOD) return (TRUE);
- return (FALSE);
- }
-
- /* Rings -- Rings of Speed are good */
- case TV_RING:
- {
- if (k_ptr->sval == SV_RING_SPEED) return (TRUE);
- if (k_ptr->sval == SV_RING_LORDLY) return (TRUE);
- return (FALSE);
- }
-
- /* Amulets -- Amulets of the Magi and Resistance are good */
- case TV_AMULET:
- {
- if (k_ptr->sval == SV_AMULET_THE_MAGI) return (TRUE);
- if (k_ptr->sval == SV_AMULET_RESISTANCE) return (TRUE);
- return (FALSE);
- }
- }
-
- /* Assume not good */
- return (FALSE);
-}
-
-/*!
* @brief 生成階に応じたベースアイテムの生成を行う。
* Attempt to make an object (normal or good/great)
* @param j_ptr 生成結果を収めたいオブジェクト構造体の参照ポインタ
/* Build a stack */
o_ptr->next_o_idx = g_ptr->o_idx;
- /* Place the object */
g_ptr->o_idx = o_idx;
-
note_spot(y, x);
-
lite_spot(y, x);
}
else
/* Build a stack */
o_ptr->next_o_idx = g_ptr->o_idx;
- /* Place the object */
g_ptr->o_idx = o_idx;
-
note_spot(y, x);
-
lite_spot(y, x);
}
}
#else
msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
#endif
- /* Debug */
if (p_ptr->wizard) msg_print(_("(破損)", "(breakage)"));
/* Failure */
/* Add new object */
if (!comb) k++;
-
- /* Paranoia */
if (k > 99) continue;
/* Calculate score */
msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
#endif
-
- /* Debug */
if (p_ptr->wizard) msg_print(_("(床スペースがない)", "(no floor space)"));
/* Failure */
ty = rand_spread(by, 1);
tx = rand_spread(bx, 1);
- /* Verify location */
if (!in_bounds(ty, tx)) continue;
/* Bounce to that location */
msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
#endif
- /* Debug */
if (p_ptr->wizard) msg_print(_("(床スペースがない)", "(no floor space)"));
/* Mega-Hack -- preserve artifacts */
msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
#endif
- /* Debug */
if (p_ptr->wizard) msg_print(_("(アイテムが多過ぎる)", "(too many objects)"));
/* Hack -- Preserve artifacts */
/* Build a stack */
j_ptr->next_o_idx = g_ptr->o_idx;
- /* Place the object */
g_ptr->o_idx = o_idx;
/* Success */
/* Add the weight */
p_ptr->total_weight += (num * o_ptr->weight);
p_ptr->update |= (PU_BONUS);
-
- /* Recalculate mana XXX */
p_ptr->update |= (PU_MANA);
p_ptr->update |= (PU_COMBINE);
p_ptr->window |= (PW_INVEN | PW_EQUIP);
/* Erase the empty slot */
object_wipe(&inventory[item]);
p_ptr->update |= (PU_BONUS);
-
p_ptr->update |= (PU_TORCH);
-
- /* Recalculate mana XXX */
p_ptr->update |= (PU_MANA);
p_ptr->window |= (PW_EQUIP);
}
}
-
- /* Paranoia */
if (inven_cnt > INVEN_PACK) return (-1);
/* Find an empty slot */
/* Get the item to take off */
o_ptr = &inventory[item];
-
- /* Paranoia */
if (amt <= 0) return (-1);
/* Verify */
}
}
-/*!
- * @brief 警告を放つアイテムを選択する /
- * Choose one of items that have warning flag
- * Calculate spell damages
- * @return 警告を行う
- */
-object_type *choose_warning_item(void)
-{
- int i;
- int choices[INVEN_TOTAL - INVEN_RARM];
- int number = 0;
-
- /* Paranoia -- Player has no warning ability */
- if (!p_ptr->warning) return NULL;
-
- /* Search Inventory */
- for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
- {
- BIT_FLAGS flgs[TR_FLAG_SIZE];
- object_type *o_ptr = &inventory[i];
-
- object_flags(o_ptr, flgs);
- if (have_flag(flgs, TR_WARNING))
- {
- choices[number] = i;
- number++;
- }
- }
-
- /* Choice one of them */
- return number ? &inventory[choices[randint0(number)]] : NULL;
-}
-
-/*!
- * @brief 警告基準を定めるために魔法の効果属性に基づいて最大魔法ダメージを計算する /
- * Calculate spell damages
- * @param m_ptr 魔法を行使するモンスターの構造体参照ポインタ
- * @param typ 効果属性のID
- * @param dam 基本ダメージ
- * @param max 算出した最大ダメージを返すポインタ
- * @return なし
- */
-static void spell_damcalc(monster_type *m_ptr, EFFECT_ID typ, HIT_POINT dam, int *max)
-{
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- int rlev = r_ptr->level;
- bool ignore_wraith_form = FALSE;
-
- /* Vulnerability, resistance and immunity */
- switch (typ)
- {
- case GF_ELEC:
- if (p_ptr->immune_elec)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else
- {
- if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
- if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
- if (prace_is_(RACE_ANDROID)) dam += dam / 3;
- if (p_ptr->resist_elec) dam = (dam + 2) / 3;
- if (IS_OPPOSE_ELEC())
- dam = (dam + 2) / 3;
- }
- break;
-
- case GF_POIS:
- if (p_ptr->resist_pois) dam = (dam + 2) / 3;
- if (IS_OPPOSE_POIS()) dam = (dam + 2) / 3;
- break;
-
- case GF_ACID:
- if (p_ptr->immune_acid)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else
- {
- if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
- if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
- if (p_ptr->resist_acid) dam = (dam + 2) / 3;
- if (IS_OPPOSE_ACID()) dam = (dam + 2) / 3;
- }
- break;
-
- case GF_COLD:
- case GF_ICE:
- if (p_ptr->immune_cold)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else
- {
- if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
- if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
- if (p_ptr->resist_cold) dam = (dam + 2) / 3;
- if (IS_OPPOSE_COLD()) dam = (dam + 2) / 3;
- }
- break;
-
- case GF_FIRE:
- if (p_ptr->immune_fire)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else
- {
- if (p_ptr->muta3 & MUT3_VULN_ELEM) dam *= 2;
- if (prace_is_(RACE_ENT)) dam += dam / 3;
- if (p_ptr->special_defense & KATA_KOUKIJIN) dam += dam / 3;
- if (p_ptr->resist_fire) dam = (dam + 2) / 3;
- if (IS_OPPOSE_FIRE()) dam = (dam + 2) / 3;
- }
- break;
-
- case GF_PSY_SPEAR:
- ignore_wraith_form = TRUE;
- break;
-
- case GF_ARROW:
- if (!p_ptr->blind &&
- ((inventory[INVEN_RARM].k_idx && (inventory[INVEN_RARM].name1 == ART_ZANTETSU)) ||
- (inventory[INVEN_LARM].k_idx && (inventory[INVEN_LARM].name1 == ART_ZANTETSU))))
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- break;
-
- case GF_LITE:
- if (p_ptr->resist_lite) dam /= 2; /* Worst case of 4 / (d4 + 7) */
- if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE)) dam *= 2;
- else if (prace_is_(RACE_S_FAIRY)) dam = dam * 4 / 3;
-
- /*
- * Cannot use "ignore_wraith_form" strictly (for "random one damage")
- * "dam *= 2;" for later "dam /= 2"
- */
- if (p_ptr->wraith_form) dam *= 2;
- break;
-
- case GF_DARK:
- if (prace_is_(RACE_VAMPIRE) || (p_ptr->mimic_form == MIMIC_VAMPIRE) || p_ptr->wraith_form)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else if (p_ptr->resist_dark) dam /= 2; /* Worst case of 4 / (d4 + 7) */
- break;
-
- case GF_SHARDS:
- if (p_ptr->resist_shard) dam = dam * 3 / 4; /* Worst case of 6 / (d4 + 7) */
- break;
-
- case GF_SOUND:
- if (p_ptr->resist_sound) dam = dam * 5 / 8; /* Worst case of 5 / (d4 + 7) */
- break;
-
- case GF_CONFUSION:
- if (p_ptr->resist_conf) dam = dam * 5 / 8; /* Worst case of 5 / (d4 + 7) */
- break;
-
- case GF_CHAOS:
- if (p_ptr->resist_chaos) dam = dam * 3 / 4; /* Worst case of 6 / (d4 + 7) */
- break;
-
- case GF_NETHER:
- if (prace_is_(RACE_SPECTRE))
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- else if (p_ptr->resist_neth) dam = dam * 3 / 4; /* Worst case of 6 / (d4 + 7) */
- break;
-
- case GF_DISENCHANT:
- if (p_ptr->resist_disen) dam = dam * 3 / 4; /* Worst case of 6 / (d4 + 7) */
- break;
-
- case GF_NEXUS:
- if (p_ptr->resist_nexus) dam = dam * 3 / 4; /* Worst case of 6 / (d4 + 7) */
- break;
-
- case GF_TIME:
- if (p_ptr->resist_time) dam /= 2; /* Worst case of 4 / (d4 + 7) */
- break;
-
- case GF_GRAVITY:
- if (p_ptr->levitation) dam = (dam * 2) / 3;
- break;
-
- case GF_ROCKET:
- if (p_ptr->resist_shard) dam /= 2;
- break;
-
- case GF_NUKE:
- if (p_ptr->resist_pois) dam = (2 * dam + 2) / 5;
- if (IS_OPPOSE_POIS()) dam = (2 * dam + 2) / 5;
- break;
-
- case GF_DEATH_RAY:
- if (p_ptr->mimic_form)
- {
- if (mimic_info[p_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- }
- else
- {
- switch (p_ptr->prace)
- {
- case RACE_GOLEM:
- case RACE_SKELETON:
- case RACE_ZOMBIE:
- case RACE_VAMPIRE:
- case RACE_DEMON:
- case RACE_SPECTRE:
- dam = 0;
- ignore_wraith_form = TRUE;
- break;
- }
- }
- break;
-
- case GF_HOLY_FIRE:
- if (p_ptr->align > 10) dam /= 2;
- else if (p_ptr->align < -10) dam *= 2;
- break;
-
- case GF_HELL_FIRE:
- if (p_ptr->align > 10) dam *= 2;
- break;
-
- case GF_MIND_BLAST:
- case GF_BRAIN_SMASH:
- if (100 + rlev / 2 <= MAX(5, p_ptr->skill_sav))
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- break;
-
- case GF_CAUSE_1:
- case GF_CAUSE_2:
- case GF_CAUSE_3:
- case GF_HAND_DOOM:
- if (100 + rlev / 2 <= p_ptr->skill_sav)
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- break;
-
- case GF_CAUSE_4:
- if ((100 + rlev / 2 <= p_ptr->skill_sav) && (m_ptr->r_idx != MON_KENSHIROU))
- {
- dam = 0;
- ignore_wraith_form = TRUE;
- }
- break;
- }
-
- if (p_ptr->wraith_form && !ignore_wraith_form)
- {
- dam /= 2;
- if (!dam) dam = 1;
- }
-
- if (dam > *max) *max = dam;
-}
-
-/*!
-* @brief 警告基準を定めるために魔法の効果属性に基づいて最大魔法ダメージを計算する。 /
-* Calculate spell damages
-* @param spell_num RF4ならRF4_SPELL_STARTのように32区切りのベースとなる数値
-* @param typ 効果属性のID
-* @param m_idx 魔法を行使するモンスターのID
-* @param max 算出した最大ダメージを返すポインタ
-* @return なし
-*/
-void spell_damcalc_by_spellnum(int spell_num, EFFECT_ID typ, MONSTER_IDX m_idx, int *max)
-{
- monster_type *m_ptr = ¤t_floor_ptr->m_list[m_idx];
- HIT_POINT dam = monspell_damage((spell_num), m_idx, DAM_MAX);
- spell_damcalc(m_ptr, typ, dam, max);
-}
-
-/*!
- * @brief 警告基準を定めるためにモンスターの打撃最大ダメージを算出する /
- * Calculate blow damages
- * @param m_ptr 打撃を行使するモンスターの構造体参照ポインタ
- * @param blow_ptr モンスターの打撃能力の構造体参照ポインタ
- * @return 算出された最大ダメージを返す。
- */
-static int blow_damcalc(monster_type *m_ptr, monster_blow *blow_ptr)
-{
- int dam = blow_ptr->d_dice * blow_ptr->d_side;
- int dummy_max = 0;
- bool check_wraith_form = TRUE;
-
- if (blow_ptr->method != RBM_EXPLODE)
- {
- ARMOUR_CLASS ac = p_ptr->ac + p_ptr->to_a;
-
- switch (blow_ptr->effect)
- {
- case RBE_SUPERHURT:
- {
- int tmp_dam = dam - (dam * ((ac < 150) ? ac : 150) / 250);
- dam = MAX(dam, tmp_dam * 2);
- break;
- }
-
- case RBE_HURT:
- case RBE_SHATTER:
- dam -= (dam * ((ac < 150) ? ac : 150) / 250);
- break;
-
- case RBE_ACID:
- spell_damcalc(m_ptr, GF_ACID, dam, &dummy_max);
- dam = dummy_max;
- check_wraith_form = FALSE;
- break;
-
- case RBE_ELEC:
- spell_damcalc(m_ptr, GF_ELEC, dam, &dummy_max);
- dam = dummy_max;
- check_wraith_form = FALSE;
- break;
-
- case RBE_FIRE:
- spell_damcalc(m_ptr, GF_FIRE, dam, &dummy_max);
- dam = dummy_max;
- check_wraith_form = FALSE;
- break;
-
- case RBE_COLD:
- spell_damcalc(m_ptr, GF_COLD, dam, &dummy_max);
- dam = dummy_max;
- check_wraith_form = FALSE;
- break;
-
- case RBE_DR_MANA:
- dam = 0;
- check_wraith_form = FALSE;
- break;
- }
-
- if (check_wraith_form && p_ptr->wraith_form)
- {
- dam /= 2;
- if (!dam) dam = 1;
- }
- }
- else
- {
- dam = (dam + 1) / 2;
- spell_damcalc(m_ptr, mbe_info[blow_ptr->effect].explode_type, dam, &dummy_max);
- dam = dummy_max;
- }
-
- return dam;
-}
-
-/*!
- * @brief プレイヤーが特定地点へ移動した場合に警告を発する処理 /
- * Examine the grid (xx,yy) and warn the player if there are any danger
- * @param xx 危険性を調査するマスのX座標
- * @param yy 危険性を調査するマスのY座標
- * @return 警告を無視して進むことを選択するかか問題が無ければTRUE、警告に従ったならFALSEを返す。
- */
-bool process_warning(POSITION xx, POSITION yy)
-{
- POSITION mx, my;
- grid_type *g_ptr;
- GAME_TEXT o_name[MAX_NLEN];
-
-#define WARNING_AWARE_RANGE 12
- int dam_max = 0;
- static int old_damage = 0;
-
- for (mx = xx - WARNING_AWARE_RANGE; mx < xx + WARNING_AWARE_RANGE + 1; mx++)
- {
- for (my = yy - WARNING_AWARE_RANGE; my < yy + WARNING_AWARE_RANGE + 1; my++)
- {
- int dam_max0 = 0;
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- if (!in_bounds(my, mx) || (distance(my, mx, yy, xx) > WARNING_AWARE_RANGE)) continue;
-
- g_ptr = ¤t_floor_ptr->grid_array[my][mx];
-
- if (!g_ptr->m_idx) continue;
-
- m_ptr = ¤t_floor_ptr->m_list[g_ptr->m_idx];
-
- if (MON_CSLEEP(m_ptr)) continue;
- if (!is_hostile(m_ptr)) continue;
-
- r_ptr = &r_info[m_ptr->r_idx];
-
- /* Monster spells (only powerful ones)*/
- if (projectable(my, mx, yy, xx))
- {
- BIT_FLAGS f4 = r_ptr->flags4;
- BIT_FLAGS f5 = r_ptr->a_ability_flags1;
- BIT_FLAGS f6 = r_ptr->a_ability_flags2;
-
- if (!(d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC))
- {
- if (f4 & RF4_BA_CHAO) spell_damcalc_by_spellnum(MS_BALL_CHAOS, GF_CHAOS, g_ptr->m_idx, &dam_max0);
- if (f5 & RF5_BA_MANA) spell_damcalc_by_spellnum(MS_BALL_MANA, GF_MANA, g_ptr->m_idx, &dam_max0);
- if (f5 & RF5_BA_DARK) spell_damcalc_by_spellnum(MS_BALL_DARK, GF_DARK, g_ptr->m_idx, &dam_max0);
- if (f5 & RF5_BA_LITE) spell_damcalc_by_spellnum(MS_STARBURST, GF_LITE, g_ptr->m_idx, &dam_max0);
- if (f6 & RF6_HAND_DOOM) spell_damcalc_by_spellnum(MS_HAND_DOOM, GF_HAND_DOOM, g_ptr->m_idx, &dam_max0);
- if (f6 & RF6_PSY_SPEAR) spell_damcalc_by_spellnum(MS_PSY_SPEAR, GF_PSY_SPEAR, g_ptr->m_idx, &dam_max0);
- }
- if (f4 & RF4_ROCKET) spell_damcalc_by_spellnum(MS_ROCKET, GF_ROCKET, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_ACID) spell_damcalc_by_spellnum(MS_BR_ACID, GF_ACID, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_ELEC) spell_damcalc_by_spellnum(MS_BR_ELEC, GF_ELEC, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_FIRE) spell_damcalc_by_spellnum(MS_BR_FIRE, GF_FIRE, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_COLD) spell_damcalc_by_spellnum(MS_BR_COLD, GF_COLD, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_POIS) spell_damcalc_by_spellnum(MS_BR_POIS, GF_POIS, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_NETH) spell_damcalc_by_spellnum(MS_BR_NETHER, GF_NETHER, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_LITE) spell_damcalc_by_spellnum(MS_BR_LITE, GF_LITE, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_DARK) spell_damcalc_by_spellnum(MS_BR_DARK, GF_DARK, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_CONF) spell_damcalc_by_spellnum(MS_BR_CONF, GF_CONFUSION, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_SOUN) spell_damcalc_by_spellnum(MS_BR_SOUND, GF_SOUND, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_CHAO) spell_damcalc_by_spellnum(MS_BR_CHAOS, GF_CHAOS, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_DISE) spell_damcalc_by_spellnum(MS_BR_DISEN, GF_DISENCHANT, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_NEXU) spell_damcalc_by_spellnum(MS_BR_NEXUS, GF_NEXUS, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_TIME) spell_damcalc_by_spellnum(MS_BR_TIME, GF_TIME, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_INER) spell_damcalc_by_spellnum(MS_BR_INERTIA, GF_INERTIAL, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_GRAV) spell_damcalc_by_spellnum(MS_BR_GRAVITY, GF_GRAVITY, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_SHAR) spell_damcalc_by_spellnum(MS_BR_SHARDS, GF_SHARDS, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_PLAS) spell_damcalc_by_spellnum(MS_BR_PLASMA, GF_PLASMA, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_WALL) spell_damcalc_by_spellnum(MS_BR_FORCE, GF_FORCE, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_MANA) spell_damcalc_by_spellnum(MS_BR_MANA, GF_MANA, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_NUKE) spell_damcalc_by_spellnum(MS_BR_NUKE, GF_NUKE, g_ptr->m_idx, &dam_max0);
- if (f4 & RF4_BR_DISI) spell_damcalc_by_spellnum(MS_BR_DISI, GF_DISINTEGRATE, g_ptr->m_idx, &dam_max0);
- }
-
- /* Monster melee attacks */
- if (!(r_ptr->flags1 & RF1_NEVER_BLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_MELEE))
- {
- if (mx <= xx + 1 && mx >= xx - 1 && my <= yy + 1 && my >= yy - 1)
- {
- int m;
- int dam_melee = 0;
- for (m = 0; m < 4; m++)
- {
- /* Skip non-attacks */
- if (!r_ptr->blow[m].method || (r_ptr->blow[m].method == RBM_SHOOT)) continue;
-
- /* Extract the attack info */
- dam_melee += blow_damcalc(m_ptr, &r_ptr->blow[m]);
- if (r_ptr->blow[m].method == RBM_EXPLODE) break;
- }
- if (dam_melee > dam_max0) dam_max0 = dam_melee;
- }
- }
-
- /* Contribution from this monster */
- dam_max += dam_max0;
- }
- }
-
- /* Prevent excessive warning */
- if (dam_max > old_damage)
- {
- old_damage = dam_max * 3 / 2;
-
- if (dam_max > p_ptr->chp / 2)
- {
- object_type *o_ptr = choose_warning_item();
-
- if (o_ptr)
- object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
- else
- strcpy(o_name, _("体", "body")); /* Warning ability without item */
- msg_format(_("%sが鋭く震えた!", "Your %s pulsates sharply!"), o_name);
-
- disturb(FALSE, TRUE);
- return get_check(_("本当にこのまま進むか?", "Really want to go ahead? "));
- }
- }
- else old_damage = old_damage / 2;
-
- g_ptr = ¤t_floor_ptr->grid_array[yy][xx];
- if (((!easy_disarm && is_trap(g_ptr->feat))
- || (g_ptr->mimic && is_trap(g_ptr->feat))) && !one_in_(13))
- {
- object_type *o_ptr = choose_warning_item();
-
- if (o_ptr)
- object_desc(o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
- else
- strcpy(o_name, _("体", "body")); /* Warning ability without item */
- msg_format(_("%sが鋭く震えた!", "Your %s pulsates sharply!"), o_name);
- disturb(FALSE, TRUE);
- return get_check(_("本当にこのまま進むか?", "Really want to go ahead? "));
- }
-
- return TRUE;
-}
-
/*!
* @brief 投擲時たいまつに投げやすい/焼棄/アンデッドスレイの特別効果を返す。