OSDN Git Service

[Refactor] #39962 Separated tokenizer.c/h from files.c
[hengband/hengband.git] / src / dungeon-file.c
1 /*!
2  * @file init1.c
3  * @brief ゲームデータ初期化1 / Initialization (part 1) -BEN-
4  * @date 2014/01/28
5  * @author
6  * <pre>
7  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8  * This software may be copied and distributed for educational, research,
9  * and not for profit purposes provided that this copyright and statement
10  * are included in all such copies.  Other copyrights may also apply.
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  * </pre>
13  * @details
14  * <pre>
15  * This file is used to initialize various variables and arrays for the
16  * Angband game.  Note the use of "fd_read()" and "fd_write()" to bypass
17  * the common limitation of "read()" and "write()" to only 32767 bytes
18  * at a time.
19  * Several of the arrays for Angband are built from "template" files in
20  * the "lib/file" directory, from which quick-load binary "image" files
21  * are constructed whenever they are not present in the "lib/data"
22  * directory, or if those files become obsolete, if we are allowed.
23  * Warning -- the "ascii" file parsers use a minor hack to collect the
24  * name and text information in a single pass.  Thus, the game will not
25  * be able to load any template file with more than 20K of names or 60K
26  * of text, even though technically, up to 64K should be legal.
27  *
28  * The code could actually be removed and placed into a "stand-alone"
29  * program, but that feels a little silly, especially considering some
30  * of the platforms that we currently support.
31  * </pre>
32  */
33
34 #include "angband.h"
35 #include "util.h"
36 #include "core.h"
37
38 #include "io/tokenizer.h"
39 #include "files.h"
40 #include "dungeon-file.h"
41 #include "rooms-vault.h"
42 #include "feature.h"
43 #include "grid.h"
44 #include "quest.h"
45 #include "monster.h"
46 #include "files.h"
47 #include "player-skill.h"
48 #include "player-race.h"
49 #include "dungeon.h"
50 #include "floor.h"
51 #include "bldg.h"
52 #include "world.h"
53 #include "rooms-vault.h"
54 #include "objectkind.h"
55 #include "object-ego.h"
56 #include "monsterrace.h"
57 #include "floor-town.h"
58 #include "realm.h"
59
60 #include "trap.h"
61 #include "artifact.h"
62 #include "cmd-activate.h"
63 #include "term.h"
64 #include "wild.h"
65 #include "view-mainwindow.h"
66 #include "player-class.h"
67
68 #include "init.h"
69
70 dungeon_grid letter[255];
71
72 /*** Helper arrays for parsing ascii template files ***/
73
74  /*!
75   * モンスターの打撃手段トークンの定義 /
76   * Monster Blow Methods
77   */
78 static concptr r_info_blow_method[] =
79 {
80         "",
81         "HIT",
82         "TOUCH",
83         "PUNCH",
84         "KICK",
85         "CLAW",
86         "BITE",
87         "STING",
88         "SLASH",
89         "BUTT",
90         "CRUSH",
91         "ENGULF",
92         "CHARGE",
93         "CRAWL",
94         "DROOL",
95         "SPIT",
96         "EXPLODE",
97         "GAZE",
98         "WAIL",
99         "SPORE",
100         "XXX4",
101         "BEG",
102         "INSULT",
103         "MOAN",
104         "SHOW",
105         "SHOOT",
106         NULL
107 };
108
109 /*!
110  * モンスターの打撃属性トークンの定義 /
111  * Monster Blow Effects
112  */
113 static concptr r_info_blow_effect[] =
114 {
115         "",
116         "HURT",
117         "POISON",
118         "UN_BONUS",
119         "UN_POWER",
120         "EAT_GOLD",
121         "EAT_ITEM",
122         "EAT_FOOD",
123         "EAT_LITE",
124         "ACID",
125         "ELEC",
126         "FIRE",
127         "COLD",
128         "BLIND",
129         "CONFUSE",
130         "TERRIFY",
131         "PARALYZE",
132         "LOSE_STR",
133         "LOSE_INT",
134         "LOSE_WIS",
135         "LOSE_DEX",
136         "LOSE_CON",
137         "LOSE_CHR",
138         "LOSE_ALL",
139         "SHATTER",
140         "EXP_10",
141         "EXP_20",
142         "EXP_40",
143         "EXP_80",
144         "DISEASE",
145         "TIME",
146         "EXP_VAMP",
147         "DR_MANA",
148         "SUPERHURT",
149         "INERTIA",
150         "STUN",
151         NULL
152 };
153
154 /*!
155  * 地形属性トークンの定義 /
156  * Feature info flags
157  */
158 static concptr f_info_flags[] =
159 {
160         "LOS",
161         "PROJECT",
162         "MOVE",
163         "PLACE",
164         "DROP",
165         "SECRET",
166         "NOTICE",
167         "REMEMBER",
168         "OPEN",
169         "CLOSE",
170         "BASH",
171         "SPIKE",
172         "DISARM",
173         "STORE",
174         "TUNNEL",
175         "MAY_HAVE_GOLD",
176         "HAS_GOLD",
177         "HAS_ITEM",
178         "DOOR",
179         "TRAP",
180         "STAIRS",
181         "GLYPH",
182         "LESS",
183         "MORE",
184         "AVOID_RUN",
185         "FLOOR",
186         "WALL",
187         "PERMANENT",
188         "XXX00",
189         "XXX01",
190         "XXX02",
191         "HIT_TRAP",
192
193         "BRIDGE",
194         "RIVER",
195         "LAKE",
196         "BRIDGED",
197         "COVERED",
198         "GLOW",
199         "ENSECRET",
200         "WATER",
201         "LAVA",
202         "SHALLOW",
203         "DEEP",
204         "POISON_PUDDLE",
205         "HURT_ROCK",
206         "HURT_FIRE",
207         "HURT_COLD",
208         "HURT_ACID",
209         "COLD_PUDDLE",
210         "ACID_PUDDLE",
211         "OIL",
212         "ELEC_PUDDLE",
213         "CAN_CLIMB",
214         "CAN_FLY",
215         "CAN_SWIM",
216         "CAN_PASS",
217         "CAN_OOZE",
218         "CAN_DIG",
219         "HIDE_ITEM",
220         "HIDE_SNEAK",
221         "HIDE_SWIM",
222         "HIDE_DIG",
223         "KILL_HUGE",
224         "KILL_MOVE",
225
226         "PICK_TRAP",
227         "PICK_DOOR",
228         "ALLOC",
229         "CHEST",
230         "DROP_1D2",
231         "DROP_2D2",
232         "DROP_GOOD",
233         "DROP_GREAT",
234         "HURT_POIS",
235         "HURT_ELEC",
236         "HURT_WATER",
237         "HURT_BWATER",
238         "USE_FEAT",
239         "GET_FEAT",
240         "GROUND",
241         "OUTSIDE",
242         "EASY_HIDE",
243         "EASY_CLIMB",
244         "MUST_CLIMB",
245         "TREE",
246         "NEED_TREE",
247         "BLOOD",
248         "DUST",
249         "SLIME",
250         "PLANT",
251         "XXX2",
252         "INSTANT",
253         "EXPLODE",
254         "TIMED",
255         "ERUPT",
256         "STRIKE",
257         "SPREAD",
258
259         "SPECIAL",
260         "HURT_DISI",
261         "QUEST_ENTER",
262         "QUEST_EXIT",
263         "QUEST",
264         "SHAFT",
265         "MOUNTAIN",
266         "BLDG",
267         "MINOR_GLYPH",
268         "PATTERN",
269         "TOWN",
270         "ENTRANCE",
271         "MIRROR",
272         "UNPERM",
273         "TELEPORTABLE",
274         "CONVERT",
275         "GLASS",
276 };
277
278 /*!
279  * モンスター特性トークンの定義1 /
280  * Monster race flags
281  */
282 static concptr r_info_flags1[] =
283 {
284         "UNIQUE",
285         "QUESTOR",
286         "MALE",
287         "FEMALE",
288         "CHAR_CLEAR",
289         "SHAPECHANGER",
290         "ATTR_CLEAR",
291         "ATTR_MULTI",
292         "FORCE_DEPTH",
293         "FORCE_MAXHP",
294         "FORCE_SLEEP",
295         "FORCE_EXTRA",
296         "ATTR_SEMIRAND",
297         "FRIENDS",
298         "ESCORT",
299         "ESCORTS",
300         "NEVER_BLOW",
301         "NEVER_MOVE",
302         "RAND_25",
303         "RAND_50",
304         "ONLY_GOLD",
305         "ONLY_ITEM",
306         "DROP_60",
307         "DROP_90",
308         "DROP_1D2",
309         "DROP_2D2",
310         "DROP_3D2",
311         "DROP_4D2",
312         "DROP_GOOD",
313         "DROP_GREAT",
314         "XXX2",
315         "XXX3"
316 };
317
318 /*!
319  * モンスター特性トークンの定義2 /
320  * Monster race flags
321  */
322 static concptr r_info_flags2[] =
323 {
324         "STUPID",
325         "SMART",
326         "CAN_SPEAK",
327         "REFLECTING",
328         "INVISIBLE",
329         "COLD_BLOOD",
330         "EMPTY_MIND",
331         "WEIRD_MIND",
332         "MULTIPLY",
333         "REGENERATE",
334         "CHAR_MULTI",
335         "ATTR_ANY",
336         "POWERFUL",
337         "ELDRITCH_HORROR",
338         "AURA_FIRE",
339         "AURA_ELEC",
340         "OPEN_DOOR",
341         "BASH_DOOR",
342         "PASS_WALL",
343         "KILL_WALL",
344         "MOVE_BODY",
345         "KILL_BODY",
346         "TAKE_ITEM",
347         "KILL_ITEM",
348         "XXX",
349         "XXX",
350         "XXX",
351         "XXX",
352         "XXX",
353         "XXX",
354         "HUMAN",
355         "QUANTUM"
356 };
357
358 /*!
359  * モンスター特性トークンの定義3 /
360  * Monster race flags
361  */
362 static concptr r_info_flags3[] =
363 {
364         "ORC",
365         "TROLL",
366         "GIANT",
367         "DRAGON",
368         "DEMON",
369         "UNDEAD",
370         "EVIL",
371         "ANIMAL",
372         "AMBERITE",
373         "GOOD",
374         "AURA_COLD",
375         "NONLIVING",
376         "HURT_LITE",
377         "HURT_ROCK",
378         "HURT_FIRE",
379         "HURT_COLD",
380         "ANGEL",
381         "XXX",
382         "XXX",
383         "XXX",
384         "XXX",
385         "XXX",
386         "XXX",
387         "XXX",
388         "XXX",
389         "XXX",
390         "XXX",
391         "XXX",
392         "NO_FEAR",
393         "NO_STUN",
394         "NO_CONF",
395         "NO_SLEEP"
396 };
397
398 /*!
399  * モンスター特性トークンの定義4 /
400  * Monster race flags
401  */
402 static concptr r_info_flags4[] =
403 {
404         "SHRIEK",
405         "XXX1",
406         "DISPEL",
407         "ROCKET",
408         "SHOOT",
409         "XXX2",
410         "XXX3",
411         "XXX4",
412         "BR_ACID",
413         "BR_ELEC",
414         "BR_FIRE",
415         "BR_COLD",
416         "BR_POIS",
417         "BR_NETH",
418         "BR_LITE",
419         "BR_DARK",
420         "BR_CONF",
421         "BR_SOUN",
422         "BR_CHAO",
423         "BR_DISE",
424         "BR_NEXU",
425         "BR_TIME",
426         "BR_INER",
427         "BR_GRAV",
428         "BR_SHAR",
429         "BR_PLAS",
430         "BR_WALL",
431         "BR_MANA",
432         "BA_NUKE",
433         "BR_NUKE",
434         "BA_CHAO",
435         "BR_DISI",
436 };
437
438 /*!
439  * モンスター特性トークン(発動型能力1) /
440  * Monster race flags
441  */
442 static concptr r_a_ability_flags1[] =
443 {
444         "BA_ACID",
445         "BA_ELEC",
446         "BA_FIRE",
447         "BA_COLD",
448         "BA_POIS",
449         "BA_NETH",
450         "BA_WATE",
451         "BA_MANA",
452         "BA_DARK",
453         "DRAIN_MANA",
454         "MIND_BLAST",
455         "BRAIN_SMASH",
456         "CAUSE_1",
457         "CAUSE_2",
458         "CAUSE_3",
459         "CAUSE_4",
460         "BO_ACID",
461         "BO_ELEC",
462         "BO_FIRE",
463         "BO_COLD",
464         "BA_LITE",
465         "BO_NETH",
466         "BO_WATE",
467         "BO_MANA",
468         "BO_PLAS",
469         "BO_ICEE",
470         "MISSILE",
471         "SCARE",
472         "BLIND",
473         "CONF",
474         "SLOW",
475         "HOLD"
476 };
477
478 /*!
479  * モンスター特性トークン(発動型能力2) /
480  * Monster race flags
481  */
482 static concptr r_a_ability_flags2[] =
483 {
484         "HASTE",
485         "HAND_DOOM",
486         "HEAL",
487         "INVULNER",
488         "BLINK",
489         "TPORT",
490         "WORLD",
491         "SPECIAL",
492         "TELE_TO",
493         "TELE_AWAY",
494         "TELE_LEVEL",
495         "PSY_SPEAR",
496         "DARKNESS",
497         "TRAPS",
498         "FORGET",
499         "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
500         "S_KIN",
501         "S_CYBER",
502         "S_MONSTER",
503         "S_MONSTERS",
504         "S_ANT",
505         "S_SPIDER",
506         "S_HOUND",
507         "S_HYDRA",
508         "S_ANGEL",
509         "S_DEMON",
510         "S_UNDEAD",
511         "S_DRAGON",
512         "S_HI_UNDEAD",
513         "S_HI_DRAGON",
514         "S_AMBERITES",
515         "S_UNIQUE"
516 };
517
518 /*!
519  * モンスター特性トークンの定義7 /
520  * Monster race flags
521  */
522 static concptr r_info_flags7[] =
523 {
524         "AQUATIC",
525         "CAN_SWIM",
526         "CAN_FLY",
527         "FRIENDLY",
528         "NAZGUL",
529         "UNIQUE2",
530         "RIDING",
531         "KAGE",
532         "HAS_LITE_1",
533         "SELF_LITE_1",
534         "HAS_LITE_2",
535         "SELF_LITE_2",
536         "GUARDIAN",
537         "CHAMELEON",
538         "XXXX4XXX",
539         "TANUKI",
540         "HAS_DARK_1",
541         "SELF_DARK_1",
542         "HAS_DARK_2",
543         "SELF_DARK_2",
544         "XXX7X20",
545         "XXX7X21",
546         "XXX7X22",
547         "XXX7X23",
548         "XXX7X24",
549         "XXX7X25",
550         "XXX7X26",
551         "XXX7X27",
552         "XXX7X28",
553         "XXX7X29",
554         "XXX7X30",
555         "XXX7X31",
556 };
557
558 /*!
559  * モンスター特性トークンの定義8 /
560  * Monster race flags
561  */
562 static concptr r_info_flags8[] =
563 {
564         "WILD_ONLY",
565         "WILD_TOWN",
566         "XXX8X02",
567         "WILD_SHORE",
568         "WILD_OCEAN",
569         "WILD_WASTE",
570         "WILD_WOOD",
571         "WILD_VOLCANO",
572         "XXX8X08",
573         "WILD_MOUNTAIN",
574         "WILD_GRASS",
575         "XXX8X11",
576         "XXX8X12",
577         "XXX8X13",
578         "XXX8X14",
579         "XXX8X15",
580         "XXX8X16",
581         "XXX8X17",
582         "XXX8X18",
583         "XXX8X19",
584         "XXX8X20",
585         "XXX8X21",
586         "XXX8X22",
587         "XXX8X23",
588         "XXX8X24",
589         "XXX8X25",
590         "XXX8X26",
591         "XXX8X27",
592         "XXX8X28",
593         "XXX8X29",
594         "WILD_SWAMP",   /* ToDo: Implement Swamp */
595         "WILD_ALL",
596 };
597
598 /*!
599  * モンスター特性トークンの定義9 /
600  * Monster race flags
601  */
602 static concptr r_info_flags9[] =
603 {
604         "DROP_CORPSE",
605         "DROP_SKELETON",
606         "EAT_BLIND",
607         "EAT_CONF",
608         "EAT_MANA",
609         "EAT_NEXUS",
610         "EAT_BLINK",
611         "EAT_SLEEP",
612         "EAT_BERSERKER",
613         "EAT_ACIDIC",
614         "EAT_SPEED",
615         "EAT_CURE",
616         "EAT_FIRE_RES",
617         "EAT_COLD_RES",
618         "EAT_ACID_RES",
619         "EAT_ELEC_RES",
620         "EAT_POIS_RES",
621         "EAT_INSANITY",
622         "EAT_DRAIN_EXP",
623         "EAT_POISONOUS",
624         "EAT_GIVE_STR",
625         "EAT_GIVE_INT",
626         "EAT_GIVE_WIS",
627         "EAT_GIVE_DEX",
628         "EAT_GIVE_CON",
629         "EAT_GIVE_CHR",
630         "EAT_LOSE_STR",
631         "EAT_LOSE_INT",
632         "EAT_LOSE_WIS",
633         "EAT_LOSE_DEX",
634         "EAT_LOSE_CON",
635         "EAT_LOSE_CHR",
636         "EAT_DRAIN_MANA",
637 };
638
639 /*!
640  * モンスター特性トークンの定義R(耐性) /
641  * Monster race flags
642  */
643 static concptr r_info_flagsr[] =
644 {
645         "IM_ACID",
646         "IM_ELEC",
647         "IM_FIRE",
648         "IM_COLD",
649         "IM_POIS",
650         "RES_LITE",
651         "RES_DARK",
652         "RES_NETH",
653         "RES_WATE",
654         "RES_PLAS",
655         "RES_SHAR",
656         "RES_SOUN",
657         "RES_CHAO",
658         "RES_NEXU",
659         "RES_DISE",
660         "RES_WALL",
661         "RES_INER",
662         "RES_TIME",
663         "RES_GRAV",
664         "RES_ALL",
665         "RES_TELE",
666         "XXX",
667         "XXX",
668         "XXX",
669         "XXX",
670         "XXX",
671         "XXX",
672         "XXX",
673         "XXX",
674         "XXX",
675         "XXX",
676         "XXX",
677 };
678
679 /*!
680  * オブジェクト基本特性トークンの定義 /
681  * Object flags
682  */
683 static concptr k_info_flags[] =
684 {
685         "STR",
686         "INT",
687         "WIS",
688         "DEX",
689         "CON",
690         "CHR",
691         "MAGIC_MASTERY",
692         "FORCE_WEAPON",
693         "STEALTH",
694         "SEARCH",
695         "INFRA",
696         "TUNNEL",
697         "SPEED",
698         "BLOWS",
699         "CHAOTIC",
700         "VAMPIRIC",
701         "SLAY_ANIMAL",
702         "SLAY_EVIL",
703         "SLAY_UNDEAD",
704         "SLAY_DEMON",
705         "SLAY_ORC",
706         "SLAY_TROLL",
707         "SLAY_GIANT",
708         "SLAY_DRAGON",
709         "KILL_DRAGON",
710         "VORPAL",
711         "IMPACT",
712         "BRAND_POIS",
713         "BRAND_ACID",
714         "BRAND_ELEC",
715         "BRAND_FIRE",
716         "BRAND_COLD",
717
718         "SUST_STR",
719         "SUST_INT",
720         "SUST_WIS",
721         "SUST_DEX",
722         "SUST_CON",
723         "SUST_CHR",
724         "RIDING",
725         "EASY_SPELL",
726         "IM_ACID",
727         "IM_ELEC",
728         "IM_FIRE",
729         "IM_COLD",
730         "THROW",
731         "REFLECT",
732         "FREE_ACT",
733         "HOLD_EXP",
734         "RES_ACID",
735         "RES_ELEC",
736         "RES_FIRE",
737         "RES_COLD",
738         "RES_POIS",
739         "RES_FEAR",
740         "RES_LITE",
741         "RES_DARK",
742         "RES_BLIND",
743         "RES_CONF",
744         "RES_SOUND",
745         "RES_SHARDS",
746         "RES_NETHER",
747         "RES_NEXUS",
748         "RES_CHAOS",
749         "RES_DISEN",
750
751         "SH_FIRE",
752         "SH_ELEC",
753         "SLAY_HUMAN",
754         "SH_COLD",
755         "NO_TELE",
756         "NO_MAGIC",
757         "DEC_MANA",
758         "TY_CURSE",
759         "WARNING",
760         "HIDE_TYPE",
761         "SHOW_MODS",
762         "SLAY_GOOD",
763         "LEVITATION",
764         "LITE",
765         "SEE_INVIS",
766         "TELEPATHY",
767         "SLOW_DIGEST",
768         "REGEN",
769         "XTRA_MIGHT",
770         "XTRA_SHOTS",
771         "IGNORE_ACID",
772         "IGNORE_ELEC",
773         "IGNORE_FIRE",
774         "IGNORE_COLD",
775         "ACTIVATE",
776         "DRAIN_EXP",
777         "TELEPORT",
778         "AGGRAVATE",
779         "BLESSED",
780         "XXX3", /* Fake flag for Smith */
781         "XXX4", /* Fake flag for Smith */
782         "KILL_GOOD",
783
784         "KILL_ANIMAL",
785         "KILL_EVIL",
786         "KILL_UNDEAD",
787         "KILL_DEMON",
788         "KILL_ORC",
789         "KILL_TROLL",
790         "KILL_GIANT",
791         "KILL_HUMAN",
792         "ESP_ANIMAL",
793         "ESP_UNDEAD",
794         "ESP_DEMON",
795         "ESP_ORC",
796         "ESP_TROLL",
797         "ESP_GIANT",
798         "ESP_DRAGON",
799         "ESP_HUMAN",
800         "ESP_EVIL",
801         "ESP_GOOD",
802         "ESP_NONLIVING",
803         "ESP_UNIQUE",
804         "FULL_NAME",
805         "FIXED_FLAVOR",
806         "ADD_L_CURSE",
807         "ADD_H_CURSE",
808         "DRAIN_HP",
809         "DRAIN_MANA",
810
811         "LITE_2",
812         "LITE_3",
813         "LITE_M1",
814         "LITE_M2",
815         "LITE_M3",
816         "LITE_FUEL",
817
818         "CALL_ANIMAL",
819         "CALL_DEMON",
820         "CALL_DRAGON",
821         "CALL_UNDEAD",
822         "COWARDICE",
823         "LOW_MELEE",
824         "LOW_AC",
825         "LOW_MAGIC",
826         "FAST_DIGEST",
827         "SLOW_REGEN",
828 };
829
830 /*!
831  * オブジェクト生成特性トークンの定義 /
832  * Object flags
833  */
834 static concptr k_info_gen_flags[] =
835 {
836         "INSTA_ART",
837         "QUESTITEM",
838         "XTRA_POWER",
839         "ONE_SUSTAIN",
840         "XTRA_RES_OR_POWER",
841         "XTRA_H_RES",
842         "XTRA_E_RES",
843         "XTRA_L_RES",
844         "XTRA_D_RES",
845         "XTRA_RES",
846         "CURSED",
847         "HEAVY_CURSE",
848         "PERMA_CURSE",
849         "RANDOM_CURSE0",
850         "RANDOM_CURSE1",
851         "RANDOM_CURSE2",
852         "XTRA_DICE",
853         "POWERFUL",
854         "XXX",
855         "XXX",
856         "XXX",
857         "XXX",
858         "XXX",
859         "XXX",
860         "XXX",
861         "XXX",
862         "XXX",
863         "XXX",
864         "XXX",
865         "XXX",
866         "XXX",
867         "XXX",
868 };
869
870 /*!
871  * ダンジョン特性トークンの定義 /
872  * Dungeon flags
873  */
874 static concptr d_info_flags1[] =
875 {
876         "WINNER",
877         "MAZE",
878         "SMALLEST",
879         "BEGINNER",
880         "BIG",
881         "NO_DOORS",
882         "WATER_RIVER",
883         "LAVA_RIVER",
884         "CURTAIN",
885         "GLASS_DOOR",
886         "CAVE",
887         "CAVERN",
888         "ARCADE",
889         "LAKE_ACID",
890         "LAKE_POISONOUS",
891         "XXX",
892         "FORGET",
893         "LAKE_WATER",
894         "LAKE_LAVA",
895         "LAKE_RUBBLE",
896         "LAKE_TREE",
897         "NO_VAULT",
898         "ARENA",
899         "DESTROY",
900         "GLASS_ROOM",
901         "NO_CAVE",
902         "NO_MAGIC",
903         "NO_MELEE",
904         "CHAMELEON",
905         "DARKNESS",
906         "ACID_RIVER",
907         "POISONOUS_RIVER"
908 };
909
910 /*!
911  * @brief データの可変文字列情報をテキストとして保管する /
912  * Add a text to the text-storage and store offset to it.
913  * @param offset 文字列保管ポインタからのオフセット
914  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
915  * @param buf 保管文字列
916  * @param normal_text テキストの正規化を行う
917  * @return
918  * 無事保管ができたらTRUEを返す。
919  * Returns FALSE when there isn't enough space available to store
920  * the text.
921  */
922 static bool add_text(u32b *offset, header *head, concptr buf, bool normal_text)
923 {
924         if (head->text_size + strlen(buf) + 8 > FAKE_TEXT_SIZE)
925                 return FALSE;
926
927         if (*offset == 0)
928         {
929                 *offset = ++head->text_size;
930         }
931         else if (normal_text)
932         {
933                 /*
934                  * If neither the end of the last line nor
935                  * the beginning of current line is not a space,
936                  * fill up a space as a correct separator of two words.
937                  */
938                 if (head->text_size > 0 &&
939 #ifdef JP
940                 (*(head->text_ptr + head->text_size - 1) != ' ') &&
941                         ((head->text_size == 1) || !iskanji(*(head->text_ptr + head->text_size - 2))) &&
942                         (buf[0] != ' ') && !iskanji(buf[0])
943 #else
944                         (*(head->text_ptr + head->text_size - 1) != ' ') &&
945                         (buf[0] != ' ')
946 #endif
947                         )
948                 {
949                         *(head->text_ptr + head->text_size) = ' ';
950                         head->text_size++;
951                 }
952         }
953
954         strcpy(head->text_ptr + head->text_size, buf);
955         head->text_size += strlen(buf);
956         return TRUE;
957 }
958
959
960 /*!
961  * @brief データの可変文字列情報を名前として保管する /
962  * Add a name to the name-storage and return an offset to it.
963  * @param offset 文字列保管ポインタからのオフセット
964  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
965  * @param buf 保管文字列
966  * @return
967  * 無事保管ができたらTRUEを返す。
968  * Returns FALSE when there isn't enough space available to store
969  * the text.
970  */
971 static bool add_name(u32b *offset, header *head, concptr buf)
972 {
973         if (head->name_size + strlen(buf) + 8 > FAKE_NAME_SIZE)
974                 return FALSE;
975
976         if (*offset == 0)
977         {
978                 *offset = ++head->name_size;
979         }
980
981         strcpy(head->name_ptr + head->name_size, buf);
982         head->name_size += strlen(buf);
983         return TRUE;
984 }
985
986
987 /*!
988  * @brief データの可変文字列情報をタグとして保管する /
989  * Add a tag to the tag-storage and return an offset to it.
990  * @param offset 文字列保管ポインタからのオフセット
991  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
992  * @param buf 保管文字列
993  * @return
994  * 無事保管ができたらTRUEを返す。
995  * Returns FALSE when there isn't enough space available to store
996  * the text.
997  */
998 static bool add_tag(STR_OFFSET *offset, header *head, concptr buf)
999 {
1000         u32b i;
1001         for (i = 1; i < head->tag_size; i += strlen(&head->tag_ptr[i]) + 1)
1002         {
1003                 if (streq(&head->tag_ptr[i], buf)) break;
1004         }
1005
1006         if (i >= head->tag_size)
1007         {
1008                 if (head->tag_size + strlen(buf) + 8 > FAKE_TAG_SIZE)
1009                         return FALSE;
1010
1011                 strcpy(head->tag_ptr + head->tag_size, buf);
1012                 i = head->tag_size;
1013                 head->tag_size += strlen(buf) + 1;
1014         }
1015
1016         *offset = (s16b)i;
1017         return TRUE;
1018 }
1019
1020
1021 /*!
1022  * @brief パース関数に基づいてデータファイルからデータを読み取る /
1023  * Initialize an "*_info" array, by parsing an ascii "template" file
1024  * @param fp 読み取りに使うファイルポインタ
1025  * @param buf 読み取りに使うバッファ領域
1026  * @param head ヘッダ構造体
1027  * @param parse_info_txt_line パース関数
1028  * @return エラーコード
1029  */
1030 errr init_info_txt(FILE *fp, char *buf, header *head, parse_info_txt_func parse_info_txt_line)
1031 {
1032         error_idx = -1;
1033         error_line = 0;
1034
1035         head->name_size = 0;
1036         head->text_size = 0;
1037         head->tag_size = 0;
1038
1039         errr err;
1040         while (my_fgets(fp, buf, 1024) == 0)
1041         {
1042                 error_line++;
1043                 if (!buf[0] || (buf[0] == '#')) continue;
1044
1045                 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
1046
1047                 if (buf[0] == 'V')
1048                 {
1049                         continue;
1050                 }
1051
1052                 if (buf[0] != 'N' && buf[0] != 'D')
1053                 {
1054                         int i;
1055                         for (i = 0; buf[i]; i++)
1056                         {
1057                                 head->v_extra += (byte)buf[i];
1058                                 head->v_extra ^= (1 << (i % 8));
1059                         }
1060                 }
1061
1062                 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
1063                         return (err);
1064         }
1065
1066         if (head->name_size) head->name_size++;
1067         if (head->text_size) head->text_size++;
1068
1069         return 0;
1070 }
1071
1072
1073 /*!
1074  * @brief Vault情報(v_info)のパース関数 /
1075  * Initialize the "v_info" array, by parsing an ascii "template" file
1076  * @param buf テキスト列
1077  * @param head ヘッダ構造体
1078  * @return エラーコード
1079  */
1080 errr parse_v_info(char *buf, header *head)
1081 {
1082         char *s;
1083         static vault_type *v_ptr = NULL;
1084
1085         if (buf[0] == 'N')
1086         {
1087                 s = my_strchr(buf + 2, ':');
1088                 if (!s) return 1;
1089
1090                 *s++ = '\0';
1091                 if (!*s) return 1;
1092
1093                 int i = atoi(buf + 2);
1094                 if (i <= error_idx) return 4;
1095                 if (i >= head->info_num) return 2;
1096
1097                 error_idx = i;
1098                 v_ptr = &v_info[i];
1099                 if (!add_name(&v_ptr->name, head, s)) return 7;
1100         }
1101         else if (!v_ptr) return 3;
1102         else if (buf[0] == 'D')
1103         {
1104                 s = buf + 2;
1105                 if (!add_text(&v_ptr->text, head, s, FALSE)) return 7;
1106         }
1107         else if (buf[0] == 'X')
1108         {
1109                 EFFECT_ID typ, rat, hgt, wid;
1110                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1111                         &typ, &rat, &hgt, &wid)) return 1;
1112
1113                 v_ptr->typ = (ROOM_IDX)typ;
1114                 v_ptr->rat = (PROB)rat;
1115                 v_ptr->hgt = (POSITION)hgt;
1116                 v_ptr->wid = (POSITION)wid;
1117         }
1118         else
1119                 return 6;
1120
1121         return 0;
1122 }
1123
1124
1125 /*!
1126  * @brief 職業技能情報(s_info)のパース関数 /
1127  * Initialize the "s_info" array, by parsing an ascii "template" file
1128  * @param buf テキスト列
1129  * @param head ヘッダ構造体
1130  * @return エラーコード
1131  */
1132 errr parse_s_info(char *buf, header *head)
1133 {
1134         static skill_table *s_ptr = NULL;
1135         if (buf[0] == 'N')
1136         {
1137                 int i = atoi(buf + 2);
1138                 if (i <= error_idx) return 4;
1139                 if (i >= head->info_num) return 2;
1140
1141                 error_idx = i;
1142                 s_ptr = &s_info[i];
1143         }
1144         else if (!s_ptr)
1145         {
1146                 return 3;
1147         }
1148         else if (buf[0] == 'W')
1149         {
1150                 int tval, sval, start, max;
1151                 const s16b exp_conv_table[] =
1152                 {
1153                         WEAPON_EXP_UNSKILLED, WEAPON_EXP_BEGINNER, WEAPON_EXP_SKILLED,
1154                         WEAPON_EXP_EXPERT, WEAPON_EXP_MASTER
1155                 };
1156
1157                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1158                         &tval, &sval, &start, &max)) return 1;
1159
1160                 if (start < EXP_LEVEL_UNSKILLED || start > EXP_LEVEL_MASTER
1161                         || max < EXP_LEVEL_UNSKILLED || max > EXP_LEVEL_MASTER) return 8;
1162
1163                 s_ptr->w_start[tval][sval] = exp_conv_table[start];
1164                 s_ptr->w_max[tval][sval] = exp_conv_table[max];
1165         }
1166         else if (buf[0] == 'S')
1167         {
1168                 int num, start, max;
1169                 if (3 != sscanf(buf + 2, "%d:%d:%d",
1170                         &num, &start, &max)) return 1;
1171
1172                 if (start < WEAPON_EXP_UNSKILLED || start > WEAPON_EXP_MASTER
1173                         || max < WEAPON_EXP_UNSKILLED || max > WEAPON_EXP_MASTER) return 8;
1174
1175                 s_ptr->s_start[num] = (SUB_EXP)start;
1176                 s_ptr->s_max[num] = (SUB_EXP)max;
1177         }
1178         else
1179                 return 6;
1180
1181         return 0;
1182 }
1183
1184
1185 /*!
1186  * @brief 職業魔法情報(m_info)のパース関数 /
1187  * Initialize the "m_info" array, by parsing an ascii "template" file
1188  * @param buf テキスト列
1189  * @param head ヘッダ構造体
1190  * @return エラーコード
1191  */
1192 errr parse_m_info(char *buf, header *head)
1193 {
1194         static player_magic *m_ptr = NULL;
1195         static int realm, magic_idx = 0, readable = 0;
1196
1197         if (buf[0] == 'N')
1198         {
1199                 int i = atoi(buf + 2);
1200
1201                 if (i <= error_idx) return 4;
1202                 if (i >= head->info_num) return 2;
1203
1204                 error_idx = i;
1205                 m_ptr = &m_info[i];
1206         }
1207         else if (!m_ptr)
1208         {
1209                 return 3;
1210         }
1211         else if (buf[0] == 'I')
1212         {
1213                 char *book, *stat;
1214                 int xtra, type, first, weight;
1215                 char *s;
1216                 s = my_strchr(buf + 2, ':');
1217
1218                 /* Verify that colon */
1219                 if (!s) return 1;
1220
1221                 /* Nuke the colon, advance to the name */
1222                 *s++ = '\0';
1223
1224                 book = buf + 2;
1225
1226                 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1227                 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1228                 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1229                 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1230                 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1231                 else return 5;
1232
1233                 stat = s;
1234                 s = my_strchr(s, ':');
1235                 if (!s) return 1;
1236                 *s++ = '\0';
1237
1238                 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1239                 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1240                 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1241                 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1242                 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1243                 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1244                 else return 5;
1245
1246                 if (4 != sscanf(s, "%x:%d:%d:%d",
1247                         (uint *)&xtra, &type, &first, &weight)) return 1;
1248
1249                 m_ptr->spell_xtra = xtra;
1250                 m_ptr->spell_type = type;
1251                 m_ptr->spell_first = first;
1252                 m_ptr->spell_weight = weight;
1253         }
1254         else if (buf[0] == 'R')
1255         {
1256                 if (2 != sscanf(buf + 2, "%d:%d",
1257                         &realm, &readable)) return 1;
1258
1259                 magic_idx = 0;
1260         }
1261         else if (buf[0] == 'T')
1262         {
1263                 int level, mana, fail, exp;
1264
1265                 if (!readable) return 1;
1266                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1267                         &level, &mana, &fail, &exp)) return 1;
1268
1269                 m_ptr->info[realm][magic_idx].slevel = (PLAYER_LEVEL)level;
1270                 m_ptr->info[realm][magic_idx].smana = (MANA_POINT)mana;
1271                 m_ptr->info[realm][magic_idx].sfail = (PERCENTAGE)fail;
1272                 m_ptr->info[realm][magic_idx].sexp = (EXP)exp;
1273                 magic_idx++;
1274         }
1275         else
1276                 return 6;
1277
1278         return 0;
1279 }
1280
1281
1282 /*!
1283  * @brief テキストトークンを走査してフラグを一つ得る(汎用) /
1284  * Grab one flag from a textual string
1285  * @param flags ビットフラグを追加する先の参照ポインタ
1286  * @param names トークン定義配列
1287  * @param what 参照元の文字列ポインタ
1288  * @return エラーコード
1289  */
1290 static errr grab_one_flag(u32b *flags, concptr names[], concptr what)
1291 {
1292         for (int i = 0; i < 32; i++)
1293         {
1294                 if (streq(what, names[i]))
1295                 {
1296                         *flags |= (1L << i);
1297                         return 0;
1298                 }
1299         }
1300
1301         return -1;
1302 }
1303
1304
1305 /*!
1306  * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
1307  * Grab one flag in an feature_type from a textual string
1308  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1309  * @param what 参照元の文字列ポインタ
1310  * @return エラーコード
1311  */
1312 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
1313 {
1314         for (int i = 0; i < FF_FLAG_MAX; i++)
1315         {
1316                 if (streq(what, f_info_flags[i]))
1317                 {
1318                         add_flag(f_ptr->flags, i);
1319                         return 0;
1320                 }
1321         }
1322
1323         msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
1324         return PARSE_ERROR_GENERIC;
1325 }
1326
1327
1328 /*!
1329  * @brief テキストトークンを走査してフラグ(ステート)を一つ得る(地形情報向け2) /
1330  * Grab an action in an feature_type from a textual string
1331  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1332  * @param what 参照元の文字列ポインタ
1333  * @param count ステートの保存先ID
1334  * @return エラーコード
1335  */
1336 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
1337 {
1338         for (FF_FLAGS_IDX i = 0; i < FF_FLAG_MAX; i++)
1339         {
1340                 if (streq(what, f_info_flags[i]))
1341                 {
1342                         f_ptr->state[count].action = i;
1343                         return 0;
1344                 }
1345         }
1346
1347         msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
1348         return PARSE_ERROR_GENERIC;
1349 }
1350
1351
1352 /*!
1353  * @brief 地形情報(f_info)のパース関数 /
1354  * Initialize the "f_info" array, by parsing an ascii "template" file
1355  * @param buf テキスト列
1356  * @param head ヘッダ構造体
1357  * @return エラーコード
1358  */
1359 errr parse_f_info(char *buf, header *head)
1360 {
1361         static feature_type *f_ptr = NULL;
1362         int i;
1363         char *s, *t;
1364         if (buf[0] == 'N')
1365         {
1366                 s = my_strchr(buf + 2, ':');
1367
1368                 if (s)
1369                 {
1370                         *s++ = '\0';
1371                 }
1372
1373                 i = atoi(buf + 2);
1374                 if (i <= error_idx) return 4;
1375                 if (i >= head->info_num) return 2;
1376
1377                 error_idx = i;
1378                 f_ptr = &f_info[i];
1379                 if (s)
1380                 {
1381                         if (!add_tag(&f_ptr->tag, head, s)) return 7;
1382                 }
1383
1384                 f_ptr->mimic = (FEAT_IDX)i;
1385                 f_ptr->destroyed = (FEAT_IDX)i;
1386                 for (i = 0; i < MAX_FEAT_STATES; i++)
1387                         f_ptr->state[i].action = FF_FLAG_MAX;
1388         }
1389         else if (!f_ptr)
1390         {
1391                 return 3;
1392         }
1393 #ifdef JP
1394         else if (buf[0] == 'J')
1395         {
1396                 if (!add_name(&f_ptr->name, head, buf + 2)) return 7;
1397         }
1398         else if (buf[0] == 'E')
1399         {
1400         }
1401 #else
1402         else if (buf[0] == 'J')
1403         {
1404         }
1405         else if (buf[0] == 'E')
1406         {
1407                 s = buf + 2;
1408                 if (!add_name(&f_ptr->name, head, s)) return 7;
1409         }
1410 #endif
1411         else if (buf[0] == 'M')
1412         {
1413                 STR_OFFSET offset;
1414                 if (!add_tag(&offset, head, buf + 2))
1415                         return PARSE_ERROR_OUT_OF_MEMORY;
1416
1417                 f_ptr->mimic_tag = offset;
1418         }
1419         else if (buf[0] == 'G')
1420         {
1421                 int j;
1422                 byte s_attr;
1423                 char char_tmp[F_LIT_MAX];
1424                 if (buf[1] != ':') return 1;
1425                 if (!buf[2]) return 1;
1426                 if (buf[3] != ':') return 1;
1427                 if (!buf[4]) return 1;
1428
1429                 char_tmp[F_LIT_STANDARD] = buf[2];
1430                 s_attr = color_char_to_attr(buf[4]);
1431                 if (s_attr > 127) return 1;
1432
1433                 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
1434                 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
1435                 if (buf[5] == ':')
1436                 {
1437                         apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
1438                         if (!streq(buf + 6, "LIT"))
1439                         {
1440                                 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
1441
1442                                 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
1443                                         &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
1444                                         &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
1445                                 if (buf[F_LIT_MAX * 4 + 1]) return 1;
1446
1447                                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1448                                 {
1449                                         switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
1450                                         {
1451                                         case '*':
1452                                                 /* Use default lighting */
1453                                                 break;
1454                                         case '-':
1455                                                 /* No lighting support */
1456                                                 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
1457                                                 break;
1458                                         default:
1459                                                 /* Extract the color */
1460                                                 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
1461                                                 if (f_ptr->d_attr[j] > 127) return 1;
1462                                                 break;
1463                                         }
1464                                         f_ptr->d_char[j] = char_tmp[j];
1465                                 }
1466                         }
1467                 }
1468                 else if (!buf[5])
1469                 {
1470                         for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1471                         {
1472                                 f_ptr->d_attr[j] = s_attr;
1473                                 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
1474                         }
1475                 }
1476                 else return 1;
1477         }
1478         else if (buf[0] == 'F')
1479         {
1480                 for (s = buf + 2; *s; )
1481                 {
1482                         /* loop */
1483                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
1484
1485                         if (*t)
1486                         {
1487                                 *t++ = '\0';
1488                                 while (*t == ' ' || *t == '|') t++;
1489                         }
1490
1491                         if (1 == sscanf(s, "SUBTYPE_%d", &i))
1492                         {
1493                                 f_ptr->subtype = (FEAT_SUBTYPE)i;
1494                                 s = t;
1495
1496                                 continue;
1497                         }
1498
1499                         if (1 == sscanf(s, "POWER_%d", &i))
1500                         {
1501                                 f_ptr->power = (FEAT_POWER)i;
1502                                 s = t;
1503                                 continue;
1504                         }
1505
1506                         if (0 != grab_one_feat_flag(f_ptr, s))
1507                                 return (PARSE_ERROR_INVALID_FLAG);
1508
1509                         s = t;
1510                 }
1511         }
1512         else if (buf[0] == 'W')
1513         {
1514                 int priority;
1515                 if (1 != sscanf(buf + 2, "%d", &priority))
1516                         return (PARSE_ERROR_GENERIC);
1517                 f_ptr->priority = (FEAT_PRIORITY)priority;
1518         }
1519         else if (buf[0] == 'K')
1520         {
1521                 STR_OFFSET offset;
1522                 for (i = 0; i < MAX_FEAT_STATES; i++)
1523                         if (f_ptr->state[i].action == FF_FLAG_MAX) break;
1524
1525                 if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
1526
1527                 /* loop */
1528                 for (s = t = buf + 2; *t && (*t != ':'); t++);
1529
1530                 if (*t == ':') *t++ = '\0';
1531
1532                 if (streq(s, "DESTROYED"))
1533                 {
1534                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1535
1536                         f_ptr->destroyed_tag = offset;
1537                 }
1538                 else
1539                 {
1540                         f_ptr->state[i].action = 0;
1541                         if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
1542                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1543
1544                         f_ptr->state[i].result_tag = offset;
1545                 }
1546         }
1547         else
1548         {
1549                 return 6;
1550         }
1551
1552         return 0;
1553 }
1554
1555
1556 /*!
1557  * @brief 地形タグからIDを得る /
1558  * Convert a fake tag to a real feat index
1559  * @param str タグ文字列
1560  * @return 地形ID
1561  */
1562 s16b f_tag_to_index(concptr str)
1563 {
1564         for (u16b i = 0; i < f_head.info_num; i++)
1565         {
1566                 if (streq(f_tag + f_info[i].tag, str))
1567                 {
1568                         return (s16b)i;
1569                 }
1570         }
1571
1572         return -1;
1573 }
1574
1575
1576 /*!
1577  * @brief 地形タグからIDを得る /
1578  * Search for real index corresponding to this fake tag
1579  * @param feat タグ文字列のオフセット
1580  * @return 地形ID。該当がないなら-1
1581  */
1582 static FEAT_IDX search_real_feat(STR_OFFSET feat)
1583 {
1584         if (feat <= 0)
1585         {
1586                 return -1;
1587         }
1588
1589         for (FEAT_IDX i = 0; i < f_head.info_num; i++)
1590         {
1591                 if (feat == f_info[i].tag)
1592                 {
1593                         return i;
1594                 }
1595         }
1596
1597         msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
1598         return -1;
1599 }
1600
1601
1602 /*!
1603  * @brief 地形情報の各種タグからIDへ変換して結果を収める /
1604  * Retouch fake tags of f_info
1605  * @param head ヘッダ構造体
1606  * @return なし
1607  */
1608 void retouch_f_info(header *head)
1609 {
1610         for (int i = 0; i < head->info_num; i++)
1611         {
1612                 feature_type *f_ptr = &f_info[i];
1613                 FEAT_IDX k = search_real_feat(f_ptr->mimic_tag);
1614                 f_ptr->mimic = k < 0 ? f_ptr->mimic : k;
1615                 k = search_real_feat(f_ptr->destroyed_tag);
1616                 f_ptr->destroyed = k < 0 ? f_ptr->destroyed : k;
1617                 for (FEAT_IDX j = 0; j < MAX_FEAT_STATES; j++)
1618                 {
1619                         k = search_real_feat(f_ptr->state[j].result_tag);
1620                         f_ptr->state[j].result = k < 0 ? f_ptr->state[j].result : k;
1621                 }
1622         }
1623 }
1624
1625
1626 /*!
1627  * @brief テキストトークンを走査してフラグを一つ得る(ベースアイテム用) /
1628  * Grab one flag in an object_kind from a textual string
1629  * @param k_ptr 保管先のベースアイテム構造体参照ポインタ
1630  * @param what 参照元の文字列ポインタ
1631  * @return エラーコード
1632  */
1633 static errr grab_one_kind_flag(object_kind *k_ptr, concptr what)
1634 {
1635         for (int i = 0; i < TR_FLAG_MAX; i++)
1636         {
1637                 if (streq(what, k_info_flags[i]))
1638                 {
1639                         add_flag(k_ptr->flags, i);
1640                         return 0;
1641                 }
1642         }
1643
1644         if (grab_one_flag(&k_ptr->gen_flags, k_info_gen_flags, what) == 0)
1645                 return 0;
1646
1647         msg_format(_("未知のアイテム・フラグ '%s'。", "Unknown object flag '%s'."), what);
1648         return 1;
1649 }
1650
1651
1652 /*!
1653  * @brief テキストトークンを走査してフラグを一つ得る(発動能力用) /
1654  * Grab one activation index flag
1655  * @param what 参照元の文字列ポインタ
1656  * @return 発動能力ID
1657  */
1658 static byte grab_one_activation_flag(concptr what)
1659 {
1660         for (int i = 0; ; i++)
1661         {
1662                 if (activation_info[i].flag == NULL) break;
1663
1664                 if (streq(what, activation_info[i].flag))
1665                 {
1666                         return activation_info[i].index;
1667                 }
1668         }
1669
1670         int j = atoi(what);
1671         if (j > 0)
1672         {
1673                 return ((byte)j);
1674         }
1675
1676         msg_format(_("未知の発動・フラグ '%s'。", "Unknown activation flag '%s'."), what);
1677         return 0;
1678 }
1679
1680
1681 /*!
1682  * @brief ベースアイテム(k_info)のパース関数 /
1683  * Initialize the "k_info" array, by parsing an ascii "template" file
1684  * @param buf テキスト列
1685  * @param head ヘッダ構造体
1686  * @return エラーコード
1687  */
1688 errr parse_k_info(char *buf, header *head)
1689 {
1690         static object_kind *k_ptr = NULL;
1691
1692         char *s, *t;
1693         if (buf[0] == 'N')
1694         {
1695 #ifdef JP
1696                 char *flavor;
1697 #endif
1698                 s = my_strchr(buf + 2, ':');
1699                 if (!s) return 1;
1700
1701                 *s++ = '\0';
1702                 int i = atoi(buf + 2);
1703
1704                 if (i <= error_idx) return 4;
1705                 if (i >= head->info_num) return 2;
1706
1707                 error_idx = i;
1708                 k_ptr = &k_info[i];
1709
1710 #ifdef JP
1711                 if (!*s) return 1;
1712
1713                 flavor = my_strchr(s, ':');
1714                 if (flavor)
1715                 {
1716                         *flavor++ = '\0';
1717                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return 7;
1718                 }
1719
1720                 if (!add_name(&k_ptr->name, head, s)) return 7;
1721 #endif
1722         }
1723         else if (!k_ptr)
1724         {
1725                 return 3;
1726         }
1727 #ifdef JP
1728         /* 英語名を読むルーチンを追加 */
1729         /* 'E' から始まる行は英語名としている */
1730         else if (buf[0] == 'E')
1731         {
1732                 /* nothing to do */
1733         }
1734 #else
1735         else if (buf[0] == 'E')
1736         {
1737                 char *flavor;
1738                 s = buf + 2;
1739                 flavor = my_strchr(s, ':');
1740                 if (flavor)
1741                 {
1742                         *flavor++ = '\0';
1743                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return 7;
1744                 }
1745
1746                 if (!add_name(&k_ptr->name, head, s)) return 7;
1747         }
1748 #endif
1749         else if (buf[0] == 'D')
1750         {
1751 #ifdef JP
1752                 if (buf[2] == '$')
1753                         return 0;
1754                 s = buf + 2;
1755 #else
1756                 if (buf[2] != '$')
1757                         return 0;
1758                 s = buf + 3;
1759 #endif
1760                 if (!add_text(&k_ptr->text, head, s, TRUE)) return 7;
1761         }
1762         else if (buf[0] == 'G')
1763         {
1764                 char sym;
1765                 byte tmp;
1766                 if (buf[1] != ':') return 1;
1767                 if (!buf[2]) return 1;
1768                 if (buf[3] != ':') return 1;
1769                 if (!buf[4]) return 1;
1770
1771                 sym = buf[2];
1772                 tmp = color_char_to_attr(buf[4]);
1773                 if (tmp > 127) return 1;
1774
1775                 k_ptr->d_attr = tmp;
1776                 k_ptr->d_char = sym;
1777         }
1778         else if (buf[0] == 'I')
1779         {
1780                 int tval, sval, pval;
1781                 if (3 != sscanf(buf + 2, "%d:%d:%d",
1782                         &tval, &sval, &pval)) return 1;
1783
1784                 k_ptr->tval = (OBJECT_TYPE_VALUE)tval;
1785                 k_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
1786                 k_ptr->pval = (PARAMETER_VALUE)pval;
1787         }
1788         else if (buf[0] == 'W')
1789         {
1790                 int level, extra, wgt;
1791                 long cost;
1792                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
1793                         &level, &extra, &wgt, &cost)) return 1;
1794
1795                 k_ptr->level = (DEPTH)level;
1796                 k_ptr->extra = (BIT_FLAGS8)extra;
1797                 k_ptr->weight = (WEIGHT)wgt;
1798                 k_ptr->cost = (PRICE)cost;
1799         }
1800         else if (buf[0] == 'A')
1801         {
1802                 int i = 0;
1803                 for (s = buf + 1; s && (s[0] == ':') && s[1]; ++i)
1804                 {
1805                         k_ptr->chance[i] = 1;
1806                         k_ptr->locale[i] = atoi(s + 1);
1807                         t = my_strchr(s + 1, '/');
1808                         s = my_strchr(s + 1, ':');
1809                         if (t && (!s || t < s))
1810                         {
1811                                 int chance = atoi(t + 1);
1812                                 if (chance > 0) k_ptr->chance[i] = (PROB)chance;
1813                         }
1814                 }
1815         }
1816         else if (buf[0] == 'P')
1817         {
1818                 int ac, hd1, hd2, th, td, ta;
1819                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
1820                         &ac, &hd1, &hd2, &th, &td, &ta)) return 1;
1821
1822                 k_ptr->ac = (ARMOUR_CLASS)ac;
1823                 k_ptr->dd = (DICE_NUMBER)hd1;
1824                 k_ptr->ds = (DICE_SID)hd2;
1825                 k_ptr->to_h = (HIT_PROB)th;
1826                 k_ptr->to_d = (HIT_POINT)td;
1827                 k_ptr->to_a = (ARMOUR_CLASS)ta;
1828         }
1829         else if (buf[0] == 'U')
1830         {
1831                 byte n;
1832                 n = grab_one_activation_flag(buf + 2);
1833                 if (n > 0)
1834                 {
1835                         k_ptr->act_idx = n;
1836                 }
1837                 else
1838                 {
1839                         return 5;
1840                 }
1841         }
1842         else if (buf[0] == 'F')
1843         {
1844                 for (s = buf + 2; *s; )
1845                 {
1846                         /* loop */
1847                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
1848
1849                         if (*t)
1850                         {
1851                                 *t++ = '\0';
1852                                 while (*t == ' ' || *t == '|') t++;
1853                         }
1854
1855                         if (0 != grab_one_kind_flag(k_ptr, s)) return 5;
1856                         s = t;
1857                 }
1858         }
1859         else
1860         {
1861                 return 6;
1862         }
1863
1864         return 0;
1865 }
1866
1867
1868 /*!
1869  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
1870  * Grab one activation index flag
1871  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
1872  * @param what 参照元の文字列ポインタ
1873  * @return エラーがあった場合1、エラーがない場合0を返す
1874  */
1875 static errr grab_one_artifact_flag(artifact_type *a_ptr, concptr what)
1876 {
1877         for (int i = 0; i < TR_FLAG_MAX; i++)
1878         {
1879                 if (streq(what, k_info_flags[i]))
1880                 {
1881                         add_flag(a_ptr->flags, i);
1882                         return 0;
1883                 }
1884         }
1885
1886         if (grab_one_flag(&a_ptr->gen_flags, k_info_gen_flags, what) == 0)
1887                 return 0;
1888
1889         msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what);
1890         return 1;
1891 }
1892
1893
1894 /*!
1895  * @brief 固定アーティファクト情報(a_info)のパース関数 /
1896  * Initialize the "a_info" array, by parsing an ascii "template" file
1897  * @param buf テキスト列
1898  * @param head ヘッダ構造体
1899  * @return エラーコード
1900  */
1901 errr parse_a_info(char *buf, header *head)
1902 {
1903         static artifact_type *a_ptr = NULL;
1904         char *s, *t;
1905         if (buf[0] == 'N')
1906         {
1907                 s = my_strchr(buf + 2, ':');
1908                 if (!s) return 1;
1909
1910                 *s++ = '\0';
1911 #ifdef JP
1912                 if (!*s) return 1;
1913 #endif
1914                 int i = atoi(buf + 2);
1915                 if (i < error_idx) return 4;
1916                 if (i >= head->info_num) return 2;
1917
1918                 error_idx = i;
1919                 a_ptr = &a_info[i];
1920                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
1921                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
1922                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
1923                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
1924 #ifdef JP
1925                 if (!add_name(&a_ptr->name, head, s)) return 7;
1926 #endif
1927         }
1928         else if (!a_ptr)
1929         {
1930                 return 3;
1931         }
1932 #ifdef JP
1933         /* 英語名を読むルーチンを追加 */
1934         /* 'E' から始まる行は英語名としている */
1935         else if (buf[0] == 'E')
1936         {
1937                 /* nothing to do */
1938         }
1939 #else
1940         else if (buf[0] == 'E')
1941         {
1942                 s = buf + 2;
1943                 if (!add_name(&a_ptr->name, head, s)) return 7;
1944         }
1945 #endif
1946         else if (buf[0] == 'D')
1947         {
1948 #ifdef JP
1949                 if (buf[2] == '$')
1950                         return 0;
1951                 s = buf + 2;
1952 #else
1953                 if (buf[2] != '$')
1954                         return 0;
1955                 s = buf + 3;
1956 #endif
1957                 if (!add_text(&a_ptr->text, head, s, TRUE)) return 7;
1958         }
1959         else if (buf[0] == 'I')
1960         {
1961                 int tval, sval, pval;
1962                 if (3 != sscanf(buf + 2, "%d:%d:%d",
1963                         &tval, &sval, &pval)) return 1;
1964
1965                 a_ptr->tval = (OBJECT_TYPE_VALUE)tval;
1966                 a_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
1967                 a_ptr->pval = (PARAMETER_VALUE)pval;
1968         }
1969         else if (buf[0] == 'W')
1970         {
1971                 int level, rarity, wgt;
1972                 long cost;
1973                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
1974                         &level, &rarity, &wgt, &cost)) return 1;
1975
1976                 a_ptr->level = (DEPTH)level;
1977                 a_ptr->rarity = (RARITY)rarity;
1978                 a_ptr->weight = (WEIGHT)wgt;
1979                 a_ptr->cost = (PRICE)cost;
1980         }
1981         else if (buf[0] == 'P')
1982         {
1983                 int ac, hd1, hd2, th, td, ta;
1984                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
1985                         &ac, &hd1, &hd2, &th, &td, &ta)) return 1;
1986
1987                 a_ptr->ac = (ARMOUR_CLASS)ac;
1988                 a_ptr->dd = (DICE_NUMBER)hd1;
1989                 a_ptr->ds = (DICE_SID)hd2;
1990                 a_ptr->to_h = (HIT_PROB)th;
1991                 a_ptr->to_d = (HIT_POINT)td;
1992                 a_ptr->to_a = (ARMOUR_CLASS)ta;
1993         }
1994         else if (buf[0] == 'U')
1995         {
1996                 byte n;
1997                 n = grab_one_activation_flag(buf + 2);
1998                 if (n > 0)
1999                 {
2000                         a_ptr->act_idx = n;
2001                 }
2002                 else
2003                 {
2004                         return 5;
2005                 }
2006         }
2007         else if (buf[0] == 'F')
2008         {
2009                 for (s = buf + 2; *s; )
2010                 {
2011                         /* loop */
2012                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2013
2014                         if (*t)
2015                         {
2016                                 *t++ = '\0';
2017                                 while ((*t == ' ') || (*t == '|')) t++;
2018                         }
2019
2020                         if (0 != grab_one_artifact_flag(a_ptr, s)) return 5;
2021
2022                         s = t;
2023                 }
2024         }
2025         else
2026         {
2027                 return 6;
2028         }
2029
2030         return 0;
2031 }
2032
2033
2034 /*!
2035  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2036  * Grab one flag in a ego-item_type from a textual string
2037  * @param e_ptr 保管先のエゴ構造体参照ポインタ
2038  * @param what 参照元の文字列ポインタ
2039  * @return エラーがあった場合1、エラーがない場合0を返す
2040  */
2041 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
2042 {
2043         for (int i = 0; i < TR_FLAG_MAX; i++)
2044         {
2045                 if (streq(what, k_info_flags[i]))
2046                 {
2047                         add_flag(e_ptr->flags, i);
2048                         return 0;
2049                 }
2050         }
2051
2052         if (grab_one_flag(&e_ptr->gen_flags, k_info_gen_flags, what) == 0)
2053                 return 0;
2054
2055         msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what);
2056         return 1;
2057 }
2058
2059
2060 /*!
2061  * @brief アイテムエゴ情報(e_info)のパース関数 /
2062  * Initialize the "e_info" array, by parsing an ascii "template" file
2063  * @param buf テキスト列
2064  * @param head ヘッダ構造体
2065  * @return エラーコード
2066  */
2067 errr parse_e_info(char *buf, header *head)
2068 {
2069         static ego_item_type *e_ptr = NULL;
2070         error_idx = -1;
2071         error_line = -1;
2072         char *s, *t;
2073         if (buf[0] == 'N')
2074         {
2075                 s = my_strchr(buf + 2, ':');
2076                 if (!s) return 1;
2077
2078                 *s++ = '\0';
2079 #ifdef JP
2080                 if (!*s) return 1;
2081 #endif
2082                 int i = atoi(buf + 2);
2083                 if (i < error_idx) return 4;
2084                 if (i >= head->info_num) return 2;
2085
2086                 error_idx = i;
2087                 e_ptr = &e_info[i];
2088 #ifdef JP
2089                 if (!add_name(&e_ptr->name, head, s)) return 7;
2090 #endif
2091         }
2092         else if (!e_ptr)
2093         {
2094                 return 3;
2095         }
2096 #ifdef JP
2097         /* 英語名を読むルーチンを追加 */
2098         /* 'E' から始まる行は英語名 */
2099         else if (buf[0] == 'E')
2100         {
2101                 /* nothing to do */
2102         }
2103 #else
2104         else if (buf[0] == 'E')
2105         {
2106                 s = buf + 2;
2107                 if (!add_name(&e_ptr->name, head, s)) return 7;
2108         }
2109 #endif
2110         else if (buf[0] == 'X')
2111         {
2112                 int slot, rating;
2113                 if (2 != sscanf(buf + 2, "%d:%d",
2114                         &slot, &rating)) return 1;
2115
2116                 e_ptr->slot = (INVENTORY_IDX)slot;
2117                 e_ptr->rating = (PRICE)rating;
2118         }
2119         else if (buf[0] == 'W')
2120         {
2121                 int level, rarity, pad2;
2122                 long cost;
2123
2124                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2125                         &level, &rarity, &pad2, &cost)) return 1;
2126
2127                 e_ptr->level = level;
2128                 e_ptr->rarity = (RARITY)rarity;
2129                 e_ptr->cost = cost;
2130         }
2131         else if (buf[0] == 'C')
2132         {
2133                 int th, td, ta, pval;
2134
2135                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
2136                         &th, &td, &ta, &pval)) return 1;
2137
2138                 e_ptr->max_to_h = (HIT_PROB)th;
2139                 e_ptr->max_to_d = (HIT_POINT)td;
2140                 e_ptr->max_to_a = (ARMOUR_CLASS)ta;
2141                 e_ptr->max_pval = (PARAMETER_VALUE)pval;
2142         }
2143         else if (buf[0] == 'U')
2144         {
2145                 byte n;
2146                 n = grab_one_activation_flag(buf + 2);
2147                 if (n > 0)
2148                 {
2149                         e_ptr->act_idx = n;
2150                 }
2151                 else
2152                 {
2153                         return 5;
2154                 }
2155         }
2156         else if (buf[0] == 'F')
2157         {
2158                 for (s = buf + 2; *s; )
2159                 {
2160                         /* loop */
2161                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2162
2163                         if (*t)
2164                         {
2165                                 *t++ = '\0';
2166                                 while ((*t == ' ') || (*t == '|')) t++;
2167                         }
2168
2169                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return 5;
2170
2171                         s = t;
2172                 }
2173         }
2174         else
2175         {
2176                 return 6;
2177         }
2178
2179         return 0;
2180 }
2181
2182
2183 /*!
2184  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用1) /
2185  * Grab one (basic) flag in a monster_race from a textual string
2186  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2187  * @param what 参照元の文字列ポインタ
2188  * @return エラーコード
2189  */
2190 static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
2191 {
2192         if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
2193                 return 0;
2194
2195         if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
2196                 return 0;
2197
2198         if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
2199                 return 0;
2200
2201         if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
2202                 return 0;
2203
2204         if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
2205                 return 0;
2206
2207         if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
2208                 return 0;
2209
2210         if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
2211                 return 0;
2212
2213         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2214         return 1;
2215 }
2216
2217
2218 /*!
2219  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用2) /
2220  * Grab one (spell) flag in a monster_race from a textual string
2221  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2222  * @param what 参照元の文字列ポインタ
2223  * @return エラーコード
2224  */
2225 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
2226 {
2227         if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
2228                 return 0;
2229
2230         if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
2231                 return 0;
2232
2233         if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
2234                 return 0;
2235
2236         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2237         return 1;
2238 }
2239
2240
2241 /*!
2242  * @brief モンスター種族情報(r_info)のパース関数 /
2243  * Initialize the "r_info" array, by parsing an ascii "template" file
2244  * @param buf テキスト列
2245  * @param head ヘッダ構造体
2246  * @return エラーコード
2247  */
2248 errr parse_r_info(char *buf, header *head)
2249 {
2250         static monster_race *r_ptr = NULL;
2251         char *s, *t;
2252         if (buf[0] == 'N')
2253         {
2254                 s = my_strchr(buf + 2, ':');
2255                 if (!s) return 1;
2256
2257                 *s++ = '\0';
2258 #ifdef JP
2259                 if (!*s) return 1;
2260 #endif
2261
2262                 int i = atoi(buf + 2);
2263                 if (i < error_idx) return 4;
2264                 if (i >= head->info_num) return 2;
2265
2266                 error_idx = i;
2267                 r_ptr = &r_info[i];
2268 #ifdef JP
2269                 if (!add_name(&r_ptr->name, head, s)) return 7;
2270 #endif
2271         }
2272         else if (!r_ptr)
2273         {
2274                 return 3;
2275         }
2276 #ifdef JP
2277         /* 英語名を読むルーチンを追加 */
2278         /* 'E' から始まる行は英語名 */
2279         else if (buf[0] == 'E')
2280         {
2281                 s = buf + 2;
2282                 if (!add_name(&r_ptr->E_name, head, s)) return 7;
2283         }
2284 #else
2285         else if (buf[0] == 'E')
2286         {
2287                 s = buf + 2;
2288                 if (!add_name(&r_ptr->name, head, s)) return 7;
2289         }
2290 #endif
2291         else if (buf[0] == 'D')
2292         {
2293 #ifdef JP
2294                 if (buf[2] == '$')
2295                         return 0;
2296                 s = buf + 2;
2297 #else
2298                 if (buf[2] != '$')
2299                         return 0;
2300                 s = buf + 3;
2301 #endif
2302                 if (!add_text(&r_ptr->text, head, s, TRUE)) return 7;
2303         }
2304         else if (buf[0] == 'G')
2305         {
2306                 if (buf[1] != ':') return 1;
2307                 if (!buf[2]) return 1;
2308                 if (buf[3] != ':') return 1;
2309                 if (!buf[4]) return 1;
2310
2311                 char sym = buf[2];
2312                 byte tmp = color_char_to_attr(buf[4]);
2313                 if (tmp > 127) return 1;
2314
2315                 r_ptr->d_char = sym;
2316                 r_ptr->d_attr = tmp;
2317         }
2318         else if (buf[0] == 'I')
2319         {
2320                 int spd, hp1, hp2, aaf, ac, slp;
2321
2322                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2323                         &spd, &hp1, &hp2, &aaf, &ac, &slp)) return 1;
2324
2325                 r_ptr->speed = (SPEED)spd;
2326                 r_ptr->hdice = (DICE_NUMBER)MAX(hp1, 1);
2327                 r_ptr->hside = (DICE_SID)MAX(hp2, 1);
2328                 r_ptr->aaf = (POSITION)aaf;
2329                 r_ptr->ac = (ARMOUR_CLASS)ac;
2330                 r_ptr->sleep = (SLEEP_DEGREE)slp;
2331         }
2332         else if (buf[0] == 'W')
2333         {
2334                 int lev, rar, pad;
2335                 long exp;
2336                 long nextexp;
2337                 int nextmon;
2338                 if (6 != sscanf(buf + 2, "%d:%d:%d:%ld:%ld:%d",
2339                         &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return 1;
2340
2341                 r_ptr->level = (DEPTH)lev;
2342                 r_ptr->rarity = (RARITY)rar;
2343                 r_ptr->extra = (BIT_FLAGS16)pad;
2344                 r_ptr->mexp = (EXP)exp;
2345                 r_ptr->next_exp = (EXP)nextexp;
2346                 r_ptr->next_r_idx = (MONRACE_IDX)nextmon;
2347         }
2348         else if (buf[0] == 'R')
2349         {
2350                 int id, ds, dd;
2351                 int i = 0;
2352                 for (; i < A_MAX; i++) if (r_ptr->reinforce_id[i] == 0) break;
2353
2354                 if (i == 6) return 1;
2355
2356                 if (3 != sscanf(buf + 2, "%d:%dd%d", &id, &dd, &ds)) return 1;
2357                 r_ptr->reinforce_id[i] = (MONRACE_IDX)id;
2358                 r_ptr->reinforce_dd[i] = (DICE_NUMBER)dd;
2359                 r_ptr->reinforce_ds[i] = (DICE_SID)ds;
2360         }
2361         else if (buf[0] == 'B')
2362         {
2363                 int n1, n2;
2364                 int i = 0;
2365                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2366
2367                 if (i == 4) return 1;
2368
2369                 /* loop */
2370                 for (s = t = buf + 2; *t && (*t != ':'); t++);
2371
2372                 if (*t == ':') *t++ = '\0';
2373
2374                 for (n1 = 0; r_info_blow_method[n1]; n1++)
2375                 {
2376                         if (streq(s, r_info_blow_method[n1])) break;
2377                 }
2378
2379                 if (!r_info_blow_method[n1]) return 1;
2380
2381                 /* loop */
2382                 for (s = t; *t && (*t != ':'); t++);
2383
2384                 if (*t == ':') *t++ = '\0';
2385
2386                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2387                 {
2388                         if (streq(s, r_info_blow_effect[n2])) break;
2389                 }
2390
2391                 if (!r_info_blow_effect[n2]) return 1;
2392
2393                 /* loop */
2394                 for (s = t; *t && (*t != 'd'); t++);
2395
2396                 if (*t == 'd') *t++ = '\0';
2397
2398                 r_ptr->blow[i].method = (BLOW_METHOD)n1;
2399                 r_ptr->blow[i].effect = (BLOW_EFFECT)n2;
2400                 r_ptr->blow[i].d_dice = atoi(s);
2401                 r_ptr->blow[i].d_side = atoi(t);
2402         }
2403         else if (buf[0] == 'F')
2404         {
2405                 for (s = buf + 2; *s; )
2406                 {
2407                         /* loop */
2408                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2409
2410                         if (*t)
2411                         {
2412                                 *t++ = '\0';
2413                                 while (*t == ' ' || *t == '|') t++;
2414                         }
2415
2416                         if (0 != grab_one_basic_flag(r_ptr, s)) return 5;
2417
2418                         s = t;
2419                 }
2420         }
2421         else if (buf[0] == 'S')
2422         {
2423                 for (s = buf + 2; *s; )
2424                 {
2425
2426                         /* loop */
2427                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2428
2429                         if (*t)
2430                         {
2431                                 *t++ = '\0';
2432                                 while ((*t == ' ') || (*t == '|')) t++;
2433                         }
2434
2435                         int i;
2436                         if (1 == sscanf(s, "1_IN_%d", &i))
2437                         {
2438                                 r_ptr->freq_spell = 100 / i;
2439                                 s = t;
2440                                 continue;
2441                         }
2442
2443                         if (0 != grab_one_spell_flag(r_ptr, s)) return 5;
2444
2445                         s = t;
2446                 }
2447         }
2448         else if (buf[0] == 'A')
2449         {
2450                 int id, per, rarity;
2451                 int i = 0;
2452                 for (i = 0; i < 4; i++) if (!r_ptr->artifact_id[i]) break;
2453
2454                 if (i == 4) return 1;
2455
2456                 if (3 != sscanf(buf + 2, "%d:%d:%d", &id, &rarity, &per)) return 1;
2457                 r_ptr->artifact_id[i] = (ARTIFACT_IDX)id;
2458                 r_ptr->artifact_rarity[i] = (RARITY)rarity;
2459                 r_ptr->artifact_percent[i] = (PERCENTAGE)per;
2460         }
2461         else if (buf[0] == 'V')
2462         {
2463                 int val;
2464                 if (3 != sscanf(buf + 2, "%d", &val)) return 1;
2465                 r_ptr->arena_ratio = (PERCENTAGE)val;
2466         }
2467         else
2468         {
2469                 return 6;
2470         }
2471
2472         return 0;
2473 }
2474
2475
2476 /*!
2477  * @brief テキストトークンを走査してフラグを一つ得る(ダンジョン用) /
2478  * Grab one flag for a dungeon type from a textual string
2479  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
2480  * @param what 参照元の文字列ポインタ
2481  * @return エラーコード
2482  */
2483 static errr grab_one_dungeon_flag(dungeon_type *d_ptr, concptr what)
2484 {
2485         if (grab_one_flag(&d_ptr->flags1, d_info_flags1, what) == 0)
2486                 return 0;
2487
2488         msg_format(_("未知のダンジョン・フラグ '%s'。", "Unknown dungeon type flag '%s'."), what);
2489         return 1;
2490 }
2491
2492
2493 /*!
2494  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用1) /
2495  * Grab one (basic) flag in a monster_race from a textual string
2496  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
2497  * @param what 参照元の文字列ポインタ
2498  * @return エラーコード
2499  */
2500 static errr grab_one_basic_monster_flag(dungeon_type *d_ptr, concptr what)
2501 {
2502         if (grab_one_flag(&d_ptr->mflags1, r_info_flags1, what) == 0)
2503                 return 0;
2504
2505         if (grab_one_flag(&d_ptr->mflags2, r_info_flags2, what) == 0)
2506                 return 0;
2507
2508         if (grab_one_flag(&d_ptr->mflags3, r_info_flags3, what) == 0)
2509                 return 0;
2510
2511         if (grab_one_flag(&d_ptr->mflags7, r_info_flags7, what) == 0)
2512                 return 0;
2513
2514         if (grab_one_flag(&d_ptr->mflags8, r_info_flags8, what) == 0)
2515                 return 0;
2516
2517         if (grab_one_flag(&d_ptr->mflags9, r_info_flags9, what) == 0)
2518                 return 0;
2519
2520         if (grab_one_flag(&d_ptr->mflagsr, r_info_flagsr, what) == 0)
2521                 return 0;
2522
2523         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2524         return 1;
2525 }
2526
2527
2528 /*!
2529  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用2) /
2530  * Grab one (spell) flag in a monster_race from a textual string
2531  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
2532  * @param what 参照元の文字列ポインタ
2533  * @return エラーコード
2534  */
2535 static errr grab_one_spell_monster_flag(dungeon_type *d_ptr, concptr what)
2536 {
2537         if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
2538                 return 0;
2539
2540         if (grab_one_flag(&d_ptr->m_a_ability_flags1, r_a_ability_flags1, what) == 0)
2541                 return 0;
2542
2543         if (grab_one_flag(&d_ptr->m_a_ability_flags2, r_a_ability_flags2, what) == 0)
2544                 return 0;
2545
2546         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2547         return 1;
2548 }
2549
2550
2551 /*!
2552  * @brief ダンジョン情報(d_info)のパース関数 /
2553  * Initialize the "d_info" array, by parsing an ascii "template" file
2554  * @param buf テキスト列
2555  * @param head ヘッダ構造体
2556  * @return エラーコード
2557  */
2558 errr parse_d_info(char *buf, header *head)
2559 {
2560         static dungeon_type *d_ptr = NULL;
2561         char *s, *t;
2562         if (buf[0] == 'N')
2563         {
2564                 s = my_strchr(buf + 2, ':');
2565                 if (!s) return 1;
2566
2567                 *s++ = '\0';
2568 #ifdef JP
2569                 if (!*s) return 1;
2570 #endif
2571
2572                 int i = atoi(buf + 2);
2573                 if (i < error_idx) return 4;
2574                 if (i >= head->info_num) return 2;
2575
2576                 error_idx = i;
2577                 d_ptr = &d_info[i];
2578 #ifdef JP
2579                 if (!add_name(&d_ptr->name, head, s)) return 7;
2580 #endif
2581         }
2582 #ifdef JP
2583         else if (buf[0] == 'E') return 0;
2584 #else
2585         else if (buf[0] == 'E')
2586         {
2587                 /* Acquire the Text */
2588                 s = buf + 2;
2589
2590                 /* Store the name */
2591                 if (!add_name(&d_ptr->name, head, s)) return 7;
2592         }
2593 #endif
2594         else if (buf[0] == 'D')
2595         {
2596 #ifdef JP
2597                 if (buf[2] == '$')
2598                         return 0;
2599                 s = buf + 2;
2600 #else
2601                 if (buf[2] != '$')
2602                         return 0;
2603                 s = buf + 3;
2604 #endif
2605                 if (!add_text(&d_ptr->text, head, s, TRUE)) return 7;
2606         }
2607         else if (buf[0] == 'W')
2608         {
2609                 int min_lev, max_lev;
2610                 int min_plev, mode;
2611                 int min_alloc, max_chance;
2612                 int obj_good, obj_great;
2613                 int pit, nest;
2614
2615                 if (10 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2616                         &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return 1;
2617
2618                 d_ptr->mindepth = (DEPTH)min_lev;
2619                 d_ptr->maxdepth = (DEPTH)max_lev;
2620                 d_ptr->min_plev = (PLAYER_LEVEL)min_plev;
2621                 d_ptr->mode = (BIT_FLAGS8)mode;
2622                 d_ptr->min_m_alloc_level = min_alloc;
2623                 d_ptr->max_m_alloc_chance = max_chance;
2624                 d_ptr->obj_good = obj_good;
2625                 d_ptr->obj_great = obj_great;
2626                 d_ptr->pit = (BIT_FLAGS16)pit;
2627                 d_ptr->nest = (BIT_FLAGS16)nest;
2628         }
2629         else if (buf[0] == 'P')
2630         {
2631                 int dy, dx;
2632                 if (2 != sscanf(buf + 2, "%d:%d", &dy, &dx)) return 1;
2633
2634                 d_ptr->dy = dy;
2635                 d_ptr->dx = dx;
2636         }
2637         else if (buf[0] == 'L')
2638         {
2639                 char *zz[16];
2640                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 1, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 1)) return 1;
2641
2642                 for (int i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
2643                 {
2644                         d_ptr->floor[i].feat = f_tag_to_index(zz[i * 2]);
2645                         if (d_ptr->floor[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2646
2647                         d_ptr->floor[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
2648                 }
2649
2650                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
2651         }
2652         else if (buf[0] == 'A')
2653         {
2654                 char *zz[16];
2655                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return 1;
2656
2657                 for (int i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
2658                 {
2659                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
2660                         if (d_ptr->fill[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2661
2662                         d_ptr->fill[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
2663                 }
2664
2665                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
2666                 if (d_ptr->outer_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2667
2668                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
2669                 if (d_ptr->inner_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2670
2671                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
2672                 if (d_ptr->stream1 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2673
2674                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
2675                 if (d_ptr->stream2 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2676         }
2677         else if (buf[0] == 'F')
2678         {
2679                 int artif = 0, monst = 0;
2680
2681                 for (s = buf + 2; *s; )
2682                 {
2683                         /* loop */
2684                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2685
2686                         if (*t)
2687                         {
2688                                 *t++ = '\0';
2689                                 while (*t == ' ' || *t == '|') t++;
2690                         }
2691
2692                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2693                         {
2694                                 d_ptr->final_artifact = (ARTIFACT_IDX)artif;
2695                                 s = t;
2696                                 continue;
2697                         }
2698
2699                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2700                         {
2701                                 d_ptr->final_object = (KIND_OBJECT_IDX)artif;
2702                                 s = t;
2703                                 continue;
2704                         }
2705
2706                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2707                         {
2708                                 d_ptr->final_guardian = (MONRACE_IDX)monst;
2709                                 s = t;
2710                                 continue;
2711                         }
2712
2713                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2714                         {
2715                                 d_ptr->special_div = (PROB)monst;
2716                                 s = t;
2717                                 continue;
2718                         }
2719
2720                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return 5;
2721
2722                         s = t;
2723                 }
2724         }
2725         else if (buf[0] == 'M')
2726         {
2727                 for (s = buf + 2; *s; )
2728                 {
2729                         /* loop */
2730                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2731
2732                         if (*t)
2733                         {
2734                                 *t++ = '\0';
2735                                 while (*t == ' ' || *t == '|') t++;
2736                         }
2737
2738                         if (!strncmp(s, "R_CHAR_", 7))
2739                         {
2740                                 s += 7;
2741                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
2742                                 s = t;
2743                                 continue;
2744                         }
2745
2746                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return 5;
2747
2748                         s = t;
2749                 }
2750         }
2751         else if (buf[0] == 'S')
2752         {
2753                 for (s = buf + 2; *s; )
2754                 {
2755                         /* loop */
2756                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t);
2757
2758                         if (*t)
2759                         {
2760                                 *t++ = '\0';
2761                                 while ((*t == ' ') || (*t == '|')) t++;
2762                         }
2763
2764                         int i;
2765                         if (1 == sscanf(s, "1_IN_%d", &i))
2766                         {
2767                                 s = t;
2768                                 continue;
2769                         }
2770
2771                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return 5;
2772
2773                         s = t;
2774                 }
2775         }
2776         else
2777         {
2778                 return 6;
2779         }
2780
2781         return 0;
2782 }
2783
2784
2785 /*!
2786  * @brief 地形情報の「F:」情報をパースする
2787  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2788  * @param floor_ptr 現在フロアへの参照ポインタ
2789  * @param buf 解析文字列
2790  * @return エラーコード
2791  */
2792 static errr parse_line_feature(floor_type *floor_ptr, char *buf)
2793 {
2794         if (init_flags & INIT_ONLY_BUILDINGS) return 0;
2795
2796         char *zz[9];
2797         int num = tokenize(buf + 2, 9, zz, 0);
2798         if (num <= 1) return 1;
2799
2800         int index = zz[0][0];
2801         letter[index].feature = feat_none;
2802         letter[index].monster = 0;
2803         letter[index].object = 0;
2804         letter[index].ego = 0;
2805         letter[index].artifact = 0;
2806         letter[index].trap = feat_none;
2807         letter[index].cave_info = 0;
2808         letter[index].special = 0;
2809         letter[index].random = RANDOM_NONE;
2810
2811         /* Fall through */
2812         switch (num)
2813         {
2814         case 9:
2815                 letter[index].special = (s16b)atoi(zz[8]);
2816         case 8:
2817                 if ((zz[7][0] == '*') && !zz[7][1])
2818                 {
2819                         letter[index].random |= RANDOM_TRAP;
2820                 }
2821                 else
2822                 {
2823                         letter[index].trap = f_tag_to_index(zz[7]);
2824                         if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2825                 }
2826         case 7:
2827                 if (zz[6][0] == '*')
2828                 {
2829                         letter[index].random |= RANDOM_ARTIFACT;
2830                         if (zz[6][1]) letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1);
2831                 }
2832                 else if (zz[6][0] == '!')
2833                 {
2834                         if (floor_ptr->inside_quest)
2835                         {
2836                                 letter[index].artifact = quest[floor_ptr->inside_quest].k_idx;
2837                         }
2838                 }
2839                 else
2840                 {
2841                         letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]);
2842                 }
2843         case 6:
2844                 if (zz[5][0] == '*')
2845                 {
2846                         letter[index].random |= RANDOM_EGO;
2847                         if (zz[5][1]) letter[index].ego = (EGO_IDX)atoi(zz[5] + 1);
2848                 }
2849                 else
2850                 {
2851                         letter[index].ego = (EGO_IDX)atoi(zz[5]);
2852                 }
2853         case 5:
2854                 if (zz[4][0] == '*')
2855                 {
2856                         letter[index].random |= RANDOM_OBJECT;
2857                         if (zz[4][1]) letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1);
2858                 }
2859                 else if (zz[4][0] == '!')
2860                 {
2861                         if (floor_ptr->inside_quest)
2862                         {
2863                                 ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx;
2864                                 if (a_idx)
2865                                 {
2866                                         artifact_type *a_ptr = &a_info[a_idx];
2867                                         if (!(a_ptr->gen_flags & TRG_INSTA_ART))
2868                                         {
2869                                                 letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
2870                                         }
2871                                 }
2872                         }
2873                 }
2874                 else
2875                 {
2876                         letter[index].object = (IDX)atoi(zz[4]);
2877                 }
2878         case 4:
2879                 if (zz[3][0] == '*')
2880                 {
2881                         letter[index].random |= RANDOM_MONSTER;
2882                         if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1);
2883                 }
2884                 else if (zz[3][0] == 'c')
2885                 {
2886                         if (!zz[3][1]) return PARSE_ERROR_GENERIC;
2887                         letter[index].monster = -atoi(zz[3] + 1);
2888                 }
2889                 else
2890                 {
2891                         letter[index].monster = (IDX)atoi(zz[3]);
2892                 }
2893         case 3:
2894                 letter[index].cave_info = atoi(zz[2]);
2895         case 2:
2896                 if ((zz[1][0] == '*') && !zz[1][1])
2897                 {
2898                         letter[index].random |= RANDOM_FEATURE;
2899                 }
2900                 else
2901                 {
2902                         letter[index].feature = f_tag_to_index(zz[1]);
2903                         if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2904                 }
2905
2906                 break;
2907         }
2908
2909         return 0;
2910 }
2911
2912
2913 /*!
2914  * @brief 地形情報の「B:」情報をパースする
2915  * Process "B:<Index>:<Command>:..." -- Building definition
2916  * @param buf 解析文字列
2917  * @return エラーコード
2918  */
2919 static errr parse_line_building(char *buf)
2920 {
2921         char *zz[1000];
2922         char *s;
2923
2924 #ifdef JP
2925         if (buf[2] == '$')
2926                 return 0;
2927         s = buf + 2;
2928 #else
2929         if (buf[2] != '$')
2930                 return 0;
2931         s = buf + 3;
2932 #endif
2933         int index = atoi(s);
2934         s = my_strchr(s, ':');
2935         if (!s) return 1;
2936
2937         *s++ = '\0';
2938         if (!*s) return 1;
2939
2940         switch (s[0])
2941         {
2942         case 'N':
2943         {
2944                 if (tokenize(s + 2, 3, zz, 0) == 3)
2945                 {
2946                         strcpy(building[index].name, zz[0]);
2947                         strcpy(building[index].owner_name, zz[1]);
2948                         strcpy(building[index].owner_race, zz[2]);
2949                         break;
2950                 }
2951
2952                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
2953         }
2954         case 'A':
2955         {
2956                 if (tokenize(s + 2, 8, zz, 0) >= 7)
2957                 {
2958                         int action_index = atoi(zz[0]);
2959                         strcpy(building[index].act_names[action_index], zz[1]);
2960                         building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
2961                         building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
2962                         building[index].letters[action_index] = zz[4][0];
2963                         building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]);
2964                         building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]);
2965                         break;
2966                 }
2967
2968                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
2969         }
2970         case 'C':
2971         {
2972                 int n;
2973                 n = tokenize(s + 2, MAX_CLASS, zz, 0);
2974                 for (int i = 0; i < MAX_CLASS; i++)
2975                 {
2976                         building[index].member_class[i] = ((i < n) ? (CLASS_IDX)atoi(zz[i]) : 1);
2977                 }
2978
2979                 break;
2980         }
2981         case 'R':
2982         {
2983                 int n;
2984                 n = tokenize(s + 2, MAX_RACES, zz, 0);
2985                 for (int i = 0; i < MAX_RACES; i++)
2986                 {
2987                         building[index].member_race[i] = ((i < n) ? (RACE_IDX)atoi(zz[i]) : 1);
2988                 }
2989
2990                 break;
2991         }
2992         case 'M':
2993         {
2994                 int n;
2995                 n = tokenize(s + 2, MAX_MAGIC, zz, 0);
2996                 for (int i = 0; i < MAX_MAGIC; i++)
2997                 {
2998                         building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1);
2999                 }
3000
3001                 break;
3002         }
3003         case 'Z':
3004         {
3005                 break;
3006         }
3007         default:
3008         {
3009                 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3010         }
3011         }
3012
3013         return 0;
3014 }
3015
3016
3017 /*!
3018  * @brief フロアの所定のマスにオブジェクトを配置する
3019  * Place the object j_ptr to a grid
3020  * @param floor_ptr 現在フロアへの参照ポインタ
3021  * @param j_ptr オブジェクト構造体の参照ポインタ
3022  * @param y 配置先Y座標
3023  * @param x 配置先X座標
3024  * @return エラーコード
3025  */
3026 static void drop_here(floor_type *floor_ptr, object_type *j_ptr, POSITION y, POSITION x)
3027 {
3028         OBJECT_IDX o_idx = o_pop(floor_ptr);
3029         object_type *o_ptr;
3030         o_ptr = &floor_ptr->o_list[o_idx];
3031         object_copy(o_ptr, j_ptr);
3032         o_ptr->iy = y;
3033         o_ptr->ix = x;
3034         o_ptr->held_m_idx = 0;
3035         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
3036         o_ptr->next_o_idx = g_ptr->o_idx;
3037         g_ptr->o_idx = o_idx;
3038 }
3039
3040
3041 /*!
3042  * todo yminとymaxは本当に使われているのか?
3043  * @brief クエスト用固定ダンジョンをフロアに生成する
3044  * Parse a sub-file of the "extra info"
3045  * @param player_ptr プレーヤーへの参照ポインタ
3046  * @param buf 文字列
3047  * @param ymin 詳細不明
3048  * @param xmin 詳細不明
3049  * @param ymax 詳細不明
3050  * @param xmax 詳細不明
3051  * @param y 詳細不明
3052  * @param x 詳細不明
3053  * @return エラーコード
3054  */
3055 static errr process_dungeon_file_aux(player_type *player_ptr, char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3056 {
3057         char *zz[33];
3058
3059         if (!buf[0]) return 0;
3060         if (iswspace(buf[0])) return 0;
3061         if (buf[0] == '#') return 0;
3062         if (buf[1] != ':') return 1;
3063
3064         if (buf[0] == '%')
3065         {
3066                 return process_dungeon_file(player_ptr, buf + 2, ymin, xmin, ymax, xmax);
3067         }
3068
3069         floor_type *floor_ptr = player_ptr->current_floor_ptr;
3070         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3071         if (buf[0] == 'F')
3072         {
3073                 return parse_line_feature(player_ptr->current_floor_ptr, buf);
3074         }
3075         else if (buf[0] == 'D')
3076         {
3077                 object_type object_type_body;
3078                 char *s = buf + 2;
3079                 int len = strlen(s);
3080                 if (init_flags & INIT_ONLY_BUILDINGS) return 0;
3081
3082                 *x = xmin;
3083                 for (int i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3084                 {
3085                         grid_type *g_ptr = &floor_ptr->grid_array[*y][*x];
3086                         int idx = s[0];
3087                         OBJECT_IDX object_index = letter[idx].object;
3088                         MONSTER_IDX monster_index = letter[idx].monster;
3089                         int random = letter[idx].random;
3090                         ARTIFACT_IDX artifact_index = letter[idx].artifact;
3091                         g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].feature);
3092                         if (init_flags & INIT_ONLY_FEATURES) continue;
3093
3094                         g_ptr->info = letter[idx].cave_info;
3095                         if (random & RANDOM_MONSTER)
3096                         {
3097                                 floor_ptr->monster_level = floor_ptr->base_level + monster_index;
3098
3099                                 place_monster(player_ptr, *y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3100
3101                                 floor_ptr->monster_level = floor_ptr->base_level;
3102                         }
3103                         else if (monster_index)
3104                         {
3105                                 int old_cur_num, old_max_num;
3106                                 bool clone = FALSE;
3107
3108                                 if (monster_index < 0)
3109                                 {
3110                                         monster_index = -monster_index;
3111                                         clone = TRUE;
3112                                 }
3113
3114                                 old_cur_num = r_info[monster_index].cur_num;
3115                                 old_max_num = r_info[monster_index].max_num;
3116
3117                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3118                                 {
3119                                         r_info[monster_index].cur_num = 0;
3120                                         r_info[monster_index].max_num = 1;
3121                                 }
3122                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3123                                 {
3124                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3125                                         {
3126                                                 r_info[monster_index].max_num++;
3127                                         }
3128                                 }
3129
3130                                 place_monster_aux(player_ptr, 0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3131                                 if (clone)
3132                                 {
3133                                         floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
3134                                         r_info[monster_index].cur_num = old_cur_num;
3135                                         r_info[monster_index].max_num = old_max_num;
3136                                 }
3137                         }
3138
3139                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3140                         {
3141                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3142
3143                                 /*
3144                                  * Random trap and random treasure defined
3145                                  * 25% chance for trap and 75% chance for object
3146                                  */
3147                                 if (randint0(100) < 75)
3148                                 {
3149                                         place_object(player_ptr, *y, *x, 0L);
3150                                 }
3151                                 else
3152                                 {
3153                                         place_trap(player_ptr, *y, *x);
3154                                 }
3155
3156                                 floor_ptr->object_level = floor_ptr->base_level;
3157                         }
3158                         else if (random & RANDOM_OBJECT)
3159                         {
3160                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3161                                 if (randint0(100) < 75)
3162                                         place_object(player_ptr, *y, *x, 0L);
3163                                 else if (randint0(100) < 80)
3164                                         place_object(player_ptr, *y, *x, AM_GOOD);
3165                                 else
3166                                         place_object(player_ptr, *y, *x, AM_GOOD | AM_GREAT);
3167
3168                                 floor_ptr->object_level = floor_ptr->base_level;
3169                         }
3170                         else if (random & RANDOM_TRAP)
3171                         {
3172                                 place_trap(player_ptr, *y, *x);
3173                         }
3174                         else if (letter[idx].trap)
3175                         {
3176                                 g_ptr->mimic = g_ptr->feat;
3177                                 g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].trap);
3178                         }
3179                         else if (object_index)
3180                         {
3181                                 object_type *o_ptr = &object_type_body;
3182                                 object_prep(o_ptr, object_index);
3183                                 if (o_ptr->tval == TV_GOLD)
3184                                 {
3185                                         coin_type = object_index - OBJ_GOLD_LIST;
3186                                         make_gold(floor_ptr, o_ptr);
3187                                         coin_type = 0;
3188                                 }
3189
3190                                 apply_magic(player_ptr, o_ptr, floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
3191                                 drop_here(floor_ptr, o_ptr, *y, *x);
3192                         }
3193
3194                         if (artifact_index)
3195                         {
3196                                 if (a_info[artifact_index].cur_num)
3197                                 {
3198                                         KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
3199                                         object_type forge;
3200                                         object_type *q_ptr = &forge;
3201
3202                                         object_prep(q_ptr, k_idx);
3203                                         drop_here(floor_ptr, q_ptr, *y, *x);
3204                                 }
3205                                 else
3206                                 {
3207                                         if (create_named_art(player_ptr, artifact_index, *y, *x))
3208                                                 a_info[artifact_index].cur_num = 1;
3209                                 }
3210                         }
3211
3212                         g_ptr->special = letter[idx].special;
3213                 }
3214
3215                 (*y)++;
3216                 return 0;
3217         }
3218         else if (buf[0] == 'Q')
3219         {
3220                 int num;
3221                 quest_type *q_ptr;
3222 #ifdef JP
3223                 if (buf[2] == '$')
3224                         return 0;
3225                 num = tokenize(buf + 2, 33, zz, 0);
3226 #else
3227                 if (buf[2] != '$')
3228                         return 0;
3229                 num = tokenize(buf + 3, 33, zz, 0);
3230 #endif
3231
3232                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3233
3234                 q_ptr = &(quest[atoi(zz[0])]);
3235                 if (zz[1][0] == 'Q')
3236                 {
3237                         if (init_flags & INIT_ASSIGN)
3238                         {
3239                                 monster_race *r_ptr;
3240                                 artifact_type *a_ptr;
3241
3242                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3243
3244                                 q_ptr->type = (QUEST_TYPE)atoi(zz[2]);
3245                                 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
3246                                 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
3247                                 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
3248                                 q_ptr->level = (DEPTH)atoi(zz[6]);
3249                                 q_ptr->r_idx = (IDX)atoi(zz[7]);
3250                                 q_ptr->k_idx = (IDX)atoi(zz[8]);
3251                                 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
3252
3253                                 if (num > 10) q_ptr->flags = atoi(zz[10]);
3254
3255                                 r_ptr = &r_info[q_ptr->r_idx];
3256                                 if (r_ptr->flags1 & RF1_UNIQUE)
3257                                         r_ptr->flags1 |= RF1_QUESTOR;
3258
3259                                 a_ptr = &a_info[q_ptr->k_idx];
3260                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3261                         }
3262
3263                         return 0;
3264                 }
3265                 else if (zz[1][0] == 'R')
3266                 {
3267                         if (init_flags & INIT_ASSIGN)
3268                         {
3269                                 int count = 0;
3270                                 IDX idx, reward_idx = 0;
3271
3272                                 for (idx = 2; idx < num; idx++)
3273                                 {
3274                                         IDX a_idx = (IDX)atoi(zz[idx]);
3275                                         if (a_idx < 1) continue;
3276                                         if (a_info[a_idx].cur_num > 0) continue;
3277                                         count++;
3278                                         if (one_in_(count)) reward_idx = a_idx;
3279                                 }
3280
3281                                 if (reward_idx)
3282                                 {
3283                                         q_ptr->k_idx = reward_idx;
3284                                         a_info[reward_idx].gen_flags |= TRG_QUESTITEM;
3285                                 }
3286                                 else
3287                                 {
3288                                         q_ptr->type = QUEST_TYPE_KILL_ALL;
3289                                 }
3290                         }
3291
3292                         return 0;
3293                 }
3294                 else if (zz[1][0] == 'N')
3295                 {
3296                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY))
3297                         {
3298                                 strcpy(q_ptr->name, zz[2]);
3299                         }
3300
3301                         return 0;
3302                 }
3303                 else if (zz[1][0] == 'T')
3304                 {
3305                         if (init_flags & INIT_SHOW_TEXT)
3306                         {
3307                                 strcpy(quest_text[quest_text_line], zz[2]);
3308                                 quest_text_line++;
3309                         }
3310
3311                         return 0;
3312                 }
3313         }
3314         else if (buf[0] == 'W')
3315         {
3316                 return parse_line_wilderness(player_ptr, buf, xmin, xmax, y, x);
3317         }
3318         else if (buf[0] == 'P')
3319         {
3320                 if (init_flags & INIT_CREATE_DUNGEON)
3321                 {
3322                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3323                         {
3324                                 int panels_x, panels_y;
3325
3326                                 panels_y = (*y / SCREEN_HGT);
3327                                 if (*y % SCREEN_HGT) panels_y++;
3328                                 floor_ptr->height = panels_y * SCREEN_HGT;
3329
3330                                 panels_x = (*x / SCREEN_WID);
3331                                 if (*x % SCREEN_WID) panels_x++;
3332                                 floor_ptr->width = panels_x * SCREEN_WID;
3333
3334                                 panel_row_min = floor_ptr->height;
3335                                 panel_col_min = floor_ptr->width;
3336
3337                                 if (floor_ptr->inside_quest)
3338                                 {
3339                                         delete_monster(player_ptr, player_ptr->y, player_ptr->x);
3340
3341                                         POSITION py = atoi(zz[0]);
3342                                         POSITION px = atoi(zz[1]);
3343
3344                                         player_ptr->y = py;
3345                                         player_ptr->x = px;
3346                                 }
3347                                 else if (!player_ptr->oldpx && !player_ptr->oldpy)
3348                                 {
3349                                         player_ptr->oldpy = atoi(zz[0]);
3350                                         player_ptr->oldpx = atoi(zz[1]);
3351                                 }
3352                         }
3353                 }
3354
3355                 return 0;
3356         }
3357         else if (buf[0] == 'B')
3358         {
3359                 return parse_line_building(buf);
3360         }
3361         else if (buf[0] == 'M')
3362         {
3363                 if (tokenize(buf + 2, 2, zz, 0) == 2)
3364                 {
3365                         if (zz[0][0] == 'T')
3366                         {
3367                                 max_towns = (TOWN_IDX)atoi(zz[1]);
3368                         }
3369                         else if (zz[0][0] == 'Q')
3370                         {
3371                                 max_q_idx = (QUEST_IDX)atoi(zz[1]);
3372                         }
3373                         else if (zz[0][0] == 'R')
3374                         {
3375                                 max_r_idx = (RACE_IDX)atoi(zz[1]);
3376                         }
3377                         else if (zz[0][0] == 'K')
3378                         {
3379                                 max_k_idx = (KIND_OBJECT_IDX)atoi(zz[1]);
3380                         }
3381                         else if (zz[0][0] == 'V')
3382                         {
3383                                 max_v_idx = (VAULT_IDX)atoi(zz[1]);
3384                         }
3385                         else if (zz[0][0] == 'F')
3386                         {
3387                                 max_f_idx = (FEAT_IDX)atoi(zz[1]);
3388                         }
3389                         else if (zz[0][0] == 'A')
3390                         {
3391                                 max_a_idx = (ARTIFACT_IDX)atoi(zz[1]);
3392                         }
3393                         else if (zz[0][0] == 'E')
3394                         {
3395                                 max_e_idx = (EGO_IDX)atoi(zz[1]);
3396                         }
3397                         else if (zz[0][0] == 'D')
3398                         {
3399                                 current_world_ptr->max_d_idx = (DUNGEON_IDX)atoi(zz[1]);
3400                         }
3401                         else if (zz[0][0] == 'O')
3402                         {
3403                                 current_world_ptr->max_o_idx = (OBJECT_IDX)atoi(zz[1]);
3404                         }
3405                         else if (zz[0][0] == 'M')
3406                         {
3407                                 current_world_ptr->max_m_idx = (MONSTER_IDX)atoi(zz[1]);
3408                         }
3409                         else if (zz[0][0] == 'W')
3410                         {
3411                                 if (zz[0][1] == 'X')
3412                                         current_world_ptr->max_wild_x = (POSITION)atoi(zz[1]);
3413
3414                                 if (zz[0][1] == 'Y')
3415                                         current_world_ptr->max_wild_y = (POSITION)atoi(zz[1]);
3416                         }
3417
3418                         return 0;
3419                 }
3420         }
3421
3422         return 1;
3423 }
3424
3425 /*
3426 * todo ここから先頭に移すとコンパイル警告が出る……
3427 */
3428 static char tmp[8];
3429 static concptr variant = "ZANGBAND";
3430
3431 /*!
3432  * @brief クエスト用固定ダンジョン生成時の分岐処理
3433  * Helper function for "process_dungeon_file()"
3434  * @param player_ptr プレーヤーへの参照ポインタ
3435  * @param sp
3436  * @param fp
3437  * @return エラーコード
3438  */
3439 static concptr process_dungeon_file_expr(player_type *player_ptr, char **sp, char *fp)
3440 {
3441         char b1 = '[';
3442         char b2 = ']';
3443
3444         char f = ' ';
3445
3446         char *s;
3447         s = (*sp);
3448
3449         while (iswspace(*s)) s++;
3450
3451         char *b;
3452         b = s;
3453         concptr v = "?o?o?";
3454         if (*s == b1)
3455         {
3456                 concptr p;
3457                 concptr t;
3458                 s++;
3459                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3460                 if (!*t)
3461                 {
3462                         /* Nothing */
3463                 }
3464                 else if (streq(t, "IOR"))
3465                 {
3466                         v = "0";
3467                         while (*s && (f != b2))
3468                         {
3469                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3470                                 if (*t && !streq(t, "0")) v = "1";
3471                         }
3472                 }
3473                 else if (streq(t, "AND"))
3474                 {
3475                         v = "1";
3476                         while (*s && (f != b2))
3477                         {
3478                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3479                                 if (*t && streq(t, "0")) v = "0";
3480                         }
3481                 }
3482                 else if (streq(t, "NOT"))
3483                 {
3484                         v = "1";
3485                         while (*s && (f != b2))
3486                         {
3487                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3488                                 if (*t && streq(t, "1")) v = "0";
3489                         }
3490                 }
3491                 else if (streq(t, "EQU"))
3492                 {
3493                         v = "0";
3494                         if (*s && (f != b2))
3495                         {
3496                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3497                         }
3498
3499                         while (*s && (f != b2))
3500                         {
3501                                 p = process_dungeon_file_expr(player_ptr, &s, &f);
3502                                 if (streq(t, p)) v = "1";
3503                         }
3504                 }
3505                 else if (streq(t, "LEQ"))
3506                 {
3507                         v = "1";
3508                         if (*s && (f != b2))
3509                         {
3510                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3511                         }
3512
3513                         while (*s && (f != b2))
3514                         {
3515                                 p = t;
3516                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3517                                 if (*t && atoi(p) > atoi(t)) v = "0";
3518                         }
3519                 }
3520                 else if (streq(t, "GEQ"))
3521                 {
3522                         v = "1";
3523                         if (*s && (f != b2))
3524                         {
3525                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3526                         }
3527
3528                         while (*s && (f != b2))
3529                         {
3530                                 p = t;
3531                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3532                                 if (*t && atoi(p) < atoi(t)) v = "0";
3533                         }
3534                 }
3535                 else
3536                 {
3537                         while (*s && (f != b2))
3538                         {
3539                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3540                         }
3541                 }
3542
3543                 if (f != b2) v = "?x?x?";
3544                 if ((f = *s) != '\0') *s++ = '\0';
3545
3546                 (*fp) = f;
3547                 (*sp) = s;
3548                 return v;
3549         }
3550
3551 #ifdef JP
3552         while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
3553         {
3554                 if (iskanji(*s)) s++;
3555                 s++;
3556         }
3557 #else
3558         while (isprint(*s) && !my_strchr(" []", *s)) ++s;
3559 #endif
3560         if ((f = *s) != '\0') *s++ = '\0';
3561
3562         if (*b != '$')
3563         {
3564                 v = b;
3565                 (*fp) = f;
3566                 (*sp) = s;
3567                 return v;
3568         }
3569
3570         if (streq(b + 1, "SYS"))
3571         {
3572                 v = ANGBAND_SYS;
3573         }
3574         else if (streq(b + 1, "GRAF"))
3575         {
3576                 v = ANGBAND_GRAF;
3577         }
3578         else if (streq(b + 1, "MONOCHROME"))
3579         {
3580                 if (arg_monochrome)
3581                         v = "ON";
3582                 else
3583                         v = "OFF";
3584         }
3585         else if (streq(b + 1, "RACE"))
3586         {
3587                 v = _(rp_ptr->E_title, rp_ptr->title);
3588         }
3589         else if (streq(b + 1, "CLASS"))
3590         {
3591                 v = _(cp_ptr->E_title, cp_ptr->title);
3592         }
3593         else if (streq(b + 1, "REALM1"))
3594         {
3595                 v = _(E_realm_names[player_ptr->realm1], realm_names[player_ptr->realm1]);
3596         }
3597         else if (streq(b + 1, "REALM2"))
3598         {
3599                 v = _(E_realm_names[player_ptr->realm2], realm_names[player_ptr->realm2]);
3600         }
3601         else if (streq(b + 1, "PLAYER"))
3602         {
3603                 static char tmp_player_name[32];
3604                 char *pn, *tpn;
3605                 for (pn = player_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
3606                 {
3607 #ifdef JP
3608                         if (iskanji(*pn))
3609                         {
3610                                 *(tpn++) = *(pn++);
3611                                 *tpn = *pn;
3612                                 continue;
3613                         }
3614 #endif
3615                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
3616                 }
3617
3618                 *tpn = '\0';
3619                 v = tmp_player_name;
3620         }
3621         else if (streq(b + 1, "TOWN"))
3622         {
3623                 sprintf(tmp, "%d", player_ptr->town_num);
3624                 v = tmp;
3625         }
3626         else if (streq(b + 1, "LEVEL"))
3627         {
3628                 sprintf(tmp, "%d", player_ptr->lev);
3629                 v = tmp;
3630         }
3631         else if (streq(b + 1, "QUEST_NUMBER"))
3632         {
3633                 sprintf(tmp, "%d", player_ptr->current_floor_ptr->inside_quest);
3634                 v = tmp;
3635         }
3636         else if (streq(b + 1, "LEAVING_QUEST"))
3637         {
3638                 sprintf(tmp, "%d", leaving_quest);
3639                 v = tmp;
3640         }
3641         else if (prefix(b + 1, "QUEST_TYPE"))
3642         {
3643                 sprintf(tmp, "%d", quest[atoi(b + 11)].type);
3644                 v = tmp;
3645         }
3646         else if (prefix(b + 1, "QUEST"))
3647         {
3648                 sprintf(tmp, "%d", quest[atoi(b + 6)].status);
3649                 v = tmp;
3650         }
3651         else if (prefix(b + 1, "RANDOM"))
3652         {
3653                 sprintf(tmp, "%d", (int)(current_world_ptr->seed_town%atoi(b + 7)));
3654                 v = tmp;
3655         }
3656         else if (streq(b + 1, "VARIANT"))
3657         {
3658                 v = variant;
3659         }
3660         else if (streq(b + 1, "WILDERNESS"))
3661         {
3662                 if (vanilla_town)
3663                         sprintf(tmp, "NONE");
3664                 else if (lite_town)
3665                         sprintf(tmp, "LITE");
3666                 else
3667                         sprintf(tmp, "NORMAL");
3668                 v = tmp;
3669         }
3670
3671         (*fp) = f;
3672         (*sp) = s;
3673         return v;
3674 }
3675
3676
3677 /*!
3678  * @brief クエスト用固定ダンジョン生成時のメインルーチン
3679  * Helper function for "process_dungeon_file()"
3680  * @param player_ptr プレーヤーへの参照ポインタ
3681  * @param name ファイル名
3682  * @param ymin 詳細不明
3683  * @param xmin 詳細不明
3684  * @param ymax 詳細不明
3685  * @param xmax 詳細不明
3686  * @return エラーコード
3687  */
3688 errr process_dungeon_file(player_type *player_ptr, concptr name, int ymin, int xmin, int ymax, int xmax)
3689 {
3690         char buf[1024];
3691         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3692         FILE *fp;
3693         fp = my_fopen(buf, "r");
3694
3695         if (!fp) return -1;
3696
3697         int num = -1;
3698         errr err = 0;
3699         bool bypass = FALSE;
3700         int x = xmin, y = ymin;
3701         while (my_fgets(fp, buf, sizeof(buf)) == 0)
3702         {
3703                 num++;
3704                 if (!buf[0]) continue;
3705                 if (iswspace(buf[0])) continue;
3706                 if (buf[0] == '#') continue;
3707                 if ((buf[0] == '?') && (buf[1] == ':'))
3708                 {
3709                         char f;
3710                         char *s;
3711                         s = buf + 2;
3712                         concptr v = process_dungeon_file_expr(player_ptr, &s, &f);
3713                         bypass = (streq(v, "0") ? TRUE : FALSE);
3714                         continue;
3715                 }
3716
3717                 if (bypass) continue;
3718
3719                 err = process_dungeon_file_aux(player_ptr, buf, ymin, xmin, ymax, xmax, &y, &x);
3720                 if (err) break;
3721         }
3722
3723         if (err != 0)
3724         {
3725                 concptr oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
3726                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
3727                 msg_format(_("'%s'を解析中。", "Parsing '%s'."), buf);
3728                 msg_print(NULL);
3729         }
3730
3731         my_fclose(fp);
3732         return err;
3733 }