2 * @brief スポイラー出力処理 (行数の都合でモンスター進化ツリーもここに入っている)
5 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
9 * 2013 Deskull rearranged comment for Doxygen.
10 * 2020 Hourier rearranged for decreasing lines.
13 #include "wizard/wizard-spoiler.h"
14 #include "io/files-util.h"
15 #include "io/input-key-acceptor.h"
16 #include "main/sound-of-music.h"
17 #include "monster-race/monster-race.h"
18 #include "monster-race/race-flags8.h"
19 #include "system/angband-version.h"
20 #include "term/screen-processor.h"
21 #include "util/angband-files.h"
22 #include "util/int-char-converter.h"
23 #include "util/sort.h"
24 #include "view/display-messages.h"
25 #include "wizard/fixed-artifacts-spoiler.h"
26 #include "wizard/items-spoiler.h"
27 #include "wizard/monster-info-spoiler.h"
28 #include "wizard/spoiler-util.h"
31 * @brief int配列でstrncmp()と似た比較処理を行う /
32 * Compare two int-type array like strncmp() and return TRUE if equals
36 * @return 両者の値が等しければTRUEを返す
38 static bool int_n_cmp(int *a, int *b, int length)
54 * @brief ある木が指定された木の部分木かどうかを返す /
55 * Returns TRUE if an evolution tree is "partial tree"
56 * @param tree 元となる木構造リスト
57 * @param partial_tree 部分木かどうか判定したい木構造リスト
58 * @return 部分木ならばTRUEを返す
60 static bool is_partial_tree(int *tree, int *partial_tree)
62 int pt_head = *(partial_tree++);
64 while (partial_tree[pt_len])
68 if (*(tree++) == pt_head) {
69 if (int_n_cmp(tree, partial_tree, pt_len))
78 * @brief 進化ツリーをスポイラー出力するメインルーチン /
79 * Print monsters' evolution information to file
80 * @param fname 出力ファイル名
83 static spoiler_output_status spoil_mon_evol(concptr fname)
88 int **evol_tree, i, j, n, r_idx;
89 int *evol_tree_zero; /* For C_KILL() */
90 path_build(buf, sizeof buf, ANGBAND_DIR_USER, fname);
91 spoiler_file = angband_fopen(buf, "w");
93 return SPOILER_OUTPUT_FAIL_FOPEN;
98 sprintf(buf, "Monster Spoilers for %s\n", title);
101 spoil_out("------------------------------------------\n\n");
102 C_MAKE(evol_tree, max_r_idx, int *);
103 C_MAKE(*evol_tree, max_r_idx * (max_evolution_depth + 1), int);
104 for (i = 1; i < max_r_idx; i++)
105 evol_tree[i] = *evol_tree + i * (max_evolution_depth + 1);
107 evol_tree_zero = *evol_tree;
108 for (i = 1; i < max_r_idx; i++) {
110 if (!r_ptr->next_exp)
114 evol_tree[i][n++] = i;
116 evol_tree[i][n++] = r_ptr->next_r_idx;
117 r_ptr = &r_info[r_ptr->next_r_idx];
118 } while (r_ptr->next_exp && (n < max_evolution_depth));
121 for (i = 1; i < max_r_idx; i++) {
122 if (!evol_tree[i][0])
125 for (j = 1; j < max_r_idx; j++) {
129 if (!evol_tree[j][0])
132 if (is_partial_tree(evol_tree[j], evol_tree[i])) {
139 ang_sort(&dummy, evol_tree, NULL, max_r_idx, ang_sort_comp_evol_tree, ang_sort_swap_evol_tree);
140 for (i = 0; i < max_r_idx; i++) {
141 r_idx = evol_tree[i][0];
145 r_ptr = &r_info[r_idx];
146 fprintf(spoiler_file, _("[%d]: %s (レベル%d, '%c')\n", "[%d]: %s (Level %d, '%c')\n"), r_idx, r_name + r_ptr->name, (int)r_ptr->level, r_ptr->d_char);
147 for (n = 1; r_ptr->next_exp; n++) {
148 fprintf(spoiler_file, "%*s-(%ld)-> ", n * 2, "", (long int)r_ptr->next_exp);
149 fprintf(spoiler_file, "[%d]: ", r_ptr->next_r_idx);
150 r_ptr = &r_info[r_ptr->next_r_idx];
151 fprintf(spoiler_file, _("%s (レベル%d, '%c')\n", "%s (Level %d, '%c')\n"), r_name + r_ptr->name, (int)r_ptr->level, r_ptr->d_char);
154 fputc('\n', spoiler_file);
157 C_KILL(evol_tree_zero, max_r_idx * (max_evolution_depth + 1), int);
158 C_KILL(evol_tree, max_r_idx, int *);
159 if (ferror(spoiler_file) || angband_fclose(spoiler_file)) {
160 return SPOILER_OUTPUT_FAIL_FCLOSE;
162 return SPOILER_OUTPUT_SUCCESS;
166 * @brief スポイラー出力を行うコマンドのメインルーチン /
167 * Create Spoiler files -BEN-
170 void exe_output_spoilers(void)
174 spoiler_output_status status = SPOILER_OUTPUT_CANCEL;
176 prt("Create a spoiler file.", 2, 0);
177 prt("(1) Brief Object Info (obj-desc.txt)", 5, 5);
178 prt("(2) Brief Artifact Info (artifact.txt)", 6, 5);
179 prt("(3) Brief Monster Info (mon-desc.txt)", 7, 5);
180 prt("(4) Full Monster Info (mon-info.txt)", 8, 5);
181 prt("(5) Monster Evolution Info (mon-evol.txt)", 9, 5);
182 prt(_("コマンド:", "Command: "), _(18, 12), 0);
188 status = spoil_obj_desc("obj-desc.txt");
191 status = spoil_fixed_artifact("artifact.txt");
194 status = spoil_mon_desc_all("mon-desc.txt");
197 status = spoil_mon_info("mon-info.txt");
200 status = spoil_mon_evol("mon-evol.txt");
208 case SPOILER_OUTPUT_FAIL_FOPEN:
209 msg_print("Cannot create spoiler file.");
211 case SPOILER_OUTPUT_FAIL_FCLOSE:
212 msg_print("Cannot close spoiler file.");
214 case SPOILER_OUTPUT_SUCCESS:
215 msg_print("Successfully created a spoiler file.");
223 * @brief 全スポイラー出力を行うコマンドのメインルーチン /
224 * Create Spoiler files -BEN-
225 * @return 成功時SPOILER_OUTPUT_SUCCESS / 失敗時エラー状態
227 spoiler_output_status output_all_spoilers(void)
229 spoiler_output_status status;
230 status = spoil_obj_desc("obj-desc.txt");
231 if (status != SPOILER_OUTPUT_SUCCESS)
234 status = spoil_fixed_artifact("artifact.txt");
235 if (status != SPOILER_OUTPUT_SUCCESS)
238 status = spoil_mon_desc_all("mon-desc.txt");
239 if (status != SPOILER_OUTPUT_SUCCESS)
242 status = spoil_mon_desc("mon-desc-wildonly.txt", FALSE, RF8_WILD_ONLY);
243 if (status != SPOILER_OUTPUT_SUCCESS)
245 status = spoil_mon_desc("mon-desc-town.txt", FALSE, RF8_WILD_TOWN);
246 if (status != SPOILER_OUTPUT_SUCCESS)
248 status = spoil_mon_desc("mon-desc-shore.txt", FALSE, RF8_WILD_SHORE);
249 if (status != SPOILER_OUTPUT_SUCCESS)
251 status = spoil_mon_desc("mon-desc-ocean.txt", FALSE, RF8_WILD_OCEAN);
252 if (status != SPOILER_OUTPUT_SUCCESS)
254 status = spoil_mon_desc("mon-desc-waste.txt", FALSE, RF8_WILD_WASTE);
255 if (status != SPOILER_OUTPUT_SUCCESS)
257 status = spoil_mon_desc("mon-desc-wood.txt", FALSE, RF8_WILD_WOOD);
258 if (status != SPOILER_OUTPUT_SUCCESS)
260 status = spoil_mon_desc("mon-desc-volcano.txt", FALSE, RF8_WILD_VOLCANO);
261 if (status != SPOILER_OUTPUT_SUCCESS)
263 status = spoil_mon_desc("mon-desc-mountain.txt", FALSE, RF8_WILD_MOUNTAIN);
264 if (status != SPOILER_OUTPUT_SUCCESS)
266 status = spoil_mon_desc("mon-desc-grass.txt", FALSE, RF8_WILD_GRASS);
267 if (status != SPOILER_OUTPUT_SUCCESS)
269 status = spoil_mon_desc("mon-desc-wildall.txt", FALSE, RF8_WILD_ALL);
270 if (status != SPOILER_OUTPUT_SUCCESS)
273 status = spoil_mon_info("mon-info.txt");
274 if (status != SPOILER_OUTPUT_SUCCESS)
277 status = spoil_mon_evol("mon-evol.txt");
278 if (status != SPOILER_OUTPUT_SUCCESS)
281 return SPOILER_OUTPUT_SUCCESS;