変愚蛮怒のメインリポジトリです
Revision | 51400183f30f37633b1812e0bc6cb3c32a063aae (tree) |
---|---|
Time | 2020-11-23 17:38:06 |
Author | iks <iks@user...> |
Commiter | iks |
[Implement] #41001 hradish氏提供のオートローラー(新確率表記)を実装。 / New autoroller function.
@@ -21,6 +21,7 @@ s32b stat_match[6]; | ||
21 | 21 | |
22 | 22 | /*! オートローラの試行回数 / Autoroll round */ |
23 | 23 | s32b auto_round; |
24 | +s32b auto_upper_round; | |
24 | 25 | |
25 | 26 | /*! |
26 | 27 | * @brief オートローラで得たい能力値の基準を決める。 |
@@ -29,17 +30,20 @@ s32b auto_round; | ||
29 | 30 | */ |
30 | 31 | bool get_stat_limits(player_type *creature_ptr) |
31 | 32 | { |
33 | + int col_stat = 25; | |
34 | + | |
32 | 35 | clear_from(10); |
33 | 36 | put_str(_("最低限得たい能力値を設定して下さい。", "Set minimum stats."), 10, 10); |
34 | 37 | put_str(_("2/8で項目選択、4/6で値の増減、Enterで次へ", "2/8 for Select, 4/6 for Change value, Enter for Goto next"), 11, 10); |
35 | 38 | put_str(_(" 基本値 種族 職業 性格 合計値 最大値", " Base Rac Cla Per Total Maximum"), 13, 10); |
36 | 39 | |
40 | + put_str(_("確率: 非常に容易(1/10000以上)", "Prob: Quite Easy(>1/10000)"), 23, col_stat); | |
41 | + | |
37 | 42 | int cval[6]; |
38 | 43 | char buf[80]; |
39 | 44 | char cur[80]; |
40 | 45 | char inp[80]; |
41 | 46 | for (int i = 0; i < A_MAX; i++) { |
42 | - stat_match[i] = 0; | |
43 | 47 | cval[i] = 3; |
44 | 48 | int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; |
45 | 49 | int m = adjust_stat(17, j); |
@@ -62,7 +66,17 @@ bool get_stat_limits(player_type *creature_ptr) | ||
62 | 66 | int os = 6; |
63 | 67 | while (TRUE) { |
64 | 68 | 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) { | |
66 | 80 | c_put_str(TERM_WHITE, _("決定する", "Accept"), 21, 35); |
67 | 81 | } else if (os < A_MAX) { |
68 | 82 | c_put_str(TERM_WHITE, cur, 14 + os, 10); |
@@ -176,7 +190,7 @@ bool get_stat_limits(player_type *creature_ptr) | ||
176 | 190 | break; |
177 | 191 | } |
178 | 192 | |
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)) | |
180 | 194 | break; |
181 | 195 | } |
182 | 196 |
@@ -441,3 +455,83 @@ bool get_chara_limits(player_type *creature_ptr, chara_limit_type *chara_limit_p | ||
441 | 455 | chara_limit_ptr->scmax = (s16b)cval[7]; |
442 | 456 | return TRUE; |
443 | 457 | } |
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 | +} |
@@ -13,6 +13,20 @@ typedef struct { | ||
13 | 13 | extern s16b stat_limit[6]; |
14 | 14 | extern s32b stat_match[6]; |
15 | 15 | 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 | +}; | |
16 | 30 | |
17 | 31 | bool get_stat_limits(player_type *creature_ptr); |
18 | 32 | void initialize_chara_limit(chara_limit_type *chara_limit_ptr); |
@@ -1,4 +1,5 @@ | ||
1 | 1 | #include "birth/birth-stat.h" |
2 | +#include "birth/auto-roller.h" | |
2 | 3 | #include "core/player-redraw-types.h" |
3 | 4 | #include "sv-definition/sv-weapon-types.h" |
4 | 5 | #include "player/player-class.h" |
@@ -56,39 +57,17 @@ void get_stats(player_type* creature_ptr) | ||
56 | 57 | s32b tmp = randint0(60 * 60 * 60); |
57 | 58 | BASE_STATUS val; |
58 | 59 | |
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 | + } | |
92 | 71 | } |
93 | 72 | |
94 | 73 | if ((sum > 42 + 5 * 6) && (sum < 57 + 5 * 6)) |
@@ -44,7 +44,7 @@ | ||
44 | 44 | * system may have problems because the user can't stop the |
45 | 45 | * autoroller for this number of rolls. |
46 | 46 | */ |
47 | -#define AUTOROLLER_STEP 5431L | |
47 | +#define AUTOROLLER_STEP 54321L | |
48 | 48 | |
49 | 49 | static void display_initial_birth_message(player_type *creature_ptr) |
50 | 50 | { |
@@ -281,16 +281,30 @@ static void display_auto_roller_success_rate(const int col) | ||
281 | 281 | if (!autoroller) |
282 | 282 | return; |
283 | 283 | |
284 | - put_str(_("最小値", " Limit"), 2, col + 5); | |
285 | - put_str(_("成功率", " Freq"), 2, col + 13); | |
284 | + put_str(_("最小値", " Limit"), 2, col + 13); | |
286 | 285 | 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 | + | |
287 | 302 | 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); | |
289 | 304 | int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; |
290 | 305 | int m = adjust_stat(stat_limit[i], j); |
291 | - char buf[32]; | |
292 | 306 | 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); | |
294 | 308 | } |
295 | 309 | } |
296 | 310 |
@@ -303,9 +317,7 @@ static void auto_roller_count(void) | ||
303 | 317 | if (!autoroller) |
304 | 318 | return; |
305 | 319 | |
306 | - for (int i = 0; i < A_MAX; i++) { | |
307 | - stat_match[i] = 0; | |
308 | - } | |
320 | + auto_upper_round++; | |
309 | 321 | } |
310 | 322 | |
311 | 323 | static bool decide_initial_stat(player_type *creature_ptr) |
@@ -315,10 +327,10 @@ static bool decide_initial_stat(player_type *creature_ptr) | ||
315 | 327 | |
316 | 328 | bool accept = TRUE; |
317 | 329 | 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]) { | |
321 | 331 | accept = FALSE; |
332 | + break; | |
333 | + } | |
322 | 334 | } |
323 | 335 | |
324 | 336 | return accept; |
@@ -352,7 +364,10 @@ static bool display_auto_roller_count(player_type *creature_ptr, const int col) | ||
352 | 364 | return FALSE; |
353 | 365 | |
354 | 366 | 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); | |
356 | 371 | term_fresh(); |
357 | 372 | inkey_scan = TRUE; |
358 | 373 | if (inkey()) { |
@@ -444,11 +459,11 @@ static bool display_auto_roller(player_type *creature_ptr, chara_limit_type char | ||
444 | 459 | bool prev = FALSE; |
445 | 460 | |
446 | 461 | while (TRUE) { |
447 | - int col = 42; | |
462 | + int col = 22; | |
448 | 463 | if (autoroller || autochara) { |
449 | 464 | 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); | |
452 | 467 | } else { |
453 | 468 | get_stats(creature_ptr); |
454 | 469 | get_ahw(creature_ptr); |
@@ -522,8 +537,11 @@ bool player_birth_wizard(player_type *creature_ptr, void (*process_autopick_file | ||
522 | 537 | return FALSE; |
523 | 538 | |
524 | 539 | display_initial_options(creature_ptr); |
525 | - if (autoroller || autochara) | |
540 | + if (autoroller || autochara) { | |
526 | 541 | auto_round = 0L; |
542 | + auto_upper_round = 0L; | |
543 | + autoroll_chance = 0L; | |
544 | + } | |
527 | 545 | |
528 | 546 | if (autoroller) |
529 | 547 | if (!get_stat_limits(creature_ptr)) |
@@ -18,20 +18,12 @@ void birth_put_stats(player_type *creature_ptr) | ||
18 | 18 | if (!autoroller) |
19 | 19 | return; |
20 | 20 | |
21 | - const int col = 42; | |
21 | + const int col = 22; | |
22 | 22 | for (int i = 0; i < A_MAX; i++) { |
23 | 23 | int j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; |
24 | 24 | int m = adjust_stat(creature_ptr->stat_max[i], j); |
25 | 25 | char buf[80]; |
26 | 26 | cnv_stat(m, buf); |
27 | 27 | 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 | - } | |
36 | 28 | } |
37 | 29 | } |