OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / wizard / monster-info-spoiler.cpp
1 #include "wizard/monster-info-spoiler.h"
2 #include "io/files-util.h"
3 #include "monster-race/monster-race.h"
4 #include "monster-race/race-flags1.h"
5 #include "monster-race/race-flags7.h"
6 #include "monster-race/race-flags8.h"
7 #include "system/angband-version.h"
8 #include "system/monster-race-info.h"
9 #include "term/term-color-types.h"
10 #include "term/z-form.h"
11 #include "util/angband-files.h"
12 #include "util/bit-flags-calculator.h"
13 #include "util/sort.h"
14 #include "util/string-processor.h"
15 #include "view/display-lore.h"
16 #include "view/display-messages.h"
17 #include "wizard/spoiler-util.h"
18
19 /*!
20  * @brief シンボル職の記述名を返す /
21  * Extract a textual representation of an attribute
22  * @param r_ptr モンスター種族の構造体ポインタ
23  * @return シンボル職の記述名
24  */
25 static concptr attr_to_text(MonsterRaceInfo *r_ptr)
26 {
27     if (r_ptr->visual_flags.has(MonsterVisualType::CLEAR_COLOR)) {
28         return _("透明な", "Clear");
29     }
30
31     if (r_ptr->visual_flags.has(MonsterVisualType::MULTI_COLOR)) {
32         return _("万色の", "Multi");
33     }
34
35     if (r_ptr->visual_flags.has(MonsterVisualType::RANDOM_COLOR)) {
36         return _("準ランダムな", "S.Rand");
37     }
38
39     switch (r_ptr->d_attr) {
40     case TERM_DARK:
41         return _("黒い", "Dark");
42     case TERM_WHITE:
43         return _("白い", "White");
44     case TERM_SLATE:
45         return _("青灰色の", "Slate");
46     case TERM_ORANGE:
47         return _("オレンジの", "Orange");
48     case TERM_RED:
49         return _("赤い", "Red");
50     case TERM_GREEN:
51         return _("緑の", "Green");
52     case TERM_BLUE:
53         return _("青い", "Blue");
54     case TERM_UMBER:
55         return _("琥珀色の", "Umber");
56     case TERM_L_DARK:
57         return _("灰色の", "L.Dark");
58     case TERM_L_WHITE:
59         return _("明るい青灰色の", "L.Slate");
60     case TERM_VIOLET:
61         return _("紫の", "Violet");
62     case TERM_YELLOW:
63         return _("黄色の", "Yellow");
64     case TERM_L_RED:
65         return _("明るい赤の", "L.Red");
66     case TERM_L_GREEN:
67         return _("明るい緑の", "L.Green");
68     case TERM_L_BLUE:
69         return _("明るい青の", "L.Blue");
70     case TERM_L_UMBER:
71         return _("明るい琥珀色の", "L.Umber");
72     }
73
74     return _("変な色の", "Icky");
75 }
76
77 SpoilerOutputResultType spoil_mon_desc(std::string_view filename, std::function<bool(const MonsterRaceInfo *)> filter_monster)
78 {
79     PlayerType dummy;
80     uint16_t why = 2;
81     const auto &path = path_build(ANGBAND_DIR_USER, filename);
82     std::ofstream ofs(path);
83     if (!ofs) {
84         return SpoilerOutputResultType::FILE_OPEN_FAILED;
85     }
86
87     ofs << format("Monster Spoilers for %s\n", get_version().data());
88     ofs << "------------------------------------------\n\n";
89     ofs << format("%-45.45s%4s %4s %4s %7s %7s  %19.19s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info");
90     ofs << format("%-45.45s%4s %4s %4s %7s %7s  %4.19s\n",
91         "---------------------------------------------"
92         "----"
93         "----------",
94         "---", "---", "---", "-----", "-----", "-------------------");
95
96     std::vector<MonsterRaceId> who;
97     for (const auto &[monrace_id, monrace] : monraces_info) {
98         if (MonsterRace(monrace_id).is_valid()) {
99             who.push_back(monrace_id);
100         }
101     }
102
103     ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
104     for (auto r_idx : who) {
105         auto *r_ptr = &monraces_info[r_idx];
106         if (filter_monster && !filter_monster(r_ptr)) {
107             continue;
108         }
109
110         if (r_ptr->misc_flags.has(MonsterMiscType::KAGE)) {
111             continue;
112         }
113
114         const auto name = str_separate(r_ptr->name, 40);
115         std::string nam;
116         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
117             nam = "[U] ";
118         } else if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
119             nam = "[N] ";
120         } else {
121             nam = _("    ", "The ");
122         }
123         nam.append(name.front());
124
125         const auto lev = format("%d", r_ptr->level);
126         const auto rar = format("%d", (int)r_ptr->rarity);
127         const auto spd = format("%+d", r_ptr->speed - STANDARD_SPEED);
128         const auto ac = format("%d", r_ptr->ac);
129         std::string hp;
130         if (r_ptr->misc_flags.has(MonsterMiscType::FORCE_MAXHP) || (r_ptr->hside == 1)) {
131             hp = format("%d", r_ptr->hdice * r_ptr->hside);
132         } else {
133             hp = format("%dd%d", r_ptr->hdice, r_ptr->hside);
134         }
135
136         const auto symbol = format("%s '%c'", attr_to_text(r_ptr), r_ptr->d_char);
137         ofs << format("%-45.45s%4s %4s %4s %7s %7s  %19.19s\n",
138             nam.data(), lev.data(), rar.data(), spd.data(), hp.data(),
139             ac.data(), symbol.data());
140
141         for (auto i = 1U; i < name.size(); ++i) {
142             ofs << format("    %s\n", name[i].data());
143         }
144     }
145
146     ofs << '\n';
147     return ofs.good() ? SpoilerOutputResultType::SUCCESSFUL : SpoilerOutputResultType::FILE_CLOSE_FAILED;
148 }
149
150 /*!
151  * @brief 関数ポインタ用の出力関数 /
152  * Hook function used in spoil_mon_info()
153  * @param attr 未使用
154  * @param str 文字列参照ポインタ
155  */
156 static void roff_func(TERM_COLOR attr, std::string_view str)
157 {
158     (void)attr;
159     spoil_out(str);
160 }
161
162 /*!
163  * @brief モンスター詳細情報をスポイラー出力するメインルーチン /
164  * Create a spoiler file for monsters (-SHAWN-)
165  * @param fname ファイル名
166  */
167 SpoilerOutputResultType spoil_mon_info()
168 {
169     PlayerType dummy;
170     const auto &path = path_build(ANGBAND_DIR_USER, "mon-info.txt");
171     spoiler_file = angband_fopen(path, FileOpenMode::WRITE);
172     if (!spoiler_file) {
173         return SpoilerOutputResultType::FILE_OPEN_FAILED;
174     }
175
176     spoil_out(std::string("Monster Spoilers for ").append(get_version()).append("\n"));
177     spoil_out("------------------------------------------\n\n");
178
179     std::vector<MonsterRaceId> who;
180     for (const auto &[monrace_id, monrace] : monraces_info) {
181         if (MonsterRace(monrace_id).is_valid()) {
182             who.push_back(monrace_id);
183         }
184     }
185
186     uint16_t why = 2;
187     ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
188     for (auto r_idx : who) {
189         auto *r_ptr = &monraces_info[r_idx];
190         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
191             spoil_out("[U] ");
192         } else if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
193             spoil_out("[N] ");
194         }
195
196         spoil_out(format(_("%s/%s  (", "%s%s ("), r_ptr->name.data(), _(r_ptr->E_name.data(), ""))); /* ---)--- */
197         spoil_out(attr_to_text(r_ptr));
198         spoil_out(format(" '%c')\n", r_ptr->d_char));
199         spoil_out("=== ");
200         spoil_out(format("Num:%d  ", enum2i(r_idx)));
201         spoil_out(format("Lev:%d  ", (int)r_ptr->level));
202         spoil_out(format("Rar:%d  ", r_ptr->rarity));
203         spoil_out(format("Spd:%+d  ", r_ptr->speed - STANDARD_SPEED));
204         if (r_ptr->misc_flags.has(MonsterMiscType::FORCE_MAXHP) || (r_ptr->hside == 1)) {
205             spoil_out(format("Hp:%d  ", r_ptr->hdice * r_ptr->hside));
206         } else {
207             spoil_out(format("Hp:%dd%d  ", r_ptr->hdice, r_ptr->hside));
208         }
209
210         spoil_out(format("Ac:%d  ", r_ptr->ac));
211         spoil_out(format("Exp:%ld\n", (long)(r_ptr->mexp)));
212         output_monster_spoiler(r_idx, roff_func);
213         spoil_out({}, true);
214     }
215
216     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
217                                                                 : SpoilerOutputResultType::SUCCESSFUL;
218 }