OSDN Git Service

[Refactor] #40413 Separated angband-files.c/h from util.c/h
[hengband/hengband.git] / src / info-reader / feature-reader.c
1 #include "info-reader/feature-reader.h"
2 #include "floor/wild.h"
3 #include "grid/feature.h"
4 #include "grid/trap.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"
10
11 angband_header f_head; /*!< 地形情報のヘッダ構造体 */
12
13 /*! 地形タグ情報から地形IDを得られなかった場合にTRUEを返す */
14 static bool feat_tag_is_not_found = FALSE;
15
16 /*!
17  * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
18  * Grab one flag in an feature_type from a textual string
19  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
20  * @param what 参照元の文字列ポインタ
21  * @return エラーコード
22  */
23 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
24 {
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);
28             return 0;
29         }
30     }
31
32     msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
33     return PARSE_ERROR_GENERIC;
34 }
35
36 /*!
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
42  * @return エラーコード
43  */
44 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
45 {
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;
49             return 0;
50         }
51     }
52
53     msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
54     return PARSE_ERROR_GENERIC;
55 }
56
57 /*!
58  * @brief 地形情報(f_info)のパース関数 /
59  * Initialize the "f_info" array, by parsing an ascii "template" file
60  * @param buf テキスト列
61  * @param head ヘッダ構造体
62  * @return エラーコード
63  */
64 errr parse_f_info(char *buf, angband_header *head)
65 {
66     static feature_type *f_ptr = NULL;
67     int i;
68     char *s, *t;
69     if (buf[0] == 'N') {
70         s = angband_strchr(buf + 2, ':');
71
72         if (s) {
73             *s++ = '\0';
74         }
75
76         i = atoi(buf + 2);
77         if (i <= error_idx)
78             return 4;
79         if (i >= head->info_num)
80             return 2;
81
82         error_idx = i;
83         f_ptr = &f_info[i];
84         if (s) {
85             if (!add_tag(&f_ptr->tag, head, s))
86                 return 7;
87         }
88
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;
93     } else if (!f_ptr) {
94         return 3;
95     }
96 #ifdef JP
97     else if (buf[0] == 'J') {
98         if (!add_name(&f_ptr->name, head, buf + 2))
99             return 7;
100     } else if (buf[0] == 'E') {
101     }
102 #else
103     else if (buf[0] == 'J') {
104     } else if (buf[0] == 'E') {
105         s = buf + 2;
106         if (!add_name(&f_ptr->name, head, s))
107             return 7;
108     }
109 #endif
110     else if (buf[0] == 'M') {
111         STR_OFFSET offset;
112         if (!add_tag(&offset, head, buf + 2))
113             return PARSE_ERROR_OUT_OF_MEMORY;
114
115         f_ptr->mimic_tag = offset;
116     } else if (buf[0] == 'G') {
117         int j;
118         byte s_attr;
119         char char_tmp[F_LIT_MAX];
120         if (buf[1] != ':')
121             return 1;
122         if (!buf[2])
123             return 1;
124         if (buf[3] != ':')
125             return 1;
126         if (!buf[4])
127             return 1;
128
129         char_tmp[F_LIT_STANDARD] = buf[2];
130         s_attr = color_char_to_attr(buf[4]);
131         if (s_attr > 127)
132             return 1;
133
134         f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
135         f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
136         if (buf[5] == ':') {
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];
140
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]))
144                     return 1;
145                 if (buf[F_LIT_MAX * 4 + 1])
146                     return 1;
147
148                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) {
149                     switch (attr_lite_tmp[j - F_LIT_NS_BEGIN]) {
150                     case '*':
151                         /* Use default lighting */
152                         break;
153                     case '-':
154                         /* No lighting support */
155                         f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
156                         break;
157                     default:
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)
161                             return 1;
162                         break;
163                     }
164                     f_ptr->d_char[j] = char_tmp[j];
165                 }
166             }
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];
171             }
172         } else
173             return 1;
174     } else if (buf[0] == 'F') {
175         for (s = buf + 2; *s;) {
176             /* loop */
177             for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
178                 ;
179
180             if (*t) {
181                 *t++ = '\0';
182                 while (*t == ' ' || *t == '|')
183                     t++;
184             }
185
186             if (1 == sscanf(s, "SUBTYPE_%d", &i)) {
187                 f_ptr->subtype = (FEAT_SUBTYPE)i;
188                 s = t;
189
190                 continue;
191             }
192
193             if (1 == sscanf(s, "POWER_%d", &i)) {
194                 f_ptr->power = (FEAT_POWER)i;
195                 s = t;
196                 continue;
197             }
198
199             if (0 != grab_one_feat_flag(f_ptr, s))
200                 return (PARSE_ERROR_INVALID_FLAG);
201
202             s = t;
203         }
204     } else if (buf[0] == 'W') {
205         int priority;
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') {
210         STR_OFFSET offset;
211         for (i = 0; i < MAX_FEAT_STATES; i++)
212             if (f_ptr->state[i].action == FF_FLAG_MAX)
213                 break;
214
215         if (i == MAX_FEAT_STATES)
216             return PARSE_ERROR_GENERIC;
217
218         /* loop */
219         for (s = t = buf + 2; *t && (*t != ':'); t++)
220             ;
221
222         if (*t == ':')
223             *t++ = '\0';
224
225         if (streq(s, "DESTROYED")) {
226             if (!add_tag(&offset, head, t))
227                 return PARSE_ERROR_OUT_OF_MEMORY;
228
229             f_ptr->destroyed_tag = offset;
230         } else {
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;
236
237             f_ptr->state[i].result_tag = offset;
238         }
239     } else {
240         return 6;
241     }
242
243     return 0;
244 }
245
246 /*!
247  * @brief 地形の汎用定義をタグを通じて取得する /
248  * Initialize feature variables
249  * @return エラーコード
250  */
251 errr init_feat_variables(void)
252 {
253     feat_none = f_tag_to_index_in_init("NONE");
254
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");
259
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");
263
264     /* Locked doors */
265     FEAT_IDX i;
266     for (i = 1; i < MAX_LJ_DOORS; i++) {
267         s16b door = f_tag_to_index(format("LOCKED_DOOR_%d", i));
268         if (door < 0)
269             break;
270         feat_door[DOOR_DOOR].locked[i - 1] = door;
271     }
272
273     if (i == 1)
274         return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
275     feat_door[DOOR_DOOR].num_locked = i - 1;
276
277     /* Jammed doors */
278     for (i = 0; i < MAX_LJ_DOORS; i++) {
279         s16b door = f_tag_to_index(format("JAMMED_DOOR_%d", i));
280         if (door < 0)
281             break;
282         feat_door[DOOR_DOOR].jammed[i] = door;
283     }
284
285     if (!i)
286         return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
287     feat_door[DOOR_DOOR].num_jammed = i;
288
289     /* Glass doors */
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");
293
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));
297         if (door < 0)
298             break;
299         feat_door[DOOR_GLASS_DOOR].locked[i - 1] = door;
300     }
301
302     if (i == 1)
303         return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
304     feat_door[DOOR_GLASS_DOOR].num_locked = i - 1;
305
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));
309         if (door < 0)
310             break;
311         feat_door[DOOR_GLASS_DOOR].jammed[i] = door;
312     }
313
314     if (!i)
315         return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
316     feat_door[DOOR_GLASS_DOOR].num_jammed = i;
317
318     /* Curtains */
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;
326
327     /* Stairs */
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");
331
332     /* Normal traps */
333     init_normal_traps();
334
335     /* Special traps */
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");
339
340     /* Rubble */
341     feat_rubble = f_tag_to_index_in_init("RUBBLE");
342
343     /* Seams */
344     feat_magma_vein = f_tag_to_index_in_init("MAGMA_VEIN");
345     feat_quartz_vein = f_tag_to_index_in_init("QUARTZ_VEIN");
346
347     /* Walls */
348     feat_granite = f_tag_to_index_in_init("GRANITE");
349     feat_permanent = f_tag_to_index_in_init("PERMANENT");
350
351     /* Glass floor */
352     feat_glass_floor = f_tag_to_index_in_init("GLASS_FLOOR");
353
354     /* Glass walls */
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");
357
358     /* Pattern */
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");
368
369     /* Various */
370     feat_black_market = f_tag_to_index_in_init("BLACK_MARKET");
371     feat_town = f_tag_to_index_in_init("TOWN");
372
373     /* Terrains */
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");
393
394     feat_undetected = f_tag_to_index_in_init("UNDETECTED");
395
396     init_wilderness_terrains();
397     return feat_tag_is_not_found ? PARSE_ERROR_UNDEFINED_TERRAIN_TAG : 0;
398 }
399
400 /*!
401  * @brief 地形タグからIDを得る /
402  * Convert a fake tag to a real feat index
403  * @param str タグ文字列
404  * @return 地形ID
405  */
406 s16b f_tag_to_index(concptr str)
407 {
408     for (u16b i = 0; i < f_head.info_num; i++) {
409         if (streq(f_tag + f_info[i].tag, str)) {
410             return (s16b)i;
411         }
412     }
413
414     return -1;
415 }
416
417 /*!
418  * @brief 地形タグからIDを得る /
419  * Initialize quest array
420  * @return 地形ID
421  */
422 s16b f_tag_to_index_in_init(concptr str)
423 {
424     FEAT_IDX feat = f_tag_to_index(str);
425
426     if (feat < 0)
427         feat_tag_is_not_found = TRUE;
428
429     return feat;
430 }
431
432 /*!
433  * @brief 地形タグからIDを得る /
434  * Search for real index corresponding to this fake tag
435  * @param feat タグ文字列のオフセット
436  * @return 地形ID。該当がないなら-1
437  */
438 static FEAT_IDX search_real_feat(STR_OFFSET feat)
439 {
440     if (feat <= 0) {
441         return -1;
442     }
443
444     for (FEAT_IDX i = 0; i < f_head.info_num; i++) {
445         if (feat == f_info[i].tag) {
446             return i;
447         }
448     }
449
450     msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
451     return -1;
452 }
453
454 /*!
455  * @brief 地形情報の各種タグからIDへ変換して結果を収める /
456  * Retouch fake tags of f_info
457  * @param head ヘッダ構造体
458  * @return なし
459  */
460 void retouch_f_info(angband_header *head)
461 {
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;
471         }
472     }
473 }