OSDN Git Service

96b96c41c0784095b7443b76f6d06ad6e1f95140
[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/baseitem-info.h"
7 #include "system/item-entity.h"
8 #include "system/player-type-definition.h"
9 #include "util/angband-files.h"
10 #include "view/display-messages.h"
11 #include "wizard/artifact-analyzer.h"
12 #include "wizard/spoiler-util.h"
13 #include <sstream>
14
15 /*!
16  * @brief フラグ名称を出力する汎用関数
17  * @param header ヘッダに出力するフラグ群の名前
18  * @param descriptions フラグ名リスト
19  * @param separator フラグ表示の区切り記号
20  */
21 void spoiler_outlist(std::string_view header, const std::vector<std::string> &descriptions, char separator)
22 {
23     if (descriptions.empty()) {
24         return;
25     }
26
27     std::string line = spoiler_indent;
28     if (!header.empty()) {
29         line.append(header).append(" ");
30     }
31
32     for (size_t i = 0; i < descriptions.size(); i++) {
33         auto elem = descriptions[i];
34         if (i < descriptions.size() - 1) {
35             elem.push_back(separator);
36             elem.push_back(' ');
37         }
38
39         if (line.length() + elem.length() <= MAX_LINE_LEN) {
40             line.append(elem);
41             continue;
42         }
43
44         if (line.length() > 1 && line[line.length() - 1] == ' ' && line[line.length() - 2] == list_separator) {
45             line[line.length() - 2] = '\0';
46             fprintf(spoiler_file, "%s\n", line.data());
47             line = spoiler_indent;
48             line.append(elem);
49         } else {
50             fprintf(spoiler_file, "%s\n", line.data());
51             line = "      ";
52             line.append(elem);
53         }
54     }
55
56     fprintf(spoiler_file, "%s\n", line.data());
57 }
58
59 /*!
60  * @brief アーティファクト情報を出力するためにダミー生成を行う
61  * @param fixed_artifact_idx 生成するアーティファクトID
62  * @return 生成したアーティファクト (連番で埋まっているので不存在例外は吐かない)
63  */
64 static ItemEntity make_fake_artifact(FixedArtifactId fixed_artifact_idx)
65 {
66     const auto &artifact = ArtifactsInfo::get_instance().get_artifact(fixed_artifact_idx);
67     const auto bi_id = lookup_baseitem_id(artifact.bi_key);
68     ItemEntity item;
69     item.prep(bi_id);
70     item.fixed_artifact_idx = fixed_artifact_idx;
71     item.pval = artifact.pval;
72     item.ac = artifact.ac;
73     item.dd = artifact.dd;
74     item.ds = artifact.ds;
75     item.to_a = artifact.to_a;
76     item.to_h = artifact.to_h;
77     item.to_d = artifact.to_d;
78     item.weight = artifact.weight;
79     return item;
80 }
81
82 /*!
83  * @brief アーティファクト一件をスポイラー出力する /
84  * Create a spoiler file entry for an artifact
85  * @param art_ptr アーティファクト情報をまとめた構造体の参照ポインタ
86  */
87 static void spoiler_print_art(obj_desc_list *art_ptr)
88 {
89     const auto *pval_ptr = &art_ptr->pval_info;
90     fprintf(spoiler_file, "%s\n", art_ptr->description.data());
91     if (!pval_ptr->pval_desc.empty()) {
92         std::stringstream ss;
93         ss << pval_ptr->pval_desc << _("の修正:", " to");
94         spoiler_outlist(ss.str(), pval_ptr->pval_affects, item_separator);
95     }
96
97     spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator);
98     spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator);
99     spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator);
100     spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator);
101     spoiler_outlist(_("弱点:", "Vulnerable"), art_ptr->vulnerabilities, item_separator);
102     spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustenances, item_separator);
103     spoiler_outlist("", art_ptr->misc_magic, list_separator);
104
105     if (!art_ptr->addition.empty()) {
106         fprintf(spoiler_file, _("%s追加: %s\n", "%sAdditional %s\n"), spoiler_indent.data(), art_ptr->addition.data());
107     }
108
109     if (!art_ptr->activation.empty()) {
110         fprintf(spoiler_file, _("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent.data(), art_ptr->activation.data());
111     }
112
113     fprintf(spoiler_file, "%s%s\n\n", spoiler_indent.data(), art_ptr->misc_desc.data());
114 }
115
116 /*!
117  * @brief アーティファクト情報のスポイラー出力を行うメインルーチン
118  */
119 SpoilerOutputResultType spoil_fixed_artifact()
120 {
121     const auto &path = path_build(ANGBAND_DIR_USER, "artifact.txt");
122     spoiler_file = angband_fopen(path, FileOpenMode::WRITE);
123     if (!spoiler_file) {
124         return SpoilerOutputResultType::FILE_OPEN_FAILED;
125     }
126
127     std::stringstream ss;
128     ss << "Artifact Spoilers for Hengband Version " << get_version();
129     spoiler_underline(ss.str());
130     for (const auto &[tval_list, name] : group_artifact_list) {
131         spoiler_blanklines(2);
132         spoiler_underline(name);
133         spoiler_blanklines(1);
134
135         for (auto tval : tval_list) {
136             for (const auto &[a_idx, artifact] : artifacts_info) {
137                 if (artifact.bi_key.tval() != tval) {
138                     continue;
139                 }
140
141                 const auto item = make_fake_artifact(a_idx);
142                 PlayerType dummy;
143                 obj_desc_list artifact_descriptions;
144                 object_analyze(&dummy, &item, &artifact_descriptions);
145                 spoiler_print_art(&artifact_descriptions);
146             }
147         }
148     }
149
150     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
151                                                                 : SpoilerOutputResultType::SUCCESSFUL;
152 }