From 5a46b167caa1809bd7d7e99f26ce46eb41c99ed0 Mon Sep 17 00:00:00 2001 From: Hourier Date: Sat, 6 Jun 2020 12:52:29 +0900 Subject: [PATCH] [Refactor] #40460 Separated general-parser.c/h from dungeon-file.c/h --- Hengband/Hengband/Hengband.vcxproj | 2 + Hengband/Hengband/Hengband.vcxproj.filters | 6 + src/Makefile.am | 1 + src/dungeon/dungeon-file.c | 305 +---------------------------- src/dungeon/dungeon-file.h | 1 - src/info-reader/dungeon-reader.h | 2 +- src/info-reader/general-parser.c | 267 +++++++++++++++++++++++++ src/info-reader/general-parser.h | 22 +++ src/main/init.c | 1 + 9 files changed, 301 insertions(+), 306 deletions(-) create mode 100644 src/info-reader/general-parser.c create mode 100644 src/info-reader/general-parser.h diff --git a/Hengband/Hengband/Hengband.vcxproj b/Hengband/Hengband/Hengband.vcxproj index 47f1579d3..cb26adfc9 100644 --- a/Hengband/Hengband/Hengband.vcxproj +++ b/Hengband/Hengband/Hengband.vcxproj @@ -175,6 +175,7 @@ + @@ -501,6 +502,7 @@ + diff --git a/Hengband/Hengband/Hengband.vcxproj.filters b/Hengband/Hengband/Hengband.vcxproj.filters index cc6cc3ee3..afa875a3b 100644 --- a/Hengband/Hengband/Hengband.vcxproj.filters +++ b/Hengband/Hengband/Hengband.vcxproj.filters @@ -1226,6 +1226,9 @@ info-reader + + info-reader + @@ -2617,6 +2620,9 @@ info-reader + + info-reader + diff --git a/src/Makefile.am b/src/Makefile.am index da35b6dcd..277360a15 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -158,6 +158,7 @@ hengband_SOURCES = \ info-reader/ego-reader.c info-reader/ego-reader.h \ info-reader/feature-info-tokens-table.c info-reader/feature-info-tokens-table.h \ info-reader/feature-reader.c info-reader/feature-reader.h \ + info-reader/general-parser.c info-reader/general-parser.h \ info-reader/info-reader-util.c info-reader/info-reader-util.h \ info-reader/kind-info-tokens-table.c info-reader/kind-info-tokens-table.h \ info-reader/kind-reader.c info-reader/kind-reader.h \ diff --git a/src/dungeon/dungeon-file.c b/src/dungeon/dungeon-file.c index f05a66418..56ff05c63 100644 --- a/src/dungeon/dungeon-file.c +++ b/src/dungeon/dungeon-file.c @@ -47,6 +47,7 @@ #include "grid/trap.h" #include "info-reader/dungeon-info-tokens-table.h" #include "info-reader/feature-reader.h" +#include "info-reader/general-parser.h" #include "info-reader/info-reader-util.h" #include "info-reader/kind-info-tokens-table.h" #include "info-reader/race-info-tokens-table.h" @@ -76,310 +77,6 @@ #include "world/world-object.h" #include "world/world.h" -typedef struct dungeon_grid { - FEAT_IDX feature; /* Terrain feature */ - MONSTER_IDX monster; /* Monster */ - OBJECT_IDX object; /* Object */ - EGO_IDX ego; /* Ego-Item */ - ARTIFACT_IDX artifact; /* Artifact */ - IDX trap; /* Trap */ - BIT_FLAGS cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */ - s16b special; /* Reserved for special terrain info */ - int random; /* Number of the random effect */ -} dungeon_grid; - -static dungeon_grid letter[255]; - -/*! - * @brief パース関数に基づいてデータファイルからデータを読み取る / - * Initialize an "*_info" array, by parsing an ascii "template" file - * @param fp 読み取りに使うファイルポインタ - * @param buf 読み取りに使うバッファ領域 - * @param head ヘッダ構造体 - * @param parse_info_txt_line パース関数 - * @return エラーコード - */ -errr init_info_txt(FILE *fp, char *buf, angband_header *head, parse_info_txt_func parse_info_txt_line) -{ - error_idx = -1; - error_line = 0; - - head->name_size = 0; - head->text_size = 0; - head->tag_size = 0; - - errr err; - while (my_fgets(fp, buf, 1024) == 0) - { - error_line++; - if (!buf[0] || (buf[0] == '#')) continue; - - if (buf[1] != ':') return (PARSE_ERROR_GENERIC); - - if (buf[0] == 'V') - { - continue; - } - - if (buf[0] != 'N' && buf[0] != 'D') - { - int i; - for (i = 0; buf[i]; i++) - { - head->v_extra += (byte)buf[i]; - head->v_extra ^= (1 << (i % 8)); - } - } - - if ((err = (*parse_info_txt_line)(buf, head)) != 0) - return (err); - } - - if (head->name_size) head->name_size++; - if (head->text_size) head->text_size++; - - return 0; -} - - -/*! - * @brief 地形情報の「F:」情報をパースする - * Process "F:::::::::" -- info for dungeon grid - * @param floor_ptr 現在フロアへの参照ポインタ - * @param buf 解析文字列 - * @return エラーコード - */ -static errr parse_line_feature(floor_type *floor_ptr, char *buf) -{ - if (init_flags & INIT_ONLY_BUILDINGS) return 0; - - char *zz[9]; - int num = tokenize(buf + 2, 9, zz, 0); - if (num <= 1) return 1; - - int index = zz[0][0]; - letter[index].feature = feat_none; - letter[index].monster = 0; - letter[index].object = 0; - letter[index].ego = 0; - letter[index].artifact = 0; - letter[index].trap = feat_none; - letter[index].cave_info = 0; - letter[index].special = 0; - letter[index].random = RANDOM_NONE; - - switch (num) - { - case 9: - letter[index].special = (s16b)atoi(zz[8]); - /* Fall through */ - case 8: - if ((zz[7][0] == '*') && !zz[7][1]) - { - letter[index].random |= RANDOM_TRAP; - } - else - { - letter[index].trap = f_tag_to_index(zz[7]); - if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG; - } - /* Fall through */ - case 7: - if (zz[6][0] == '*') - { - letter[index].random |= RANDOM_ARTIFACT; - if (zz[6][1]) letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1); - } - else if (zz[6][0] == '!') - { - if (floor_ptr->inside_quest) - { - letter[index].artifact = quest[floor_ptr->inside_quest].k_idx; - } - } - else - { - letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]); - } - /* Fall through */ - case 6: - if (zz[5][0] == '*') - { - letter[index].random |= RANDOM_EGO; - if (zz[5][1]) letter[index].ego = (EGO_IDX)atoi(zz[5] + 1); - } - else - { - letter[index].ego = (EGO_IDX)atoi(zz[5]); - } - /* Fall through */ - case 5: - if (zz[4][0] == '*') - { - letter[index].random |= RANDOM_OBJECT; - if (zz[4][1]) letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1); - } - else if (zz[4][0] == '!') - { - if (floor_ptr->inside_quest) - { - ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx; - if (a_idx) - { - artifact_type *a_ptr = &a_info[a_idx]; - if (!(a_ptr->gen_flags & TRG_INSTA_ART)) - { - letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval); - } - } - } - } - else - { - letter[index].object = (IDX)atoi(zz[4]); - } - /* Fall through */ - case 4: - if (zz[3][0] == '*') - { - letter[index].random |= RANDOM_MONSTER; - if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1); - } - else if (zz[3][0] == 'c') - { - if (!zz[3][1]) return PARSE_ERROR_GENERIC; - letter[index].monster = -atoi(zz[3] + 1); - } - else - { - letter[index].monster = (IDX)atoi(zz[3]); - } - /* Fall through */ - case 3: - letter[index].cave_info = atoi(zz[2]); - /* Fall through */ - case 2: - if ((zz[1][0] == '*') && !zz[1][1]) - { - letter[index].random |= RANDOM_FEATURE; - } - else - { - letter[index].feature = f_tag_to_index(zz[1]); - if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG; - } - - break; - } - - return 0; -} - - -/*! - * @brief 地形情報の「B:」情報をパースする - * Process "B:::..." -- Building definition - * @param buf 解析文字列 - * @return エラーコード - */ -static errr parse_line_building(char *buf) -{ - char *zz[1000]; - char *s; - -#ifdef JP - if (buf[2] == '$') - return 0; - s = buf + 2; -#else - if (buf[2] != '$') - return 0; - s = buf + 3; -#endif - int index = atoi(s); - s = my_strchr(s, ':'); - if (!s) return 1; - - *s++ = '\0'; - if (!*s) return 1; - - switch (s[0]) - { - case 'N': - { - if (tokenize(s + 2, 3, zz, 0) == 3) - { - strcpy(building[index].name, zz[0]); - strcpy(building[index].owner_name, zz[1]); - strcpy(building[index].owner_race, zz[2]); - break; - } - - return (PARSE_ERROR_TOO_FEW_ARGUMENTS); - } - case 'A': - { - if (tokenize(s + 2, 8, zz, 0) >= 7) - { - int action_index = atoi(zz[0]); - strcpy(building[index].act_names[action_index], zz[1]); - building[index].member_costs[action_index] = (PRICE)atoi(zz[2]); - building[index].other_costs[action_index] = (PRICE)atoi(zz[3]); - building[index].letters[action_index] = zz[4][0]; - building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]); - building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]); - break; - } - - return (PARSE_ERROR_TOO_FEW_ARGUMENTS); - } - case 'C': - { - int n; - n = tokenize(s + 2, MAX_CLASS, zz, 0); - for (int i = 0; i < MAX_CLASS; i++) - { - building[index].member_class[i] = ((i < n) ? (player_class_type)atoi(zz[i]) : 1); - } - - break; - } - case 'R': - { - int n; - n = tokenize(s + 2, MAX_RACES, zz, 0); - for (int i = 0; i < MAX_RACES; i++) - { - building[index].member_race[i] = ((i < n) ? (player_race_type)atoi(zz[i]) : 1); - } - - break; - } - case 'M': - { - int n; - n = tokenize(s + 2, MAX_MAGIC, zz, 0); - for (int i = 0; i < MAX_MAGIC; i++) - { - building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1); - } - - break; - } - case 'Z': - { - break; - } - default: - { - return (PARSE_ERROR_UNDEFINED_DIRECTIVE); - } - } - - return 0; -} - - /*! * @brief フロアの所定のマスにオブジェクトを配置する * Place the object j_ptr to a grid diff --git a/src/dungeon/dungeon-file.h b/src/dungeon/dungeon-file.h index f4a39043b..9407bb0bf 100644 --- a/src/dungeon/dungeon-file.h +++ b/src/dungeon/dungeon-file.h @@ -6,5 +6,4 @@ extern concptr err_str[PARSE_ERROR_MAX]; -errr init_info_txt(FILE *fp, char *buf, angband_header *head, parse_info_txt_func parse_info_txt_line); errr process_dungeon_file(player_type *player_ptr, concptr name, int ymin, int xmin, int ymax, int xmax); diff --git a/src/info-reader/dungeon-reader.h b/src/info-reader/dungeon-reader.h index 854e88b22..42c692b1b 100644 --- a/src/info-reader/dungeon-reader.h +++ b/src/info-reader/dungeon-reader.h @@ -1,6 +1,6 @@ #pragma once -#include "info-reader/info-reader-util.h" #include "system/angband.h" +#include "info-reader/info-reader-util.h" errr parse_d_info(char *buf, angband_header *head); diff --git a/src/info-reader/general-parser.c b/src/info-reader/general-parser.c new file mode 100644 index 000000000..361003246 --- /dev/null +++ b/src/info-reader/general-parser.c @@ -0,0 +1,267 @@ +#include "info-reader/general-parser.h" +#include "dungeon/quest.h" +#include "floor/floor.h" +#include "grid/feature.h" +#include "info-reader/feature-reader.h" +#include "info-reader/parse-error-types.h" +#include "info-reader/random-grid-effect-types.h" +#include "io/tokenizer.h" +#include "object-enchant/artifact.h" +#include "object/object-kind-hook.h" +#include "system/system-variables.h" + +/*! + * @brief パース関数に基づいてデータファイルからデータを読み取る / + * Initialize an "*_info" array, by parsing an ascii "template" file + * @param fp 読み取りに使うファイルポインタ + * @param buf 読み取りに使うバッファ領域 + * @param head ヘッダ構造体 + * @param parse_info_txt_line パース関数 + * @return エラーコード + */ +errr init_info_txt(FILE *fp, char *buf, angband_header *head, parse_info_txt_func parse_info_txt_line) +{ + error_idx = -1; + error_line = 0; + + head->name_size = 0; + head->text_size = 0; + head->tag_size = 0; + + errr err; + while (my_fgets(fp, buf, 1024) == 0) { + error_line++; + if (!buf[0] || (buf[0] == '#')) + continue; + + if (buf[1] != ':') + return (PARSE_ERROR_GENERIC); + + if (buf[0] == 'V') { + continue; + } + + if (buf[0] != 'N' && buf[0] != 'D') { + int i; + for (i = 0; buf[i]; i++) { + head->v_extra += (byte)buf[i]; + head->v_extra ^= (1 << (i % 8)); + } + } + + if ((err = (*parse_info_txt_line)(buf, head)) != 0) + return (err); + } + + if (head->name_size) + head->name_size++; + if (head->text_size) + head->text_size++; + + return 0; +} + +/*! + * @brief 地形情報の「F:」情報をパースする + * Process "F:::::::::" -- info for dungeon grid + * @param floor_ptr 現在フロアへの参照ポインタ + * @param buf 解析文字列 + * @return エラーコード + */ +errr parse_line_feature(floor_type *floor_ptr, char *buf) +{ + if (init_flags & INIT_ONLY_BUILDINGS) + return 0; + + char *zz[9]; + int num = tokenize(buf + 2, 9, zz, 0); + if (num <= 1) + return 1; + + int index = zz[0][0]; + letter[index].feature = feat_none; + letter[index].monster = 0; + letter[index].object = 0; + letter[index].ego = 0; + letter[index].artifact = 0; + letter[index].trap = feat_none; + letter[index].cave_info = 0; + letter[index].special = 0; + letter[index].random = RANDOM_NONE; + + switch (num) { + case 9: + letter[index].special = (s16b)atoi(zz[8]); + /* Fall through */ + case 8: + if ((zz[7][0] == '*') && !zz[7][1]) { + letter[index].random |= RANDOM_TRAP; + } else { + letter[index].trap = f_tag_to_index(zz[7]); + if (letter[index].trap < 0) + return PARSE_ERROR_UNDEFINED_TERRAIN_TAG; + } + /* Fall through */ + case 7: + if (zz[6][0] == '*') { + letter[index].random |= RANDOM_ARTIFACT; + if (zz[6][1]) + letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1); + } else if (zz[6][0] == '!') { + if (floor_ptr->inside_quest) { + letter[index].artifact = quest[floor_ptr->inside_quest].k_idx; + } + } else { + letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]); + } + /* Fall through */ + case 6: + if (zz[5][0] == '*') { + letter[index].random |= RANDOM_EGO; + if (zz[5][1]) + letter[index].ego = (EGO_IDX)atoi(zz[5] + 1); + } else { + letter[index].ego = (EGO_IDX)atoi(zz[5]); + } + /* Fall through */ + case 5: + if (zz[4][0] == '*') { + letter[index].random |= RANDOM_OBJECT; + if (zz[4][1]) + letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1); + } else if (zz[4][0] == '!') { + if (floor_ptr->inside_quest) { + ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx; + if (a_idx) { + artifact_type *a_ptr = &a_info[a_idx]; + if (!(a_ptr->gen_flags & TRG_INSTA_ART)) { + letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval); + } + } + } + } else { + letter[index].object = (IDX)atoi(zz[4]); + } + /* Fall through */ + case 4: + if (zz[3][0] == '*') { + letter[index].random |= RANDOM_MONSTER; + if (zz[3][1]) + letter[index].monster = (IDX)atoi(zz[3] + 1); + } else if (zz[3][0] == 'c') { + if (!zz[3][1]) + return PARSE_ERROR_GENERIC; + letter[index].monster = -atoi(zz[3] + 1); + } else { + letter[index].monster = (IDX)atoi(zz[3]); + } + /* Fall through */ + case 3: + letter[index].cave_info = atoi(zz[2]); + /* Fall through */ + case 2: + if ((zz[1][0] == '*') && !zz[1][1]) { + letter[index].random |= RANDOM_FEATURE; + } else { + letter[index].feature = f_tag_to_index(zz[1]); + if (letter[index].feature < 0) + return PARSE_ERROR_UNDEFINED_TERRAIN_TAG; + } + + break; + } + + return 0; +} + +/*! + * @brief 地形情報の「B:」情報をパースする + * Process "B:::..." -- Building definition + * @param buf 解析文字列 + * @return エラーコード + */ +errr parse_line_building(char *buf) +{ + char *zz[1000]; + char *s; + +#ifdef JP + if (buf[2] == '$') + return 0; + s = buf + 2; +#else + if (buf[2] != '$') + return 0; + s = buf + 3; +#endif + int index = atoi(s); + s = my_strchr(s, ':'); + if (!s) + return 1; + + *s++ = '\0'; + if (!*s) + return 1; + + switch (s[0]) { + case 'N': { + if (tokenize(s + 2, 3, zz, 0) == 3) { + strcpy(building[index].name, zz[0]); + strcpy(building[index].owner_name, zz[1]); + strcpy(building[index].owner_race, zz[2]); + break; + } + + return (PARSE_ERROR_TOO_FEW_ARGUMENTS); + } + case 'A': { + if (tokenize(s + 2, 8, zz, 0) >= 7) { + int action_index = atoi(zz[0]); + strcpy(building[index].act_names[action_index], zz[1]); + building[index].member_costs[action_index] = (PRICE)atoi(zz[2]); + building[index].other_costs[action_index] = (PRICE)atoi(zz[3]); + building[index].letters[action_index] = zz[4][0]; + building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]); + building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]); + break; + } + + return (PARSE_ERROR_TOO_FEW_ARGUMENTS); + } + case 'C': { + int n; + n = tokenize(s + 2, MAX_CLASS, zz, 0); + for (int i = 0; i < MAX_CLASS; i++) { + building[index].member_class[i] = ((i < n) ? (player_class_type)atoi(zz[i]) : 1); + } + + break; + } + case 'R': { + int n; + n = tokenize(s + 2, MAX_RACES, zz, 0); + for (int i = 0; i < MAX_RACES; i++) { + building[index].member_race[i] = ((i < n) ? (player_race_type)atoi(zz[i]) : 1); + } + + break; + } + case 'M': { + int n; + n = tokenize(s + 2, MAX_MAGIC, zz, 0); + for (int i = 0; i < MAX_MAGIC; i++) { + building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1); + } + + break; + } + case 'Z': { + break; + } + default: { + return (PARSE_ERROR_UNDEFINED_DIRECTIVE); + } + } + + return 0; +} diff --git a/src/info-reader/general-parser.h b/src/info-reader/general-parser.h new file mode 100644 index 000000000..9d603f146 --- /dev/null +++ b/src/info-reader/general-parser.h @@ -0,0 +1,22 @@ +#pragma once + +#include "system/angband.h" +#include "info-reader/info-reader-util.h" + +typedef struct dungeon_grid { + FEAT_IDX feature; /* Terrain feature */ + MONSTER_IDX monster; /* Monster */ + OBJECT_IDX object; /* Object */ + EGO_IDX ego; /* Ego-Item */ + ARTIFACT_IDX artifact; /* Artifact */ + IDX trap; /* Trap */ + BIT_FLAGS cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */ + s16b special; /* Reserved for special terrain info */ + int random; /* Number of the random effect */ +} dungeon_grid; + +dungeon_grid letter[255]; + +errr init_info_txt(FILE *fp, char *buf, angband_header *head, parse_info_txt_func parse_info_txt_line); +errr parse_line_feature(floor_type *floor_ptr, char *buf); +errr parse_line_building(char *buf); diff --git a/src/main/init.c b/src/main/init.c index b73ff48f3..b8699f6ed 100644 --- a/src/main/init.c +++ b/src/main/init.c @@ -43,6 +43,7 @@ #include "info-reader/dungeon-reader.h" #include "info-reader/ego-reader.h" #include "info-reader/feature-reader.h" +#include "info-reader/general-parser.h" #include "info-reader/kind-reader.h" #include "info-reader/magic-reader.h" #include "info-reader/race-reader.h" -- 2.11.0