1 #include "info-reader/general-parser.h"
2 #include "dungeon/quest.h"
3 #include "grid/feature.h"
4 #include "info-reader/feature-reader.h"
5 #include "info-reader/info-reader-util.h"
6 #include "info-reader/parse-error-types.h"
7 #include "info-reader/random-grid-effect-types.h"
8 #include "io/tokenizer.h"
9 #include "main/angband-headers.h"
10 #include "object-enchant/trg-types.h"
11 #include "object/object-kind-hook.h"
12 #include "realm/realm-types.h"
13 #include "system/artifact-type-definition.h"
14 #include "system/building-type-definition.h"
15 #include "system/floor-type-definition.h"
16 #include "system/system-variables.h"
17 #include "util/angband-files.h"
18 #include "util/string-processor.h"
21 dungeon_grid letter[255];
24 * @brief パース関数に基づいてデータファイルからデータを読み取る /
25 * Initialize an "*_info" array, by parsing an ascii "template" file
26 * @param fp 読み取りに使うファイルポインタ
27 * @param buf 読み取りに使うバッファ領域
29 * @param parse_info_txt_line パース関数
32 errr init_info_txt(FILE *fp, char *buf, angband_header *head, std::function<errr(std::string_view, angband_header *)> parse_info_txt_line)
38 while (angband_fgets(fp, buf, 1024) == 0) {
40 if (!buf[0] || (buf[0] == '#'))
44 return (PARSE_ERROR_GENERIC);
50 if (buf[0] != 'N' && buf[0] != 'D') {
52 for (i = 0; buf[i]; i++) {
53 head->checksum += (byte)buf[i];
54 head->checksum ^= (1U << (i % 8));
58 if ((err = parse_info_txt_line(buf, head)) != 0)
66 * @brief 地形情報の「F:」情報をパースする
67 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
68 * @param floor_ptr 現在フロアへの参照ポインタ
72 parse_error_type parse_line_feature(floor_type *floor_ptr, char *buf)
74 if (init_flags & INIT_ONLY_BUILDINGS)
75 return PARSE_ERROR_NONE;
78 int num = tokenize(buf + 2, 9, zz, 0);
80 return PARSE_ERROR_GENERIC;
83 letter[index].feature = feat_none;
84 letter[index].monster = 0;
85 letter[index].object = 0;
86 letter[index].ego = 0;
87 letter[index].artifact = 0;
88 letter[index].trap = feat_none;
89 letter[index].cave_info = 0;
90 letter[index].special = 0;
91 letter[index].random = RANDOM_NONE;
95 letter[index].special = (int16_t)atoi(zz[8]);
98 if ((zz[7][0] == '*') && !zz[7][1]) {
99 letter[index].random |= RANDOM_TRAP;
101 letter[index].trap = f_tag_to_index(zz[7]);
102 if (letter[index].trap < 0)
103 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
107 if (zz[6][0] == '*') {
108 letter[index].random |= RANDOM_ARTIFACT;
110 letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1);
111 } else if (zz[6][0] == '!') {
112 if (floor_ptr->inside_quest) {
113 letter[index].artifact = quest[floor_ptr->inside_quest].k_idx;
116 letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]);
120 if (zz[5][0] == '*') {
121 letter[index].random |= RANDOM_EGO;
123 letter[index].ego = (EGO_IDX)atoi(zz[5] + 1);
125 letter[index].ego = (EGO_IDX)atoi(zz[5]);
129 if (zz[4][0] == '*') {
130 letter[index].random |= RANDOM_OBJECT;
132 letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1);
133 } else if (zz[4][0] == '!') {
134 if (floor_ptr->inside_quest) {
135 ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx;
137 artifact_type *a_ptr = &a_info[a_idx];
138 if (a_ptr->gen_flags.has_not(TRG::INSTA_ART)) {
139 letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
144 letter[index].object = (OBJECT_IDX)atoi(zz[4]);
148 if (zz[3][0] == '*') {
149 letter[index].random |= RANDOM_MONSTER;
151 letter[index].monster = (MONSTER_IDX)atoi(zz[3] + 1);
152 } else if (zz[3][0] == 'c') {
154 return PARSE_ERROR_GENERIC;
155 letter[index].monster = -atoi(zz[3] + 1);
157 letter[index].monster = (MONSTER_IDX)atoi(zz[3]);
161 letter[index].cave_info = atoi(zz[2]);
164 if ((zz[1][0] == '*') && !zz[1][1]) {
165 letter[index].random |= RANDOM_FEATURE;
167 letter[index].feature = f_tag_to_index(zz[1]);
168 if (letter[index].feature < 0)
169 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
175 return PARSE_ERROR_NONE;
179 * @brief 地形情報の「B:」情報をパースする
180 * Process "B:<Index>:<Command>:..." -- Building definition
184 parse_error_type parse_line_building(char *buf)
191 return PARSE_ERROR_NONE;
195 return PARSE_ERROR_NONE;
199 s = angband_strchr(s, ':');
201 return PARSE_ERROR_GENERIC;
205 return PARSE_ERROR_GENERIC;
209 if (tokenize(s + 2, 3, zz, 0) == 3) {
210 strcpy(building[index].name, zz[0]);
211 strcpy(building[index].owner_name, zz[1]);
212 strcpy(building[index].owner_race, zz[2]);
216 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
219 if (tokenize(s + 2, 8, zz, 0) >= 7) {
220 int action_index = atoi(zz[0]);
221 strcpy(building[index].act_names[action_index], zz[1]);
222 building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
223 building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
224 building[index].letters[action_index] = zz[4][0];
225 building[index].actions[action_index] = static_cast<int16_t>(atoi(zz[5]));
226 building[index].action_restr[action_index] = static_cast<int16_t>(atoi(zz[6]));
230 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
234 n = tokenize(s + 2, MAX_CLASS, zz, 0);
235 for (int i = 0; i < MAX_CLASS; i++) {
236 building[index].member_class[i] = static_cast<player_class_type>((i < n) ? atoi(zz[i]) : 1);
243 n = tokenize(s + 2, MAX_RACES, zz, 0);
244 for (int i = 0; i < MAX_RACES; i++) {
245 building[index].member_race[i] = static_cast<player_race_type>((i < n) ? atoi(zz[i]) : 1);
252 n = tokenize(s + 2, MAX_MAGIC, zz, 0);
253 for (int i = 0; i < MAX_MAGIC; i++) {
254 building[index].member_realm[i + 1] = ((i < n) ? static_cast<int16_t>(atoi(zz[i])) : 1);
263 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
267 return PARSE_ERROR_NONE;