OSDN Git Service

[Refactor] #40569 Separated floor-type-definition.h from floor.h
[hengband/hengband.git] / src / object-enchant / object-boost.c
1 #include "object-enchant/object-boost.h"
2 #include "art-definition/random-art-effects.h"
3 #include "object-enchant/tr-types.h"
4 #include "system/floor-type-definition.h"
5 #include "system/object-type-definition.h"
6 #include "util/bit-flags-calculator.h"
7
8 /*!
9  * @brief 上質以上のオブジェクトに与えるための各種ボーナスを正規乱数も加えて算出する。
10  * Help determine an "enchantment bonus" for an object.
11  * @param max ボーナス値の限度
12  * @param level ボーナス値に加味する基準生成階
13  * @return 算出されたボーナス値
14  * @details
15  * To avoid floating point but still provide a smooth distribution of bonuses,\n
16  * we simply round the results of division in such a way as to "average" the\n
17  * correct floating point value.\n
18  *\n
19  * This function has been changed.  It uses "randnor()" to choose values from\n
20  * a normal distribution, whose mean moves from zero towards the max as the\n
21  * level increases, and whose standard deviation is equal to 1/4 of the max,\n
22  * and whose values are forced to lie between zero and the max, inclusive.\n
23  *\n
24  * Since the "level" rarely passes 100 before Morgoth is dead, it is very\n
25  * rare to get the "full" enchantment on an object, even a deep levels.\n
26  *\n
27  * It is always possible (albeit unlikely) to get the "full" enchantment.\n
28  *\n
29  * A sample distribution of values from "m_bonus(10, N)" is shown below:\n
30  *\n
31  *   N       0     1     2     3     4     5     6     7     8     9    10\n
32  * ---    ----  ----  ----  ----  ----  ----  ----  ----  ----  ----  ----\n
33  *   0   66.37 13.01  9.73  5.47  2.89  1.31  0.72  0.26  0.12  0.09  0.03\n
34  *   8   46.85 24.66 12.13  8.13  4.20  2.30  1.05  0.36  0.19  0.08  0.05\n
35  *  16   30.12 27.62 18.52 10.52  6.34  3.52  1.95  0.90  0.31  0.15  0.05\n
36  *  24   22.44 15.62 30.14 12.92  8.55  5.30  2.39  1.63  0.62  0.28  0.11\n
37  *  32   16.23 11.43 23.01 22.31 11.19  7.18  4.46  2.13  1.20  0.45  0.41\n
38  *  40   10.76  8.91 12.80 29.51 16.00  9.69  5.90  3.43  1.47  0.88  0.65\n
39  *  48    7.28  6.81 10.51 18.27 27.57 11.76  7.85  4.99  2.80  1.22  0.94\n
40  *  56    4.41  4.73  8.52 11.96 24.94 19.78 11.06  7.18  3.68  1.96  1.78\n
41  *  64    2.81  3.07  5.65  9.17 13.01 31.57 13.70  9.30  6.04  3.04  2.64\n
42  *  72    1.87  1.99  3.68  7.15 10.56 20.24 25.78 12.17  7.52  4.42  4.62\n
43  *  80    1.02  1.23  2.78  4.75  8.37 12.04 27.61 18.07 10.28  6.52  7.33\n
44  *  88    0.70  0.57  1.56  3.12  6.34 10.06 15.76 30.46 12.58  8.47 10.38\n
45  *  96    0.27  0.60  1.25  2.28  4.30  7.60 10.77 22.52 22.51 11.37 16.53\n
46  * 104    0.22  0.42  0.77  1.36  2.62  5.33  8.93 13.05 29.54 15.23 22.53\n
47  * 112    0.15  0.20  0.56  0.87  2.00  3.83  6.86 10.06 17.89 27.31 30.27\n
48  * 120    0.03  0.11  0.31  0.46  1.31  2.48  4.60  7.78 11.67 25.53 45.72\n
49  * 128    0.02  0.01  0.13  0.33  0.83  1.41  3.24  6.17  9.57 14.22 64.07\n
50  */
51 int m_bonus(int max, DEPTH level)
52 {
53         int bonus, stand, extra, value;
54
55
56         /* Paranoia -- enforce maximal "level" */
57         if (level > MAX_DEPTH - 1) level = MAX_DEPTH - 1;
58
59
60         /* The "bonus" moves towards the max */
61         bonus = ((max * level) / MAX_DEPTH);
62
63         /* Hack -- determine fraction of error */
64         extra = ((max * level) % MAX_DEPTH);
65
66         /* Hack -- simulate floating point computations */
67         if (randint0(MAX_DEPTH) < extra) bonus++;
68
69
70         /* The "stand" is equal to one quarter of the max */
71         stand = (max / 4);
72
73         /* Hack -- determine fraction of error */
74         extra = (max % 4);
75
76         /* Hack -- simulate floating point computations */
77         if (randint0(4) < extra) stand++;
78
79
80         /* Choose an "interesting" value */
81         value = randnor(bonus, stand);
82
83         /* Enforce the minimum value */
84         if (value < 0) return 0;
85
86         /* Enforce the maximum value */
87         if (value > max) return (max);
88         return (value);
89 }
90
91 /*!
92  * @brief 対象のオブジェクトにランダムな能力維持を一つ付加する。/ Choose one random sustain
93  * @details 重複の抑止はない。
94  * @param o_ptr 対象のオブジェクト構造体ポインタ
95  * @return なし
96  */
97 void one_sustain(object_type *o_ptr)
98 {
99         switch (randint0(A_MAX))
100         {
101         case 0: add_flag(o_ptr->art_flags, TR_SUST_STR); break;
102         case 1: add_flag(o_ptr->art_flags, TR_SUST_INT); break;
103         case 2: add_flag(o_ptr->art_flags, TR_SUST_WIS); break;
104         case 3: add_flag(o_ptr->art_flags, TR_SUST_DEX); break;
105         case 4: add_flag(o_ptr->art_flags, TR_SUST_CON); break;
106         case 5: add_flag(o_ptr->art_flags, TR_SUST_CHR); break;
107         }
108 }
109
110 /*!
111  * @brief オブジェクトにランダムな強いESPを与える
112  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
113  * @return TR_ESP_NONLIVINGがついたならばTRUE
114  */
115 bool add_esp_strong(object_type *o_ptr)
116 {
117         bool nonliv = FALSE;
118
119         switch (randint1(3))
120         {
121         case 1: add_flag(o_ptr->art_flags, TR_ESP_EVIL); break;
122         case 2: add_flag(o_ptr->art_flags, TR_TELEPATHY); break;
123         case 3: add_flag(o_ptr->art_flags, TR_ESP_NONLIVING); nonliv = TRUE; break;
124         }
125
126         return nonliv;
127 }
128
129 /*!
130  * @brief オブジェクトにランダムな弱いESPを与える
131  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
132  * @param extra TRUEならばESPの最大付与数が増える(TRUE -> 3+1d6 / FALSE -> 1d3)
133  * @return なし
134  */
135 void add_esp_weak(object_type *o_ptr, bool extra)
136 {
137         int i;
138         u32b weak_esp_list[] = {
139                 TR_ESP_ANIMAL,
140                 TR_ESP_UNDEAD,
141                 TR_ESP_DEMON,
142                 TR_ESP_ORC,
143                 TR_ESP_TROLL,
144                 TR_ESP_GIANT,
145                 TR_ESP_DRAGON,
146                 TR_ESP_HUMAN,
147                 TR_ESP_GOOD,
148                 TR_ESP_UNIQUE,
149         };
150         const int MAX_ESP_WEAK = sizeof(weak_esp_list) / sizeof(weak_esp_list[0]);
151         const int add_count = MIN(MAX_ESP_WEAK, (extra) ? (3 + randint1(randint1(6))) : randint1(3));
152
153         /* Add unduplicated weak esp flags randomly */
154         for (i = 0; i < add_count; ++i)
155         {
156                 int choice = rand_range(i, MAX_ESP_WEAK - 1);
157
158                 add_flag(o_ptr->art_flags, weak_esp_list[choice]);
159                 weak_esp_list[choice] = weak_esp_list[i];
160         }
161 }
162
163 /*!
164  * @brief 対象のオブジェクトに元素耐性を一つ付加する。/ Choose one random element resistance
165  * @details 候補は火炎、冷気、電撃、酸のいずれかであり、重複の抑止はない。
166  * @param o_ptr 対象のオブジェクト構造体ポインタ
167  * @return なし
168  */
169 void one_ele_resistance(object_type *o_ptr)
170 {
171         switch (randint0(4))
172         {
173         case  0: add_flag(o_ptr->art_flags, TR_RES_ACID); break;
174         case  1: add_flag(o_ptr->art_flags, TR_RES_ELEC); break;
175         case  2: add_flag(o_ptr->art_flags, TR_RES_COLD); break;
176         case  3: add_flag(o_ptr->art_flags, TR_RES_FIRE); break;
177         }
178 }
179
180 /*!
181  * @brief 対象のオブジェクトにドラゴン装備向け元素耐性を一つ付加する。/ Choose one random element or poison resistance
182  * @details 候補は1/7の確率で毒、6/7の確率で火炎、冷気、電撃、酸のいずれか(one_ele_resistance()のコール)であり、重複の抑止はない。
183  * @param o_ptr 対象のオブジェクト構造体ポインタ
184  * @return なし
185  */
186 void one_dragon_ele_resistance(object_type *o_ptr)
187 {
188         if (one_in_(7))
189         {
190                 add_flag(o_ptr->art_flags, TR_RES_POIS);
191         }
192         else
193         {
194                 one_ele_resistance(o_ptr);
195         }
196 }
197
198 /*!
199  * @brief 対象のオブジェクトにランダムな上位耐性を一つ付加する。/ Choose one random high resistance
200  * @details 重複の抑止はない。候補は毒、閃光、暗黒、破片、盲目、混乱、地獄、因果混乱、カオス、劣化、恐怖のいずれか。
201  * @param o_ptr 対象のオブジェクト構造体ポインタ
202  * @return なし
203  */
204 void one_high_resistance(object_type *o_ptr)
205 {
206         switch (randint0(12))
207         {
208         case  0: add_flag(o_ptr->art_flags, TR_RES_POIS);   break;
209         case  1: add_flag(o_ptr->art_flags, TR_RES_LITE);   break;
210         case  2: add_flag(o_ptr->art_flags, TR_RES_DARK);   break;
211         case  3: add_flag(o_ptr->art_flags, TR_RES_SHARDS); break;
212         case  4: add_flag(o_ptr->art_flags, TR_RES_BLIND);  break;
213         case  5: add_flag(o_ptr->art_flags, TR_RES_CONF);   break;
214         case  6: add_flag(o_ptr->art_flags, TR_RES_SOUND);  break;
215         case  7: add_flag(o_ptr->art_flags, TR_RES_NETHER); break;
216         case  8: add_flag(o_ptr->art_flags, TR_RES_NEXUS);  break;
217         case  9: add_flag(o_ptr->art_flags, TR_RES_CHAOS);  break;
218         case 10: add_flag(o_ptr->art_flags, TR_RES_DISEN);  break;
219         case 11: add_flag(o_ptr->art_flags, TR_RES_FEAR);   break;
220         }
221 }
222
223
224 /*!
225  * @brief ドラゴン装備にランダムな耐性を与える
226  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
227  * @return なし
228  */
229 void dragon_resist(object_type *o_ptr)
230 {
231         do
232         {
233                 if (one_in_(4))
234                         one_dragon_ele_resistance(o_ptr);
235                 else
236                         one_high_resistance(o_ptr);
237         } while (one_in_(2));
238 }
239
240
241 /*!
242  * @brief 対象のオブジェクトに耐性を一つ付加する。/ Choose one random resistance
243  * @details 1/3で元素耐性(one_ele_resistance())、2/3で上位耐性(one_high_resistance)
244  * をコールする。重複の抑止はない。
245  * @param o_ptr 対象のオブジェクト構造体ポインタ
246  * @return なし
247  */
248 void one_resistance(object_type *o_ptr)
249 {
250         if (one_in_(3))
251         {
252                 one_ele_resistance(o_ptr);
253         }
254         else
255         {
256                 one_high_resistance(o_ptr);
257         }
258 }
259
260
261 /*!
262  * @brief 対象のオブジェクトに能力を一つ付加する。/ Choose one random ability
263  * @details 候補は浮遊、永久光源+1、透明視、警告、遅消化、急回復、麻痺知らず、経験値維持のいずれか。
264  * 重複の抑止はない。
265  * @param o_ptr 対象のオブジェクト構造体ポインタ
266  * @return なし
267  */
268 void one_ability(object_type *o_ptr)
269 {
270         switch (randint0(10))
271         {
272         case 0: add_flag(o_ptr->art_flags, TR_LEVITATION);  break;
273         case 1: add_flag(o_ptr->art_flags, TR_LITE_1);      break;
274         case 2: add_flag(o_ptr->art_flags, TR_SEE_INVIS);   break;
275         case 3: add_flag(o_ptr->art_flags, TR_WARNING);     break;
276         case 4: add_flag(o_ptr->art_flags, TR_SLOW_DIGEST); break;
277         case 5: add_flag(o_ptr->art_flags, TR_REGEN);       break;
278         case 6: add_flag(o_ptr->art_flags, TR_FREE_ACT);    break;
279         case 7: add_flag(o_ptr->art_flags, TR_HOLD_EXP);   break;
280         case 8:
281         case 9:
282                 one_low_esp(o_ptr);
283                 break;
284         }
285 }
286
287
288 /*!
289  * @brief 対象のオブジェクトに弱いESPを一つ付加する。/ Choose one lower rank esp
290  * @details 候補は動物、アンデッド、悪魔、オーク、トロル、巨人、
291  * ドラゴン、人間、善良、ユニークESPのいずれかであり、重複の抑止はない。
292  * @param o_ptr 対象のオブジェクト構造体ポインタ
293  * @return なし
294  */
295 void one_low_esp(object_type *o_ptr)
296 {
297         switch (randint1(10))
298         {
299         case 1:  add_flag(o_ptr->art_flags, TR_ESP_ANIMAL);   break;
300         case 2:  add_flag(o_ptr->art_flags, TR_ESP_UNDEAD);   break;
301         case 3:  add_flag(o_ptr->art_flags, TR_ESP_DEMON);   break;
302         case 4:  add_flag(o_ptr->art_flags, TR_ESP_ORC);   break;
303         case 5:  add_flag(o_ptr->art_flags, TR_ESP_TROLL);   break;
304         case 6:  add_flag(o_ptr->art_flags, TR_ESP_GIANT);   break;
305         case 7:  add_flag(o_ptr->art_flags, TR_ESP_DRAGON);   break;
306         case 8:  add_flag(o_ptr->art_flags, TR_ESP_HUMAN);   break;
307         case 9:  add_flag(o_ptr->art_flags, TR_ESP_GOOD);   break;
308         case 10: add_flag(o_ptr->art_flags, TR_ESP_UNIQUE);   break;
309         }
310 }
311
312
313 /*!
314  * @brief 対象のオブジェクトに発動を一つ付加する。/ Choose one random activation
315  * @details 候補多数。ランダムアーティファクトのバイアスには一切依存せず、
316  * whileループによる構造で能力的に強力なものほど確率を落としている。
317  * @param o_ptr 対象のオブジェクト構造体ポインタ
318  * @return なし
319  */
320 void one_activation(object_type *o_ptr)
321 {
322         int type = 0;
323         PERCENTAGE chance = 0;
324
325         while (randint1(100) >= chance)
326         {
327                 type = randint1(255);
328                 switch (type)
329                 {
330                 case ACT_SUNLIGHT:
331                 case ACT_BO_MISS_1:
332                 case ACT_BA_POIS_1:
333                 case ACT_BO_ELEC_1:
334                 case ACT_BO_ACID_1:
335                 case ACT_BO_COLD_1:
336                 case ACT_BO_FIRE_1:
337                 case ACT_CONFUSE:
338                 case ACT_SLEEP:
339                 case ACT_QUAKE:
340                 case ACT_CURE_LW:
341                 case ACT_CURE_MW:
342                 case ACT_CURE_POISON:
343                 case ACT_BERSERK:
344                 case ACT_LIGHT:
345                 case ACT_MAP_LIGHT:
346                 case ACT_DEST_DOOR:
347                 case ACT_STONE_MUD:
348                 case ACT_TELEPORT:
349                         chance = 101;
350                         break;
351                 case ACT_BA_COLD_1:
352                 case ACT_BA_FIRE_1:
353                 case ACT_HYPODYNAMIA_1:
354                 case ACT_TELE_AWAY:
355                 case ACT_ESP:
356                 case ACT_RESIST_ALL:
357                 case ACT_DETECT_ALL:
358                 case ACT_RECALL:
359                 case ACT_SATIATE:
360                 case ACT_RECHARGE:
361                         chance = 85;
362                         break;
363                 case ACT_TERROR:
364                 case ACT_PROT_EVIL:
365                 case ACT_ID_PLAIN:
366                         chance = 75;
367                         break;
368                 case ACT_HYPODYNAMIA_2:
369                 case ACT_DRAIN_1:
370                 case ACT_BO_MISS_2:
371                 case ACT_BA_FIRE_2:
372                 case ACT_REST_EXP:
373                         chance = 66;
374                         break;
375                 case ACT_BA_FIRE_3:
376                 case ACT_BA_COLD_3:
377                 case ACT_BA_ELEC_3:
378                 case ACT_WHIRLWIND:
379                 case ACT_DRAIN_2:
380                 case ACT_CHARM_ANIMAL:
381                         chance = 50;
382                         break;
383                 case ACT_SUMMON_ANIMAL:
384                         chance = 40;
385                         break;
386                 case ACT_DISP_EVIL:
387                 case ACT_BA_MISS_3:
388                 case ACT_DISP_GOOD:
389                 case ACT_BANISH_EVIL:
390                 case ACT_GENOCIDE:
391                 case ACT_MASS_GENO:
392                 case ACT_CHARM_UNDEAD:
393                 case ACT_CHARM_OTHER:
394                 case ACT_SUMMON_PHANTOM:
395                 case ACT_REST_ALL:
396                 case ACT_RUNE_EXPLO:
397                         chance = 33;
398                         break;
399                 case ACT_CALL_CHAOS:
400                 case ACT_ROCKET:
401                 case ACT_CHARM_ANIMALS:
402                 case ACT_CHARM_OTHERS:
403                 case ACT_SUMMON_ELEMENTAL:
404                 case ACT_CURE_700:
405                 case ACT_SPEED:
406                 case ACT_ID_FULL:
407                 case ACT_RUNE_PROT:
408                         chance = 25;
409                         break;
410                 case ACT_CURE_1000:
411                 case ACT_XTRA_SPEED:
412                 case ACT_DETECT_XTRA:
413                 case ACT_DIM_DOOR:
414                         chance = 10;
415                         break;
416                 case ACT_SUMMON_UNDEAD:
417                 case ACT_SUMMON_DEMON:
418                 case ACT_WRAITH:
419                 case ACT_INVULN:
420                 case ACT_ALCHEMY:
421                         chance = 5;
422                         break;
423                 default:
424                         chance = 0;
425                 }
426         }
427
428         /* A type was chosen... */
429         o_ptr->xtra2 = (byte)type;
430         add_flag(o_ptr->art_flags, TR_ACTIVATE);
431         o_ptr->timeout = 0;
432 }
433
434
435 /*!
436  * @brief 対象のオブジェクトに王者の指輪向けの上位耐性を一つ付加する。/ Choose one random high resistance
437  * @details 候補は閃光、暗黒、破片、盲目、混乱、地獄、因果混乱、カオス、恐怖であり
438  * 王者の指輪にあらかじめついている耐性をone_high_resistance()から除外したものである。
439  * ランダム付加そのものに重複の抑止はない。
440  * @param o_ptr 対象のオブジェクト構造体ポインタ
441  * @return なし
442  */
443 void one_lordly_high_resistance(object_type *o_ptr)
444 {
445         switch (randint0(10))
446         {
447         case 0: add_flag(o_ptr->art_flags, TR_RES_LITE);   break;
448         case 1: add_flag(o_ptr->art_flags, TR_RES_DARK);   break;
449         case 2: add_flag(o_ptr->art_flags, TR_RES_SHARDS); break;
450         case 3: add_flag(o_ptr->art_flags, TR_RES_BLIND);  break;
451         case 4: add_flag(o_ptr->art_flags, TR_RES_CONF);   break;
452         case 5: add_flag(o_ptr->art_flags, TR_RES_SOUND);  break;
453         case 6: add_flag(o_ptr->art_flags, TR_RES_NETHER); break;
454         case 7: add_flag(o_ptr->art_flags, TR_RES_NEXUS);  break;
455         case 8: add_flag(o_ptr->art_flags, TR_RES_CHAOS);  break;
456         case 9: add_flag(o_ptr->art_flags, TR_RES_FEAR);   break;
457         }
458 }