OSDN Git Service

Merge pull request #2122 from sikabane-works/release/3.0.0Alpha52
[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-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"
16
17 /*!
18  * @brief シンボル職の記述名を返す /
19  * Extract a textual representation of an attribute
20  * @param r_ptr モンスター種族の構造体ポインタ
21  * @return シンボル職の記述名
22  */
23 static concptr attr_to_text(monster_race *r_ptr)
24 {
25     if (r_ptr->visual_flags.has(MonsterVisualType::CLEAR_COLOR)) {
26         return _("透明な", "Clear");
27     }
28
29     if (r_ptr->visual_flags.has(MonsterVisualType::MULTI_COLOR)) {
30         return _("万色の", "Multi");
31     }
32
33     if (r_ptr->visual_flags.has(MonsterVisualType::RANDOM_COLOR)) {
34         return _("準ランダムな", "S.Rand");
35     }
36
37     switch (r_ptr->d_attr) {
38     case TERM_DARK:
39         return _("黒い", "Dark");
40     case TERM_WHITE:
41         return _("白い", "White");
42     case TERM_SLATE:
43         return _("青灰色の", "Slate");
44     case TERM_ORANGE:
45         return _("オレンジの", "Orange");
46     case TERM_RED:
47         return _("赤い", "Red");
48     case TERM_GREEN:
49         return _("緑の", "Green");
50     case TERM_BLUE:
51         return _("青い", "Blue");
52     case TERM_UMBER:
53         return _("琥珀色の", "Umber");
54     case TERM_L_DARK:
55         return _("灰色の", "L.Dark");
56     case TERM_L_WHITE:
57         return _("明るい青灰色の", "L.Slate");
58     case TERM_VIOLET:
59         return _("紫の", "Violet");
60     case TERM_YELLOW:
61         return _("黄色の", "Yellow");
62     case TERM_L_RED:
63         return _("明るい赤の", "L.Red");
64     case TERM_L_GREEN:
65         return _("明るい緑の", "L.Green");
66     case TERM_L_BLUE:
67         return _("明るい青の", "L.Blue");
68     case TERM_L_UMBER:
69         return _("明るい琥珀色の", "L.Umber");
70     }
71
72     return _("変な色の", "Icky");
73 }
74
75 SpoilerOutputResultType spoil_mon_desc(concptr fname, std::function<bool(const monster_race *)> filter_monster)
76 {
77     PlayerType dummy;
78     uint16_t why = 2;
79     char buf[1024];
80     char nam[MAX_MONSTER_NAME + 10]; // ユニークには[U] が付くので少し伸ばす
81     char lev[80];
82     char rar[80];
83     char spd[80];
84     char ac[80];
85     char hp[80];
86     char symbol[80];
87     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
88     spoiler_file = angband_fopen(buf, "w");
89     if (!spoiler_file) {
90         return SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FOPEN;
91     }
92
93     char title[200];
94     put_version(title);
95
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         "---------------------------------------------"
101         "----"
102         "----------",
103         "---", "---", "---", "-----", "-----", "-------------------");
104
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);
109     }
110
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)) {
116             continue;
117         }
118
119         char name_buf[41];
120         angband_strcpy(name_buf, name, sizeof(name_buf));
121         name += strlen(name_buf);
122
123         if (any_bits(r_ptr->flags7, RF7_KAGE)) {
124             continue;
125         }
126
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);
131         } else {
132             sprintf(nam, _("    %s", "The %s"), name_buf);
133         }
134
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));
139         } else {
140             sprintf(spd, "-%d", (110 - r_ptr->speed));
141         }
142
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);
146         } else {
147             sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside);
148         }
149
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);
153
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);
158         }
159     }
160
161     fprintf(spoiler_file, "\n");
162     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FCLOSE
163                                                                 : SpoilerOutputResultType::SPOILER_OUTPUT_SUCCESS;
164 }
165
166 /*!
167  * @brief 関数ポインタ用の出力関数 /
168  * Hook function used in spoil_mon_info()
169  * @param attr 未使用
170  * @param str 文字列参照ポインタ
171  */
172 static void roff_func(TERM_COLOR attr, concptr str)
173 {
174     (void)attr;
175     spoil_out(str);
176 }
177
178 /*!
179  * @brief モンスター詳細情報をスポイラー出力するメインルーチン /
180  * Create a spoiler file for monsters (-SHAWN-)
181  * @param fname ファイル名
182  */
183 SpoilerOutputResultType spoil_mon_info(concptr fname)
184 {
185     PlayerType dummy;
186     char buf[1024];
187     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
188     spoiler_file = angband_fopen(buf, "w");
189     if (!spoiler_file) {
190         return SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FOPEN;
191     }
192
193     char title[200];
194     put_version(title);
195     sprintf(buf, "Monster Spoilers for %s\n", title);
196     spoil_out(buf);
197     spoil_out("------------------------------------------\n\n");
198
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);
203     }
204
205     uint16_t why = 2;
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)) {
211             spoil_out("[U] ");
212         } else if (any_bits(r_ptr->flags7, RF7_NAZGUL)) {
213             spoil_out("[N] ");
214         }
215
216         sprintf(buf, _("%s/%s  (", "%s%s ("), r_ptr->name.c_str(), _(r_ptr->E_name.c_str(), "")); /* ---)--- */
217         spoil_out(buf);
218         spoil_out(attr_to_text(r_ptr));
219         sprintf(buf, " '%c')\n", r_ptr->d_char);
220         spoil_out(buf);
221         sprintf(buf, "=== ");
222         spoil_out(buf);
223         sprintf(buf, "Num:%d  ", r_idx);
224         spoil_out(buf);
225         sprintf(buf, "Lev:%d  ", (int)r_ptr->level);
226         spoil_out(buf);
227         sprintf(buf, "Rar:%d  ", r_ptr->rarity);
228         spoil_out(buf);
229         if (r_ptr->speed >= 110) {
230             sprintf(buf, "Spd:+%d  ", (r_ptr->speed - 110));
231         } else {
232             sprintf(buf, "Spd:-%d  ", (110 - r_ptr->speed));
233         }
234
235         spoil_out(buf);
236         if (any_bits(flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
237             sprintf(buf, "Hp:%d  ", r_ptr->hdice * r_ptr->hside);
238         } else {
239             sprintf(buf, "Hp:%dd%d  ", r_ptr->hdice, r_ptr->hside);
240         }
241
242         spoil_out(buf);
243         sprintf(buf, "Ac:%d  ", r_ptr->ac);
244         spoil_out(buf);
245         sprintf(buf, "Exp:%ld\n", (long)(r_ptr->mexp));
246         spoil_out(buf);
247         output_monster_spoiler(r_idx, roff_func);
248         spoil_out(nullptr);
249     }
250
251     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FCLOSE
252                                                                 : SpoilerOutputResultType::SPOILER_OUTPUT_SUCCESS;
253 }