OSDN Git Service

[Refactor] #2645 strip_name() の戻り値をvoid からstd::string に変更し、引数からchar* を消した
[hengbandforosx/hengbandosx.git] / src / cmd-visual / cmd-visuals.cpp
1 #include "cmd-visual/cmd-visuals.h"
2 #include "cmd-visual/cmd-draw.h"
3 #include "core/asking-player.h"
4 #include "core/visuals-reseter.h"
5 #include "flavor/flavor-describer.h"
6 #include "flavor/object-flavor-types.h"
7 #include "flavor/object-flavor.h"
8 #include "game-option/special-options.h"
9 #include "io/files-util.h"
10 #include "io/input-key-acceptor.h"
11 #include "io/read-pref-file.h"
12 #include "knowledge/knowledge-features.h"
13 #include "knowledge/knowledge-items.h"
14 #include "knowledge/knowledge-monsters.h"
15 #include "knowledge/lighting-level-table.h"
16 #include "main/sound-of-music.h"
17 #include "monster-race/monster-race.h"
18 #include "object/object-kind.h"
19 #include "system/monster-race-definition.h"
20 #include "system/object-type-definition.h"
21 #include "system/player-type-definition.h"
22 #include "term/screen-processor.h"
23 #include "term/term-color-types.h"
24 #include "util/angband-files.h"
25 #include "util/int-char-converter.h"
26 #include "view/display-messages.h"
27
28 /*!
29  * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
30  * @param i 指定対象となるキャラクタコード
31  * @param num 指定されたビジュアルIDを返す参照ポインタ
32  * @param max ビジュアルIDの最大数
33  * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
34  */
35 static bool cmd_visuals_aux(int i, IDX *num, IDX max)
36 {
37     if (iscntrl(i)) {
38         char str[10] = "";
39         sprintf(str, "%d", *num);
40         if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4)) {
41             return false;
42         }
43
44         IDX tmp = (IDX)strtol(str, nullptr, 0);
45         if (tmp >= 0 && tmp < max) {
46             *num = tmp;
47         }
48     } else if (isupper(i)) {
49         *num = (*num + max - 1) % max;
50     } else {
51         *num = (*num + 1) % max;
52     }
53
54     return true;
55 }
56
57 /*!
58  * @brief キャラクタの変更メニュー表示
59  * @param choice_msg 選択メッセージ
60  */
61 static void print_visuals_menu(concptr choice_msg)
62 {
63     prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
64     prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
65     prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
66     prt(_("(2) アイテムの   色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
67     prt(_("(3) 地形の       色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
68     prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
69     prt(_("(5) アイテムの   色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
70     prt(_("(6) 地形の       色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
71     prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
72     prt(_("(8) アイテムの   色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
73     prt(_("(9) 地形の       色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
74     prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
75     prt(format(_("コマンド: %s", "Command: %s"), choice_msg ? choice_msg : _("", "")), 15, 0);
76 }
77
78 /*
79  * Interact with "visuals"
80  */
81 void do_cmd_visuals(PlayerType *player_ptr)
82 {
83     FILE *auto_dump_stream;
84     char tmp[160];
85     char buf[1024];
86     bool need_redraw = false;
87     concptr empty_symbol = "<< ? >>";
88     if (use_bigtile) {
89         empty_symbol = "<< ?? >>";
90     }
91
92     screen_save();
93     while (true) {
94         term_clear();
95         print_visuals_menu(nullptr);
96         int i = inkey();
97         if (i == ESCAPE) {
98             break;
99         }
100
101         switch (i) {
102         case '0': {
103             prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
104             prt(_("ファイル: ", "File: "), 17, 0);
105             sprintf(tmp, "%s.prf", player_ptr->base_name);
106             if (!askfor(tmp, 70)) {
107                 continue;
108             }
109
110             (void)process_pref_file(player_ptr, tmp, true);
111             need_redraw = true;
112             break;
113         }
114         case '1': {
115             static concptr mark = "Monster attr/chars";
116             prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
117             prt(_("ファイル: ", "File: "), 17, 0);
118             sprintf(tmp, "%s.prf", player_ptr->base_name);
119             if (!askfor(tmp, 70)) {
120                 continue;
121             }
122
123             path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
124             if (!open_auto_dump(&auto_dump_stream, buf, mark)) {
125                 continue;
126             }
127
128             auto_dump_printf(auto_dump_stream, _("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
129             for (const auto &[r_idx, r_ref] : r_info) {
130                 if (r_ref.name.empty()) {
131                     continue;
132                 }
133
134                 auto_dump_printf(auto_dump_stream, "# %s\n", r_ref.name.c_str());
135                 auto_dump_printf(auto_dump_stream, "R:%d:0x%02X/0x%02X\n\n", r_ref.idx, (byte)(r_ref.x_attr), (byte)(r_ref.x_char));
136             }
137
138             close_auto_dump(&auto_dump_stream, mark);
139             msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
140             break;
141         }
142         case '2': {
143             static concptr mark = "Object attr/chars";
144             prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
145             prt(_("ファイル: ", "File: "), 17, 0);
146             sprintf(tmp, "%s.prf", player_ptr->base_name);
147             if (!askfor(tmp, 70)) {
148                 continue;
149             }
150
151             path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
152             if (!open_auto_dump(&auto_dump_stream, buf, mark)) {
153                 continue;
154             }
155
156             auto_dump_printf(auto_dump_stream, _("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
157             for (const auto &k_ref : k_info) {
158                 if (k_ref.name.empty()) {
159                     continue;
160                 }
161
162                 std::string o_name("");
163                 GAME_TEXT char_o_name[MAX_NLEN]{};
164                 if (!k_ref.flavor) {
165                     o_name = strip_name(k_ref.idx);
166                 } else {
167                     ObjectType dummy;
168                     dummy.prep(k_ref.idx);
169                     describe_flavor(player_ptr, char_o_name, &dummy, OD_FORCE_FLAVOR);
170                 }
171
172                 if (o_name == "") {
173                     o_name = char_o_name;
174                 }
175
176                 auto_dump_printf(auto_dump_stream, "# %s\n", o_name.data());
177                 auto_dump_printf(auto_dump_stream, "K:%d:0x%02X/0x%02X\n\n", (int)k_ref.idx, (byte)(k_ref.x_attr), (byte)(k_ref.x_char));
178             }
179
180             close_auto_dump(&auto_dump_stream, mark);
181             msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
182             break;
183         }
184         case '3': {
185             static concptr mark = "Feature attr/chars";
186             prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
187             prt(_("ファイル: ", "File: "), 17, 0);
188             sprintf(tmp, "%s.prf", player_ptr->base_name);
189             if (!askfor(tmp, 70)) {
190                 continue;
191             }
192
193             path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
194             if (!open_auto_dump(&auto_dump_stream, buf, mark)) {
195                 continue;
196             }
197
198             auto_dump_printf(auto_dump_stream, _("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
199             for (const auto &f_ref : f_info) {
200                 if (f_ref.name.empty()) {
201                     continue;
202                 }
203                 if (f_ref.mimic != f_ref.idx) {
204                     continue;
205                 }
206
207                 auto_dump_printf(auto_dump_stream, "# %s\n", (f_ref.name.c_str()));
208                 auto_dump_printf(auto_dump_stream, "F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", f_ref.idx, (byte)(f_ref.x_attr[F_LIT_STANDARD]),
209                     (byte)(f_ref.x_char[F_LIT_STANDARD]), (byte)(f_ref.x_attr[F_LIT_LITE]), (byte)(f_ref.x_char[F_LIT_LITE]),
210                     (byte)(f_ref.x_attr[F_LIT_DARK]), (byte)(f_ref.x_char[F_LIT_DARK]));
211             }
212
213             close_auto_dump(&auto_dump_stream, mark);
214             msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
215             break;
216         }
217         case '4': {
218             IDX num = 0;
219             static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
220             static MonsterRaceId r = r_info.begin()->second.idx;
221             prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
222             while (true) {
223                 auto *r_ptr = &r_info[r];
224                 int c;
225                 IDX t;
226
227                 TERM_COLOR da = r_ptr->d_attr;
228                 byte dc = r_ptr->d_char;
229                 TERM_COLOR ca = r_ptr->x_attr;
230                 byte cc = r_ptr->x_char;
231
232                 term_putstr(5, 17, -1, TERM_WHITE, format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, r_ptr->name.c_str()));
233                 term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値  色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
234                 term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
235                 term_queue_bigchar(43, 19, da, dc, 0, 0);
236                 term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値  色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
237                 term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
238                 term_queue_bigchar(43, 20, ca, cc, 0, 0);
239                 term_putstr(0, 22, -1, TERM_WHITE, _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
240                 i = inkey();
241                 if (i == ESCAPE) {
242                     break;
243                 }
244
245                 if (iscntrl(i)) {
246                     c = 'a' + i - KTRL('A');
247                 } else if (isupper(i)) {
248                     c = 'a' + i - 'A';
249                 } else {
250                     c = i;
251                 }
252
253                 switch (c) {
254                 case 'n': {
255                     auto prev_r = r;
256                     do {
257                         if (!cmd_visuals_aux(i, &num, static_cast<IDX>(r_info.size()))) {
258                             r = prev_r;
259                             break;
260                         }
261                         r = i2enum<MonsterRaceId>(num);
262                     } while (r_info[r].name.empty());
263                 }
264
265                 break;
266                 case 'a':
267                     t = (int)r_ptr->x_attr;
268                     (void)cmd_visuals_aux(i, &t, 256);
269                     r_ptr->x_attr = (byte)t;
270                     need_redraw = true;
271                     break;
272                 case 'c':
273                     t = (int)r_ptr->x_char;
274                     (void)cmd_visuals_aux(i, &t, 256);
275                     r_ptr->x_char = (byte)t;
276                     need_redraw = true;
277                     break;
278                 case 'v':
279                     do_cmd_knowledge_monsters(player_ptr, &need_redraw, true, r);
280                     term_clear();
281                     print_visuals_menu(choice_msg);
282                     break;
283                 }
284             }
285
286             break;
287         }
288         case '5': {
289             static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
290             static IDX k = 0;
291             prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
292             while (true) {
293                 auto *k_ptr = &k_info[k];
294                 int c;
295                 IDX t;
296
297                 TERM_COLOR da = k_ptr->d_attr;
298                 auto dc = k_ptr->d_char;
299                 TERM_COLOR ca = k_ptr->x_attr;
300                 auto cc = k_ptr->x_char;
301
302                 term_putstr(5, 17, -1, TERM_WHITE,
303                     format(
304                         _("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"), k, (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name).c_str()));
305                 term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
306                 term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
307                 term_queue_bigchar(43, 19, da, dc, 0, 0);
308                 term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
309                 term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
310                 term_queue_bigchar(43, 20, ca, cc, 0, 0);
311                 term_putstr(0, 22, -1, TERM_WHITE, _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
312
313                 i = inkey();
314                 if (i == ESCAPE) {
315                     break;
316                 }
317
318                 if (iscntrl(i)) {
319                     c = 'a' + i - KTRL('A');
320                 } else if (isupper(i)) {
321                     c = 'a' + i - 'A';
322                 } else {
323                     c = i;
324                 }
325
326                 switch (c) {
327                 case 'n': {
328                     IDX prev_k = k;
329                     do {
330                         if (!cmd_visuals_aux(i, &k, static_cast<IDX>(k_info.size()))) {
331                             k = prev_k;
332                             break;
333                         }
334                     } while (k_info[k].name.empty());
335                 }
336
337                 break;
338                 case 'a':
339                     t = (int)k_ptr->x_attr;
340                     (void)cmd_visuals_aux(i, &t, 256);
341                     k_ptr->x_attr = (byte)t;
342                     need_redraw = true;
343                     break;
344                 case 'c':
345                     t = (int)k_ptr->x_char;
346                     (void)cmd_visuals_aux(i, &t, 256);
347                     k_ptr->x_char = (byte)t;
348                     need_redraw = true;
349                     break;
350                 case 'v':
351                     do_cmd_knowledge_objects(player_ptr, &need_redraw, true, k);
352                     term_clear();
353                     print_visuals_menu(choice_msg);
354                     break;
355                 }
356             }
357
358             break;
359         }
360         case '6': {
361             static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
362             static IDX f = 0;
363             static IDX lighting_level = F_LIT_STANDARD;
364             prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
365             while (true) {
366                 auto *f_ptr = &f_info[f];
367                 int c;
368                 IDX t;
369
370                 TERM_COLOR da = f_ptr->d_attr[lighting_level];
371                 byte dc = f_ptr->d_char[lighting_level];
372                 TERM_COLOR ca = f_ptr->x_attr[lighting_level];
373                 byte cc = f_ptr->x_char[lighting_level];
374
375                 prt("", 17, 5);
376                 term_putstr(5, 17, -1, TERM_WHITE,
377                     format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"), f, (f_ptr->name.c_str()),
378                         lighting_level_str[lighting_level]));
379                 term_putstr(10, 19, -1, TERM_WHITE, format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
380                 term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
381                 term_queue_bigchar(43, 19, da, dc, 0, 0);
382                 term_putstr(10, 20, -1, TERM_WHITE, format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
383                 term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
384                 term_queue_bigchar(43, 20, ca, cc, 0, 0);
385                 term_putstr(0, 22, -1, TERM_WHITE,
386                     _("コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): "));
387
388                 i = inkey();
389                 if (i == ESCAPE) {
390                     break;
391                 }
392
393                 if (iscntrl(i)) {
394                     c = 'a' + i - KTRL('A');
395                 } else if (isupper(i)) {
396                     c = 'a' + i - 'A';
397                 } else {
398                     c = i;
399                 }
400
401                 switch (c) {
402                 case 'n': {
403                     IDX prev_f = f;
404                     do {
405                         if (!cmd_visuals_aux(i, &f, static_cast<IDX>(f_info.size()))) {
406                             f = prev_f;
407                             break;
408                         }
409                     } while (f_info[f].name.empty() || (f_info[f].mimic != f));
410                 }
411
412                 break;
413                 case 'a':
414                     t = (int)f_ptr->x_attr[lighting_level];
415                     (void)cmd_visuals_aux(i, &t, 256);
416                     f_ptr->x_attr[lighting_level] = (byte)t;
417                     need_redraw = true;
418                     break;
419                 case 'c':
420                     t = (int)f_ptr->x_char[lighting_level];
421                     (void)cmd_visuals_aux(i, &t, 256);
422                     f_ptr->x_char[lighting_level] = (byte)t;
423                     need_redraw = true;
424                     break;
425                 case 'l':
426                     (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
427                     break;
428                 case 'd':
429                     apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
430                     need_redraw = true;
431                     break;
432                 case 'v':
433                     do_cmd_knowledge_features(&need_redraw, true, f, &lighting_level);
434                     term_clear();
435                     print_visuals_menu(choice_msg);
436                     break;
437                 }
438             }
439
440             break;
441         }
442         case '7':
443             do_cmd_knowledge_monsters(player_ptr, &need_redraw, true);
444             break;
445         case '8':
446             do_cmd_knowledge_objects(player_ptr, &need_redraw, true, -1);
447             break;
448         case '9': {
449             IDX lighting_level = F_LIT_STANDARD;
450             do_cmd_knowledge_features(&need_redraw, true, -1, &lighting_level);
451             break;
452         }
453         case 'R':
454         case 'r':
455             reset_visuals(player_ptr);
456             msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
457             need_redraw = true;
458             break;
459         default:
460             bell();
461             break;
462         }
463
464         msg_erase();
465     }
466
467     screen_load();
468     if (need_redraw) {
469         do_cmd_redraw(player_ptr);
470     }
471 }