OSDN Git Service

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