1 #include "view/display-scores.h"
2 #include "core/score-util.h"
3 #include "io/files-util.h"
4 #include "io/input-key-acceptor.h"
5 #include "locale/japanese.h"
6 #include "player-info/class-info.h"
7 #include "player/player-personality.h"
8 #include "player/race-info-table.h"
9 #include "system/angband.h"
10 #include "term/gameterm.h"
11 #include "term/screen-processor.h"
12 #include "term/term-color-types.h"
13 #include "term/z-form.h"
14 #include "util/angband-files.h"
15 #include "util/int-char-converter.h"
18 * @brief 指定された順位範囲でスコアを並べて表示する / Display the scores in a given range.
21 * @param note 黄色表示でハイライトする順位
22 * @param score スコア配列参照ポインタ
25 * Assumes the high score list is already open.
26 * Only five entries per line, too much info.
28 * Mega-Hack -- allow "fake" entry at the given position.
31 void display_scores(int from, int to, int note, high_score *score)
33 if (highscore_fd < 0) {
45 if (to > MAX_HISCORES) {
49 if (highscore_seek(0)) {
55 for (; num_scores < MAX_HISCORES; num_scores++) {
56 if (highscore_read(&the_score)) {
61 if ((note == num_scores) && score) {
65 if (num_scores > to) {
69 constexpr auto per_screen = (MAIN_TERM_MIN_ROWS - 4) / 4;
70 for (auto k = from, place = k + 1; k < num_scores; k += per_screen) {
71 TermCenteredOffsetSetter tcos(MAIN_TERM_MIN_COLS, MAIN_TERM_MIN_ROWS);
74 put_str(_(" 変愚蛮怒: 勇者の殿堂", " Hengband Hall of Fame"), 0, 0);
76 put_str(format(_("( %d 位以下 )", "(from position %d)"), k + 1), 0, 40);
79 for (auto n = 0, j = k; (j < num_scores) && (n < per_screen); place++, j++, n++) {
80 auto attr = (j == note) ? TERM_YELLOW : TERM_WHITE;
81 if ((note == j) && score) {
87 } else if (highscore_seek(j) || highscore_read(&the_score)) {
91 auto pr = atoi(the_score.p_r);
92 auto pc = atoi(the_score.p_c);
93 auto pa = atoi(the_score.p_a);
95 auto clev = atoi(the_score.cur_lev);
96 auto mlev = atoi(the_score.max_lev);
97 auto cdun = atoi(the_score.cur_dun);
98 auto mdun = atoi(the_score.max_dun);
101 for (user = the_score.uid; iswspace(*user); user++) { /* loop */
106 for (when = the_score.day; iswspace(*when); when++) { /* loop */
111 for (gold = the_score.gold; iswspace(*gold); gold++) { /* loop */
116 for (aged = the_score.turns; iswspace(*aged); aged++) { /* loop */
120 std::string alt_when;
121 if ((*when == '@') && strlen(when) == 9) {
122 alt_when = format("%.4s-%.2s-%.2s", when + 1, when + 5, when + 7);
123 when = alt_when.data();
128 /* out_val = format("%3d.%9s %s%s%sという名の%sの%s (レベル %d)", */
129 out_val = format("%3d.%9s %s%s%s - %s%s (レベル %d)", place, the_score.pts, personality_info[pa].title, (personality_info[pa].no ? "の" : ""),
130 the_score.who, race_info[pr].title, class_info[pc].title, clev);
133 out_val = format("%3d.%9s %s %s the %s %s, Level %d", place, the_score.pts, personality_info[pa].title, the_score.who, race_info[pr].title,
134 class_info[pc].title, clev);
137 out_val.append(format(_(" (最高%d)", " (Max %d)"), mlev));
140 c_put_str(attr, out_val, n * 4 + 2, 0);
143 out_val = format(" 最高%3d階", mdun);
148 /* 死亡原因をオリジナルより細かく表示 */
149 if (streq(the_score.how, "yet")) {
150 out_val.append(format(" まだ生きている (%d%s)", cdun, "階"));
151 } else if (streq(the_score.how, "ripe")) {
152 out_val.append(format(" 勝利の後に引退 (%d%s)", cdun, "階"));
153 } else if (streq(the_score.how, "Seppuku")) {
154 out_val.append(format(" 勝利の後に切腹 (%d%s)", cdun, "階"));
156 codeconv(the_score.how);
158 out_val.append(format(" 地上で%sに殺された", the_score.how));
160 out_val.append(format(" %d階で%sに殺された", cdun, the_score.how));
165 out_val = format(" Killed by %s on the surface", the_score.how);
167 out_val = format(" Killed by %s on %s %d", the_score.how, "Dungeon Level", cdun);
171 out_val.append(format(" (Max %d)", mdun));
174 c_put_str(attr, out_val, n * 4 + 3, 0);
176 /* 日付を 19yy/mm/dd の形式に変更する */
177 if (strlen(when) == 8 && when[2] == '/' && when[5] == '/') {
178 alt_when = format("%d%s/%.5s", 19 + (when[6] < '8'), when + 6, when);
179 when = alt_when.data();
182 out_val = format(" (ユーザー:%s, 日付:%s, 所持金:%s, ターン:%s)", user, when, gold, aged);
184 out_val = format(" (User %s, Date %s, Gold %s, Turn %s).", user, when, gold, aged);
187 c_put_str(attr, out_val, n * 4 + 4, 0);
190 prt(_("[ ESCで中断, その他のキーで続けます ]", "[Press ESC to quit, any other key to continue.]"), MAIN_TERM_MIN_ROWS - 1, _(21, 17));
192 prt("", MAIN_TERM_MIN_ROWS - 1, 0);
201 * @brief スコア表示処理メインルーチン / Display the scores in a given range and quit.
205 * スコア表示した後、或いは表示に失敗したら終了する (Windows版は表示処理の中で終了することはない)
206 * main.cpp からしか呼ばれていない。暫定でプリプロで包んでおく
207 * 取り敢えずWindows版はオーバーロード解決できている。他は不明
209 void display_scores(int from, int to)
211 const auto &path = path_build(ANGBAND_DIR_APEX, "scores.raw");
212 const auto &filename = path.string();
213 highscore_fd = fd_open(filename, O_RDONLY);
214 if (highscore_fd < 0) {
215 quit(_("スコア・ファイルが使用できません。", "Score file unavailable."));
219 display_scores(from, to, -1, nullptr);
220 (void)fd_close(highscore_fd);