OSDN Git Service

[refactor] 意図したswitch-case文のfall throughをコメント
[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 "gameterm.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         switch (num)
2812         {
2813         case 9:
2814                 letter[index].special = (s16b)atoi(zz[8]);
2815                 /* Fall through */
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                 /* Fall through */
2827         case 7:
2828                 if (zz[6][0] == '*')
2829                 {
2830                         letter[index].random |= RANDOM_ARTIFACT;
2831                         if (zz[6][1]) letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1);
2832                 }
2833                 else if (zz[6][0] == '!')
2834                 {
2835                         if (floor_ptr->inside_quest)
2836                         {
2837                                 letter[index].artifact = quest[floor_ptr->inside_quest].k_idx;
2838                         }
2839                 }
2840                 else
2841                 {
2842                         letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]);
2843                 }
2844                 /* Fall through */
2845         case 6:
2846                 if (zz[5][0] == '*')
2847                 {
2848                         letter[index].random |= RANDOM_EGO;
2849                         if (zz[5][1]) letter[index].ego = (EGO_IDX)atoi(zz[5] + 1);
2850                 }
2851                 else
2852                 {
2853                         letter[index].ego = (EGO_IDX)atoi(zz[5]);
2854                 }
2855                 /* Fall through */
2856         case 5:
2857                 if (zz[4][0] == '*')
2858                 {
2859                         letter[index].random |= RANDOM_OBJECT;
2860                         if (zz[4][1]) letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1);
2861                 }
2862                 else if (zz[4][0] == '!')
2863                 {
2864                         if (floor_ptr->inside_quest)
2865                         {
2866                                 ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx;
2867                                 if (a_idx)
2868                                 {
2869                                         artifact_type *a_ptr = &a_info[a_idx];
2870                                         if (!(a_ptr->gen_flags & TRG_INSTA_ART))
2871                                         {
2872                                                 letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
2873                                         }
2874                                 }
2875                         }
2876                 }
2877                 else
2878                 {
2879                         letter[index].object = (IDX)atoi(zz[4]);
2880                 }
2881                 /* Fall through */
2882         case 4:
2883                 if (zz[3][0] == '*')
2884                 {
2885                         letter[index].random |= RANDOM_MONSTER;
2886                         if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1);
2887                 }
2888                 else if (zz[3][0] == 'c')
2889                 {
2890                         if (!zz[3][1]) return PARSE_ERROR_GENERIC;
2891                         letter[index].monster = -atoi(zz[3] + 1);
2892                 }
2893                 else
2894                 {
2895                         letter[index].monster = (IDX)atoi(zz[3]);
2896                 }
2897                 /* Fall through */
2898         case 3:
2899                 letter[index].cave_info = atoi(zz[2]);
2900                 /* Fall through */
2901         case 2:
2902                 if ((zz[1][0] == '*') && !zz[1][1])
2903                 {
2904                         letter[index].random |= RANDOM_FEATURE;
2905                 }
2906                 else
2907                 {
2908                         letter[index].feature = f_tag_to_index(zz[1]);
2909                         if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
2910                 }
2911
2912                 break;
2913         }
2914
2915         return 0;
2916 }
2917
2918
2919 /*!
2920  * @brief 地形情報の「B:」情報をパースする
2921  * Process "B:<Index>:<Command>:..." -- Building definition
2922  * @param buf 解析文字列
2923  * @return エラーコード
2924  */
2925 static errr parse_line_building(char *buf)
2926 {
2927         char *zz[1000];
2928         char *s;
2929
2930 #ifdef JP
2931         if (buf[2] == '$')
2932                 return 0;
2933         s = buf + 2;
2934 #else
2935         if (buf[2] != '$')
2936                 return 0;
2937         s = buf + 3;
2938 #endif
2939         int index = atoi(s);
2940         s = my_strchr(s, ':');
2941         if (!s) return 1;
2942
2943         *s++ = '\0';
2944         if (!*s) return 1;
2945
2946         switch (s[0])
2947         {
2948         case 'N':
2949         {
2950                 if (tokenize(s + 2, 3, zz, 0) == 3)
2951                 {
2952                         strcpy(building[index].name, zz[0]);
2953                         strcpy(building[index].owner_name, zz[1]);
2954                         strcpy(building[index].owner_race, zz[2]);
2955                         break;
2956                 }
2957
2958                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
2959         }
2960         case 'A':
2961         {
2962                 if (tokenize(s + 2, 8, zz, 0) >= 7)
2963                 {
2964                         int action_index = atoi(zz[0]);
2965                         strcpy(building[index].act_names[action_index], zz[1]);
2966                         building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
2967                         building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
2968                         building[index].letters[action_index] = zz[4][0];
2969                         building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]);
2970                         building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]);
2971                         break;
2972                 }
2973
2974                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
2975         }
2976         case 'C':
2977         {
2978                 int n;
2979                 n = tokenize(s + 2, MAX_CLASS, zz, 0);
2980                 for (int i = 0; i < MAX_CLASS; i++)
2981                 {
2982                         building[index].member_class[i] = ((i < n) ? (CLASS_IDX)atoi(zz[i]) : 1);
2983                 }
2984
2985                 break;
2986         }
2987         case 'R':
2988         {
2989                 int n;
2990                 n = tokenize(s + 2, MAX_RACES, zz, 0);
2991                 for (int i = 0; i < MAX_RACES; i++)
2992                 {
2993                         building[index].member_race[i] = ((i < n) ? (RACE_IDX)atoi(zz[i]) : 1);
2994                 }
2995
2996                 break;
2997         }
2998         case 'M':
2999         {
3000                 int n;
3001                 n = tokenize(s + 2, MAX_MAGIC, zz, 0);
3002                 for (int i = 0; i < MAX_MAGIC; i++)
3003                 {
3004                         building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1);
3005                 }
3006
3007                 break;
3008         }
3009         case 'Z':
3010         {
3011                 break;
3012         }
3013         default:
3014         {
3015                 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3016         }
3017         }
3018
3019         return 0;
3020 }
3021
3022
3023 /*!
3024  * @brief フロアの所定のマスにオブジェクトを配置する
3025  * Place the object j_ptr to a grid
3026  * @param floor_ptr 現在フロアへの参照ポインタ
3027  * @param j_ptr オブジェクト構造体の参照ポインタ
3028  * @param y 配置先Y座標
3029  * @param x 配置先X座標
3030  * @return エラーコード
3031  */
3032 static void drop_here(floor_type *floor_ptr, object_type *j_ptr, POSITION y, POSITION x)
3033 {
3034         OBJECT_IDX o_idx = o_pop(floor_ptr);
3035         object_type *o_ptr;
3036         o_ptr = &floor_ptr->o_list[o_idx];
3037         object_copy(o_ptr, j_ptr);
3038         o_ptr->iy = y;
3039         o_ptr->ix = x;
3040         o_ptr->held_m_idx = 0;
3041         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
3042         o_ptr->next_o_idx = g_ptr->o_idx;
3043         g_ptr->o_idx = o_idx;
3044 }
3045
3046
3047 /*!
3048  * todo yminとymaxは本当に使われているのか?
3049  * @brief クエスト用固定ダンジョンをフロアに生成する
3050  * Parse a sub-file of the "extra info"
3051  * @param player_ptr プレーヤーへの参照ポインタ
3052  * @param buf 文字列
3053  * @param ymin 詳細不明
3054  * @param xmin 詳細不明
3055  * @param ymax 詳細不明
3056  * @param xmax 詳細不明
3057  * @param y 詳細不明
3058  * @param x 詳細不明
3059  * @return エラーコード
3060  */
3061 static errr process_dungeon_file_aux(player_type *player_ptr, char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3062 {
3063         char *zz[33];
3064
3065         if (!buf[0]) return 0;
3066         if (iswspace(buf[0])) return 0;
3067         if (buf[0] == '#') return 0;
3068         if (buf[1] != ':') return 1;
3069
3070         if (buf[0] == '%')
3071         {
3072                 return process_dungeon_file(player_ptr, buf + 2, ymin, xmin, ymax, xmax);
3073         }
3074
3075         floor_type *floor_ptr = player_ptr->current_floor_ptr;
3076         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3077         if (buf[0] == 'F')
3078         {
3079                 return parse_line_feature(player_ptr->current_floor_ptr, buf);
3080         }
3081         else if (buf[0] == 'D')
3082         {
3083                 object_type object_type_body;
3084                 char *s = buf + 2;
3085                 int len = strlen(s);
3086                 if (init_flags & INIT_ONLY_BUILDINGS) return 0;
3087
3088                 *x = xmin;
3089                 for (int i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3090                 {
3091                         grid_type *g_ptr = &floor_ptr->grid_array[*y][*x];
3092                         int idx = s[0];
3093                         OBJECT_IDX object_index = letter[idx].object;
3094                         MONSTER_IDX monster_index = letter[idx].monster;
3095                         int random = letter[idx].random;
3096                         ARTIFACT_IDX artifact_index = letter[idx].artifact;
3097                         g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].feature);
3098                         if (init_flags & INIT_ONLY_FEATURES) continue;
3099
3100                         g_ptr->info = letter[idx].cave_info;
3101                         if (random & RANDOM_MONSTER)
3102                         {
3103                                 floor_ptr->monster_level = floor_ptr->base_level + monster_index;
3104
3105                                 place_monster(player_ptr, *y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3106
3107                                 floor_ptr->monster_level = floor_ptr->base_level;
3108                         }
3109                         else if (monster_index)
3110                         {
3111                                 int old_cur_num, old_max_num;
3112                                 bool clone = FALSE;
3113
3114                                 if (monster_index < 0)
3115                                 {
3116                                         monster_index = -monster_index;
3117                                         clone = TRUE;
3118                                 }
3119
3120                                 old_cur_num = r_info[monster_index].cur_num;
3121                                 old_max_num = r_info[monster_index].max_num;
3122
3123                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3124                                 {
3125                                         r_info[monster_index].cur_num = 0;
3126                                         r_info[monster_index].max_num = 1;
3127                                 }
3128                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3129                                 {
3130                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3131                                         {
3132                                                 r_info[monster_index].max_num++;
3133                                         }
3134                                 }
3135
3136                                 place_monster_aux(player_ptr, 0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3137                                 if (clone)
3138                                 {
3139                                         floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
3140                                         r_info[monster_index].cur_num = old_cur_num;
3141                                         r_info[monster_index].max_num = old_max_num;
3142                                 }
3143                         }
3144
3145                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3146                         {
3147                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3148
3149                                 /*
3150                                  * Random trap and random treasure defined
3151                                  * 25% chance for trap and 75% chance for object
3152                                  */
3153                                 if (randint0(100) < 75)
3154                                 {
3155                                         place_object(player_ptr, *y, *x, 0L);
3156                                 }
3157                                 else
3158                                 {
3159                                         place_trap(player_ptr, *y, *x);
3160                                 }
3161
3162                                 floor_ptr->object_level = floor_ptr->base_level;
3163                         }
3164                         else if (random & RANDOM_OBJECT)
3165                         {
3166                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3167                                 if (randint0(100) < 75)
3168                                         place_object(player_ptr, *y, *x, 0L);
3169                                 else if (randint0(100) < 80)
3170                                         place_object(player_ptr, *y, *x, AM_GOOD);
3171                                 else
3172                                         place_object(player_ptr, *y, *x, AM_GOOD | AM_GREAT);
3173
3174                                 floor_ptr->object_level = floor_ptr->base_level;
3175                         }
3176                         else if (random & RANDOM_TRAP)
3177                         {
3178                                 place_trap(player_ptr, *y, *x);
3179                         }
3180                         else if (letter[idx].trap)
3181                         {
3182                                 g_ptr->mimic = g_ptr->feat;
3183                                 g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].trap);
3184                         }
3185                         else if (object_index)
3186                         {
3187                                 object_type *o_ptr = &object_type_body;
3188                                 object_prep(o_ptr, object_index);
3189                                 if (o_ptr->tval == TV_GOLD)
3190                                 {
3191                                         coin_type = object_index - OBJ_GOLD_LIST;
3192                                         make_gold(floor_ptr, o_ptr);
3193                                         coin_type = 0;
3194                                 }
3195
3196                                 apply_magic(player_ptr, o_ptr, floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
3197                                 drop_here(floor_ptr, o_ptr, *y, *x);
3198                         }
3199
3200                         if (artifact_index)
3201                         {
3202                                 if (a_info[artifact_index].cur_num)
3203                                 {
3204                                         KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
3205                                         object_type forge;
3206                                         object_type *q_ptr = &forge;
3207
3208                                         object_prep(q_ptr, k_idx);
3209                                         drop_here(floor_ptr, q_ptr, *y, *x);
3210                                 }
3211                                 else
3212                                 {
3213                                         if (create_named_art(player_ptr, artifact_index, *y, *x))
3214                                                 a_info[artifact_index].cur_num = 1;
3215                                 }
3216                         }
3217
3218                         g_ptr->special = letter[idx].special;
3219                 }
3220
3221                 (*y)++;
3222                 return 0;
3223         }
3224         else if (buf[0] == 'Q')
3225         {
3226                 int num;
3227                 quest_type *q_ptr;
3228 #ifdef JP
3229                 if (buf[2] == '$')
3230                         return 0;
3231                 num = tokenize(buf + 2, 33, zz, 0);
3232 #else
3233                 if (buf[2] != '$')
3234                         return 0;
3235                 num = tokenize(buf + 3, 33, zz, 0);
3236 #endif
3237
3238                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3239
3240                 q_ptr = &(quest[atoi(zz[0])]);
3241                 if (zz[1][0] == 'Q')
3242                 {
3243                         if (init_flags & INIT_ASSIGN)
3244                         {
3245                                 monster_race *r_ptr;
3246                                 artifact_type *a_ptr;
3247
3248                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3249
3250                                 q_ptr->type = (QUEST_TYPE)atoi(zz[2]);
3251                                 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
3252                                 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
3253                                 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
3254                                 q_ptr->level = (DEPTH)atoi(zz[6]);
3255                                 q_ptr->r_idx = (IDX)atoi(zz[7]);
3256                                 q_ptr->k_idx = (IDX)atoi(zz[8]);
3257                                 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
3258
3259                                 if (num > 10) q_ptr->flags = atoi(zz[10]);
3260
3261                                 r_ptr = &r_info[q_ptr->r_idx];
3262                                 if (r_ptr->flags1 & RF1_UNIQUE)
3263                                         r_ptr->flags1 |= RF1_QUESTOR;
3264
3265                                 a_ptr = &a_info[q_ptr->k_idx];
3266                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3267                         }
3268
3269                         return 0;
3270                 }
3271                 else if (zz[1][0] == 'R')
3272                 {
3273                         if (init_flags & INIT_ASSIGN)
3274                         {
3275                                 int count = 0;
3276                                 IDX idx, reward_idx = 0;
3277
3278                                 for (idx = 2; idx < num; idx++)
3279                                 {
3280                                         IDX a_idx = (IDX)atoi(zz[idx]);
3281                                         if (a_idx < 1) continue;
3282                                         if (a_info[a_idx].cur_num > 0) continue;
3283                                         count++;
3284                                         if (one_in_(count)) reward_idx = a_idx;
3285                                 }
3286
3287                                 if (reward_idx)
3288                                 {
3289                                         q_ptr->k_idx = reward_idx;
3290                                         a_info[reward_idx].gen_flags |= TRG_QUESTITEM;
3291                                 }
3292                                 else
3293                                 {
3294                                         q_ptr->type = QUEST_TYPE_KILL_ALL;
3295                                 }
3296                         }
3297
3298                         return 0;
3299                 }
3300                 else if (zz[1][0] == 'N')
3301                 {
3302                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY))
3303                         {
3304                                 strcpy(q_ptr->name, zz[2]);
3305                         }
3306
3307                         return 0;
3308                 }
3309                 else if (zz[1][0] == 'T')
3310                 {
3311                         if (init_flags & INIT_SHOW_TEXT)
3312                         {
3313                                 strcpy(quest_text[quest_text_line], zz[2]);
3314                                 quest_text_line++;
3315                         }
3316
3317                         return 0;
3318                 }
3319         }
3320         else if (buf[0] == 'W')
3321         {
3322                 return parse_line_wilderness(player_ptr, buf, xmin, xmax, y, x);
3323         }
3324         else if (buf[0] == 'P')
3325         {
3326                 if (init_flags & INIT_CREATE_DUNGEON)
3327                 {
3328                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3329                         {
3330                                 int panels_x, panels_y;
3331
3332                                 panels_y = (*y / SCREEN_HGT);
3333                                 if (*y % SCREEN_HGT) panels_y++;
3334                                 floor_ptr->height = panels_y * SCREEN_HGT;
3335
3336                                 panels_x = (*x / SCREEN_WID);
3337                                 if (*x % SCREEN_WID) panels_x++;
3338                                 floor_ptr->width = panels_x * SCREEN_WID;
3339
3340                                 panel_row_min = floor_ptr->height;
3341                                 panel_col_min = floor_ptr->width;
3342
3343                                 if (floor_ptr->inside_quest)
3344                                 {
3345                                         delete_monster(player_ptr, player_ptr->y, player_ptr->x);
3346
3347                                         POSITION py = atoi(zz[0]);
3348                                         POSITION px = atoi(zz[1]);
3349
3350                                         player_ptr->y = py;
3351                                         player_ptr->x = px;
3352                                 }
3353                                 else if (!player_ptr->oldpx && !player_ptr->oldpy)
3354                                 {
3355                                         player_ptr->oldpy = atoi(zz[0]);
3356                                         player_ptr->oldpx = atoi(zz[1]);
3357                                 }
3358                         }
3359                 }
3360
3361                 return 0;
3362         }
3363         else if (buf[0] == 'B')
3364         {
3365                 return parse_line_building(buf);
3366         }
3367         else if (buf[0] == 'M')
3368         {
3369                 if (tokenize(buf + 2, 2, zz, 0) == 2)
3370                 {
3371                         if (zz[0][0] == 'T')
3372                         {
3373                                 max_towns = (TOWN_IDX)atoi(zz[1]);
3374                         }
3375                         else if (zz[0][0] == 'Q')
3376                         {
3377                                 max_q_idx = (QUEST_IDX)atoi(zz[1]);
3378                         }
3379                         else if (zz[0][0] == 'R')
3380                         {
3381                                 max_r_idx = (RACE_IDX)atoi(zz[1]);
3382                         }
3383                         else if (zz[0][0] == 'K')
3384                         {
3385                                 max_k_idx = (KIND_OBJECT_IDX)atoi(zz[1]);
3386                         }
3387                         else if (zz[0][0] == 'V')
3388                         {
3389                                 max_v_idx = (VAULT_IDX)atoi(zz[1]);
3390                         }
3391                         else if (zz[0][0] == 'F')
3392                         {
3393                                 max_f_idx = (FEAT_IDX)atoi(zz[1]);
3394                         }
3395                         else if (zz[0][0] == 'A')
3396                         {
3397                                 max_a_idx = (ARTIFACT_IDX)atoi(zz[1]);
3398                         }
3399                         else if (zz[0][0] == 'E')
3400                         {
3401                                 max_e_idx = (EGO_IDX)atoi(zz[1]);
3402                         }
3403                         else if (zz[0][0] == 'D')
3404                         {
3405                                 current_world_ptr->max_d_idx = (DUNGEON_IDX)atoi(zz[1]);
3406                         }
3407                         else if (zz[0][0] == 'O')
3408                         {
3409                                 current_world_ptr->max_o_idx = (OBJECT_IDX)atoi(zz[1]);
3410                         }
3411                         else if (zz[0][0] == 'M')
3412                         {
3413                                 current_world_ptr->max_m_idx = (MONSTER_IDX)atoi(zz[1]);
3414                         }
3415                         else if (zz[0][0] == 'W')
3416                         {
3417                                 if (zz[0][1] == 'X')
3418                                         current_world_ptr->max_wild_x = (POSITION)atoi(zz[1]);
3419
3420                                 if (zz[0][1] == 'Y')
3421                                         current_world_ptr->max_wild_y = (POSITION)atoi(zz[1]);
3422                         }
3423
3424                         return 0;
3425                 }
3426         }
3427
3428         return 1;
3429 }
3430
3431 /*
3432 * todo ここから先頭に移すとコンパイル警告が出る……
3433 */
3434 static char tmp[8];
3435 static concptr variant = "ZANGBAND";
3436
3437 /*!
3438  * @brief クエスト用固定ダンジョン生成時の分岐処理
3439  * Helper function for "process_dungeon_file()"
3440  * @param player_ptr プレーヤーへの参照ポインタ
3441  * @param sp
3442  * @param fp
3443  * @return エラーコード
3444  */
3445 static concptr process_dungeon_file_expr(player_type *player_ptr, char **sp, char *fp)
3446 {
3447         char b1 = '[';
3448         char b2 = ']';
3449
3450         char f = ' ';
3451
3452         char *s;
3453         s = (*sp);
3454
3455         while (iswspace(*s)) s++;
3456
3457         char *b;
3458         b = s;
3459         concptr v = "?o?o?";
3460         if (*s == b1)
3461         {
3462                 concptr p;
3463                 concptr t;
3464                 s++;
3465                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3466                 if (!*t)
3467                 {
3468                         /* Nothing */
3469                 }
3470                 else if (streq(t, "IOR"))
3471                 {
3472                         v = "0";
3473                         while (*s && (f != b2))
3474                         {
3475                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3476                                 if (*t && !streq(t, "0")) v = "1";
3477                         }
3478                 }
3479                 else if (streq(t, "AND"))
3480                 {
3481                         v = "1";
3482                         while (*s && (f != b2))
3483                         {
3484                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3485                                 if (*t && streq(t, "0")) v = "0";
3486                         }
3487                 }
3488                 else if (streq(t, "NOT"))
3489                 {
3490                         v = "1";
3491                         while (*s && (f != b2))
3492                         {
3493                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3494                                 if (*t && streq(t, "1")) v = "0";
3495                         }
3496                 }
3497                 else if (streq(t, "EQU"))
3498                 {
3499                         v = "0";
3500                         if (*s && (f != b2))
3501                         {
3502                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3503                         }
3504
3505                         while (*s && (f != b2))
3506                         {
3507                                 p = process_dungeon_file_expr(player_ptr, &s, &f);
3508                                 if (streq(t, p)) v = "1";
3509                         }
3510                 }
3511                 else if (streq(t, "LEQ"))
3512                 {
3513                         v = "1";
3514                         if (*s && (f != b2))
3515                         {
3516                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3517                         }
3518
3519                         while (*s && (f != b2))
3520                         {
3521                                 p = t;
3522                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3523                                 if (*t && atoi(p) > atoi(t)) v = "0";
3524                         }
3525                 }
3526                 else if (streq(t, "GEQ"))
3527                 {
3528                         v = "1";
3529                         if (*s && (f != b2))
3530                         {
3531                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3532                         }
3533
3534                         while (*s && (f != b2))
3535                         {
3536                                 p = t;
3537                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3538                                 if (*t && atoi(p) < atoi(t)) v = "0";
3539                         }
3540                 }
3541                 else
3542                 {
3543                         while (*s && (f != b2))
3544                         {
3545                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
3546                         }
3547                 }
3548
3549                 if (f != b2) v = "?x?x?";
3550                 if ((f = *s) != '\0') *s++ = '\0';
3551
3552                 (*fp) = f;
3553                 (*sp) = s;
3554                 return v;
3555         }
3556
3557 #ifdef JP
3558         while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
3559         {
3560                 if (iskanji(*s)) s++;
3561                 s++;
3562         }
3563 #else
3564         while (isprint(*s) && !my_strchr(" []", *s)) ++s;
3565 #endif
3566         if ((f = *s) != '\0') *s++ = '\0';
3567
3568         if (*b != '$')
3569         {
3570                 v = b;
3571                 (*fp) = f;
3572                 (*sp) = s;
3573                 return v;
3574         }
3575
3576         if (streq(b + 1, "SYS"))
3577         {
3578                 v = ANGBAND_SYS;
3579         }
3580         else if (streq(b + 1, "GRAF"))
3581         {
3582                 v = ANGBAND_GRAF;
3583         }
3584         else if (streq(b + 1, "MONOCHROME"))
3585         {
3586                 if (arg_monochrome)
3587                         v = "ON";
3588                 else
3589                         v = "OFF";
3590         }
3591         else if (streq(b + 1, "RACE"))
3592         {
3593                 v = _(rp_ptr->E_title, rp_ptr->title);
3594         }
3595         else if (streq(b + 1, "CLASS"))
3596         {
3597                 v = _(cp_ptr->E_title, cp_ptr->title);
3598         }
3599         else if (streq(b + 1, "REALM1"))
3600         {
3601                 v = _(E_realm_names[player_ptr->realm1], realm_names[player_ptr->realm1]);
3602         }
3603         else if (streq(b + 1, "REALM2"))
3604         {
3605                 v = _(E_realm_names[player_ptr->realm2], realm_names[player_ptr->realm2]);
3606         }
3607         else if (streq(b + 1, "PLAYER"))
3608         {
3609                 static char tmp_player_name[32];
3610                 char *pn, *tpn;
3611                 for (pn = player_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
3612                 {
3613 #ifdef JP
3614                         if (iskanji(*pn))
3615                         {
3616                                 *(tpn++) = *(pn++);
3617                                 *tpn = *pn;
3618                                 continue;
3619                         }
3620 #endif
3621                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
3622                 }
3623
3624                 *tpn = '\0';
3625                 v = tmp_player_name;
3626         }
3627         else if (streq(b + 1, "TOWN"))
3628         {
3629                 sprintf(tmp, "%d", player_ptr->town_num);
3630                 v = tmp;
3631         }
3632         else if (streq(b + 1, "LEVEL"))
3633         {
3634                 sprintf(tmp, "%d", player_ptr->lev);
3635                 v = tmp;
3636         }
3637         else if (streq(b + 1, "QUEST_NUMBER"))
3638         {
3639                 sprintf(tmp, "%d", player_ptr->current_floor_ptr->inside_quest);
3640                 v = tmp;
3641         }
3642         else if (streq(b + 1, "LEAVING_QUEST"))
3643         {
3644                 sprintf(tmp, "%d", leaving_quest);
3645                 v = tmp;
3646         }
3647         else if (prefix(b + 1, "QUEST_TYPE"))
3648         {
3649                 sprintf(tmp, "%d", quest[atoi(b + 11)].type);
3650                 v = tmp;
3651         }
3652         else if (prefix(b + 1, "QUEST"))
3653         {
3654                 sprintf(tmp, "%d", quest[atoi(b + 6)].status);
3655                 v = tmp;
3656         }
3657         else if (prefix(b + 1, "RANDOM"))
3658         {
3659                 sprintf(tmp, "%d", (int)(current_world_ptr->seed_town%atoi(b + 7)));
3660                 v = tmp;
3661         }
3662         else if (streq(b + 1, "VARIANT"))
3663         {
3664                 v = variant;
3665         }
3666         else if (streq(b + 1, "WILDERNESS"))
3667         {
3668                 if (vanilla_town)
3669                         sprintf(tmp, "NONE");
3670                 else if (lite_town)
3671                         sprintf(tmp, "LITE");
3672                 else
3673                         sprintf(tmp, "NORMAL");
3674                 v = tmp;
3675         }
3676
3677         (*fp) = f;
3678         (*sp) = s;
3679         return v;
3680 }
3681
3682
3683 /*!
3684  * @brief クエスト用固定ダンジョン生成時のメインルーチン
3685  * Helper function for "process_dungeon_file()"
3686  * @param player_ptr プレーヤーへの参照ポインタ
3687  * @param name ファイル名
3688  * @param ymin 詳細不明
3689  * @param xmin 詳細不明
3690  * @param ymax 詳細不明
3691  * @param xmax 詳細不明
3692  * @return エラーコード
3693  */
3694 errr process_dungeon_file(player_type *player_ptr, concptr name, int ymin, int xmin, int ymax, int xmax)
3695 {
3696         char buf[1024];
3697         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3698         FILE *fp;
3699         fp = my_fopen(buf, "r");
3700
3701         if (!fp) return -1;
3702
3703         int num = -1;
3704         errr err = 0;
3705         bool bypass = FALSE;
3706         int x = xmin, y = ymin;
3707         while (my_fgets(fp, buf, sizeof(buf)) == 0)
3708         {
3709                 num++;
3710                 if (!buf[0]) continue;
3711                 if (iswspace(buf[0])) continue;
3712                 if (buf[0] == '#') continue;
3713                 if ((buf[0] == '?') && (buf[1] == ':'))
3714                 {
3715                         char f;
3716                         char *s;
3717                         s = buf + 2;
3718                         concptr v = process_dungeon_file_expr(player_ptr, &s, &f);
3719                         bypass = (streq(v, "0") ? TRUE : FALSE);
3720                         continue;
3721                 }
3722
3723                 if (bypass) continue;
3724
3725                 err = process_dungeon_file_aux(player_ptr, buf, ymin, xmin, ymax, xmax, &y, &x);
3726                 if (err) break;
3727         }
3728
3729         if (err != 0)
3730         {
3731                 concptr oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
3732                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
3733                 msg_format(_("'%s'を解析中。", "Parsing '%s'."), buf);
3734                 msg_print(NULL);
3735         }
3736
3737         my_fclose(fp);
3738         return err;
3739 }