OSDN Git Service

Merge branch 'For3.0.0-Monster-Adjustment' into release/3.0.0Alpha
[hengbandforosx/hengbandosx.git] / src / birth / birth-stat.c
1 #include "birth/birth-stat.h"
2 #include "birth/auto-roller.h"
3 #include "core/player-redraw-types.h"
4 #include "sv-definition/sv-weapon-types.h"
5 #include "player/player-class.h"
6 #include "player/player-personality.h"
7 #include "player/player-personalities-types.h"
8 #include "player/player-race.h"
9 #include "player/player-skill.h"
10 #include "spell/spells-status.h"
11 #include "player/player-race-types.h"
12
13 /*! オートロール能力値の乱数分布 / emulate 5 + 1d3 + 1d4 + 1d5 by randint0(60) */
14 BASE_STATUS rand3_4_5[60] = {
15     8, 9, 9, 9, 10, 10, 10, 10, 10, 10, /*00-09*/
16     11, 11, 11, 11, 11, 11, 11, 11, 11, 12, /*10-19*/
17     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /*20-29*/
18     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /*30-49*/
19     13, 14, 14, 14, 14, 14, 14, 14, 14, 14, /*40-49*/
20     15, 15, 15, 15, 15, 15, 16, 16, 16, 17 /*50-59*/
21 };
22
23 /*!
24  * @brief プレイヤーの能力値表現に基づいて加減算を行う。
25  * @param value 現在の能力値
26  * @param amount 加減算する値
27  * @return 加減算の結果
28  */
29 int adjust_stat(int value, int amount)
30 {
31     if (amount < 0) {
32         for (int i = 0; i < (0 - amount); i++) {
33             if (value >= 18 + 10) {
34                 value -= 10;
35             } else if (value > 18) {
36                 value = 18;
37             } else if (value > 3) {
38                 value--;
39             }
40         }
41     } else if (amount > 0) {
42         for (int i = 0; i < amount; i++) {
43             if (value < 18) {
44                 value++;
45             } else {
46                 value += 10;
47             }
48         }
49     }
50
51     return value;
52 }
53
54 /*!
55  * @brief プレイヤーの能力値を一通りロールする。 / Roll for a characters stats
56  * @param creature_ptr プレーヤーへの参照ポインタ
57  * @return なし
58  * @details
59  * calc_bonuses()による、独立ステータスからの副次ステータス算出も行っている。
60  * For efficiency, we include a chunk of "calc_bonuses()".\n
61  */
62 void get_stats(player_type* creature_ptr)
63 {
64     while (TRUE) {
65         int sum = 0;
66         for (int i = 0; i < 2; i++) {
67             s32b tmp = randint0(60 * 60 * 60);
68             BASE_STATUS val;
69
70             for (int j = 0; j < 3; j++) {
71                 int stat = i * 3 + j;
72
73                 /* Extract 5 + 1d3 + 1d4 + 1d5 */
74                 val = rand3_4_5[tmp % 60];
75
76                 sum += val;
77                 creature_ptr->stat_cur[stat] = creature_ptr->stat_max[stat] = val;
78
79                 tmp /= 60;
80             }
81         }
82
83         if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6))
84             break;
85     }
86 }
87
88 /*!
89  * @brief その他「オートローラ中は算出の対象にしない」副次ステータスを処理する / Roll for some info that the auto-roller ignores
90  * @return なし
91  */
92 void get_extra(player_type* creature_ptr, bool roll_hitdie)
93 {
94     if (creature_ptr->prace == RACE_ANDROID)
95         creature_ptr->expfact = rp_ptr->r_exp;
96     else
97         creature_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp;
98
99     if (((creature_ptr->pclass == CLASS_MONK) || (creature_ptr->pclass == CLASS_FORCETRAINER) || (creature_ptr->pclass == CLASS_NINJA)) && ((creature_ptr->prace == RACE_KLACKON) || (creature_ptr->prace == RACE_SPRITE)))
100         creature_ptr->expfact -= 15;
101
102     /* Reset record of race/realm changes */
103     creature_ptr->start_race = creature_ptr->prace;
104     creature_ptr->old_race1 = 0L;
105     creature_ptr->old_race2 = 0L;
106     creature_ptr->old_realm = 0;
107
108     for (int i = 0; i < 64; i++) {
109         if (creature_ptr->pclass == CLASS_SORCERER)
110             creature_ptr->spell_exp[i] = SPELL_EXP_MASTER;
111         else if (creature_ptr->pclass == CLASS_RED_MAGE)
112             creature_ptr->spell_exp[i] = SPELL_EXP_SKILLED;
113         else
114             creature_ptr->spell_exp[i] = SPELL_EXP_UNSKILLED;
115     }
116
117     for (int i = 0; i < 5; i++)
118         for (int j = 0; j < 64; j++)
119             creature_ptr->weapon_exp[i][j] = s_info[creature_ptr->pclass].w_start[i][j];
120
121     if ((creature_ptr->pseikaku == PERSONALITY_SEXY) && (creature_ptr->weapon_exp[TV_HAFTED - TV_WEAPON_BEGIN][SV_WHIP] < WEAPON_EXP_BEGINNER)) {
122         creature_ptr->weapon_exp[TV_HAFTED - TV_WEAPON_BEGIN][SV_WHIP] = WEAPON_EXP_BEGINNER;
123     }
124
125     for (int i = 0; i < GINOU_MAX; i++)
126         creature_ptr->skill_exp[i] = s_info[creature_ptr->pclass].s_start[i];
127
128     if (creature_ptr->pclass == CLASS_SORCERER)
129         creature_ptr->hitdie = rp_ptr->r_mhp / 2 + cp_ptr->c_mhp + ap_ptr->a_mhp;
130     else
131         creature_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp + ap_ptr->a_mhp;
132
133     if (roll_hitdie)
134         roll_hitdice(creature_ptr, SPOP_NO_UPDATE);
135
136     creature_ptr->mhp = creature_ptr->player_hp[0];
137 }
138
139 /*!
140  * @brief プレイヤーの限界ステータスを決める。
141  * @param creature_ptr プレーヤーへの参照ポインタ
142  * @return なし
143  * @details 新生の薬やステータスシャッフルでもこの関数が呼ばれる
144  */
145 void get_max_stats(player_type* creature_ptr)
146 {
147     int dice[6];
148     while (TRUE) {
149         int j = 0;
150         for (int i = 0; i < A_MAX; i++) {
151             dice[i] = randint1(7);
152             j += dice[i];
153         }
154
155         if (j == 24)
156             break;
157     }
158
159     for (int i = 0; i < A_MAX; i++) {
160         BASE_STATUS max_max = 18 + 60 + dice[i] * 10;
161         creature_ptr->stat_max_max[i] = max_max;
162         if (creature_ptr->stat_max[i] > max_max)
163             creature_ptr->stat_max[i] = max_max;
164         if (creature_ptr->stat_cur[i] > max_max)
165             creature_ptr->stat_cur[i] = max_max;
166     }
167
168     creature_ptr->knowledge &= ~(KNOW_STAT);
169     creature_ptr->redraw |= (PR_STATS);
170 }