OSDN Git Service

[Refactor] #3554 固定/ランダムアーティファクト情報の出力処理からspoiler_file グローバル変数を消した
authorHourier <66951241+Hourier@users.noreply.github.com>
Fri, 14 Jul 2023 11:43:17 +0000 (20:43 +0900)
committerHourier <66951241+Hourier@users.noreply.github.com>
Sun, 16 Jul 2023 13:54:26 +0000 (22:54 +0900)
src/io-dump/random-art-info-dumper.cpp
src/wizard/fixed-artifacts-spoiler.cpp
src/wizard/fixed-artifacts-spoiler.h
src/wizard/spoiler-util.cpp
src/wizard/spoiler-util.h

index cdb61f4..2f9aeb4 100644 (file)
@@ -21,7 +21,7 @@
  * @param art_ptr 記述内容を収めた構造体参照ポインタ
  * Fill in an object description structure for a given object
  */
-static void spoiler_print_randart(ItemEntity *o_ptr, obj_desc_list *art_ptr)
+static void spoiler_print_randart(ItemEntity *o_ptr, obj_desc_list *art_ptr, std::ofstream &ofs)
 {
     const auto finalizer = util::make_finalizer([art_ptr]() {
         fprintf(spoiler_file, "%s%s\n\n", spoiler_indent.data(), art_ptr->misc_desc.data());
@@ -36,17 +36,17 @@ static void spoiler_print_randart(ItemEntity *o_ptr, obj_desc_list *art_ptr)
     if (!pval_ptr->pval_desc.empty()) {
         std::stringstream ss;
         ss << pval_ptr->pval_desc << _("の修正:", " to");
-        spoiler_outlist(ss.str(), pval_ptr->pval_affects, item_separator);
+        spoiler_outlist(ss.str(), pval_ptr->pval_affects, item_separator, ofs);
     }
 
-    spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator);
-    spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator);
-    spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator);
-    spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator);
-    spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustenances, item_separator);
-    spoiler_outlist("", art_ptr->misc_magic, list_separator);
+    spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator, ofs);
+    spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator, ofs);
+    spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator, ofs);
+    spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator, ofs);
+    spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustenances, item_separator, ofs);
+    spoiler_outlist("", art_ptr->misc_magic, list_separator, ofs);
     if (!art_ptr->activation.empty()) {
-        fprintf(spoiler_file, _("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent.data(), art_ptr->activation.data());
+        ofs << format(_("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent.data(), art_ptr->activation.data());
     }
 }
 
@@ -56,7 +56,7 @@ static void spoiler_print_randart(ItemEntity *o_ptr, obj_desc_list *art_ptr)
  * @param o_ptr ランダムアーティファクトのオブジェクト構造体参照ポインタ
  * @param tval 出力したいランダムアーティファクトの種類
  */
-static void spoil_random_artifact_aux(PlayerType *player_ptr, ItemEntity *o_ptr, ItemKindType tval)
+static void spoil_random_artifact_aux(PlayerType *player_ptr, ItemEntity *o_ptr, ItemKindType tval, std::ofstream &ofs)
 {
     obj_desc_list artifact;
     if (!o_ptr->is_known() || !o_ptr->is_random_artifact() || (o_ptr->bi_key.tval() != tval)) {
@@ -64,7 +64,7 @@ static void spoil_random_artifact_aux(PlayerType *player_ptr, ItemEntity *o_ptr,
     }
 
     random_artifact_analyze(player_ptr, o_ptr, &artifact);
-    spoiler_print_randart(o_ptr, &artifact);
+    spoiler_print_randart(o_ptr, &artifact, ofs);
 }
 
 /*!
@@ -75,43 +75,39 @@ static void spoil_random_artifact_aux(PlayerType *player_ptr, ItemEntity *o_ptr,
 void spoil_random_artifact(PlayerType *player_ptr, concptr fname)
 {
     const auto &path = path_build(ANGBAND_DIR_USER, fname);
-    spoiler_file = angband_fopen(path, FileOpenMode::WRITE);
-    if (!spoiler_file) {
+    std::ofstream ofs(path);
+    if (!ofs) {
         msg_print("Cannot create list file.");
         return;
     }
 
-    spoiler_underline("Random artifacts list.\r");
+    spoiler_underline("Random artifacts list.\r", ofs);
     for (const auto &[tval_list, name] : group_artifact_list) {
         for (auto tval : tval_list) {
             for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
                 auto *q_ptr = &player_ptr->inventory_list[i];
-                spoil_random_artifact_aux(player_ptr, q_ptr, tval);
+                spoil_random_artifact_aux(player_ptr, q_ptr, tval, ofs);
             }
 
             for (int i = 0; i < INVEN_PACK; i++) {
                 auto *q_ptr = &player_ptr->inventory_list[i];
-                spoil_random_artifact_aux(player_ptr, q_ptr, tval);
+                spoil_random_artifact_aux(player_ptr, q_ptr, tval, ofs);
             }
 
             const auto *store_ptr = &towns_info[1].stores[StoreSaleType::HOME];
             for (int i = 0; i < store_ptr->stock_num; i++) {
                 auto *q_ptr = &store_ptr->stock[i];
-                spoil_random_artifact_aux(player_ptr, q_ptr, tval);
+                spoil_random_artifact_aux(player_ptr, q_ptr, tval, ofs);
             }
 
             store_ptr = &towns_info[1].stores[StoreSaleType::MUSEUM];
             for (int i = 0; i < store_ptr->stock_num; i++) {
                 auto *q_ptr = &store_ptr->stock[i];
-                spoil_random_artifact_aux(player_ptr, q_ptr, tval);
+                spoil_random_artifact_aux(player_ptr, q_ptr, tval, ofs);
             }
         }
     }
 
-    if (ferror(spoiler_file) || angband_fclose(spoiler_file)) {
-        msg_print("Cannot close list file.");
-        return;
-    }
-
-    msg_print("Successfully created a list file.");
+    const auto mes = ofs.good() ? "Successfully created a list file." : "Failed to create a list file.";
+    msg_print(mes);
 }
index 96b96c4..67adea9 100644 (file)
@@ -18,7 +18,7 @@
  * @param descriptions フラグ名リスト
  * @param separator フラグ表示の区切り記号
  */
-void spoiler_outlist(std::string_view header, const std::vector<std::string> &descriptions, char separator)
+void spoiler_outlist(std::string_view header, const std::vector<std::string> &descriptions, char separator, std::ofstream &ofs)
 {
     if (descriptions.empty()) {
         return;
@@ -29,6 +29,9 @@ void spoiler_outlist(std::string_view header, const std::vector<std::string> &de
         line.append(header).append(" ");
     }
 
+    std::stringstream ss;
+    ss << list_separator << ' ';
+    const auto last_separator = ss.str();
     for (size_t i = 0; i < descriptions.size(); i++) {
         auto elem = descriptions[i];
         if (i < descriptions.size() - 1) {
@@ -41,19 +44,18 @@ void spoiler_outlist(std::string_view header, const std::vector<std::string> &de
             continue;
         }
 
-        if (line.length() > 1 && line[line.length() - 1] == ' ' && line[line.length() - 2] == list_separator) {
-            line[line.length() - 2] = '\0';
-            fprintf(spoiler_file, "%s\n", line.data());
+        if (line.length() > 1 && line.ends_with(last_separator)) {
+            ofs << std::string_view(line).substr(0, line.length() - 2) << '\n';
             line = spoiler_indent;
             line.append(elem);
         } else {
-            fprintf(spoiler_file, "%s\n", line.data());
+            ofs << line << '\n';
             line = "      ";
             line.append(elem);
         }
     }
 
-    fprintf(spoiler_file, "%s\n", line.data());
+    ofs << line << '\n';
 }
 
 /*!
@@ -84,53 +86,54 @@ static ItemEntity make_fake_artifact(FixedArtifactId fixed_artifact_idx)
  * Create a spoiler file entry for an artifact
  * @param art_ptr アーティファクト情報をまとめた構造体の参照ポインタ
  */
-static void spoiler_print_art(obj_desc_list *art_ptr)
+static void spoiler_print_art(obj_desc_list *art_ptr, std::ofstream &ofs)
 {
     const auto *pval_ptr = &art_ptr->pval_info;
-    fprintf(spoiler_file, "%s\n", art_ptr->description.data());
+    ofs << art_ptr->description << '\n';
     if (!pval_ptr->pval_desc.empty()) {
         std::stringstream ss;
         ss << pval_ptr->pval_desc << _("の修正:", " to");
-        spoiler_outlist(ss.str(), pval_ptr->pval_affects, item_separator);
+        spoiler_outlist(ss.str(), pval_ptr->pval_affects, item_separator, ofs);
     }
 
-    spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator);
-    spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator);
-    spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator);
-    spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator);
-    spoiler_outlist(_("弱点:", "Vulnerable"), art_ptr->vulnerabilities, item_separator);
-    spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustenances, item_separator);
-    spoiler_outlist("", art_ptr->misc_magic, list_separator);
+    spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator, ofs);
+    spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator, ofs);
+    spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator, ofs);
+    spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator, ofs);
+    spoiler_outlist(_("弱点:", "Vulnerable"), art_ptr->vulnerabilities, item_separator, ofs);
+    spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustenances, item_separator, ofs);
+    spoiler_outlist("", art_ptr->misc_magic, list_separator, ofs);
 
     if (!art_ptr->addition.empty()) {
-        fprintf(spoiler_file, _("%s追加: %s\n", "%sAdditional %s\n"), spoiler_indent.data(), art_ptr->addition.data());
+        ofs << format(_("%s追加: %s\n", "%sAdditional %s\n"), spoiler_indent.data(), art_ptr->addition.data());
     }
 
     if (!art_ptr->activation.empty()) {
-        fprintf(spoiler_file, _("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent.data(), art_ptr->activation.data());
+        ofs << format(_("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent.data(), art_ptr->activation.data());
     }
 
-    fprintf(spoiler_file, "%s%s\n\n", spoiler_indent.data(), art_ptr->misc_desc.data());
+    ofs << format("%s%s\n\n", spoiler_indent.data(), art_ptr->misc_desc.data());
 }
 
 /*!
  * @brief アーティファクト情報のスポイラー出力を行うメインルーチン
+ * @details エラーコードと実際のエラー処理が不一致だが、後でまとめて修正する.
  */
 SpoilerOutputResultType spoil_fixed_artifact()
 {
     const auto &path = path_build(ANGBAND_DIR_USER, "artifact.txt");
-    spoiler_file = angband_fopen(path, FileOpenMode::WRITE);
-    if (!spoiler_file) {
+    std::ofstream ofs(path);
+    if (!ofs) {
         return SpoilerOutputResultType::FILE_OPEN_FAILED;
     }
 
     std::stringstream ss;
     ss << "Artifact Spoilers for Hengband Version " << get_version();
-    spoiler_underline(ss.str());
+    spoiler_underline(ss.str(), ofs);
     for (const auto &[tval_list, name] : group_artifact_list) {
-        spoiler_blanklines(2);
-        spoiler_underline(name);
-        spoiler_blanklines(1);
+        spoiler_blanklines(2, ofs);
+        spoiler_underline(name, ofs);
+        spoiler_blanklines(1, ofs);
 
         for (auto tval : tval_list) {
             for (const auto &[a_idx, artifact] : artifacts_info) {
@@ -142,11 +145,10 @@ SpoilerOutputResultType spoil_fixed_artifact()
                 PlayerType dummy;
                 obj_desc_list artifact_descriptions;
                 object_analyze(&dummy, &item, &artifact_descriptions);
-                spoiler_print_art(&artifact_descriptions);
+                spoiler_print_art(&artifact_descriptions, ofs);
             }
         }
     }
 
-    return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
-                                                                : SpoilerOutputResultType::SUCCESSFUL;
+    return ofs.good() ? SpoilerOutputResultType::SUCCESSFUL : SpoilerOutputResultType::FILE_CLOSE_FAILED;
 }
index c263da3..079ba8c 100644 (file)
@@ -1,9 +1,10 @@
 #pragma once
 
+#include <fstream>
 #include <string>
 #include <string_view>
 #include <vector>
 
 enum class SpoilerOutputResultType;
-void spoiler_outlist(std::string_view header, const std::vector<std::string> &descriptions, char seperator);
+void spoiler_outlist(std::string_view header, const std::vector<std::string> &descriptions, char seperator, std::ofstream &ofs);
 SpoilerOutputResultType spoil_fixed_artifact();
index 0a0afa6..27dd440 100644 (file)
@@ -1,6 +1,7 @@
 #include "wizard/spoiler-util.h"
 #include "object/object-flags.h"
 #include "system/item-entity.h"
+#include <fstream>
 
 const char item_separator = ',';
 const char list_separator = _(',', ';');
@@ -34,10 +35,10 @@ std::vector<std::string> extract_spoiler_flags(const TrFlags &art_flags, const s
  * @param n 出力する数
  * @param c 出力するキャラクタ
  */
-static void spoiler_out_n_chars(int n, char c)
+static void spoiler_out_n_chars(int n, char c, std::ofstream &ofs)
 {
-    while (--n >= 0) {
-        fputc(c, spoiler_file);
+    for (auto i = 0; i < n; i++) {
+        ofs << c;
     }
 }
 
@@ -46,9 +47,9 @@ static void spoiler_out_n_chars(int n, char c)
  * Write out `n' blank lines to the spoiler file
  * @param n 改行を出力する数
  */
-void spoiler_blanklines(int n)
+void spoiler_blanklines(int n, std::ofstream &ofs)
 {
-    spoiler_out_n_chars(n, '\n');
+    spoiler_out_n_chars(n, '\n', ofs);
 }
 
 /*!
@@ -56,11 +57,11 @@ void spoiler_blanklines(int n)
  * Write a line to the spoiler file and then "underline" it with hypens
  * @param str 出力したい文字列
  */
-void spoiler_underline(std::string_view str)
+void spoiler_underline(std::string_view str, std::ofstream &ofs)
 {
-    fprintf(spoiler_file, "%s\n", str.data());
-    spoiler_out_n_chars(str.length(), '-');
-    fprintf(spoiler_file, "\n");
+    ofs << str.data() << '\n';
+    spoiler_out_n_chars(str.length(), '-', ofs);
+    ofs << '\n';
 }
 
 /*!
index b9f97d5..ce7f97f 100644 (file)
@@ -3,6 +3,7 @@
 #include "object-enchant/tr-flags.h"
 #include "system/angband.h"
 #include "wizard/spoiler-table.h"
+#include <fstream>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -54,6 +55,6 @@ extern FILE *spoiler_file;
 
 struct flag_desc;
 std::vector<std::string> extract_spoiler_flags(const TrFlags &art_flags, const std::vector<flag_desc> &definitions);
-void spoiler_blanklines(int n);
-void spoiler_underline(std::string_view str);
+void spoiler_blanklines(int n, std::ofstream &ofs);
+void spoiler_underline(std::string_view str, std::ofstream &ofs);
 void spoil_out(std::string_view sv, bool flush_buffer = false);