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-definition.h"
9 #include "term/term-color-types.h"
10 #include "util/angband-files.h"
11 #include "util/bit-flags-calculator.h"
12 #include "util/sort.h"
13 #include "util/string-processor.h"
14 #include "view/display-lore.h"
15 #include "view/display-messages.h"
18 * @brief シンボル職の記述名を返す /
19 * Extract a textual representation of an attribute
20 * @param r_ptr モンスター種族の構造体ポインタ
23 static concptr attr_to_text(monster_race *r_ptr)
25 if (r_ptr->visual_flags.has(MonsterVisualType::CLEAR_COLOR)) {
26 return _("透明な", "Clear");
29 if (r_ptr->visual_flags.has(MonsterVisualType::MULTI_COLOR)) {
30 return _("万色の", "Multi");
33 if (r_ptr->visual_flags.has(MonsterVisualType::RANDOM_COLOR)) {
34 return _("準ランダムな", "S.Rand");
37 switch (r_ptr->d_attr) {
39 return _("黒い", "Dark");
41 return _("白い", "White");
43 return _("青灰色の", "Slate");
45 return _("オレンジの", "Orange");
47 return _("赤い", "Red");
49 return _("緑の", "Green");
51 return _("青い", "Blue");
53 return _("琥珀色の", "Umber");
55 return _("灰色の", "L.Dark");
57 return _("明るい青灰色の", "L.Slate");
59 return _("紫の", "Violet");
61 return _("黄色の", "Yellow");
63 return _("明るい赤の", "L.Red");
65 return _("明るい緑の", "L.Green");
67 return _("明るい青の", "L.Blue");
69 return _("明るい琥珀色の", "L.Umber");
72 return _("変な色の", "Icky");
75 SpoilerOutputResultType spoil_mon_desc(concptr fname, std::function<bool(const monster_race *)> filter_monster)
80 char nam[MAX_MONSTER_NAME + 10]; // ユニークには[U] が付くので少し伸ばす
87 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
88 spoiler_file = angband_fopen(buf, "w");
90 return SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FOPEN;
96 fprintf(spoiler_file, "Monster Spoilers for %s\n", title);
97 fprintf(spoiler_file, "------------------------------------------\n\n");
98 fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s %19.19s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info");
99 fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s %4.19s\n",
100 "---------------------------------------------"
103 "---", "---", "---", "-----", "-----", "-------------------");
105 std::vector<MONRACE_IDX> who;
106 for (const auto &r_ref : r_info) {
107 if (r_ref.idx > 0 && !r_ref.name.empty())
108 who.push_back(r_ref.idx);
111 ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
112 for (auto r_idx : who) {
113 monster_race *r_ptr = &r_info[r_idx];
114 concptr name = r_ptr->name.c_str();
115 if (filter_monster && !filter_monster(r_ptr)) {
120 angband_strcpy(name_buf, name, sizeof(name_buf));
121 name += strlen(name_buf);
123 if (any_bits(r_ptr->flags7, RF7_KAGE)) {
127 if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
128 sprintf(nam, "[U] %s", name_buf);
129 } else if (any_bits(r_ptr->flags7, RF7_NAZGUL)) {
130 sprintf(nam, "[N] %s", name_buf);
132 sprintf(nam, _(" %s", "The %s"), name_buf);
135 sprintf(lev, "%d", (int)r_ptr->level);
136 sprintf(rar, "%d", (int)r_ptr->rarity);
137 if (r_ptr->speed >= 110) {
138 sprintf(spd, "+%d", (r_ptr->speed - 110));
140 sprintf(spd, "-%d", (110 - r_ptr->speed));
143 sprintf(ac, "%d", r_ptr->ac);
144 if (any_bits(r_ptr->flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
145 sprintf(hp, "%d", r_ptr->hdice * r_ptr->hside);
147 sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside);
150 sprintf(symbol, "%ld", (long)(r_ptr->mexp));
151 sprintf(symbol, "%s '%c'", attr_to_text(r_ptr), r_ptr->d_char);
152 fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s %19.19s\n", nam, lev, rar, spd, hp, ac, symbol);
154 while (*name != '\0') {
155 angband_strcpy(name_buf, name, sizeof(name_buf));
156 name += strlen(name_buf);
157 fprintf(spoiler_file, " %s\n", name_buf);
161 fprintf(spoiler_file, "\n");
162 return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FCLOSE
163 : SpoilerOutputResultType::SPOILER_OUTPUT_SUCCESS;
167 * @brief 関数ポインタ用の出力関数 /
168 * Hook function used in spoil_mon_info()
170 * @param str 文字列参照ポインタ
172 static void roff_func(TERM_COLOR attr, concptr str)
179 * @brief モンスター詳細情報をスポイラー出力するメインルーチン /
180 * Create a spoiler file for monsters (-SHAWN-)
183 SpoilerOutputResultType spoil_mon_info(concptr fname)
187 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
188 spoiler_file = angband_fopen(buf, "w");
190 return SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FOPEN;
195 sprintf(buf, "Monster Spoilers for %s\n", title);
197 spoil_out("------------------------------------------\n\n");
199 std::vector<MONRACE_IDX> who;
200 for (const auto &r_ref : r_info) {
201 if (r_ref.idx > 0 && !r_ref.name.empty())
202 who.push_back(r_ref.idx);
206 ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
207 for (auto r_idx : who) {
208 monster_race *r_ptr = &r_info[r_idx];
209 BIT_FLAGS flags1 = r_ptr->flags1;
210 if (any_bits(flags1, RF1_UNIQUE)) {
212 } else if (any_bits(r_ptr->flags7, RF7_NAZGUL)) {
216 sprintf(buf, _("%s/%s (", "%s%s ("), r_ptr->name.c_str(), _(r_ptr->E_name.c_str(), "")); /* ---)--- */
218 spoil_out(attr_to_text(r_ptr));
219 sprintf(buf, " '%c')\n", r_ptr->d_char);
221 sprintf(buf, "=== ");
223 sprintf(buf, "Num:%d ", r_idx);
225 sprintf(buf, "Lev:%d ", (int)r_ptr->level);
227 sprintf(buf, "Rar:%d ", r_ptr->rarity);
229 if (r_ptr->speed >= 110) {
230 sprintf(buf, "Spd:+%d ", (r_ptr->speed - 110));
232 sprintf(buf, "Spd:-%d ", (110 - r_ptr->speed));
236 if (any_bits(flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
237 sprintf(buf, "Hp:%d ", r_ptr->hdice * r_ptr->hside);
239 sprintf(buf, "Hp:%dd%d ", r_ptr->hdice, r_ptr->hside);
243 sprintf(buf, "Ac:%d ", r_ptr->ac);
245 sprintf(buf, "Exp:%ld\n", (long)(r_ptr->mexp));
247 output_monster_spoiler(r_idx, roff_func);
251 return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FCLOSE
252 : SpoilerOutputResultType::SPOILER_OUTPUT_SUCCESS;