OSDN Git Service

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