OSDN Git Service

93becd27d270fa78dbff59ea4f02034b10ed0f37
[hengbandforosx/hengbandosx.git] / src / lore / lore-calculator.cpp
1 #include "lore/lore-calculator.h"
2 #include "game-option/cheat-options.h"
3 #include "lore/lore-util.h"
4 #include "monster-race/monster-race.h"
5 #include "monster-race/race-ability-flags.h"
6 #include "monster-race/race-flags1.h"
7 #include "mspell/mspell-damage-calculator.h"
8 #include "system/monster-race-info.h"
9 #include "system/player-type-definition.h"
10
11 /*!
12  * @brief ダイス目を文字列に変換する
13  * @param base_damage 固定値
14  * @param dice_num ダイス数
15  * @param dice_side ダイス面
16  * @param dice_mult ダイス倍率
17  * @param dice_div ダイス除数
18  * @param msg 文字列を格納するポインタ
19  */
20 void dice_to_string(int base_damage, int dice_num, int dice_side, int dice_mult, int dice_div, char *msg)
21 {
22     char base[80] = "", dice[80] = "", mult[80] = "";
23
24     if (dice_num == 0) {
25         sprintf(msg, "%d", base_damage);
26         return;
27     }
28
29     if (base_damage != 0) {
30         sprintf(base, "%d+", base_damage);
31     }
32
33     if (dice_num == 1) {
34         sprintf(dice, "d%d", dice_side);
35     } else {
36         sprintf(dice, "%dd%d", dice_num, dice_side);
37     }
38
39     if (dice_mult != 1 || dice_div != 1) {
40         if (dice_div == 1) {
41             sprintf(mult, "*%d", dice_mult);
42         } else {
43             sprintf(mult, "*(%d/%d)", dice_mult, dice_div);
44         }
45     }
46
47     sprintf(msg, "%s%s%s", base, dice, mult);
48 }
49
50 /*!
51  * @brief モンスターのAC情報を得ることができるかを返す / Determine if the "armor" is known
52  * @param r_idx モンスターの種族ID
53  * @param know_everything 全知フラグ。TRUEを渡すとTRUEが返る。
54  * @return 敵のACを知る条件が満たされているならTRUEを返す
55  * @details
56  * The higher the level, the fewer kills needed.
57  */
58 bool know_armour(MonsterRaceId r_idx, const bool know_everything)
59 {
60     auto *r_ptr = &monraces_info[r_idx];
61     DEPTH level = r_ptr->level;
62     MONSTER_NUMBER kills = r_ptr->r_tkills;
63
64     bool known = r_ptr->r_cast_spell == MAX_UCHAR;
65
66     if (know_everything || known) {
67         return true;
68     }
69     if (kills > 304 / (4 + level)) {
70         return true;
71     }
72     if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
73         return false;
74     }
75     if (kills > 304 / (38 + (5 * level) / 4)) {
76         return true;
77     }
78     return false;
79 }
80
81 /*!
82  * @brief モンスターの打撃威力を知ることができるかどうかを返す
83  * Determine if the "damage" of the given attack is known
84  * @param r_idx モンスターの種族ID
85  * @param i 確認したい攻撃手番
86  * @return 敵のダメージダイスを知る条件が満たされているならTRUEを返す
87  * @details
88  * <pre>
89  * the higher the level of the monster, the fewer the attacks you need,
90  * the more damage an attack does, the more attacks you need
91  * </pre>
92  */
93 bool know_damage(MonsterRaceId r_idx, int i)
94 {
95     auto *r_ptr = &monraces_info[r_idx];
96     DEPTH level = r_ptr->level;
97     int32_t a = r_ptr->r_blows[i];
98
99     int32_t d1 = r_ptr->blow[i].d_dice;
100     int32_t d2 = r_ptr->blow[i].d_side;
101     int32_t d = d1 * d2;
102
103     if (d >= ((4 + level) * MAX_UCHAR) / 80) {
104         d = ((4 + level) * MAX_UCHAR - 1) / 80;
105     }
106     if ((4 + level) * a > 80 * d) {
107         return true;
108     }
109     if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
110         return false;
111     }
112     if ((4 + level) * (2 * a) > 80 * d) {
113         return true;
114     }
115
116     return false;
117 }
118
119 /*!
120  * @brief 文字列にモンスターの攻撃力を加える
121  * @param r_idx モンスターの種族ID
122  * @param SPELL_NUM 呪文番号
123  * @param msg 表示する文字列
124  */
125 void set_damage(PlayerType *player_ptr, lore_type *lore_ptr, MonsterAbilityType ms_type, concptr msg)
126 {
127     MonsterRaceId r_idx = lore_ptr->r_idx;
128     int base_damage = monspell_race_damage(player_ptr, ms_type, r_idx, BASE_DAM);
129     int dice_num = monspell_race_damage(player_ptr, ms_type, r_idx, DICE_NUM);
130     int dice_side = monspell_race_damage(player_ptr, ms_type, r_idx, DICE_SIDE);
131     int dice_mult = monspell_race_damage(player_ptr, ms_type, r_idx, DICE_MULT);
132     int dice_div = monspell_race_damage(player_ptr, ms_type, r_idx, DICE_DIV);
133     char dmg_str[80], dice_str[sizeof(dmg_str) + 10];
134     char *tmp = lore_ptr->tmp_msg[lore_ptr->vn];
135     dice_to_string(base_damage, dice_num, dice_side, dice_mult, dice_div, dmg_str);
136     sprintf(dice_str, "(%s)", dmg_str);
137
138     if (know_armour(r_idx, lore_ptr->know_everything)) {
139         sprintf(tmp, msg, dice_str);
140     } else {
141         sprintf(tmp, msg, "");
142     }
143 }
144
145 void set_drop_flags(lore_type *lore_ptr)
146 {
147     if (!lore_ptr->know_everything) {
148         return;
149     }
150
151     lore_ptr->drop_gold = lore_ptr->drop_item = ((lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_4D2) ? 8 : 0) + (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_3D2) ? 6 : 0) + (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_2D2) ? 4 : 0) + (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_1D2) ? 2 : 0) + (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_90) ? 1 : 0) + (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::DROP_60) ? 1 : 0));
152
153     if (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::ONLY_GOLD)) {
154         lore_ptr->drop_item = 0;
155     }
156
157     if (lore_ptr->r_ptr->drop_flags.has(MonsterDropType::ONLY_ITEM)) {
158         lore_ptr->drop_gold = 0;
159     }
160
161     lore_ptr->flags1 = lore_ptr->r_ptr->flags1;
162     lore_ptr->flags2 = lore_ptr->r_ptr->flags2;
163     lore_ptr->flags3 = lore_ptr->r_ptr->flags3;
164     lore_ptr->ability_flags = lore_ptr->r_ptr->ability_flags;
165     lore_ptr->aura_flags = lore_ptr->r_ptr->aura_flags;
166     lore_ptr->behavior_flags = lore_ptr->r_ptr->behavior_flags;
167     lore_ptr->resistance_flags = lore_ptr->r_ptr->resistance_flags;
168     lore_ptr->feature_flags = lore_ptr->r_ptr->feature_flags;
169 }