OSDN Git Service

[fix] #41503 超能力者でゲームを開始しようとするとクラッシュ
[hengband/hengband.git] / src / object-enchant / object-boost.c
1 #include "object-enchant/object-boost.h"
2 #include "artifact/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     /* Paranoia -- enforce maximal "level" */
56     if (level > MAX_DEPTH - 1)
57         level = MAX_DEPTH - 1;
58
59     /* The "bonus" moves towards the max */
60     bonus = ((max * level) / MAX_DEPTH);
61
62     /* Hack -- determine fraction of error */
63     extra = ((max * level) % MAX_DEPTH);
64
65     /* Hack -- simulate floating point computations */
66     if (randint0(MAX_DEPTH) < extra)
67         bonus++;
68
69     /* The "stand" is equal to one quarter of the max */
70     stand = (max / 4);
71
72     /* Hack -- determine fraction of error */
73     extra = (max % 4);
74
75     /* Hack -- simulate floating point computations */
76     if (randint0(4) < extra)
77         stand++;
78
79     /* Choose an "interesting" value */
80     value = randnor(bonus, stand);
81
82     /* Enforce the minimum value */
83     if (value < 0)
84         return 0;
85
86     /* Enforce the maximum value */
87     if (value > max)
88         return (max);
89     return (value);
90 }
91
92 /*!
93  * @brief 対象のオブジェクトにランダムな能力維持を一つ付加する。/ Choose one random sustain
94  * @details 重複の抑止はない。
95  * @param o_ptr 対象のオブジェクト構造体ポインタ
96  * @return なし
97  */
98 void one_sustain(object_type *o_ptr)
99 {
100     switch (randint0(A_MAX)) {
101     case 0:
102         add_flag(o_ptr->art_flags, TR_SUST_STR);
103         break;
104     case 1:
105         add_flag(o_ptr->art_flags, TR_SUST_INT);
106         break;
107     case 2:
108         add_flag(o_ptr->art_flags, TR_SUST_WIS);
109         break;
110     case 3:
111         add_flag(o_ptr->art_flags, TR_SUST_DEX);
112         break;
113     case 4:
114         add_flag(o_ptr->art_flags, TR_SUST_CON);
115         break;
116     case 5:
117         add_flag(o_ptr->art_flags, TR_SUST_CHR);
118         break;
119     }
120 }
121
122 /*!
123  * @brief オブジェクトにランダムな強いESPを与える
124  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
125  * @return TR_ESP_NONLIVINGがついたならばTRUE
126  */
127 bool add_esp_strong(object_type *o_ptr)
128 {
129     bool nonliv = FALSE;
130
131     switch (randint1(3)) {
132     case 1:
133         add_flag(o_ptr->art_flags, TR_ESP_EVIL);
134         break;
135     case 2:
136         add_flag(o_ptr->art_flags, TR_TELEPATHY);
137         break;
138     case 3:
139         add_flag(o_ptr->art_flags, TR_ESP_NONLIVING);
140         nonliv = TRUE;
141         break;
142     }
143
144     return nonliv;
145 }
146
147 /*!
148  * @brief オブジェクトにランダムな弱いESPを与える
149  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
150  * @param extra TRUEならばESPの最大付与数が増える(TRUE -> 3+1d6 / FALSE -> 1d3)
151  * @return なし
152  */
153 void add_esp_weak(object_type *o_ptr, bool extra)
154 {
155     int i;
156     u32b weak_esp_list[] = {
157         TR_ESP_ANIMAL,
158         TR_ESP_UNDEAD,
159         TR_ESP_DEMON,
160         TR_ESP_ORC,
161         TR_ESP_TROLL,
162         TR_ESP_GIANT,
163         TR_ESP_DRAGON,
164         TR_ESP_HUMAN,
165         TR_ESP_GOOD,
166         TR_ESP_UNIQUE,
167     };
168     const int MAX_ESP_WEAK = sizeof(weak_esp_list) / sizeof(weak_esp_list[0]);
169     const int add_count = MIN(MAX_ESP_WEAK, (extra) ? (3 + randint1(randint1(6))) : randint1(3));
170
171     /* Add unduplicated weak esp flags randomly */
172     for (i = 0; i < add_count; ++i) {
173         int choice = rand_range(i, MAX_ESP_WEAK - 1);
174
175         add_flag(o_ptr->art_flags, weak_esp_list[choice]);
176         weak_esp_list[choice] = weak_esp_list[i];
177     }
178 }
179
180 /*!
181  * @brief 対象のオブジェクトに元素耐性を一つ付加する。/ Choose one random element resistance
182  * @details 候補は火炎、冷気、電撃、酸のいずれかであり、重複の抑止はない。
183  * @param o_ptr 対象のオブジェクト構造体ポインタ
184  * @return なし
185  */
186 void one_ele_resistance(object_type *o_ptr)
187 {
188     switch (randint0(4)) {
189     case 0:
190         add_flag(o_ptr->art_flags, TR_RES_ACID);
191         break;
192     case 1:
193         add_flag(o_ptr->art_flags, TR_RES_ELEC);
194         break;
195     case 2:
196         add_flag(o_ptr->art_flags, TR_RES_COLD);
197         break;
198     case 3:
199         add_flag(o_ptr->art_flags, TR_RES_FIRE);
200         break;
201     }
202 }
203
204 /*!
205  * @brief 対象のオブジェクトにドラゴン装備向け元素耐性を一つ付加する。/ Choose one random element or poison resistance
206  * @details 候補は1/7の確率で毒、6/7の確率で火炎、冷気、電撃、酸のいずれか(one_ele_resistance()のコール)であり、重複の抑止はない。
207  * @param o_ptr 対象のオブジェクト構造体ポインタ
208  * @return なし
209  */
210 void one_dragon_ele_resistance(object_type *o_ptr)
211 {
212     if (one_in_(7)) {
213         add_flag(o_ptr->art_flags, TR_RES_POIS);
214     } else {
215         one_ele_resistance(o_ptr);
216     }
217 }
218
219 /*!
220  * @brief 対象のオブジェクトにランダムな上位耐性を一つ付加する。/ Choose one random high resistance
221  * @details 重複の抑止はない。候補は毒、閃光、暗黒、破片、盲目、混乱、地獄、因果混乱、カオス、劣化、恐怖のいずれか。
222  * @param o_ptr 対象のオブジェクト構造体ポインタ
223  * @return なし
224  */
225 void one_high_resistance(object_type *o_ptr)
226 {
227     switch (randint0(12)) {
228     case 0:
229         add_flag(o_ptr->art_flags, TR_RES_POIS);
230         break;
231     case 1:
232         add_flag(o_ptr->art_flags, TR_RES_LITE);
233         break;
234     case 2:
235         add_flag(o_ptr->art_flags, TR_RES_DARK);
236         break;
237     case 3:
238         add_flag(o_ptr->art_flags, TR_RES_SHARDS);
239         break;
240     case 4:
241         add_flag(o_ptr->art_flags, TR_RES_BLIND);
242         break;
243     case 5:
244         add_flag(o_ptr->art_flags, TR_RES_CONF);
245         break;
246     case 6:
247         add_flag(o_ptr->art_flags, TR_RES_SOUND);
248         break;
249     case 7:
250         add_flag(o_ptr->art_flags, TR_RES_NETHER);
251         break;
252     case 8:
253         add_flag(o_ptr->art_flags, TR_RES_NEXUS);
254         break;
255     case 9:
256         add_flag(o_ptr->art_flags, TR_RES_CHAOS);
257         break;
258     case 10:
259         add_flag(o_ptr->art_flags, TR_RES_DISEN);
260         break;
261     case 11:
262         add_flag(o_ptr->art_flags, TR_RES_FEAR);
263         break;
264     }
265 }
266
267 /*!
268  * @brief ドラゴン装備にランダムな耐性を与える
269  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
270  * @return なし
271  */
272 void dragon_resist(object_type *o_ptr)
273 {
274     do {
275         if (one_in_(4))
276             one_dragon_ele_resistance(o_ptr);
277         else
278             one_high_resistance(o_ptr);
279     } while (one_in_(2));
280 }
281
282 /*!
283  * @brief 対象のオブジェクトに耐性を一つ付加する。/ Choose one random resistance
284  * @details 1/3で元素耐性(one_ele_resistance())、2/3で上位耐性(one_high_resistance)
285  * をコールする。重複の抑止はない。
286  * @param o_ptr 対象のオブジェクト構造体ポインタ
287  * @return なし
288  */
289 void one_resistance(object_type *o_ptr)
290 {
291     if (one_in_(3)) {
292         one_ele_resistance(o_ptr);
293     } else {
294         one_high_resistance(o_ptr);
295     }
296 }
297
298 /*!
299  * @brief 対象のオブジェクトに能力を一つ付加する。/ Choose one random ability
300  * @details 候補は浮遊、永久光源+1、透明視、警告、遅消化、急回復、麻痺知らず、経験値維持のいずれか。
301  * 重複の抑止はない。
302  * @param o_ptr 対象のオブジェクト構造体ポインタ
303  * @return なし
304  */
305 void one_ability(object_type *o_ptr)
306 {
307     switch (randint0(10)) {
308     case 0:
309         add_flag(o_ptr->art_flags, TR_LEVITATION);
310         break;
311     case 1:
312         add_flag(o_ptr->art_flags, TR_LITE_1);
313         break;
314     case 2:
315         add_flag(o_ptr->art_flags, TR_SEE_INVIS);
316         break;
317     case 3:
318         add_flag(o_ptr->art_flags, TR_WARNING);
319         break;
320     case 4:
321         add_flag(o_ptr->art_flags, TR_SLOW_DIGEST);
322         break;
323     case 5:
324         add_flag(o_ptr->art_flags, TR_REGEN);
325         break;
326     case 6:
327         add_flag(o_ptr->art_flags, TR_FREE_ACT);
328         break;
329     case 7:
330         add_flag(o_ptr->art_flags, TR_HOLD_EXP);
331         break;
332     case 8:
333     case 9:
334         one_low_esp(o_ptr);
335         break;
336     }
337 }
338
339 /*!
340  * @brief 対象のオブジェクトに弱いESPを一つ付加する。/ Choose one lower rank esp
341  * @details 候補は動物、アンデッド、悪魔、オーク、トロル、巨人、
342  * ドラゴン、人間、善良、ユニークESPのいずれかであり、重複の抑止はない。
343  * @param o_ptr 対象のオブジェクト構造体ポインタ
344  * @return なし
345  */
346 void one_low_esp(object_type *o_ptr)
347 {
348     switch (randint1(10)) {
349     case 1:
350         add_flag(o_ptr->art_flags, TR_ESP_ANIMAL);
351         break;
352     case 2:
353         add_flag(o_ptr->art_flags, TR_ESP_UNDEAD);
354         break;
355     case 3:
356         add_flag(o_ptr->art_flags, TR_ESP_DEMON);
357         break;
358     case 4:
359         add_flag(o_ptr->art_flags, TR_ESP_ORC);
360         break;
361     case 5:
362         add_flag(o_ptr->art_flags, TR_ESP_TROLL);
363         break;
364     case 6:
365         add_flag(o_ptr->art_flags, TR_ESP_GIANT);
366         break;
367     case 7:
368         add_flag(o_ptr->art_flags, TR_ESP_DRAGON);
369         break;
370     case 8:
371         add_flag(o_ptr->art_flags, TR_ESP_HUMAN);
372         break;
373     case 9:
374         add_flag(o_ptr->art_flags, TR_ESP_GOOD);
375         break;
376     case 10:
377         add_flag(o_ptr->art_flags, TR_ESP_UNIQUE);
378         break;
379     }
380 }
381
382 /*!
383  * @brief 対象のオブジェクトに発動を一つ付加する。/ Choose one random activation
384  * @details 候補多数。ランダムアーティファクトのバイアスには一切依存せず、
385  * whileループによる構造で能力的に強力なものほど確率を落としている。
386  * @param o_ptr 対象のオブジェクト構造体ポインタ
387  * @return なし
388  */
389 void one_activation(object_type *o_ptr)
390 {
391     int type = 0;
392     PERCENTAGE chance = 0;
393     while (randint1(100) >= chance) {
394         type = randint1(ACT_MAX);
395         switch (type) {
396         case ACT_SUNLIGHT:
397         case ACT_BO_MISS_1:
398         case ACT_BA_POIS_1:
399         case ACT_BO_ELEC_1:
400         case ACT_BO_ACID_1:
401         case ACT_BO_COLD_1:
402         case ACT_BO_FIRE_1:
403         case ACT_CONFUSE:
404         case ACT_SLEEP:
405         case ACT_QUAKE:
406         case ACT_CURE_LW:
407         case ACT_CURE_MW:
408         case ACT_CURE_POISON:
409         case ACT_BERSERK:
410         case ACT_LIGHT:
411         case ACT_MAP_LIGHT:
412         case ACT_DEST_DOOR:
413         case ACT_STONE_MUD:
414         case ACT_TELEPORT:
415             chance = 101;
416             break;
417         case ACT_BA_COLD_1:
418         case ACT_BA_FIRE_1:
419         case ACT_HYPODYNAMIA_1:
420         case ACT_TELE_AWAY:
421         case ACT_ESP:
422         case ACT_RESIST_ALL:
423         case ACT_DETECT_ALL:
424         case ACT_RECALL:
425         case ACT_SATIATE:
426         case ACT_RECHARGE:
427             chance = 85;
428             break;
429         case ACT_TERROR:
430         case ACT_PROT_EVIL:
431         case ACT_ID_PLAIN:
432             chance = 75;
433             break;
434         case ACT_HYPODYNAMIA_2:
435         case ACT_DRAIN_1:
436         case ACT_BO_MISS_2:
437         case ACT_BA_FIRE_2:
438         case ACT_REST_EXP:
439             chance = 66;
440             break;
441         case ACT_BA_FIRE_3:
442         case ACT_BA_COLD_3:
443         case ACT_BA_ELEC_3:
444         case ACT_WHIRLWIND:
445         case ACT_DRAIN_2:
446         case ACT_CHARM_ANIMAL:
447             chance = 50;
448             break;
449         case ACT_SUMMON_ANIMAL:
450         case ACT_ANIM_DEAD:
451             chance = 40;
452             break;
453         case ACT_DISP_EVIL:
454         case ACT_BA_MISS_3:
455         case ACT_DISP_GOOD:
456         case ACT_BANISH_EVIL:
457         case ACT_GENOCIDE:
458         case ACT_MASS_GENO:
459         case ACT_CHARM_UNDEAD:
460         case ACT_CHARM_OTHER:
461         case ACT_SUMMON_PHANTOM:
462         case ACT_REST_ALL:
463         case ACT_RUNE_EXPLO:
464             chance = 33;
465             break;
466         case ACT_CALL_CHAOS:
467         case ACT_ROCKET:
468         case ACT_CHARM_ANIMALS:
469         case ACT_CHARM_OTHERS:
470         case ACT_SUMMON_ELEMENTAL:
471         case ACT_CURE_700:
472         case ACT_SPEED:
473         case ACT_ID_FULL:
474         case ACT_RUNE_PROT:
475             chance = 25;
476             break;
477         case ACT_CURE_1000:
478         case ACT_XTRA_SPEED:
479         case ACT_DETECT_XTRA:
480         case ACT_DIM_DOOR:
481             chance = 10;
482             break;
483         case ACT_TREE_CREATION:
484         case ACT_SUMMON_DEMON:
485         case ACT_SUMMON_UNDEAD:
486         case ACT_WRAITH:
487         case ACT_INVULN:
488         case ACT_ALCHEMY:
489             chance = 5;
490             break;
491         default:
492             chance = 0;
493         }
494     }
495
496     o_ptr->xtra2 = (byte)type;
497     add_flag(o_ptr->art_flags, TR_ACTIVATE);
498     o_ptr->timeout = 0;
499 }
500
501 /*!
502  * @brief 対象のオブジェクトに王者の指輪向けの上位耐性を一つ付加する。/ Choose one random high resistance
503  * @details 候補は閃光、暗黒、破片、盲目、混乱、地獄、因果混乱、カオス、恐怖であり
504  * 王者の指輪にあらかじめついている耐性をone_high_resistance()から除外したものである。
505  * ランダム付加そのものに重複の抑止はない。
506  * @param o_ptr 対象のオブジェクト構造体ポインタ
507  * @return なし
508  */
509 void one_lordly_high_resistance(object_type *o_ptr)
510 {
511     switch (randint0(10)) {
512     case 0:
513         add_flag(o_ptr->art_flags, TR_RES_LITE);
514         break;
515     case 1:
516         add_flag(o_ptr->art_flags, TR_RES_DARK);
517         break;
518     case 2:
519         add_flag(o_ptr->art_flags, TR_RES_SHARDS);
520         break;
521     case 3:
522         add_flag(o_ptr->art_flags, TR_RES_BLIND);
523         break;
524     case 4:
525         add_flag(o_ptr->art_flags, TR_RES_CONF);
526         break;
527     case 5:
528         add_flag(o_ptr->art_flags, TR_RES_SOUND);
529         break;
530     case 6:
531         add_flag(o_ptr->art_flags, TR_RES_NETHER);
532         break;
533     case 7:
534         add_flag(o_ptr->art_flags, TR_RES_NEXUS);
535         break;
536     case 8:
537         add_flag(o_ptr->art_flags, TR_RES_CHAOS);
538         break;
539     case 9:
540         add_flag(o_ptr->art_flags, TR_RES_FEAR);
541         break;
542     }
543 }