OSDN Git Service

Merge branch 'develop' into feature/Unite-Command-Throw
[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 (any_bits(r_ptr->flags1, RF1_ATTR_CLEAR)) {
26         return _("透明な", "Clear");
27     }
28
29     if (any_bits(r_ptr->flags1, RF1_ATTR_MULTI)) {
30         return _("万色の", "Multi");
31     }
32
33     if (any_bits(r_ptr->flags1, RF1_ATTR_SEMIRAND)) {
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 spoiler_output_status spoil_mon_desc(concptr fname, std::function<bool(const monster_race *)> filter_monster)
76 {
77     player_type dummy;
78     uint16_t why = 2;
79     MONRACE_IDX *who;
80     char buf[1024];
81     char nam[MAX_MONSTER_NAME + 10]; // ユニークには[U] が付くので少し伸ばす
82     char lev[80];
83     char rar[80];
84     char spd[80];
85     char ac[80];
86     char hp[80];
87     char symbol[80];
88     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
89     spoiler_file = angband_fopen(buf, "w");
90     if (!spoiler_file) {
91         return spoiler_output_status::SPOILER_OUTPUT_FAIL_FOPEN;
92     }
93
94     char title[200];
95     put_version(title);
96
97     C_MAKE(who, max_r_idx, MONRACE_IDX);
98     fprintf(spoiler_file, "Monster Spoilers for %s\n", title);
99     fprintf(spoiler_file, "------------------------------------------\n\n");
100     fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s  %19.19s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info");
101     fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s  %4.19s\n",
102         "---------------------------------------------"
103         "----"
104         "----------",
105         "---", "---", "---", "-----", "-----", "-------------------");
106
107     int n = 0;
108     for (auto i = 1; i < max_r_idx; i++) {
109         monster_race *r_ptr = &r_info[i];
110         if (!r_ptr->name.empty())
111             who[n++] = (int16_t)i;
112     }
113
114     ang_sort(&dummy, who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
115     for (auto i = 0; i < n; i++) {
116         monster_race *r_ptr = &r_info[who[i]];
117         concptr name = r_ptr->name.c_str();
118         if (filter_monster && !filter_monster(r_ptr)) {
119             continue;
120         }
121
122         char name_buf[41];
123         angband_strcpy(name_buf, name, sizeof(name_buf));
124         name += strlen(name_buf);
125
126         if (any_bits(r_ptr->flags7, RF7_KAGE)) {
127             continue;
128         }
129
130         if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
131             sprintf(nam, "[U] %s", name_buf);
132         } else if (any_bits(r_ptr->flags7, RF7_NAZGUL)) {
133             sprintf(nam, "[N] %s", name_buf);
134         } else {
135             sprintf(nam, _("    %s", "The %s"), name_buf);
136         }
137
138         sprintf(lev, "%d", (int)r_ptr->level);
139         sprintf(rar, "%d", (int)r_ptr->rarity);
140         if (r_ptr->speed >= 110) {
141             sprintf(spd, "+%d", (r_ptr->speed - 110));
142         } else {
143             sprintf(spd, "-%d", (110 - r_ptr->speed));
144         }
145
146         sprintf(ac, "%d", r_ptr->ac);
147         if (any_bits(r_ptr->flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
148             sprintf(hp, "%d", r_ptr->hdice * r_ptr->hside);
149         } else {
150             sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside);
151         }
152
153         sprintf(symbol, "%ld", (long)(r_ptr->mexp));
154         sprintf(symbol, "%s '%c'", attr_to_text(r_ptr), r_ptr->d_char);
155         fprintf(spoiler_file, "%-45.45s%4s %4s %4s %7s %7s  %19.19s\n", nam, lev, rar, spd, hp, ac, symbol);
156
157         while (*name != '\0') {
158             angband_strcpy(name_buf, name, sizeof(name_buf));
159             name += strlen(name_buf);
160             fprintf(spoiler_file, "    %s\n", name_buf);
161         }
162     }
163
164     fprintf(spoiler_file, "\n");
165     C_KILL(who, max_r_idx, int16_t);
166     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? spoiler_output_status::SPOILER_OUTPUT_FAIL_FCLOSE
167                                                                 : spoiler_output_status::SPOILER_OUTPUT_SUCCESS;
168 }
169
170 /*!
171  * @brief 関数ポインタ用の出力関数 /
172  * Hook function used in spoil_mon_info()
173  * @param attr 未使用
174  * @param str 文字列参照ポインタ
175  */
176 static void roff_func(TERM_COLOR attr, concptr str)
177 {
178     (void)attr;
179     spoil_out(str);
180 }
181
182 /*!
183  * @brief モンスター詳細情報をスポイラー出力するメインルーチン /
184  * Create a spoiler file for monsters (-SHAWN-)
185  * @param fname ファイル名
186  */
187 spoiler_output_status spoil_mon_info(concptr fname)
188 {
189     player_type dummy;
190     char buf[1024];
191     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
192     spoiler_file = angband_fopen(buf, "w");
193     if (!spoiler_file) {
194         return spoiler_output_status::SPOILER_OUTPUT_FAIL_FOPEN;
195     }
196
197     char title[200];
198     put_version(title);
199     sprintf(buf, "Monster Spoilers for %s\n", title);
200     spoil_out(buf);
201     spoil_out("------------------------------------------\n\n");
202
203     MONRACE_IDX *who;
204     C_MAKE(who, max_r_idx, MONRACE_IDX);
205     int n = 0;
206     for (int i = 1; i < max_r_idx; i++) {
207         monster_race *r_ptr = &r_info[i];
208         if (!r_ptr->name.empty())
209             who[n++] = (int16_t)i;
210     }
211
212     uint16_t why = 2;
213     ang_sort(&dummy, who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
214     for (int i = 0; i < n; i++) {
215         monster_race *r_ptr = &r_info[who[i]];
216         BIT_FLAGS flags1 = r_ptr->flags1;
217         if (any_bits(flags1, RF1_UNIQUE)) {
218             spoil_out("[U] ");
219         } else if (any_bits(r_ptr->flags7, RF7_NAZGUL)) {
220             spoil_out("[N] ");
221         }
222
223         sprintf(buf, _("%s/%s  (", "%s%s ("), r_ptr->name.c_str(), _(r_ptr->E_name.c_str(), "")); /* ---)--- */
224         spoil_out(buf);
225         spoil_out(attr_to_text(r_ptr));
226         sprintf(buf, " '%c')\n", r_ptr->d_char);
227         spoil_out(buf);
228         sprintf(buf, "=== ");
229         spoil_out(buf);
230         sprintf(buf, "Num:%d  ", who[i]);
231         spoil_out(buf);
232         sprintf(buf, "Lev:%d  ", (int)r_ptr->level);
233         spoil_out(buf);
234         sprintf(buf, "Rar:%d  ", r_ptr->rarity);
235         spoil_out(buf);
236         if (r_ptr->speed >= 110) {
237             sprintf(buf, "Spd:+%d  ", (r_ptr->speed - 110));
238         } else {
239             sprintf(buf, "Spd:-%d  ", (110 - r_ptr->speed));
240         }
241
242         spoil_out(buf);
243         if (any_bits(flags1, RF1_FORCE_MAXHP) || (r_ptr->hside == 1)) {
244             sprintf(buf, "Hp:%d  ", r_ptr->hdice * r_ptr->hside);
245         } else {
246             sprintf(buf, "Hp:%dd%d  ", r_ptr->hdice, r_ptr->hside);
247         }
248
249         spoil_out(buf);
250         sprintf(buf, "Ac:%d  ", r_ptr->ac);
251         spoil_out(buf);
252         sprintf(buf, "Exp:%ld\n", (long)(r_ptr->mexp));
253         spoil_out(buf);
254         output_monster_spoiler(who[i], roff_func);
255         spoil_out(NULL);
256     }
257
258     C_KILL(who, max_r_idx, int16_t);
259     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? spoiler_output_status::SPOILER_OUTPUT_FAIL_FCLOSE
260                                                                 : spoiler_output_status::SPOILER_OUTPUT_SUCCESS;
261 }