1 #include "birth/birth-stat.h"
2 #include "birth/auto-roller.h"
3 #include "core/player-redraw-types.h"
4 #include "player-base/player-class.h"
5 #include "player-base/player-race.h"
6 #include "player-info/class-info.h"
7 #include "player-info/race-info.h"
8 #include "player-info/race-types.h"
9 #include "player/player-personality-types.h"
10 #include "player/player-personality.h"
11 #include "player/player-skill.h"
12 #include "spell/spells-status.h"
13 #include "sv-definition/sv-weapon-types.h"
14 #include "system/player-type-definition.h"
15 #include "system/redrawing-flags-updater.h"
20 constexpr auto random_distribution = 60;
22 /*! オートロール能力値の乱数分布 (1d3, 1d4, 1d5 を3 * 4 * 5 = 60個で表現) */
23 constexpr std::array<short, random_distribution> auto_roller_distribution = {
25 8, 9, 9, 9, 10, 10, 10, 10, 10, 10, /*00-09*/
26 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, /*10-19*/
27 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /*20-29*/
28 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /*30-49*/
29 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, /*40-49*/
30 15, 15, 15, 15, 15, 15, 16, 16, 16, 17 /*50-59*/
36 * @brief プレイヤーの能力値表現に基づいて加減算を行う。
38 * @param amount 加減算する値
41 int adjust_stat(int value, int amount)
44 for (int i = 0; i < (0 - amount); i++) {
45 if (value >= 18 + 10) {
47 } else if (value > 18) {
49 } else if (value > 3) {
53 } else if (amount > 0) {
54 for (int i = 0; i < amount; i++) {
67 * @brief プレイヤーの能力値を一通りロールする。 / Roll for a characters stats
68 * @param player_ptr プレイヤーへの参照ポインタ
70 * calc_bonuses()による、独立ステータスからの副次ステータス算出も行っている。
71 * For efficiency, we include a chunk of "calc_bonuses()".\n
73 void get_stats(PlayerType *player_ptr)
77 for (auto i = 0; i < 2; i++) {
78 auto tmp = randint0(random_distribution * random_distribution * random_distribution);
79 for (auto j = 0; j < 3; j++) {
80 auto stat = i * 3 + j;
81 auto val = auto_roller_distribution[tmp % random_distribution];
83 player_ptr->stat_cur[stat] = player_ptr->stat_max[stat] = val;
84 tmp /= random_distribution;
88 if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6)) {
97 uint16_t get_expfact(PlayerType *player_ptr)
99 uint16_t expfact = rp_ptr->r_exp;
101 PlayerRace pr(player_ptr);
102 if (!pr.equals(PlayerRaceType::ANDROID)) {
103 expfact += cp_ptr->c_exp;
106 auto is_race_gaining_additional_speed = pr.equals(PlayerRaceType::KLACKON) || pr.equals(PlayerRaceType::SPRITE);
107 auto is_class_gaining_additional_speed = PlayerClass(player_ptr).has_additional_speed();
108 if (is_race_gaining_additional_speed && is_class_gaining_additional_speed) {
116 * @brief その他「オートローラ中は算出の対象にしない」副次ステータスを処理する / Roll for some info that the auto-roller ignores
118 void get_extra(PlayerType *player_ptr, bool roll_hitdie)
120 player_ptr->expfact = get_expfact(player_ptr);
122 /* Reset record of race/realm changes */
123 player_ptr->start_race = player_ptr->prace;
124 player_ptr->old_race1 = 0L;
125 player_ptr->old_race2 = 0L;
126 player_ptr->old_realm = 0;
128 PlayerClass pc(player_ptr);
129 auto is_sorcerer = pc.equals(PlayerClassType::SORCERER);
130 for (int i = 0; i < 64; i++) {
132 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::MASTER);
133 } else if (pc.equals(PlayerClassType::RED_MAGE)) {
134 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::SKILLED);
136 player_ptr->spell_exp[i] = PlayerSkill::spell_exp_at(PlayerSkillRank::UNSKILLED);
140 auto pclass = enum2i(player_ptr->pclass);
141 player_ptr->weapon_exp = class_skills_info[pclass].w_start;
142 player_ptr->weapon_exp_max = class_skills_info[pclass].w_max;
144 if (player_ptr->ppersonality == PERSONALITY_SEXY) {
145 auto &whip_exp = player_ptr->weapon_exp[ItemKindType::HAFTED][SV_WHIP];
146 whip_exp = std::max(whip_exp, PlayerSkill::weapon_exp_at(PlayerSkillRank::BEGINNER));
149 for (auto i : PLAYER_SKILL_KIND_TYPE_RANGE) {
150 player_ptr->skill_exp[i] = class_skills_info[pclass].s_start[i];
153 player_ptr->hitdie = cp_ptr->c_mhp + ap_ptr->a_mhp;
154 player_ptr->hitdie += is_sorcerer ? rp_ptr->r_mhp / 2 : rp_ptr->r_mhp;
156 roll_hitdice(player_ptr, SPOP_NO_UPDATE);
159 player_ptr->mhp = player_ptr->player_hp[0];
163 * @brief プレイヤーの限界ステータスを決める。
164 * @param player_ptr プレイヤーへの参照ポインタ
165 * @details 新生の薬やステータスシャッフルでもこの関数が呼ばれる
167 void get_max_stats(PlayerType *player_ptr)
172 for (auto i = 0; i < A_MAX; i++) {
173 dice[i] = randint1(7);
182 for (auto i = 0; i < A_MAX; i++) {
183 short max_max = 18 + 60 + dice[i] * 10;
184 player_ptr->stat_max_max[i] = max_max;
185 if (player_ptr->stat_max[i] > max_max) {
186 player_ptr->stat_max[i] = max_max;
188 if (player_ptr->stat_cur[i] > max_max) {
189 player_ptr->stat_cur[i] = max_max;
193 player_ptr->knowledge &= ~(KNOW_STAT);
194 RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::ABILITY_SCORE);