OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / cmd-io / cmd-lore.cpp
1 #include "cmd-io/cmd-lore.h"
2 #include "core/asking-player.h"
3 #include "core/stuff-handler.h"
4 #include "game-option/cheat-options.h"
5 #include "game-option/game-play-options.h"
6 #include "io/input-key-acceptor.h"
7 #include "lore/lore-util.h"
8 #include "system/monster-race-info.h"
9 #include "system/player-type-definition.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 "tracking/lore-tracker.h"
15 #include "util/int-char-converter.h"
16 #include "util/string-processor.h"
17 #include "view/display-lore.h"
18
19 /*!
20  * @brief モンスターの思い出を見るコマンドのメインルーチン
21  * Identify a character, allow recall of monsters
22  * @param player_ptr プレイヤーへの参照ポインタ
23  * @details
24  * <pre>
25  * Several "special" responses recall "multiple" monsters:
26  *   ^A (all monsters)
27  *   ^U (all unique monsters)
28  *   ^N (all non-unique monsters)
29  *
30  * The responses may be sorted in several ways, see below.
31  *
32  * Note that the player ghosts are ignored.
33  * </pre>
34  */
35 void do_cmd_query_symbol(PlayerType *player_ptr)
36 {
37     bool all = false;
38     bool uniq = false;
39     bool norm = false;
40     bool ride = false;
41     bool recall = false;
42
43     constexpr auto prompt = _("知りたい文字を入力して下さい(記号 or ^A全,^Uユ,^N非ユ,^R乗馬,^M名前): ",
44         "Enter character to be identified(^A:All,^U:Uniqs,^N:Non uniqs,^M:Name): ");
45     const auto symbol = input_command(prompt);
46     if (!symbol) {
47         return;
48     }
49
50     int ident_i;
51     for (ident_i = 0; ident_info[ident_i]; ++ident_i) {
52         if (symbol == ident_info[ident_i][0]) {
53             break;
54         }
55     }
56
57     std::string buf;
58     std::string monster_name("");
59     if (symbol == KTRL('A')) {
60         all = true;
61         buf = _("全モンスターのリスト", "Full monster list.");
62     } else if (symbol == KTRL('U')) {
63         all = uniq = true;
64         buf = _("ユニーク・モンスターのリスト", "Unique monster list.");
65     } else if (symbol == KTRL('N')) {
66         all = norm = true;
67         buf = _("ユニーク外モンスターのリスト", "Non-unique monster list.");
68     } else if (symbol == KTRL('R')) {
69         all = ride = true;
70         buf = _("乗馬可能モンスターのリスト", "Ridable monster list.");
71     } else if (symbol == KTRL('M')) {
72         all = true;
73         const auto monster_name_opt = input_string(_("名前(英語の場合小文字で可)", "Enter name:"), MAX_MONSTER_NAME);
74         if (!monster_name_opt) {
75             return;
76         }
77
78         monster_name = *monster_name_opt;
79         buf = format(_("名前:%sにマッチ", "Monsters' names with \"%s\""), monster_name.data());
80     } else if (ident_info[ident_i]) {
81         buf = format("%c - %s.", *symbol, ident_info[ident_i] + 2);
82     } else {
83         buf = format("%c - %s", *symbol, _("無効な文字", "Unknown Symbol"));
84     }
85
86     prt(buf, 0, 0);
87     std::vector<MonsterRaceId> monrace_ids;
88     const auto &monraces = MonraceList::get_instance();
89     for (const auto &[monrace_id, monrace] : monraces) {
90         if (!cheat_know && !monrace.r_sights) {
91             continue;
92         }
93
94         if (norm && monrace.kind_flags.has(MonsterKindType::UNIQUE)) {
95             continue;
96         }
97
98         if (uniq && monrace.kind_flags.has_not(MonsterKindType::UNIQUE)) {
99             continue;
100         }
101
102         if (ride && monrace.misc_flags.has_not(MonsterMiscType::RIDING)) {
103             continue;
104         }
105
106         if (!monster_name.empty()) {
107             for (size_t xx = 0; xx < monster_name.length(); xx++) {
108 #ifdef JP
109                 if (iskanji(monster_name[xx])) {
110                     xx++;
111                     continue;
112                 }
113 #endif
114                 if (isupper(monster_name[xx])) {
115                     monster_name[xx] = (char)tolower(monster_name[xx]);
116                 }
117             }
118
119             std::string temp2 = monrace.name.en_string();
120             for (size_t xx = 0; xx < temp2.length(); xx++) {
121                 if (isupper(temp2[xx])) {
122                     temp2[xx] = (char)tolower(temp2[xx]);
123                 }
124             }
125
126 #ifdef JP
127             if (str_find(temp2, monster_name) || str_find(monrace.name.string(), monster_name))
128 #else
129             if (str_find(temp2, monster_name))
130 #endif
131                 monrace_ids.push_back(monrace_id);
132         }
133
134         else if (all || (monrace.symbol_definition.character == symbol)) {
135             monrace_ids.push_back(monrace_id);
136         }
137     }
138
139     if (monrace_ids.empty()) {
140         return;
141     }
142
143     put_str(_("思い出を見ますか? (k:殺害順/y/n): ", "Recall details? (k/y/n): "), 0, _(36, 40));
144     auto query = inkey();
145     prt(buf, 0, 0);
146     auto is_detailed = false;
147     if (query == 'k') {
148         is_detailed = true;
149         query = 'y';
150     }
151
152     if (query != 'y') {
153         return;
154     }
155
156     std::stable_sort(monrace_ids.begin(), monrace_ids.end(),
157         [&monraces, is_detailed](auto x, auto y) { return monraces.order(x, y, is_detailed); });
158     auto i = std::ssize(monrace_ids) - 1;
159     auto &tracker = LoreTracker::get_instance();
160     while (true) {
161         const auto monrace_id = monrace_ids[i];
162         tracker.set_trackee(monrace_id);
163         handle_stuff(player_ptr);
164         while (true) {
165             if (recall) {
166                 screen_save();
167                 screen_roff(player_ptr, monrace_ids[i], MONSTER_LORE_NORMAL);
168             }
169
170             roff_top(monrace_id);
171             term_addstr(-1, TERM_WHITE, _(" ['r'思い出, ESC]", " [(r)ecall, ESC]"));
172             query = inkey();
173             if (recall) {
174                 screen_load();
175             }
176
177             if (query != 'r') {
178                 break;
179             }
180             recall = !recall;
181         }
182
183         if (query == ESCAPE) {
184             break;
185         }
186
187         if (query == '-') {
188             if (++i == std::ssize(monrace_ids)) {
189                 i = 0;
190                 if (!expand_list) {
191                     break;
192                 }
193             }
194         } else {
195             if (i-- == 0) {
196                 i = monrace_ids.size() - 1;
197                 if (!expand_list) {
198                     break;
199                 }
200             }
201         }
202     }
203
204     prt(buf, 0, 0);
205 }