OSDN Git Service

Merge pull request #1774 from habu1010/feature/refactor-weapon-skill-table
[hengbandforosx/hengbandosx.git] / src / view / display-scores.cpp
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 "player-info/class-info.h"
6 #include "player/player-personality.h"
7 #include "player/race-info-table.h"
8 #include "system/angband.h"
9 #include "term/screen-processor.h"
10 #include "term/term-color-types.h"
11 #include "util/angband-files.h"
12 #include "util/int-char-converter.h"
13
14 #ifdef JP
15 #include "locale/japanese.h"
16 #endif
17
18 /*!
19  * @brief 指定された順位範囲でスコアを並べて表示する / Display the scores in a given range.
20  * @param from 順位先頭
21  * @param to 順位末尾
22  * @param note 黄色表示でハイライトする順位
23  * @param score スコア配列参照ポインタ
24  * @details
25  * <pre>
26  * Assumes the high score list is already open.
27  * Only five entries per line, too much info.
28  *
29  * Mega-Hack -- allow "fake" entry at the given position.
30  * </pre>
31  */
32 void display_scores(int from, int to, int note, high_score *score)
33 {
34     TERM_LEN wid, hgt;
35     term_get_size(&wid, &hgt);
36     auto per_screen = (TERM_LEN)((hgt - 4) / 4);
37     if (highscore_fd < 0) {
38         return;
39     }
40
41     if (from < 0) {
42         from = 0;
43     }
44
45     if (to < 0) {
46         to = 10;
47     }
48
49     if (to > MAX_HISCORES) {
50         to = MAX_HISCORES;
51     }
52
53     if (highscore_seek(0)) {
54         return;
55     }
56
57     auto num_scores = 0;
58     high_score the_score;
59     for (; num_scores < MAX_HISCORES; num_scores++) {
60         if (highscore_read(&the_score)) {
61             break;
62         }
63     }
64
65     if ((note == num_scores) && score) {
66         num_scores++;
67     }
68
69     if (num_scores > to) {
70         num_scores = to;
71     }
72
73     for (auto k = from, place = k + 1; k < num_scores; k += per_screen) {
74         term_clear();
75         put_str(_("                変愚蛮怒: 勇者の殿堂", "                Hengband Hall of Fame"), 0, 0);
76         GAME_TEXT tmp_val[160];
77         if (k > 0) {
78             sprintf(tmp_val, _("( %d 位以下 )", "(from position %d)"), k + 1);
79             put_str(tmp_val, 0, 40);
80         }
81
82         for (auto n = 0, j = k; (j < num_scores) && (n < per_screen); place++, j++, n++) {
83             auto attr = (j == note) ? TERM_YELLOW : TERM_WHITE;
84             if ((note == j) && score) {
85                 the_score = (*score);
86                 attr = TERM_L_GREEN;
87                 score = nullptr;
88                 note = -1;
89                 j--;
90             } else if (highscore_seek(j) || highscore_read(&the_score)) {
91                 break;
92             }
93
94             auto pr = atoi(the_score.p_r);
95             auto pc = atoi(the_score.p_c);
96             auto pa = atoi(the_score.p_a);
97
98             auto clev = atoi(the_score.cur_lev);
99             auto mlev = atoi(the_score.max_lev);
100             auto cdun = atoi(the_score.cur_dun);
101             auto mdun = atoi(the_score.max_dun);
102
103             concptr user;
104             for (user = the_score.uid; iswspace(*user); user++) /* loop */
105                 ;
106
107             concptr when;
108             for (when = the_score.day; iswspace(*when); when++) /* loop */
109                 ;
110
111             concptr gold;
112             for (gold = the_score.gold; iswspace(*gold); gold++) /* loop */
113                 ;
114
115             concptr aged;
116             for (aged = the_score.turns; iswspace(*aged); aged++) /* loop */
117                 ;
118
119             if ((*when == '@') && strlen(when) == 9) {
120                 sprintf(tmp_val, "%.4s-%.2s-%.2s", when + 1, when + 5, when + 7);
121                 when = tmp_val;
122             }
123
124             GAME_TEXT out_val[256];
125 #ifdef JP
126             /*sprintf(out_val, "%3d.%9s  %s%s%sという名の%sの%s (レベル %d)", */
127             sprintf(out_val, "%3d.%9s  %s%s%s - %s%s (レベル %d)", place, the_score.pts, personality_info[pa].title, (personality_info[pa].no ? "の" : ""),
128                 the_score.who, race_info[pr].title, class_info[pc].title, clev);
129
130 #else
131             sprintf(out_val, "%3d.%9s  %s %s the %s %s, Level %d", place, the_score.pts, personality_info[pa].title, the_score.who, race_info[pr].title,
132                 class_info[pc].title, clev);
133 #endif
134             if (mlev > clev) {
135                 strcat(out_val, format(_(" (最高%d)", " (Max %d)"), mlev));
136             }
137
138             c_put_str(attr, out_val, n * 4 + 2, 0);
139 #ifdef JP
140             if (mdun != 0) {
141                 sprintf(out_val, "    最高%3d階", mdun);
142             } else {
143                 sprintf(out_val, "             ");
144             }
145
146             /* 死亡原因をオリジナルより細かく表示 */
147             if (streq(the_score.how, "yet")) {
148                 sprintf(out_val + 13, "  まだ生きている (%d%s)", cdun, "階");
149             } else if (streq(the_score.how, "ripe")) {
150                 sprintf(out_val + 13, "  勝利の後に引退 (%d%s)", cdun, "階");
151             } else if (streq(the_score.how, "Seppuku")) {
152                 sprintf(out_val + 13, "  勝利の後に切腹 (%d%s)", cdun, "階");
153             } else {
154                 codeconv(the_score.how);
155                 if (!cdun) {
156                     sprintf(out_val + 13, "  地上で%sに殺された", the_score.how);
157                 } else {
158                     sprintf(out_val + 13, "  %d階で%sに殺された", cdun, the_score.how);
159                 }
160             }
161 #else
162             if (!cdun) {
163                 sprintf(out_val, "               Killed by %s on the surface", the_score.how);
164             } else {
165                 sprintf(out_val, "               Killed by %s on %s %d", the_score.how, "Dungeon Level", cdun);
166             }
167
168             if (mdun > cdun) {
169                 strcat(out_val, format(" (Max %d)", mdun));
170             }
171 #endif
172             c_put_str(attr, out_val, n * 4 + 3, 0);
173 #ifdef JP
174             char buf[11];
175
176             /* 日付を 19yy/mm/dd の形式に変更する */
177             if (strlen(when) == 8 && when[2] == '/' && when[5] == '/') {
178                 sprintf(buf, "%d%s/%.5s", 19 + (when[6] < '8'), when + 6, when);
179                 when = buf;
180             }
181
182             sprintf(out_val, "        (ユーザー:%s, 日付:%s, 所持金:%s, ターン:%s)", user, when, gold, aged);
183 #else
184             sprintf(out_val, "               (User %s, Date %s, Gold %s, Turn %s).", user, when, gold, aged);
185 #endif
186
187             c_put_str(attr, out_val, n * 4 + 4, 0);
188         }
189
190         prt(_("[ ESCで中断, その他のキーで続けます ]", "[Press ESC to quit, any other key to continue.]"), hgt - 1, _(21, 17));
191         auto key = inkey();
192         prt("", hgt - 1, 0);
193         if (key == ESCAPE) {
194             break;
195         }
196     }
197 }
198
199 #ifndef WINDOWS
200 /*!
201  * @brief スコア表示処理メインルーチン / Display the scores in a given range and quit.
202  * @param from 順位先頭
203  * @param to 順位末尾
204  * @details
205  * スコア表示した後、或いは表示に失敗したら終了する (Windows版は表示処理の中で終了することはない)
206  * main.cpp からしか呼ばれていない。暫定でプリプロで包んでおく
207  * 取り敢えずWindows版はオーバーロード解決できている。他は不明
208  */
209 void display_scores(int from, int to)
210 {
211     char buf[1024];
212     path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw");
213     highscore_fd = fd_open(buf, O_RDONLY);
214     if (highscore_fd < 0) {
215         quit(_("スコア・ファイルが使用できません。", "Score file unavailable."));
216     }
217
218     term_clear();
219     display_scores(from, to, -1, nullptr);
220     (void)fd_close(highscore_fd);
221     highscore_fd = -1;
222     quit(nullptr);
223 }
224 #endif