1 #include "info-reader/feature-reader.h"
2 #include "floor/wild.h"
3 #include "grid/feature.h"
5 #include "info-reader/feature-info-tokens-table.h"
6 #include "info-reader/parse-error-types.h"
7 #include "room/rooms.h"
8 #include "term/gameterm.h"
9 #include "view/display-main-window.h"
11 angband_header f_head; /*!< 地形情報のヘッダ構造体 */
13 /*! 地形タグ情報から地形IDを得られなかった場合にTRUEを返す */
14 static bool feat_tag_is_not_found = FALSE;
17 * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
18 * Grab one flag in an feature_type from a textual string
19 * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
20 * @param what 参照元の文字列ポインタ
23 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
25 for (int i = 0; i < FF_FLAG_MAX; i++) {
26 if (streq(what, f_info_flags[i])) {
27 add_flag(f_ptr->flags, i);
32 msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
33 return PARSE_ERROR_GENERIC;
37 * @brief テキストトークンを走査してフラグ(ステート)を一つ得る(地形情報向け2) /
38 * Grab an action in an feature_type from a textual string
39 * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
40 * @param what 参照元の文字列ポインタ
41 * @param count ステートの保存先ID
44 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
46 for (FF_FLAGS_IDX i = 0; i < FF_FLAG_MAX; i++) {
47 if (streq(what, f_info_flags[i])) {
48 f_ptr->state[count].action = i;
53 msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
54 return PARSE_ERROR_GENERIC;
58 * @brief 地形情報(f_info)のパース関数 /
59 * Initialize the "f_info" array, by parsing an ascii "template" file
64 errr parse_f_info(char *buf, angband_header *head)
66 static feature_type *f_ptr = NULL;
70 s = angband_strchr(buf + 2, ':');
79 if (i >= head->info_num)
85 if (!add_tag(&f_ptr->tag, head, s))
89 f_ptr->mimic = (FEAT_IDX)i;
90 f_ptr->destroyed = (FEAT_IDX)i;
91 for (i = 0; i < MAX_FEAT_STATES; i++)
92 f_ptr->state[i].action = FF_FLAG_MAX;
97 else if (buf[0] == 'J') {
98 if (!add_name(&f_ptr->name, head, buf + 2))
100 } else if (buf[0] == 'E') {
103 else if (buf[0] == 'J') {
104 } else if (buf[0] == 'E') {
106 if (!add_name(&f_ptr->name, head, s))
110 else if (buf[0] == 'M') {
112 if (!add_tag(&offset, head, buf + 2))
113 return PARSE_ERROR_OUT_OF_MEMORY;
115 f_ptr->mimic_tag = offset;
116 } else if (buf[0] == 'G') {
119 char char_tmp[F_LIT_MAX];
129 char_tmp[F_LIT_STANDARD] = buf[2];
130 s_attr = color_char_to_attr(buf[4]);
134 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
135 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
137 apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
138 if (!streq(buf + 6, "LIT")) {
139 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
141 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2
142 != sscanf(buf + 6, "%c:%c:%c:%c", &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN], &char_tmp[F_LIT_DARK],
143 &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN]))
145 if (buf[F_LIT_MAX * 4 + 1])
148 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) {
149 switch (attr_lite_tmp[j - F_LIT_NS_BEGIN]) {
151 /* Use default lighting */
154 /* No lighting support */
155 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
158 /* Extract the color */
159 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
160 if (f_ptr->d_attr[j] > 127)
164 f_ptr->d_char[j] = char_tmp[j];
167 } else if (!buf[5]) {
168 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) {
169 f_ptr->d_attr[j] = s_attr;
170 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
174 } else if (buf[0] == 'F') {
175 for (s = buf + 2; *s;) {
177 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
182 while (*t == ' ' || *t == '|')
186 if (1 == sscanf(s, "SUBTYPE_%d", &i)) {
187 f_ptr->subtype = (FEAT_SUBTYPE)i;
193 if (1 == sscanf(s, "POWER_%d", &i)) {
194 f_ptr->power = (FEAT_POWER)i;
199 if (0 != grab_one_feat_flag(f_ptr, s))
200 return (PARSE_ERROR_INVALID_FLAG);
204 } else if (buf[0] == 'W') {
206 if (1 != sscanf(buf + 2, "%d", &priority))
207 return (PARSE_ERROR_GENERIC);
208 f_ptr->priority = (FEAT_PRIORITY)priority;
209 } else if (buf[0] == 'K') {
211 for (i = 0; i < MAX_FEAT_STATES; i++)
212 if (f_ptr->state[i].action == FF_FLAG_MAX)
215 if (i == MAX_FEAT_STATES)
216 return PARSE_ERROR_GENERIC;
219 for (s = t = buf + 2; *t && (*t != ':'); t++)
225 if (streq(s, "DESTROYED")) {
226 if (!add_tag(&offset, head, t))
227 return PARSE_ERROR_OUT_OF_MEMORY;
229 f_ptr->destroyed_tag = offset;
231 f_ptr->state[i].action = 0;
232 if (0 != grab_one_feat_action(f_ptr, s, i))
233 return PARSE_ERROR_INVALID_FLAG;
234 if (!add_tag(&offset, head, t))
235 return PARSE_ERROR_OUT_OF_MEMORY;
237 f_ptr->state[i].result_tag = offset;
247 * @brief 地形の汎用定義をタグを通じて取得する /
248 * Initialize feature variables
251 errr init_feat_variables(void)
253 feat_none = f_tag_to_index_in_init("NONE");
255 feat_floor = f_tag_to_index_in_init("FLOOR");
256 feat_glyph = f_tag_to_index_in_init("GLYPH");
257 feat_explosive_rune = f_tag_to_index_in_init("EXPLOSIVE_RUNE");
258 feat_mirror = f_tag_to_index_in_init("MIRROR");
260 feat_door[DOOR_DOOR].open = f_tag_to_index_in_init("OPEN_DOOR");
261 feat_door[DOOR_DOOR].broken = f_tag_to_index_in_init("BROKEN_DOOR");
262 feat_door[DOOR_DOOR].closed = f_tag_to_index_in_init("CLOSED_DOOR");
266 for (i = 1; i < MAX_LJ_DOORS; i++) {
267 s16b door = f_tag_to_index(format("LOCKED_DOOR_%d", i));
270 feat_door[DOOR_DOOR].locked[i - 1] = door;
274 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
275 feat_door[DOOR_DOOR].num_locked = i - 1;
278 for (i = 0; i < MAX_LJ_DOORS; i++) {
279 s16b door = f_tag_to_index(format("JAMMED_DOOR_%d", i));
282 feat_door[DOOR_DOOR].jammed[i] = door;
286 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
287 feat_door[DOOR_DOOR].num_jammed = i;
290 feat_door[DOOR_GLASS_DOOR].open = f_tag_to_index_in_init("OPEN_GLASS_DOOR");
291 feat_door[DOOR_GLASS_DOOR].broken = f_tag_to_index_in_init("BROKEN_GLASS_DOOR");
292 feat_door[DOOR_GLASS_DOOR].closed = f_tag_to_index_in_init("CLOSED_GLASS_DOOR");
294 /* Locked glass doors */
295 for (i = 1; i < MAX_LJ_DOORS; i++) {
296 s16b door = f_tag_to_index(format("LOCKED_GLASS_DOOR_%d", i));
299 feat_door[DOOR_GLASS_DOOR].locked[i - 1] = door;
303 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
304 feat_door[DOOR_GLASS_DOOR].num_locked = i - 1;
306 /* Jammed glass doors */
307 for (i = 0; i < MAX_LJ_DOORS; i++) {
308 s16b door = f_tag_to_index(format("JAMMED_GLASS_DOOR_%d", i));
311 feat_door[DOOR_GLASS_DOOR].jammed[i] = door;
315 return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
316 feat_door[DOOR_GLASS_DOOR].num_jammed = i;
319 feat_door[DOOR_CURTAIN].open = f_tag_to_index_in_init("OPEN_CURTAIN");
320 feat_door[DOOR_CURTAIN].broken = feat_door[DOOR_CURTAIN].open;
321 feat_door[DOOR_CURTAIN].closed = f_tag_to_index_in_init("CLOSED_CURTAIN");
322 feat_door[DOOR_CURTAIN].locked[0] = feat_door[DOOR_CURTAIN].closed;
323 feat_door[DOOR_CURTAIN].num_locked = 1;
324 feat_door[DOOR_CURTAIN].jammed[0] = feat_door[DOOR_CURTAIN].closed;
325 feat_door[DOOR_CURTAIN].num_jammed = 1;
328 feat_up_stair = f_tag_to_index_in_init("UP_STAIR");
329 feat_down_stair = f_tag_to_index_in_init("DOWN_STAIR");
330 feat_entrance = f_tag_to_index_in_init("ENTRANCE");
336 feat_trap_open = f_tag_to_index_in_init("TRAP_OPEN");
337 feat_trap_armageddon = f_tag_to_index_in_init("TRAP_ARMAGEDDON");
338 feat_trap_piranha = f_tag_to_index_in_init("TRAP_PIRANHA");
341 feat_rubble = f_tag_to_index_in_init("RUBBLE");
344 feat_magma_vein = f_tag_to_index_in_init("MAGMA_VEIN");
345 feat_quartz_vein = f_tag_to_index_in_init("QUARTZ_VEIN");
348 feat_granite = f_tag_to_index_in_init("GRANITE");
349 feat_permanent = f_tag_to_index_in_init("PERMANENT");
352 feat_glass_floor = f_tag_to_index_in_init("GLASS_FLOOR");
355 feat_glass_wall = f_tag_to_index_in_init("GLASS_WALL");
356 feat_permanent_glass_wall = f_tag_to_index_in_init("PERMANENT_GLASS_WALL");
359 feat_pattern_start = f_tag_to_index_in_init("PATTERN_START");
360 feat_pattern_1 = f_tag_to_index_in_init("PATTERN_1");
361 feat_pattern_2 = f_tag_to_index_in_init("PATTERN_2");
362 feat_pattern_3 = f_tag_to_index_in_init("PATTERN_3");
363 feat_pattern_4 = f_tag_to_index_in_init("PATTERN_4");
364 feat_pattern_end = f_tag_to_index_in_init("PATTERN_END");
365 feat_pattern_old = f_tag_to_index_in_init("PATTERN_OLD");
366 feat_pattern_exit = f_tag_to_index_in_init("PATTERN_EXIT");
367 feat_pattern_corrupted = f_tag_to_index_in_init("PATTERN_CORRUPTED");
370 feat_black_market = f_tag_to_index_in_init("BLACK_MARKET");
371 feat_town = f_tag_to_index_in_init("TOWN");
374 feat_deep_water = f_tag_to_index_in_init("DEEP_WATER");
375 feat_shallow_water = f_tag_to_index_in_init("SHALLOW_WATER");
376 feat_deep_lava = f_tag_to_index_in_init("DEEP_LAVA");
377 feat_shallow_lava = f_tag_to_index_in_init("SHALLOW_LAVA");
378 feat_heavy_cold_zone = f_tag_to_index_in_init("HEAVY_COLD_ZONE");
379 feat_cold_zone = f_tag_to_index_in_init("COLD_ZONE");
380 feat_heavy_electrical_zone = f_tag_to_index_in_init("HEAVY_ELECTRICAL_ZONE");
381 feat_electrical_zone = f_tag_to_index_in_init("ELECTRICAL_ZONE");
382 feat_deep_acid_puddle = f_tag_to_index_in_init("DEEP_ACID_PUDDLE");
383 feat_shallow_acid_puddle = f_tag_to_index_in_init("SHALLOW_ACID_PUDDLE");
384 feat_deep_poisonous_puddle = f_tag_to_index_in_init("DEEP_POISONOUS_PUDDLE");
385 feat_shallow_poisonous_puddle = f_tag_to_index_in_init("SHALLOW_POISONOUS_PUDDLE");
386 feat_dirt = f_tag_to_index_in_init("DIRT");
387 feat_grass = f_tag_to_index_in_init("GRASS");
388 feat_flower = f_tag_to_index_in_init("FLOWER");
389 feat_brake = f_tag_to_index_in_init("BRAKE");
390 feat_tree = f_tag_to_index_in_init("TREE");
391 feat_mountain = f_tag_to_index_in_init("MOUNTAIN");
392 feat_swamp = f_tag_to_index_in_init("SWAMP");
394 feat_undetected = f_tag_to_index_in_init("UNDETECTED");
396 init_wilderness_terrains();
397 return feat_tag_is_not_found ? PARSE_ERROR_UNDEFINED_TERRAIN_TAG : 0;
401 * @brief 地形タグからIDを得る /
402 * Convert a fake tag to a real feat index
406 s16b f_tag_to_index(concptr str)
408 for (u16b i = 0; i < f_head.info_num; i++) {
409 if (streq(f_tag + f_info[i].tag, str)) {
418 * @brief 地形タグからIDを得る /
419 * Initialize quest array
422 s16b f_tag_to_index_in_init(concptr str)
424 FEAT_IDX feat = f_tag_to_index(str);
427 feat_tag_is_not_found = TRUE;
433 * @brief 地形タグからIDを得る /
434 * Search for real index corresponding to this fake tag
435 * @param feat タグ文字列のオフセット
436 * @return 地形ID。該当がないなら-1
438 static FEAT_IDX search_real_feat(STR_OFFSET feat)
444 for (FEAT_IDX i = 0; i < f_head.info_num; i++) {
445 if (feat == f_info[i].tag) {
450 msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
455 * @brief 地形情報の各種タグからIDへ変換して結果を収める /
456 * Retouch fake tags of f_info
460 void retouch_f_info(angband_header *head)
462 for (int i = 0; i < head->info_num; i++) {
463 feature_type *f_ptr = &f_info[i];
464 FEAT_IDX k = search_real_feat(f_ptr->mimic_tag);
465 f_ptr->mimic = k < 0 ? f_ptr->mimic : k;
466 k = search_real_feat(f_ptr->destroyed_tag);
467 f_ptr->destroyed = k < 0 ? f_ptr->destroyed : k;
468 for (FEAT_IDX j = 0; j < MAX_FEAT_STATES; j++) {
469 k = search_real_feat(f_ptr->state[j].result_tag);
470 f_ptr->state[j].result = k < 0 ? f_ptr->state[j].result : k;