/*! オートローラの試行回数 / Autoroll round */
s32b auto_round;
+s32b auto_upper_round;
/*!
* @brief オートローラで得たい能力値の基準を決める。
*/
bool get_stat_limits(player_type *creature_ptr)
{
+ int col_stat = 25;
+
clear_from(10);
put_str(_("最低限得たい能力値を設定して下さい。", "Set minimum stats."), 10, 10);
put_str(_("2/8で項目選択、4/6で値の増減、Enterで次へ", "2/8 for Select, 4/6 for Change value, Enter for Goto next"), 11, 10);
put_str(_(" 基本値 種族 職業 性格 合計値 最大値", " Base Rac Cla Per Total Maximum"), 13, 10);
+ put_str(_("確率: 非常に容易(1/10000以上)", "Prob: Quite Easy(>1/10000)"), 23, col_stat);
+
int cval[6];
char buf[80];
char cur[80];
char inp[80];
for (int i = 0; i < A_MAX; i++) {
- stat_match[i] = 0;
cval[i] = 3;
int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
int m = adjust_stat(17, j);
int os = 6;
while (TRUE) {
if (cs != os) {
- if (os == 6) {
+ if (os == 7) {
+ autoroll_chance = get_autoroller_prob(cval);
+ if (autoroll_chance == -999)
+ sprintf(buf, _("確率: 不可能(合計86超) ", "Prob: Impossible(>86 tot stats)"));
+ else if (autoroll_chance < 1)
+ sprintf(buf, _("確率: 非常に容易(1/10000以上)", "Prob: Quite Easy(>1/10000) "));
+ else
+ sprintf(buf, _("確率: 約 1/%8d00 ", "Prob: ~ 1/%8d00 "), autoroll_chance);
+ put_str(buf, 23, col_stat);
+ }
+ else if (os == 6) {
c_put_str(TERM_WHITE, _("決定する", "Accept"), 21, 35);
} else if (os < A_MAX) {
c_put_str(TERM_WHITE, cur, 14 + os, 10);
break;
}
- if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6))
+ if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6 && autoroll_chance != -999))
break;
}
chara_limit_ptr->scmax = (s16b)cval[7];
return TRUE;
}
+
+/*
+ * @breif オートローラーで指定した能力値以上が出る確率を計算する。
+ * @return 確率 / 100
+ */
+ static s32b get_autoroller_prob(int *minval)
+{
+ /* 1 percent of the valid random space (60^6 && 72<sum<87) */
+ s32b tot_rand_1p = 320669745;
+ int i, j, tmp;
+ int ii[6];
+ int tval[6];
+ int tot = 0;
+
+ /* success count */
+ s32b succ = 0;
+
+ /* random combinations out of 60 (1d3+1d4+1d5) patterns */
+ int pp[18] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
+ 1, 3, 6, 9, 11, 11, 9, 6, 3, 1 /* 8-17 */
+ };
+
+ /* Copy */
+ for (i = 0; i < 6; i++)
+ {
+ tval[i] = MAX(8, minval[i]);
+ tot += tval[i];
+ }
+
+ /* No Chance */
+ if (tot > 86) return -999;
+
+ /* bubble sort for speed-up */
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 5; j > i; j--)
+ {
+ if (tval[j - 1] < tval[j])
+ {
+ tmp = tval[j - 1];
+ tval[j - 1] = tval[j];
+ tval[j] = tmp;
+ }
+ }
+ }
+
+ tot = 0;
+
+ /* calc. prob. */
+ for (ii[0] = tval[0]; ii[0] < 18; ii[0]++)
+ {
+ for (ii[1] = tval[1]; ii[1] < 18; ii[1]++)
+ {
+ for (ii[2] = tval[2]; ii[2] < 18; ii[2]++)
+ {
+ for (ii[3] = tval[3]; ii[3] < 18; ii[3]++)
+ {
+ for (ii[4] = tval[4]; ii[4] < 18; ii[4]++)
+ {
+ for (ii[5] = tval[5]; ii[5] < 18; ii[5]++)
+ {
+ tot = ii[0] + ii[1] + ii[2] + ii[3] + ii[4] + ii[5];
+
+ if (tot > 86) break;
+ if (tot <= 72) continue;
+
+ succ += (pp[ii[0]] * pp[ii[1]] * pp[ii[2]] * pp[ii[3]] * pp[ii[4]] * pp[ii[5]]);
+
+ /* If given condition is easy enough, quit calc. to save CPU. */
+ if (succ > 320670) return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return tot_rand_1p / succ;
+}
extern s16b stat_limit[6];
extern s32b stat_match[6];
extern s32b auto_round;
+extern s32b auto_upper_round;
+
+/*! オートローラの要求値実現確率 */
+static s32b autoroll_chance;
+
+/* emulate 5 + 1d3 + 1d4 + 1d5 by randint0(60) */
+static BASE_STATUS rand3_4_5[60] = {
+ 8, 9, 9, 9, 10, 10, 10, 10, 10, 10, /*00-09*/
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, /*10-19*/
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /*20-29*/
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /*30-49*/
+ 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, /*40-49*/
+ 15, 15, 15, 15, 15, 15, 16, 16, 16, 17 /*50-59*/
+};
bool get_stat_limits(player_type *creature_ptr);
void initialize_chara_limit(chara_limit_type *chara_limit_ptr);
#include "birth/birth-stat.h"
+#include "birth/auto-roller.h"
#include "core/player-redraw-types.h"
#include "sv-definition/sv-weapon-types.h"
#include "player/player-class.h"
s32b tmp = randint0(60 * 60 * 60);
BASE_STATUS val;
- /* Extract 5 + 1d3 + 1d4 + 1d5 */
- val = 5 + 3;
- val += tmp % 3;
- tmp /= 3;
- val += tmp % 4;
- tmp /= 4;
- val += tmp % 5;
- tmp /= 5;
-
- sum += val;
- creature_ptr->stat_cur[3 * i] = creature_ptr->stat_max[3 * i] = val;
-
- /* Extract 5 + 1d3 + 1d4 + 1d5 */
- val = 5 + 3;
- val += tmp % 3;
- tmp /= 3;
- val += tmp % 4;
- tmp /= 4;
- val += tmp % 5;
- tmp /= 5;
-
- sum += val;
- creature_ptr->stat_cur[3 * i + 1] = creature_ptr->stat_max[3 * i + 1] = val;
-
- val = 5 + 3;
- val += tmp % 3;
- tmp /= 3;
- val += tmp % 4;
- tmp /= 4;
- val += (BASE_STATUS)tmp;
-
- sum += val;
- creature_ptr->stat_cur[3 * i + 2] = creature_ptr->stat_max[3 * i + 2] = val;
+ for (int j = 0; j < 3; j++) {
+ int stat = i * 3 + j;
+
+ /* Extract 5 + 1d3 + 1d4 + 1d5 */
+ val = rand3_4_5[tmp % 60];
+
+ sum += val;
+ creature_ptr->stat_cur[stat] = creature_ptr->stat_max[stat] = val;
+
+ tmp /= 60;
+ }
}
if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6))
* system may have problems because the user can't stop the
* autoroller for this number of rolls.
*/
-#define AUTOROLLER_STEP 5431L
+#define AUTOROLLER_STEP 54321L
static void display_initial_birth_message(player_type *creature_ptr)
{
if (!autoroller)
return;
- put_str(_("最小値", " Limit"), 2, col + 5);
- put_str(_("成功率", " Freq"), 2, col + 13);
+ put_str(_("最小値", " Limit"), 2, col + 13);
put_str(_("現在値", " Roll"), 2, col + 24);
+
+ char buf[32];
+
+ if (autoroll_chance >= 1)
+ sprintf(buf, _("確率 : 1/%8d00", "Prob : 1/%8d00"), autoroll_chance);
+ else if (autoroll_chance == -999)
+ sprintf(buf, _("確率 : 不可能", "Prob : Impossible"));
+ else
+ sprintf(buf, _("確率 : 1/10000以上", "Prob : >1/10000"));
+ put_str(buf, 11, col + 10);
+
+ put_str(_(
+ "注意 : 体格等のオートローラを併用時は、上記確率より困難です。",
+ "Note : Prob may be lower when you use the 'autochara' option."
+ ), 22, 5);
+
for (int i = 0; i < A_MAX; i++) {
- put_str(stat_names[i], 3 + i, col);
+ put_str(stat_names[i], 3 + i, col + 8);
int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
int m = adjust_stat(stat_limit[i], j);
- char buf[32];
cnv_stat(m, buf);
- c_put_str(TERM_L_BLUE, buf, 3 + i, col + 5);
+ c_put_str(TERM_L_BLUE, buf, 3 + i, col + 13);
}
}
if (!autoroller)
return;
- for (int i = 0; i < A_MAX; i++) {
- stat_match[i] = 0;
- }
+ auto_upper_round++;
}
static bool decide_initial_stat(player_type *creature_ptr)
bool accept = TRUE;
for (int i = 0; i < A_MAX; i++) {
- if (creature_ptr->stat_max[i] >= stat_limit[i])
- stat_match[i]++;
- else
+ if (p_ptr->stat_max[i] < stat_limit[i]) {
accept = FALSE;
+ break;
+ }
}
return accept;
return FALSE;
birth_put_stats(creature_ptr);
- put_str(format("%10ld", auto_round), 10, col + 20);
+ if (auto_upper_round)
+ put_str(format("%ld%09ld", auto_upper_round, auto_round), 10, col + 20);
+ else
+ put_str(format("%10ld", auto_round), 10, col + 20);
term_fresh();
inkey_scan = TRUE;
if (inkey()) {
bool prev = FALSE;
while (TRUE) {
- int col = 42;
+ int col = 22;
if (autoroller || autochara) {
term_clear();
- put_str(_("回数 :", "Round:"), 10, col + 13);
- put_str(_("(ESCで停止)", "(Hit ESC to stop)"), 12, col + 13);
+ put_str(_("回数 :", "Round:"), 10, col + 10);
+ put_str(_("(ESCで停止)", "(Hit ESC to stop)"), 13, col + 13);
} else {
get_stats(creature_ptr);
get_ahw(creature_ptr);
return FALSE;
display_initial_options(creature_ptr);
- if (autoroller || autochara)
+ if (autoroller || autochara) {
auto_round = 0L;
+ auto_upper_round = 0L;
+ autoroll_chance = 0L;
+ }
if (autoroller)
if (!get_stat_limits(creature_ptr))
if (!autoroller)
return;
- const int col = 42;
+ const int col = 22;
for (int i = 0; i < A_MAX; i++) {
int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
int m = adjust_stat(creature_ptr->stat_max[i], j);
char buf[80];
cnv_stat(m, buf);
c_put_str(TERM_L_GREEN, buf, 3 + i, col + 24);
- if (stat_match[i]) {
- int p = stat_match[i] > 1000000L ? stat_match[i] / (auto_round / 1000L) : 1000L * stat_match[i] / auto_round;
- TERM_COLOR attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN;
- sprintf(buf, "%3d.%d%%", p / 10, p % 10);
- c_put_str(attr, buf, 3 + i, col + 13);
- } else {
- c_put_str(TERM_RED, _("(なし)", "(NONE)"), 3 + i, col + 13);
- }
}
}