OSDN Git Service

Merge pull request #3532 from sikabane-works/release/3.0.0.87-alpha
[hengbandforosx/hengbandosx.git] / src / info-reader / magic-reader.cpp
1 #include "info-reader/magic-reader.h"
2 #include "info-reader/info-reader-util.h"
3 #include "info-reader/parse-error-types.h"
4 #include "main/angband-headers.h"
5 #include "player-ability/player-ability-types.h"
6 #include "player-info/class-info.h"
7 #include "util/string-processor.h"
8
9 namespace {
10 /*!
11  * @brief 魔法タイプ名とtvalの対応表
12  */
13 const std::unordered_map<std::string_view, ItemKindType> name_to_tval = {
14     { "SORCERY", ItemKindType::SORCERY_BOOK },
15     { "LIFE", ItemKindType::LIFE_BOOK },
16     { "MUSIC", ItemKindType::MUSIC_BOOK },
17     { "HISSATSU", ItemKindType::HISSATSU_BOOK },
18     { "NONE", ItemKindType::NONE },
19 };
20
21 /*!
22  * @brief 魔法必須能力とenumの対応表
23  */
24 const std::unordered_map<std::string_view, int> name_to_stat = {
25     { "STR", A_STR },
26     { "INT", A_INT },
27     { "WIS", A_WIS },
28     { "DEX", A_DEX },
29     { "CON", A_CON },
30     { "CHR", A_CHR },
31 };
32 }
33
34 /*!
35  * @brief 職業魔法情報(ClassMagicDefinitions)のパース関数
36  * @param buf テキスト列
37  * @param head ヘッダ構造体
38  * @return エラーコード
39  */
40 errr parse_class_magics_info(std::string_view buf, angband_header *head)
41 {
42     static player_magic *m_ptr = nullptr;
43     static int realm, magic_idx = 0, readable = 0;
44     const auto &tokens = str_split(buf, ':', false, 7);
45
46     if (tokens[0] == "N") {
47         // N:class-index
48         if (tokens.size() < 2 && tokens[1].size() == 0) {
49             return PARSE_ERROR_GENERIC;
50         }
51
52         auto i = std::stoi(tokens[1]);
53         if (i < error_idx) {
54             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
55         }
56         if (i >= head->info_num) {
57             return PARSE_ERROR_OUT_OF_BOUNDS;
58         }
59
60         error_idx = i;
61         m_ptr = &class_magics_info[i];
62     } else if (!m_ptr) {
63         return PARSE_ERROR_MISSING_RECORD_HEADER;
64     } else if (tokens[0] == "I") {
65         if (tokens.size() < 7 || tokens[1].size() == 0) {
66             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
67         }
68
69         const auto tval = name_to_tval.find(tokens[1]);
70         if (tval == name_to_tval.end()) {
71             return PARSE_ERROR_INVALID_FLAG;
72         }
73
74         m_ptr->spell_book = tval->second;
75
76         const auto stat = name_to_stat.find(tokens[2]);
77         if (stat == name_to_stat.end()) {
78             return PARSE_ERROR_INVALID_FLAG;
79         }
80
81         m_ptr->spell_stat = stat->second;
82
83         info_set_value(m_ptr->spell_xtra, tokens[3], 16);
84         info_set_value(m_ptr->spell_type, tokens[4]);
85         info_set_value(m_ptr->spell_first, tokens[5]);
86         info_set_value(m_ptr->spell_weight, tokens[6]);
87     } else if (tokens[0] == "R") {
88         if (tokens.size() < 3) {
89             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
90         }
91
92         info_set_value(realm, tokens[1]);
93         info_set_value(readable, tokens[2]);
94         magic_idx = 0;
95     } else if (tokens[0] == "T") {
96         if (!readable) {
97             return PARSE_ERROR_GENERIC;
98         }
99
100         if (tokens.size() < 5) {
101             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
102         }
103
104         auto &magic = m_ptr->info[realm][magic_idx];
105         info_set_value(magic.slevel, tokens[1]);
106         info_set_value(magic.smana, tokens[2]);
107         info_set_value(magic.sfail, tokens[3]);
108         info_set_value(magic.sexp, tokens[4]);
109         magic_idx++;
110     } else {
111         return PARSE_ERROR_UNDEFINED_DIRECTIVE;
112     }
113
114     return PARSE_ERROR_NONE;
115 }