• R/O
  • HTTP
  • SSH
  • HTTPS

hengband: Commit

変愚蛮怒のメインリポジトリです


Commit MetaInfo

Revision51400183f30f37633b1812e0bc6cb3c32a063aae (tree)
Time2020-11-23 17:38:06
Authoriks <iks@user...>
Commiteriks

Log Message

[Implement] #41001 hradish氏提供のオートローラー(新確率表記)を実装。 / New autoroller function.

Change Summary

Incremental Difference

--- a/src/birth/auto-roller.c
+++ b/src/birth/auto-roller.c
@@ -21,6 +21,7 @@ s32b stat_match[6];
2121
2222 /*! オートローラの試行回数 / Autoroll round */
2323 s32b auto_round;
24+s32b auto_upper_round;
2425
2526 /*!
2627 * @brief オートローラで得たい能力値の基準を決める。
@@ -29,17 +30,20 @@ s32b auto_round;
2930 */
3031 bool get_stat_limits(player_type *creature_ptr)
3132 {
33+ int col_stat = 25;
34+
3235 clear_from(10);
3336 put_str(_("最低限得たい能力値を設定して下さい。", "Set minimum stats."), 10, 10);
3437 put_str(_("2/8で項目選択、4/6で値の増減、Enterで次へ", "2/8 for Select, 4/6 for Change value, Enter for Goto next"), 11, 10);
3538 put_str(_(" 基本値 種族 職業 性格 合計値 最大値", " Base Rac Cla Per Total Maximum"), 13, 10);
3639
40+ put_str(_("確率: 非常に容易(1/10000以上)", "Prob: Quite Easy(>1/10000)"), 23, col_stat);
41+
3742 int cval[6];
3843 char buf[80];
3944 char cur[80];
4045 char inp[80];
4146 for (int i = 0; i < A_MAX; i++) {
42- stat_match[i] = 0;
4347 cval[i] = 3;
4448 int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
4549 int m = adjust_stat(17, j);
@@ -62,7 +66,17 @@ bool get_stat_limits(player_type *creature_ptr)
6266 int os = 6;
6367 while (TRUE) {
6468 if (cs != os) {
65- if (os == 6) {
69+ if (os == 7) {
70+ autoroll_chance = get_autoroller_prob(cval);
71+ if (autoroll_chance == -999)
72+ sprintf(buf, _("確率: 不可能(合計86超) ", "Prob: Impossible(>86 tot stats)"));
73+ else if (autoroll_chance < 1)
74+ sprintf(buf, _("確率: 非常に容易(1/10000以上)", "Prob: Quite Easy(>1/10000) "));
75+ else
76+ sprintf(buf, _("確率: 約 1/%8d00 ", "Prob: ~ 1/%8d00 "), autoroll_chance);
77+ put_str(buf, 23, col_stat);
78+ }
79+ else if (os == 6) {
6680 c_put_str(TERM_WHITE, _("決定する", "Accept"), 21, 35);
6781 } else if (os < A_MAX) {
6882 c_put_str(TERM_WHITE, cur, 14 + os, 10);
@@ -176,7 +190,7 @@ bool get_stat_limits(player_type *creature_ptr)
176190 break;
177191 }
178192
179- if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6))
193+ if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == 6 && autoroll_chance != -999))
180194 break;
181195 }
182196
@@ -441,3 +455,83 @@ bool get_chara_limits(player_type *creature_ptr, chara_limit_type *chara_limit_p
441455 chara_limit_ptr->scmax = (s16b)cval[7];
442456 return TRUE;
443457 }
458+
459+/*
460+ * @breif オートローラーで指定した能力値以上が出る確率を計算する。
461+ * @return 確率 / 100
462+ */
463+ static s32b get_autoroller_prob(int *minval)
464+{
465+ /* 1 percent of the valid random space (60^6 && 72<sum<87) */
466+ s32b tot_rand_1p = 320669745;
467+ int i, j, tmp;
468+ int ii[6];
469+ int tval[6];
470+ int tot = 0;
471+
472+ /* success count */
473+ s32b succ = 0;
474+
475+ /* random combinations out of 60 (1d3+1d4+1d5) patterns */
476+ int pp[18] = {
477+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
478+ 1, 3, 6, 9, 11, 11, 9, 6, 3, 1 /* 8-17 */
479+ };
480+
481+ /* Copy */
482+ for (i = 0; i < 6; i++)
483+ {
484+ tval[i] = MAX(8, minval[i]);
485+ tot += tval[i];
486+ }
487+
488+ /* No Chance */
489+ if (tot > 86) return -999;
490+
491+ /* bubble sort for speed-up */
492+ for (i = 0; i < 5; i++)
493+ {
494+ for (j = 5; j > i; j--)
495+ {
496+ if (tval[j - 1] < tval[j])
497+ {
498+ tmp = tval[j - 1];
499+ tval[j - 1] = tval[j];
500+ tval[j] = tmp;
501+ }
502+ }
503+ }
504+
505+ tot = 0;
506+
507+ /* calc. prob. */
508+ for (ii[0] = tval[0]; ii[0] < 18; ii[0]++)
509+ {
510+ for (ii[1] = tval[1]; ii[1] < 18; ii[1]++)
511+ {
512+ for (ii[2] = tval[2]; ii[2] < 18; ii[2]++)
513+ {
514+ for (ii[3] = tval[3]; ii[3] < 18; ii[3]++)
515+ {
516+ for (ii[4] = tval[4]; ii[4] < 18; ii[4]++)
517+ {
518+ for (ii[5] = tval[5]; ii[5] < 18; ii[5]++)
519+ {
520+ tot = ii[0] + ii[1] + ii[2] + ii[3] + ii[4] + ii[5];
521+
522+ if (tot > 86) break;
523+ if (tot <= 72) continue;
524+
525+ succ += (pp[ii[0]] * pp[ii[1]] * pp[ii[2]] * pp[ii[3]] * pp[ii[4]] * pp[ii[5]]);
526+
527+ /* If given condition is easy enough, quit calc. to save CPU. */
528+ if (succ > 320670) return -1;
529+ }
530+ }
531+ }
532+ }
533+ }
534+ }
535+
536+ return tot_rand_1p / succ;
537+}
--- a/src/birth/auto-roller.h
+++ b/src/birth/auto-roller.h
@@ -13,6 +13,20 @@ typedef struct {
1313 extern s16b stat_limit[6];
1414 extern s32b stat_match[6];
1515 extern s32b auto_round;
16+extern s32b auto_upper_round;
17+
18+/*! オートローラの要求値実現確率 */
19+static s32b autoroll_chance;
20+
21+/* emulate 5 + 1d3 + 1d4 + 1d5 by randint0(60) */
22+static BASE_STATUS rand3_4_5[60] = {
23+ 8, 9, 9, 9, 10, 10, 10, 10, 10, 10, /*00-09*/
24+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, /*10-19*/
25+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, /*20-29*/
26+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /*30-49*/
27+ 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, /*40-49*/
28+ 15, 15, 15, 15, 15, 15, 16, 16, 16, 17 /*50-59*/
29+};
1630
1731 bool get_stat_limits(player_type *creature_ptr);
1832 void initialize_chara_limit(chara_limit_type *chara_limit_ptr);
--- a/src/birth/birth-stat.c
+++ b/src/birth/birth-stat.c
@@ -1,4 +1,5 @@
11 #include "birth/birth-stat.h"
2+#include "birth/auto-roller.h"
23 #include "core/player-redraw-types.h"
34 #include "sv-definition/sv-weapon-types.h"
45 #include "player/player-class.h"
@@ -56,39 +57,17 @@ void get_stats(player_type* creature_ptr)
5657 s32b tmp = randint0(60 * 60 * 60);
5758 BASE_STATUS val;
5859
59- /* Extract 5 + 1d3 + 1d4 + 1d5 */
60- val = 5 + 3;
61- val += tmp % 3;
62- tmp /= 3;
63- val += tmp % 4;
64- tmp /= 4;
65- val += tmp % 5;
66- tmp /= 5;
67-
68- sum += val;
69- creature_ptr->stat_cur[3 * i] = creature_ptr->stat_max[3 * i] = val;
70-
71- /* Extract 5 + 1d3 + 1d4 + 1d5 */
72- val = 5 + 3;
73- val += tmp % 3;
74- tmp /= 3;
75- val += tmp % 4;
76- tmp /= 4;
77- val += tmp % 5;
78- tmp /= 5;
79-
80- sum += val;
81- creature_ptr->stat_cur[3 * i + 1] = creature_ptr->stat_max[3 * i + 1] = val;
82-
83- val = 5 + 3;
84- val += tmp % 3;
85- tmp /= 3;
86- val += tmp % 4;
87- tmp /= 4;
88- val += (BASE_STATUS)tmp;
89-
90- sum += val;
91- creature_ptr->stat_cur[3 * i + 2] = creature_ptr->stat_max[3 * i + 2] = val;
60+ for (int j = 0; j < 3; j++) {
61+ int stat = i * 3 + j;
62+
63+ /* Extract 5 + 1d3 + 1d4 + 1d5 */
64+ val = rand3_4_5[tmp % 60];
65+
66+ sum += val;
67+ creature_ptr->stat_cur[stat] = creature_ptr->stat_max[stat] = val;
68+
69+ tmp /= 60;
70+ }
9271 }
9372
9473 if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6))
--- a/src/birth/birth-wizard.c
+++ b/src/birth/birth-wizard.c
@@ -44,7 +44,7 @@
4444 * system may have problems because the user can't stop the
4545 * autoroller for this number of rolls.
4646 */
47-#define AUTOROLLER_STEP 5431L
47+#define AUTOROLLER_STEP 54321L
4848
4949 static void display_initial_birth_message(player_type *creature_ptr)
5050 {
@@ -281,16 +281,30 @@ static void display_auto_roller_success_rate(const int col)
281281 if (!autoroller)
282282 return;
283283
284- put_str(_("最小値", " Limit"), 2, col + 5);
285- put_str(_("成功率", " Freq"), 2, col + 13);
284+ put_str(_("最小値", " Limit"), 2, col + 13);
286285 put_str(_("現在値", " Roll"), 2, col + 24);
286+
287+ char buf[32];
288+
289+ if (autoroll_chance >= 1)
290+ sprintf(buf, _("確率 : 1/%8d00", "Prob : 1/%8d00"), autoroll_chance);
291+ else if (autoroll_chance == -999)
292+ sprintf(buf, _("確率 : 不可能", "Prob : Impossible"));
293+ else
294+ sprintf(buf, _("確率 : 1/10000以上", "Prob : >1/10000"));
295+ put_str(buf, 11, col + 10);
296+
297+ put_str(_(
298+ "注意 : 体格等のオートローラを併用時は、上記確率より困難です。",
299+ "Note : Prob may be lower when you use the 'autochara' option."
300+ ), 22, 5);
301+
287302 for (int i = 0; i < A_MAX; i++) {
288- put_str(stat_names[i], 3 + i, col);
303+ put_str(stat_names[i], 3 + i, col + 8);
289304 int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
290305 int m = adjust_stat(stat_limit[i], j);
291- char buf[32];
292306 cnv_stat(m, buf);
293- c_put_str(TERM_L_BLUE, buf, 3 + i, col + 5);
307+ c_put_str(TERM_L_BLUE, buf, 3 + i, col + 13);
294308 }
295309 }
296310
@@ -303,9 +317,7 @@ static void auto_roller_count(void)
303317 if (!autoroller)
304318 return;
305319
306- for (int i = 0; i < A_MAX; i++) {
307- stat_match[i] = 0;
308- }
320+ auto_upper_round++;
309321 }
310322
311323 static bool decide_initial_stat(player_type *creature_ptr)
@@ -315,10 +327,10 @@ static bool decide_initial_stat(player_type *creature_ptr)
315327
316328 bool accept = TRUE;
317329 for (int i = 0; i < A_MAX; i++) {
318- if (creature_ptr->stat_max[i] >= stat_limit[i])
319- stat_match[i]++;
320- else
330+ if (p_ptr->stat_max[i] < stat_limit[i]) {
321331 accept = FALSE;
332+ break;
333+ }
322334 }
323335
324336 return accept;
@@ -352,7 +364,10 @@ static bool display_auto_roller_count(player_type *creature_ptr, const int col)
352364 return FALSE;
353365
354366 birth_put_stats(creature_ptr);
355- put_str(format("%10ld", auto_round), 10, col + 20);
367+ if (auto_upper_round)
368+ put_str(format("%ld%09ld", auto_upper_round, auto_round), 10, col + 20);
369+ else
370+ put_str(format("%10ld", auto_round), 10, col + 20);
356371 term_fresh();
357372 inkey_scan = TRUE;
358373 if (inkey()) {
@@ -444,11 +459,11 @@ static bool display_auto_roller(player_type *creature_ptr, chara_limit_type char
444459 bool prev = FALSE;
445460
446461 while (TRUE) {
447- int col = 42;
462+ int col = 22;
448463 if (autoroller || autochara) {
449464 term_clear();
450- put_str(_("回数 :", "Round:"), 10, col + 13);
451- put_str(_("(ESCで停止)", "(Hit ESC to stop)"), 12, col + 13);
465+ put_str(_("回数 :", "Round:"), 10, col + 10);
466+ put_str(_("(ESCで停止)", "(Hit ESC to stop)"), 13, col + 13);
452467 } else {
453468 get_stats(creature_ptr);
454469 get_ahw(creature_ptr);
@@ -522,8 +537,11 @@ bool player_birth_wizard(player_type *creature_ptr, void (*process_autopick_file
522537 return FALSE;
523538
524539 display_initial_options(creature_ptr);
525- if (autoroller || autochara)
540+ if (autoroller || autochara) {
526541 auto_round = 0L;
542+ auto_upper_round = 0L;
543+ autoroll_chance = 0L;
544+ }
527545
528546 if (autoroller)
529547 if (!get_stat_limits(creature_ptr))
--- a/src/view/display-birth.c
+++ b/src/view/display-birth.c
@@ -18,20 +18,12 @@ void birth_put_stats(player_type *creature_ptr)
1818 if (!autoroller)
1919 return;
2020
21- const int col = 42;
21+ const int col = 22;
2222 for (int i = 0; i < A_MAX; i++) {
2323 int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i];
2424 int m = adjust_stat(creature_ptr->stat_max[i], j);
2525 char buf[80];
2626 cnv_stat(m, buf);
2727 c_put_str(TERM_L_GREEN, buf, 3 + i, col + 24);
28- if (stat_match[i]) {
29- int p = stat_match[i] > 1000000L ? stat_match[i] / (auto_round / 1000L) : 1000L * stat_match[i] / auto_round;
30- TERM_COLOR attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN;
31- sprintf(buf, "%3d.%d%%", p / 10, p % 10);
32- c_put_str(attr, buf, 3 + i, col + 13);
33- } else {
34- c_put_str(TERM_RED, _("(なし)", "(NONE)"), 3 + i, col + 13);
35- }
3628 }
3729 }
Show on old repository browser