OSDN Git Service

4721982257aeb97df2627492cf339ec946d6ccf2
[hengbandforosx/hengbandosx.git] / src / wizard / fixed-artifacts-spoiler.cpp
1 #include "wizard/fixed-artifacts-spoiler.h"
2 #include "io/files-util.h"
3 #include "object/object-kind-hook.h"
4 #include "system/angband-version.h"
5 #include "system/artifact-type-definition.h"
6 #include "system/object-type-definition.h"
7 #include "system/player-type-definition.h"
8 #include "util/angband-files.h"
9 #include "view/display-messages.h"
10 #include "wizard/artifact-analyzer.h"
11 #include "wizard/spoiler-util.h"
12
13 /*!
14  * @brief フラグ名称を出力する汎用関数
15  * @param header ヘッダに出力するフラグ群の名前
16  * @param list フラグ名リスト
17  * @param separator フラグ表示の区切り記号
18  * @todo 固定アーティファクトとランダムアーティファクトで共用、ここに置くべきかは要調整.
19  */
20 void spoiler_outlist(concptr header, concptr *list, char separator)
21 {
22     char line[MAX_LINE_LEN + 20], buf[80];
23     if (*list == nullptr)
24         return;
25
26     strcpy(line, spoiler_indent);
27     if (header && (header[0])) {
28         strcat(line, header);
29         strcat(line, " ");
30     }
31
32     int buf_len;
33     int line_len = strlen(line);
34     while (true) {
35         strcpy(buf, *list);
36         buf_len = strlen(buf);
37         if (list[1]) {
38             sprintf(buf + buf_len, "%c ", separator);
39             buf_len += 2;
40         }
41
42         if (line_len + buf_len <= MAX_LINE_LEN) {
43             strcat(line, buf);
44             line_len += buf_len;
45         } else {
46             if (line_len > 1 && line[line_len - 1] == ' ' && line[line_len - 2] == list_separator) {
47                 line[line_len - 2] = '\0';
48                 fprintf(spoiler_file, "%s\n", line);
49                 sprintf(line, "%s%s", spoiler_indent, buf);
50             } else {
51                 fprintf(spoiler_file, "%s\n", line);
52                 concptr ident2 = "      ";
53                 sprintf(line, "%s%s", ident2, buf);
54             }
55
56             line_len = strlen(line);
57         }
58
59         if (!*++list)
60             break;
61     }
62
63     fprintf(spoiler_file, "%s\n", line);
64 }
65
66 /*!
67  * @brief バッファにアーティファクト出力情報ヘッダを収める /
68  */
69 static void print_header(void)
70 {
71     char buf[360];
72     char title[180];
73     put_version(title);
74     sprintf(buf, "Artifact Spoilers for Hengband Version %s", title);
75     spoiler_underline(buf);
76 }
77
78 /*!
79  * @brief アーティファクト情報を出力するためにダミー生成を行う /
80  * Hack -- Create a "forged" artifact
81  * @param o_ptr 一時生成先を保管するオブジェクト構造体
82  * @param name1 生成するアーティファクトID
83  * @return 生成が成功した場合TRUEを返す
84  */
85 static bool make_fake_artifact(object_type *o_ptr, ARTIFACT_IDX name1)
86 {
87     artifact_type *a_ptr = &a_info[name1];
88     if (a_ptr->name.empty())
89         return false;
90
91     OBJECT_IDX i = lookup_kind(a_ptr->tval, a_ptr->sval);
92     if (!i)
93         return false;
94
95     o_ptr->prep(i);
96     o_ptr->name1 = name1;
97     o_ptr->pval = a_ptr->pval;
98     o_ptr->ac = a_ptr->ac;
99     o_ptr->dd = a_ptr->dd;
100     o_ptr->ds = a_ptr->ds;
101     o_ptr->to_a = a_ptr->to_a;
102     o_ptr->to_h = a_ptr->to_h;
103     o_ptr->to_d = a_ptr->to_d;
104     o_ptr->weight = a_ptr->weight;
105     return true;
106 }
107
108 /*!
109  * @brief アーティファクト一件をスポイラー出力する /
110  * Create a spoiler file entry for an artifact
111  * @param art_ptr アーティファクト情報をまとめた構造体の参照ポインタ
112  */
113 static void spoiler_print_art(obj_desc_list *art_ptr)
114 {
115     pval_info_type *pval_ptr = &art_ptr->pval_info;
116     char buf[80];
117     fprintf(spoiler_file, "%s\n", art_ptr->description);
118     if (pval_ptr->pval_desc[0]) {
119         sprintf(buf, _("%sの修正:", "%s to"), pval_ptr->pval_desc);
120         spoiler_outlist(buf, pval_ptr->pval_affects, item_separator);
121     }
122
123     spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator);
124     spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator);
125     spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator);
126     spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator);
127     spoiler_outlist(_("弱点:", "Vulnerable"), art_ptr->vulnerables, item_separator);
128     spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustains, item_separator);
129     spoiler_outlist("", art_ptr->misc_magic, list_separator);
130
131     if (art_ptr->addition[0])
132         fprintf(spoiler_file, _("%s追加: %s\n", "%sAdditional %s\n"), spoiler_indent, art_ptr->addition);
133
134     if (art_ptr->activation)
135         fprintf(spoiler_file, _("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent, art_ptr->activation);
136
137     fprintf(spoiler_file, "%s%s\n\n", spoiler_indent, art_ptr->misc_desc);
138 }
139
140 /*!
141  * @brief アーティファクト情報のスポイラー出力を行うメインルーチン /
142  * Create a spoiler file for artifacts
143  * @param fname 生成ファイル名
144  */
145 SpoilerOutputResultType spoil_fixed_artifact(concptr fname)
146 {
147     char buf[1024];
148     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
149     spoiler_file = angband_fopen(buf, "w");
150     if (!spoiler_file) {
151         return SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FOPEN;
152     }
153
154     print_header();
155     for (const auto &[tval_list, name] : group_artifact_list) {
156         spoiler_blanklines(2);
157         spoiler_underline(name);
158         spoiler_blanklines(1);
159
160         for (auto tval : tval_list) {
161             for (const auto &a_ref : a_info) {
162                 if (a_ref.tval != tval)
163                     continue;
164
165                 object_type obj;
166                 obj.wipe();
167                 if (!make_fake_artifact(&obj, a_ref.idx))
168                     continue;
169
170                 PlayerType dummy;
171                 obj_desc_list artifact;
172                 object_analyze(&dummy, &obj, &artifact);
173                 spoiler_print_art(&artifact);
174             }
175         }
176     }
177
178     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::SPOILER_OUTPUT_FAIL_FCLOSE
179                                                                 : SpoilerOutputResultType::SPOILER_OUTPUT_SUCCESS;
180 }