OSDN Git Service

Merge pull request #2659 from Hourier/Enter-MonsterType-Functions-2
[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::FILE_OPEN_FAILED;
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<MonsterRaceId> who;
106     for (const auto &[r_idx, r_ref] : r_info) {
107         if (MonsterRace(r_ref.idx).is_valid() && !r_ref.name.empty()) {
108             who.push_back(r_ref.idx);
109         }
110     }
111
112     ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
113     for (auto r_idx : who) {
114         auto *r_ptr = &r_info[r_idx];
115         if (filter_monster && !filter_monster(r_ptr)) {
116             continue;
117         }
118
119         if (any_bits(r_ptr->flags7, RF7_KAGE)) {
120             continue;
121         }
122
123         const auto name = str_separate(r_ptr->name, 40);
124         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
125             sprintf(nam, "[U] %s", name.front().c_str());
126         } else if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
127             sprintf(nam, "[N] %s", name.front().c_str());
128         } else {
129             sprintf(nam, _("    %s", "The %s"), name.front().c_str());
130         }
131
132         sprintf(lev, "%d", (int)r_ptr->level);
133         sprintf(rar, "%d", (int)r_ptr->rarity);
134         sprintf(spd, "%+d", r_ptr->speed - STANDARD_SPEED);
135         sprintf(ac, "%d", r_ptr->ac);
136         if (any_bits(r_ptr->flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
137             sprintf(hp, "%d", r_ptr->hdice * r_ptr->hside);
138         } else {
139             sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside);
140         }
141
142         sprintf(symbol, "%ld", (long)(r_ptr->mexp));
143         sprintf(symbol, "%s '%c'", attr_to_text(r_ptr), r_ptr->d_char);
144         fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s  %19.19s\n", nam, lev, rar, spd, hp, ac, symbol);
145
146         for (auto i = 1U; i < name.size(); ++i) {
147             fprintf(spoiler_file, "    %s\n", name[i].c_str());
148         }
149     }
150
151     fprintf(spoiler_file, "\n");
152     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
153                                                                 : SpoilerOutputResultType::SUCCESSFUL;
154 }
155
156 /*!
157  * @brief 関数ポインタ用の出力関数 /
158  * Hook function used in spoil_mon_info()
159  * @param attr 未使用
160  * @param str 文字列参照ポインタ
161  */
162 static void roff_func(TERM_COLOR attr, concptr str)
163 {
164     (void)attr;
165     spoil_out(str);
166 }
167
168 /*!
169  * @brief モンスター詳細情報をスポイラー出力するメインルーチン /
170  * Create a spoiler file for monsters (-SHAWN-)
171  * @param fname ファイル名
172  */
173 SpoilerOutputResultType spoil_mon_info(concptr fname)
174 {
175     PlayerType dummy;
176     char buf[1024];
177     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
178     spoiler_file = angband_fopen(buf, "w");
179     if (!spoiler_file) {
180         return SpoilerOutputResultType::FILE_OPEN_FAILED;
181     }
182
183     char title[200];
184     put_version(title);
185     sprintf(buf, "Monster Spoilers for %s\n", title);
186     spoil_out(buf);
187     spoil_out("------------------------------------------\n\n");
188
189     std::vector<MonsterRaceId> who;
190     for (const auto &[r_idx, r_ref] : r_info) {
191         if (MonsterRace(r_ref.idx).is_valid() && !r_ref.name.empty()) {
192             who.push_back(r_ref.idx);
193         }
194     }
195
196     uint16_t why = 2;
197     ang_sort(&dummy, who.data(), &why, who.size(), ang_sort_comp_hook, ang_sort_swap_hook);
198     for (auto r_idx : who) {
199         auto *r_ptr = &r_info[r_idx];
200         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
201             spoil_out("[U] ");
202         } else if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
203             spoil_out("[N] ");
204         }
205
206         sprintf(buf, _("%s/%s  (", "%s%s ("), r_ptr->name.c_str(), _(r_ptr->E_name.c_str(), "")); /* ---)--- */
207         spoil_out(buf);
208         spoil_out(attr_to_text(r_ptr));
209         sprintf(buf, " '%c')\n", r_ptr->d_char);
210         spoil_out(buf);
211         sprintf(buf, "=== ");
212         spoil_out(buf);
213         sprintf(buf, "Num:%d  ", enum2i(r_idx));
214         spoil_out(buf);
215         sprintf(buf, "Lev:%d  ", (int)r_ptr->level);
216         spoil_out(buf);
217         sprintf(buf, "Rar:%d  ", r_ptr->rarity);
218         spoil_out(buf);
219         sprintf(buf, "%+d", r_ptr->speed - STANDARD_SPEED);
220         spoil_out(buf);
221         if (any_bits(r_ptr->flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
222             sprintf(buf, "Hp:%d  ", r_ptr->hdice * r_ptr->hside);
223         } else {
224             sprintf(buf, "Hp:%dd%d  ", r_ptr->hdice, r_ptr->hside);
225         }
226
227         spoil_out(buf);
228         sprintf(buf, "Ac:%d  ", r_ptr->ac);
229         spoil_out(buf);
230         sprintf(buf, "Exp:%ld\n", (long)(r_ptr->mexp));
231         spoil_out(buf);
232         output_monster_spoiler(r_idx, roff_func);
233         spoil_out(nullptr);
234     }
235
236     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
237                                                                 : SpoilerOutputResultType::SUCCESSFUL;
238 }