OSDN Git Service

[Refactor] #37353 player-skill.c/h を追加。
[hengband/hengband.git] / src / dungeon-file.c
1 
2 #include "angband.h"
3 #include "util.h"
4
5 #include "dungeon-file.h"
6 #include "feature.h"
7 #include "grid.h"
8 #include "quest.h"
9 #include "monster.h"
10 #include "files.h"
11 #include "player-skill.h"
12
13 dungeon_grid letter[255];
14
15 /*!
16  * @file init1.c
17  * @brief ゲームデータ初期化1 / Initialization (part 1) -BEN-
18  * @date 2014/01/28
19  * @author
20  * <pre>
21  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
22  * This software may be copied and distributed for educational, research,
23  * and not for profit purposes provided that this copyright and statement
24  * are included in all such copies.  Other copyrights may also apply.
25  * 2014 Deskull rearranged comment for Doxygen.\n
26  * </pre>
27  * @details
28  * <pre>
29  * This file is used to initialize various variables and arrays for the
30  * Angband game.  Note the use of "fd_read()" and "fd_write()" to bypass
31  * the common limitation of "read()" and "write()" to only 32767 bytes
32  * at a time.
33  * Several of the arrays for Angband are built from "template" files in
34  * the "lib/file" directory, from which quick-load binary "image" files
35  * are constructed whenever they are not present in the "lib/data"
36  * directory, or if those files become obsolete, if we are allowed.
37  * Warning -- the "ascii" file parsers use a minor hack to collect the
38  * name and text information in a single pass.  Thus, the game will not
39  * be able to load any template file with more than 20K of names or 60K
40  * of text, even though technically, up to 64K should be legal.
41  *
42  * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
43  * in this file is compiled out, and the game will not run unless valid
44  * "binary template files" already exist in "lib/data".  Thus, one can
45  * compile Angband with ALLOW_TEMPLATES defined, run once to create the
46  * "*.raw" files in "lib/data", and then quit, and recompile without
47  * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
48  * from changing the ascii template files in potentially dangerous ways.
49  * ノートとして記録:ALLOW_TEMPLATESが定義されていない場合、
50  * このファイルのコードの多くはコンパイル出力され、本ゲームは
51  * 正規の「バイナリテンプレートファイル」がlib/dataファイル内に
52  * 存在しない限り起動しなくなる。一方ALLOW_TEMPLATESが定義されている
53  * ならば1度ゲームが起動するごとに*.rawファイル群が作成され、終了時には
54  * ALLOW_TEMPLATEの定義に関係なくリコンパイルされる。これにより20K(バイト?)
55  * のデータが保存され、プレイヤーが潜在的に危険な方法でascii文字の
56  * テンプレートファイルを変更することを妨げることができる。
57  * The code could actually be removed and placed into a "stand-alone"
58  * program, but that feels a little silly, especially considering some
59  * of the platforms that we currently support.
60  * </pre>
61  */
62
63 #include "angband.h"
64 #include "dungeon-file.h"
65 #include "trap.h"
66 #include "grid.h"
67 #include "monster.h"
68 #include "artifact.h"
69 #include "cmd-activate.h"
70 #include "term.h"
71 #include "wild.h"
72 #include "quest.h"
73 #include "view-mainwindow.h"
74
75
76
77 #ifdef ALLOW_TEMPLATES
78
79 #include "init.h"
80
81
82  /*** Helper arrays for parsing ascii template files ***/
83
84  /*!
85   * モンスターの打撃手段トークンの定義 /
86   * Monster Blow Methods
87   */
88 static concptr r_info_blow_method[] =
89 {
90         "",
91         "HIT",
92         "TOUCH",
93         "PUNCH",
94         "KICK",
95         "CLAW",
96         "BITE",
97         "STING",
98         "SLASH",
99         "BUTT",
100         "CRUSH",
101         "ENGULF",
102         "CHARGE",
103         "CRAWL",
104         "DROOL",
105         "SPIT",
106         "EXPLODE",
107         "GAZE",
108         "WAIL",
109         "SPORE",
110         "XXX4",
111         "BEG",
112         "INSULT",
113         "MOAN",
114         "SHOW",
115         "SHOOT",
116         NULL
117 };
118
119
120 /*!
121  * モンスターの打撃属性トークンの定義 /
122  * Monster Blow Effects
123  */
124 static concptr r_info_blow_effect[] =
125 {
126         "",
127         "HURT",
128         "POISON",
129         "UN_BONUS",
130         "UN_POWER",
131         "EAT_GOLD",
132         "EAT_ITEM",
133         "EAT_FOOD",
134         "EAT_LITE",
135         "ACID",
136         "ELEC",
137         "FIRE",
138         "COLD",
139         "BLIND",
140         "CONFUSE",
141         "TERRIFY",
142         "PARALYZE",
143         "LOSE_STR",
144         "LOSE_INT",
145         "LOSE_WIS",
146         "LOSE_DEX",
147         "LOSE_CON",
148         "LOSE_CHR",
149         "LOSE_ALL",
150         "SHATTER",
151         "EXP_10",
152         "EXP_20",
153         "EXP_40",
154         "EXP_80",
155         "DISEASE",
156         "TIME",
157         "EXP_VAMP",
158         "DR_MANA",
159         "SUPERHURT",
160         "INERTIA",
161         "STUN",
162         NULL
163 };
164
165 /*!
166  * 地形属性トークンの定義 /
167  * Feature info flags
168  */
169 static concptr f_info_flags[] =
170 {
171         "LOS",
172         "PROJECT",
173         "MOVE",
174         "PLACE",
175         "DROP",
176         "SECRET",
177         "NOTICE",
178         "REMEMBER",
179         "OPEN",
180         "CLOSE",
181         "BASH",
182         "SPIKE",
183         "DISARM",
184         "STORE",
185         "TUNNEL",
186         "MAY_HAVE_GOLD",
187         "HAS_GOLD",
188         "HAS_ITEM",
189         "DOOR",
190         "TRAP",
191         "STAIRS",
192         "GLYPH",
193         "LESS",
194         "MORE",
195         "AVOID_RUN",
196         "FLOOR",
197         "WALL",
198         "PERMANENT",
199         "XXX00",
200         "XXX01",
201         "XXX02",
202         "HIT_TRAP",
203
204         "BRIDGE",
205         "RIVER",
206         "LAKE",
207         "BRIDGED",
208         "COVERED",
209         "GLOW",
210         "ENSECRET",
211         "WATER",
212         "LAVA",
213         "SHALLOW",
214         "DEEP",
215         "POISON_PUDDLE",
216         "HURT_ROCK",
217         "HURT_FIRE",
218         "HURT_COLD",
219         "HURT_ACID",
220         "COLD_PUDDLE",
221         "ACID_PUDDLE",
222         "OIL",
223         "ELEC_PUDDLE",
224         "CAN_CLIMB",
225         "CAN_FLY",
226         "CAN_SWIM",
227         "CAN_PASS",
228         "CAN_OOZE",
229         "CAN_DIG",
230         "HIDE_ITEM",
231         "HIDE_SNEAK",
232         "HIDE_SWIM",
233         "HIDE_DIG",
234         "KILL_HUGE",
235         "KILL_MOVE",
236
237         "PICK_TRAP",
238         "PICK_DOOR",
239         "ALLOC",
240         "CHEST",
241         "DROP_1D2",
242         "DROP_2D2",
243         "DROP_GOOD",
244         "DROP_GREAT",
245         "HURT_POIS",
246         "HURT_ELEC",
247         "HURT_WATER",
248         "HURT_BWATER",
249         "USE_FEAT",
250         "GET_FEAT",
251         "GROUND",
252         "OUTSIDE",
253         "EASY_HIDE",
254         "EASY_CLIMB",
255         "MUST_CLIMB",
256         "TREE",
257         "NEED_TREE",
258         "BLOOD",
259         "DUST",
260         "SLIME",
261         "PLANT",
262         "XXX2",
263         "INSTANT",
264         "EXPLODE",
265         "TIMED",
266         "ERUPT",
267         "STRIKE",
268         "SPREAD",
269
270         "SPECIAL",
271         "HURT_DISI",
272         "QUEST_ENTER",
273         "QUEST_EXIT",
274         "QUEST",
275         "SHAFT",
276         "MOUNTAIN",
277         "BLDG",
278         "MINOR_GLYPH",
279         "PATTERN",
280         "TOWN",
281         "ENTRANCE",
282         "MIRROR",
283         "UNPERM",
284         "TELEPORTABLE",
285         "CONVERT",
286         "GLASS",
287 };
288
289
290 /*!
291  * モンスター特性トークンの定義1 /
292  * Monster race flags
293  */
294 static concptr r_info_flags1[] =
295 {
296         "UNIQUE",
297         "QUESTOR",
298         "MALE",
299         "FEMALE",
300         "CHAR_CLEAR",
301         "SHAPECHANGER",
302         "ATTR_CLEAR",
303         "ATTR_MULTI",
304         "FORCE_DEPTH",
305         "FORCE_MAXHP",
306         "FORCE_SLEEP",
307         "FORCE_EXTRA",
308         "ATTR_SEMIRAND",
309         "FRIENDS",
310         "ESCORT",
311         "ESCORTS",
312         "NEVER_BLOW",
313         "NEVER_MOVE",
314         "RAND_25",
315         "RAND_50",
316         "ONLY_GOLD",
317         "ONLY_ITEM",
318         "DROP_60",
319         "DROP_90",
320         "DROP_1D2",
321         "DROP_2D2",
322         "DROP_3D2",
323         "DROP_4D2",
324         "DROP_GOOD",
325         "DROP_GREAT",
326         "XXX2",
327         "XXX3"
328 };
329
330 /*!
331  * モンスター特性トークンの定義2 /
332  * Monster race flags
333  */
334 static concptr r_info_flags2[] =
335 {
336         "STUPID",
337         "SMART",
338         "CAN_SPEAK",
339         "REFLECTING",
340         "INVISIBLE",
341         "COLD_BLOOD",
342         "EMPTY_MIND",
343         "WEIRD_MIND",
344         "MULTIPLY",
345         "REGENERATE",
346         "CHAR_MULTI",
347         "ATTR_ANY",
348         "POWERFUL",
349         "ELDRITCH_HORROR",
350         "AURA_FIRE",
351         "AURA_ELEC",
352         "OPEN_DOOR",
353         "BASH_DOOR",
354         "PASS_WALL",
355         "KILL_WALL",
356         "MOVE_BODY",
357         "KILL_BODY",
358         "TAKE_ITEM",
359         "KILL_ITEM",
360         "XXX",
361         "XXX",
362         "XXX",
363         "XXX",
364         "XXX",
365         "XXX",
366         "HUMAN",
367         "QUANTUM"
368 };
369
370 /*!
371  * モンスター特性トークンの定義3 /
372  * Monster race flags
373  */
374 static concptr r_info_flags3[] =
375 {
376         "ORC",
377         "TROLL",
378         "GIANT",
379         "DRAGON",
380         "DEMON",
381         "UNDEAD",
382         "EVIL",
383         "ANIMAL",
384         "AMBERITE",
385         "GOOD",
386         "AURA_COLD",
387         "NONLIVING",
388         "HURT_LITE",
389         "HURT_ROCK",
390         "HURT_FIRE",
391         "HURT_COLD",
392         "ANGEL",
393         "XXX",
394         "XXX",
395         "XXX",
396         "XXX",
397         "XXX",
398         "XXX",
399         "XXX",
400         "XXX",
401         "XXX",
402         "XXX",
403         "XXX",
404         "NO_FEAR",
405         "NO_STUN",
406         "NO_CONF",
407         "NO_SLEEP"
408 };
409
410 /*!
411  * モンスター特性トークンの定義4 /
412  * Monster race flags
413  */
414 static concptr r_info_flags4[] =
415 {
416         "SHRIEK",
417         "XXX1",
418         "DISPEL",
419         "ROCKET",
420         "SHOOT",
421         "XXX2",
422         "XXX3",
423         "XXX4",
424         "BR_ACID",
425         "BR_ELEC",
426         "BR_FIRE",
427         "BR_COLD",
428         "BR_POIS",
429         "BR_NETH",
430         "BR_LITE",
431         "BR_DARK",
432         "BR_CONF",
433         "BR_SOUN",
434         "BR_CHAO",
435         "BR_DISE",
436         "BR_NEXU",
437         "BR_TIME",
438         "BR_INER",
439         "BR_GRAV",
440         "BR_SHAR",
441         "BR_PLAS",
442         "BR_WALL",
443         "BR_MANA",
444         "BA_NUKE",
445         "BR_NUKE",
446         "BA_CHAO",
447         "BR_DISI",
448 };
449
450 /*!
451  * モンスター特性トークン(発動型能力1) /
452  * Monster race flags
453  */
454 static concptr r_a_ability_flags1[] =
455 {
456         "BA_ACID",
457         "BA_ELEC",
458         "BA_FIRE",
459         "BA_COLD",
460         "BA_POIS",
461         "BA_NETH",
462         "BA_WATE",
463         "BA_MANA",
464         "BA_DARK",
465         "DRAIN_MANA",
466         "MIND_BLAST",
467         "BRAIN_SMASH",
468         "CAUSE_1",
469         "CAUSE_2",
470         "CAUSE_3",
471         "CAUSE_4",
472         "BO_ACID",
473         "BO_ELEC",
474         "BO_FIRE",
475         "BO_COLD",
476         "BA_LITE",
477         "BO_NETH",
478         "BO_WATE",
479         "BO_MANA",
480         "BO_PLAS",
481         "BO_ICEE",
482         "MISSILE",
483         "SCARE",
484         "BLIND",
485         "CONF",
486         "SLOW",
487         "HOLD"
488 };
489
490 /*!
491  * モンスター特性トークン(発動型能力2) /
492  * Monster race flags
493  */
494 static concptr r_a_ability_flags2[] =
495 {
496         "HASTE",
497         "HAND_DOOM",
498         "HEAL",
499         "INVULNER",
500         "BLINK",
501         "TPORT",
502         "WORLD",
503         "SPECIAL",
504         "TELE_TO",
505         "TELE_AWAY",
506         "TELE_LEVEL",
507         "PSY_SPEAR",
508         "DARKNESS",
509         "TRAPS",
510         "FORGET",
511         "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
512         "S_KIN",
513         "S_CYBER",
514         "S_MONSTER",
515         "S_MONSTERS",
516         "S_ANT",
517         "S_SPIDER",
518         "S_HOUND",
519         "S_HYDRA",
520         "S_ANGEL",
521         "S_DEMON",
522         "S_UNDEAD",
523         "S_DRAGON",
524         "S_HI_UNDEAD",
525         "S_HI_DRAGON",
526         "S_AMBERITES",
527         "S_UNIQUE"
528 };
529
530 #if 0
531 /*!
532  * モンスター特性トークン(発動型能力3) /
533  * Monster race flags
534  */
535 static concptr r_a_ability_flags3[] =
536 {
537         "XXXA3X00",
538         "XXXA3X01",
539         "XXXA3X02",
540         "XXXA3X03",
541         "XXXA3X04",
542         "XXXA3X05",
543         "XXXA3X06",
544         "XXXA3X07",
545         "XXXA3X08",
546         "XXXA3X09",
547         "XXXA3X10",
548         "XXXA3X11",
549         "XXXA3X12",
550         "XXXA3X13",
551         "XXXA3X14",
552         "XXXA3X15",
553         "XXXA3X16",
554         "XXXA3X17",
555         "XXXA3X18",
556         "XXXA3X19",
557         "XXXA3X20",
558         "XXXA3X21",
559         "XXXA3X22",
560         "XXXA3X23",
561         "XXXA3X24",
562         "XXXA3X25",
563         "XXXA3X26",
564         "XXXA3X27",
565         "XXXA3X28",
566         "XXXA3X29",
567         "XXXA3X30",
568         "XXXA3X31",
569 };
570 #endif
571
572 #if 0
573 /*!
574  * モンスター特性トークン(発動型能力4) /
575  * Monster race flags
576  */
577 static concptr r_a_ability_flags4[] =
578 {
579         "XXXA4X00",
580         "XXXA4X01",
581         "XXXA4X02",
582         "XXXA4X03",
583         "XXXA4X04",
584         "XXXA4X05",
585         "XXXA4X06",
586         "XXXA4X07",
587         "XXXA4X08",
588         "XXXA4X09",
589         "XXXA4X10",
590         "XXXA4X11",
591         "XXXA4X12",
592         "XXXA4X13",
593         "XXXA4X14",
594         "XXXA4X15",
595         "XXXA4X16",
596         "XXXA4X17",
597         "XXXA4X18",
598         "XXXA4X19",
599         "XXXA4X20",
600         "XXXA4X21",
601         "XXXA4X22",
602         "XXXA4X23",
603         "XXXA4X24",
604         "XXXA4X25",
605         "XXXA4X26",
606         "XXXA4X27",
607         "XXXA4X28",
608         "XXXA4X29",
609         "XXXA4X30",
610         "XXXA4X31",
611 };
612 #endif
613
614
615 /*!
616  * モンスター特性トークンの定義7 /
617  * Monster race flags
618  */
619 static concptr r_info_flags7[] =
620 {
621         "AQUATIC",
622         "CAN_SWIM",
623         "CAN_FLY",
624         "FRIENDLY",
625         "NAZGUL",
626         "UNIQUE2",
627         "RIDING",
628         "KAGE",
629         "HAS_LITE_1",
630         "SELF_LITE_1",
631         "HAS_LITE_2",
632         "SELF_LITE_2",
633         "GUARDIAN",
634         "CHAMELEON",
635         "XXXX4XXX",
636         "TANUKI",
637         "HAS_DARK_1",
638         "SELF_DARK_1",
639         "HAS_DARK_2",
640         "SELF_DARK_2",
641         "XXX7X20",
642         "XXX7X21",
643         "XXX7X22",
644         "XXX7X23",
645         "XXX7X24",
646         "XXX7X25",
647         "XXX7X26",
648         "XXX7X27",
649         "XXX7X28",
650         "XXX7X29",
651         "XXX7X30",
652         "XXX7X31",
653 };
654
655 /*!
656  * モンスター特性トークンの定義8 /
657  * Monster race flags
658  */
659 static concptr r_info_flags8[] =
660 {
661         "WILD_ONLY",
662         "WILD_TOWN",
663         "XXX8X02",
664         "WILD_SHORE",
665         "WILD_OCEAN",
666         "WILD_WASTE",
667         "WILD_WOOD",
668         "WILD_VOLCANO",
669         "XXX8X08",
670         "WILD_MOUNTAIN",
671         "WILD_GRASS",
672         "XXX8X11",
673         "XXX8X12",
674         "XXX8X13",
675         "XXX8X14",
676         "XXX8X15",
677         "XXX8X16",
678         "XXX8X17",
679         "XXX8X18",
680         "XXX8X19",
681         "XXX8X20",
682         "XXX8X21",
683         "XXX8X22",
684         "XXX8X23",
685         "XXX8X24",
686         "XXX8X25",
687         "XXX8X26",
688         "XXX8X27",
689         "XXX8X28",
690         "XXX8X29",
691         "WILD_SWAMP",   /* ToDo: Implement Swamp */
692         "WILD_ALL",
693 };
694
695
696 /*!
697  * モンスター特性トークンの定義9 /
698  * Monster race flags
699  */
700 static concptr r_info_flags9[] =
701 {
702         "DROP_CORPSE",
703         "DROP_SKELETON",
704         "EAT_BLIND",
705         "EAT_CONF",
706         "EAT_MANA",
707         "EAT_NEXUS",
708         "EAT_BLINK",
709         "EAT_SLEEP",
710         "EAT_BERSERKER",
711         "EAT_ACIDIC",
712         "EAT_SPEED",
713         "EAT_CURE",
714         "EAT_FIRE_RES",
715         "EAT_COLD_RES",
716         "EAT_ACID_RES",
717         "EAT_ELEC_RES",
718         "EAT_POIS_RES",
719         "EAT_INSANITY",
720         "EAT_DRAIN_EXP",
721         "EAT_POISONOUS",
722         "EAT_GIVE_STR",
723         "EAT_GIVE_INT",
724         "EAT_GIVE_WIS",
725         "EAT_GIVE_DEX",
726         "EAT_GIVE_CON",
727         "EAT_GIVE_CHR",
728         "EAT_LOSE_STR",
729         "EAT_LOSE_INT",
730         "EAT_LOSE_WIS",
731         "EAT_LOSE_DEX",
732         "EAT_LOSE_CON",
733         "EAT_LOSE_CHR",
734         "EAT_DRAIN_MANA",
735 };
736
737
738 /*!
739  * モンスター特性トークンの定義R(耐性) /
740  * Monster race flags
741  */
742 static concptr r_info_flagsr[] =
743 {
744         "IM_ACID",
745         "IM_ELEC",
746         "IM_FIRE",
747         "IM_COLD",
748         "IM_POIS",
749         "RES_LITE",
750         "RES_DARK",
751         "RES_NETH",
752         "RES_WATE",
753         "RES_PLAS",
754         "RES_SHAR",
755         "RES_SOUN",
756         "RES_CHAO",
757         "RES_NEXU",
758         "RES_DISE",
759         "RES_WALL",
760         "RES_INER",
761         "RES_TIME",
762         "RES_GRAV",
763         "RES_ALL",
764         "RES_TELE",
765         "XXX",
766         "XXX",
767         "XXX",
768         "XXX",
769         "XXX",
770         "XXX",
771         "XXX",
772         "XXX",
773         "XXX",
774         "XXX",
775         "XXX",
776 };
777
778
779 /*!
780  * オブジェクト基本特性トークンの定義 /
781  * Object flags
782  */
783 static concptr k_info_flags[] =
784 {
785         "STR",
786         "INT",
787         "WIS",
788         "DEX",
789         "CON",
790         "CHR",
791         "MAGIC_MASTERY",
792         "FORCE_WEAPON",
793         "STEALTH",
794         "SEARCH",
795         "INFRA",
796         "TUNNEL",
797         "SPEED",
798         "BLOWS",
799         "CHAOTIC",
800         "VAMPIRIC",
801         "SLAY_ANIMAL",
802         "SLAY_EVIL",
803         "SLAY_UNDEAD",
804         "SLAY_DEMON",
805         "SLAY_ORC",
806         "SLAY_TROLL",
807         "SLAY_GIANT",
808         "SLAY_DRAGON",
809         "KILL_DRAGON",
810         "VORPAL",
811         "IMPACT",
812         "BRAND_POIS",
813         "BRAND_ACID",
814         "BRAND_ELEC",
815         "BRAND_FIRE",
816         "BRAND_COLD",
817
818         "SUST_STR",
819         "SUST_INT",
820         "SUST_WIS",
821         "SUST_DEX",
822         "SUST_CON",
823         "SUST_CHR",
824         "RIDING",
825         "EASY_SPELL",
826         "IM_ACID",
827         "IM_ELEC",
828         "IM_FIRE",
829         "IM_COLD",
830         "THROW",
831         "REFLECT",
832         "FREE_ACT",
833         "HOLD_EXP",
834         "RES_ACID",
835         "RES_ELEC",
836         "RES_FIRE",
837         "RES_COLD",
838         "RES_POIS",
839         "RES_FEAR",
840         "RES_LITE",
841         "RES_DARK",
842         "RES_BLIND",
843         "RES_CONF",
844         "RES_SOUND",
845         "RES_SHARDS",
846         "RES_NETHER",
847         "RES_NEXUS",
848         "RES_CHAOS",
849         "RES_DISEN",
850
851         "SH_FIRE",
852         "SH_ELEC",
853         "SLAY_HUMAN",
854         "SH_COLD",
855         "NO_TELE",
856         "NO_MAGIC",
857         "DEC_MANA",
858         "TY_CURSE",
859         "WARNING",
860         "HIDE_TYPE",
861         "SHOW_MODS",
862         "SLAY_GOOD",
863         "LEVITATION",
864         "LITE",
865         "SEE_INVIS",
866         "TELEPATHY",
867         "SLOW_DIGEST",
868         "REGEN",
869         "XTRA_MIGHT",
870         "XTRA_SHOTS",
871         "IGNORE_ACID",
872         "IGNORE_ELEC",
873         "IGNORE_FIRE",
874         "IGNORE_COLD",
875         "ACTIVATE",
876         "DRAIN_EXP",
877         "TELEPORT",
878         "AGGRAVATE",
879         "BLESSED",
880         "XXX3", /* Fake flag for Smith */
881         "XXX4", /* Fake flag for Smith */
882         "KILL_GOOD",
883
884         "KILL_ANIMAL",
885         "KILL_EVIL",
886         "KILL_UNDEAD",
887         "KILL_DEMON",
888         "KILL_ORC",
889         "KILL_TROLL",
890         "KILL_GIANT",
891         "KILL_HUMAN",
892         "ESP_ANIMAL",
893         "ESP_UNDEAD",
894         "ESP_DEMON",
895         "ESP_ORC",
896         "ESP_TROLL",
897         "ESP_GIANT",
898         "ESP_DRAGON",
899         "ESP_HUMAN",
900         "ESP_EVIL",
901         "ESP_GOOD",
902         "ESP_NONLIVING",
903         "ESP_UNIQUE",
904         "FULL_NAME",
905         "FIXED_FLAVOR",
906         "ADD_L_CURSE",
907         "ADD_H_CURSE",
908         "DRAIN_HP",
909         "DRAIN_MANA",
910
911         "LITE_2",
912         "LITE_3",
913         "LITE_M1",
914         "LITE_M2",
915         "LITE_M3",
916         "LITE_FUEL",
917
918         "CALL_ANIMAL",
919         "CALL_DEMON",
920         "CALL_DRAGON",
921         "CALL_UNDEAD",
922         "COWARDICE",
923         "LOW_MELEE",
924         "LOW_AC",
925         "LOW_MAGIC",
926         "FAST_DIGEST",
927         "SLOW_REGEN",
928 };
929
930 /*!
931  * オブジェクト生成特性トークンの定義 /
932  * Object flags
933  */
934 static concptr k_info_gen_flags[] =
935 {
936         "INSTA_ART",
937         "QUESTITEM",
938         "XTRA_POWER",
939         "ONE_SUSTAIN",
940         "XTRA_RES_OR_POWER",
941         "XTRA_H_RES",
942         "XTRA_E_RES",
943         "XTRA_L_RES",
944         "XTRA_D_RES",
945         "XTRA_RES",
946         "CURSED",
947         "HEAVY_CURSE",
948         "PERMA_CURSE",
949         "RANDOM_CURSE0",
950         "RANDOM_CURSE1",
951         "RANDOM_CURSE2",
952         "XTRA_DICE",
953         "POWERFUL",
954         "XXX",
955         "XXX",
956         "XXX",
957         "XXX",
958         "XXX",
959         "XXX",
960         "XXX",
961         "XXX",
962         "XXX",
963         "XXX",
964         "XXX",
965         "XXX",
966         "XXX",
967         "XXX",
968 };
969
970 /*!
971  * ダンジョン特性トークンの定義 /
972  * Dungeon flags
973  */
974 static concptr d_info_flags1[] =
975 {
976         "WINNER",
977         "MAZE",
978         "SMALLEST",
979         "BEGINNER",
980         "BIG",
981         "NO_DOORS",
982         "WATER_RIVER",
983         "LAVA_RIVER",
984         "CURTAIN",
985         "GLASS_DOOR",
986         "CAVE",
987         "CAVERN",
988         "ARCADE",
989         "LAKE_ACID",
990         "LAKE_POISONOUS",
991         "XXX",
992         "FORGET",
993         "LAKE_WATER",
994         "LAKE_LAVA",
995         "LAKE_RUBBLE",
996         "LAKE_TREE",
997         "NO_VAULT",
998         "ARENA",
999         "DESTROY",
1000         "GLASS_ROOM",
1001         "NO_CAVE",
1002         "NO_MAGIC",
1003         "NO_MELEE",
1004         "CHAMELEON",
1005         "DARKNESS",
1006         "ACID_RIVER",
1007         "POISONOUS_RIVER"
1008 };
1009
1010
1011 /*!
1012  * @brief データの可変文字列情報をテキストとして保管する /
1013  * Add a text to the text-storage and store offset to it.
1014  * @param offset 文字列保管ポインタからのオフセット
1015  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
1016  * @param buf 保管文字列
1017  * @param normal_text テキストの正規化を行う
1018  * @return
1019  * 無事保管ができたらTRUEを返す。
1020  * Returns FALSE when there isn't enough space available to store
1021  * the text.
1022  */
1023 static bool add_text(u32b *offset, header *head, concptr buf, bool normal_text)
1024 {
1025         /* Hack -- Verify space */
1026         if (head->text_size + strlen(buf) + 8 > FAKE_TEXT_SIZE)
1027                 return (FALSE);
1028
1029         /* New text? */
1030         if (*offset == 0)
1031         {
1032                 /* Advance and save the text index */
1033                 *offset = ++head->text_size;
1034         }
1035
1036         /* Additional text */
1037         else if (normal_text)
1038         {
1039                 /*
1040                  * If neither the end of the last line nor
1041                  * the beginning of current line is not a space,
1042                  * fill up a space as a correct separator of two words.
1043                  */
1044                 if (head->text_size > 0 &&
1045 #ifdef JP
1046                 (*(head->text_ptr + head->text_size - 1) != ' ') &&
1047                         ((head->text_size == 1) || !iskanji(*(head->text_ptr + head->text_size - 2))) &&
1048                         (buf[0] != ' ') && !iskanji(buf[0])
1049 #else
1050                         (*(head->text_ptr + head->text_size - 1) != ' ') &&
1051                         (buf[0] != ' ')
1052 #endif
1053                         )
1054                 {
1055                         /* Append a space */
1056                         *(head->text_ptr + head->text_size) = ' ';
1057
1058                         /* Advance the index */
1059                         head->text_size++;
1060                 }
1061         }
1062
1063         /* Append chars to the text */
1064         strcpy(head->text_ptr + head->text_size, buf);
1065
1066         /* Advance the index */
1067         head->text_size += strlen(buf);
1068
1069         /* Success */
1070         return (TRUE);
1071 }
1072
1073
1074 /*!
1075  * @brief データの可変文字列情報を名前として保管する /
1076  * Add a name to the name-storage and return an offset to it.
1077  * @param offset 文字列保管ポインタからのオフセット
1078  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
1079  * @param buf 保管文字列
1080  * @return
1081  * 無事保管ができたらTRUEを返す。
1082  * Returns FALSE when there isn't enough space available to store
1083  * the text.
1084  */
1085 static bool add_name(u32b *offset, header *head, concptr buf)
1086 {
1087         /* Hack -- Verify space */
1088         if (head->name_size + strlen(buf) + 8 > FAKE_NAME_SIZE)
1089                 return (FALSE);
1090
1091         /* New name? */
1092         if (*offset == 0)
1093         {
1094                 /* Advance and save the name index */
1095                 *offset = ++head->name_size;
1096         }
1097
1098         /* Append chars to the names */
1099         strcpy(head->name_ptr + head->name_size, buf);
1100
1101         /* Advance the index */
1102         head->name_size += strlen(buf);
1103
1104         /* Success */
1105         return (TRUE);
1106 }
1107
1108
1109 /*!
1110  * @brief データの可変文字列情報をタグとして保管する /
1111  * Add a tag to the tag-storage and return an offset to it.
1112  * @param offset 文字列保管ポインタからのオフセット
1113  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
1114  * @param buf 保管文字列
1115  * @return
1116  * 無事保管ができたらTRUEを返す。
1117  * Returns FALSE when there isn't enough space available to store
1118  * the text.
1119  */
1120 static bool add_tag(STR_OFFSET *offset, header *head, concptr buf)
1121 {
1122         u32b i;
1123
1124         /* Search for an existing (fake) tag */
1125         for (i = 1; i < head->tag_size; i += strlen(&head->tag_ptr[i]) + 1)
1126         {
1127                 /* Found it */
1128                 if (streq(&head->tag_ptr[i], buf)) break;
1129         }
1130
1131         /* There was no existing tag */
1132         if (i >= head->tag_size)
1133         {
1134                 /* Hack -- Verify space */
1135                 if (head->tag_size + strlen(buf) + 8 > FAKE_TAG_SIZE)
1136                         return FALSE;
1137
1138                 /* Append chars to the tags */
1139                 strcpy(head->tag_ptr + head->tag_size, buf);
1140
1141                 /* Point the new tag */
1142                 i = head->tag_size;
1143
1144                 /* Advance the index */
1145                 head->tag_size += strlen(buf) + 1;
1146         }
1147
1148         /* Return offset of the tag */
1149         *offset = (s16b)i;
1150
1151         /* Success */
1152         return TRUE;
1153 }
1154
1155
1156 /*** Initialize from ascii template files ***/
1157
1158
1159 /*!
1160  * @brief パース関数に基づいてデータファイルからデータを読み取る /
1161  * Initialize an "*_info" array, by parsing an ascii "template" file
1162  * @param fp 読み取りに使うファイルポインタ
1163  * @param buf 読み取りに使うバッファ領域
1164  * @param head ヘッダ構造体
1165  * @param parse_info_txt_line パース関数
1166  * @return エラーコード
1167  */
1168 errr init_info_txt(FILE *fp, char *buf, header *head, parse_info_txt_func parse_info_txt_line)
1169 {
1170         errr err;
1171
1172         /* Just before the first record */
1173         error_idx = -1;
1174
1175         /* Just before the first line */
1176         error_line = 0;
1177
1178
1179         /* Prepare the "fake" stuff */
1180         head->name_size = 0;
1181         head->text_size = 0;
1182         head->tag_size = 0;
1183
1184         /* Parse */
1185         while (0 == my_fgets(fp, buf, 1024))
1186         {
1187                 /* Advance the line number */
1188                 error_line++;
1189
1190                 /* Skip comments and blank lines */
1191                 if (!buf[0] || (buf[0] == '#')) continue;
1192
1193                 /* Verify correct "colon" format */
1194                 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
1195
1196
1197                 /* Hack -- Process 'V' for "Version" */
1198                 if (buf[0] == 'V')
1199                 {
1200                         /* ignore */
1201                         continue;
1202                 }
1203
1204                 /* Mega Hack -- Calculate Check Sum */
1205                 if (buf[0] != 'N' && buf[0] != 'D')
1206                 {
1207                         int i;
1208                         for (i = 0; buf[i]; i++)
1209                         {
1210                                 head->v_extra += (byte)buf[i];
1211                                 head->v_extra ^= (1 << (i % 8));
1212                         }
1213                 }
1214
1215                 /* Parse the line */
1216                 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
1217                         return (err);
1218         }
1219
1220
1221         /* Complete the "name" and "text" sizes */
1222         if (head->name_size) head->name_size++;
1223         if (head->text_size) head->text_size++;
1224
1225         /* Success */
1226         return (0);
1227 }
1228
1229
1230 /*!
1231  * @brief Vault情報(v_info)のパース関数 /
1232  * Initialize the "v_info" array, by parsing an ascii "template" file
1233  * @param buf テキスト列
1234  * @param head ヘッダ構造体
1235  * @return エラーコード
1236  */
1237 errr parse_v_info(char *buf, header *head)
1238 {
1239         int i;
1240         char *s;
1241
1242         /* Current entry */
1243         static vault_type *v_ptr = NULL;
1244
1245         /* Process 'N' for "New/Number/Name" */
1246         if (buf[0] == 'N')
1247         {
1248                 /* Find the colon before the name */
1249                 s = my_strchr(buf + 2, ':');
1250
1251                 /* Verify that colon */
1252                 if (!s) return (1);
1253
1254                 /* Nuke the colon, advance to the name */
1255                 *s++ = '\0';
1256
1257                 /* Paranoia -- require a name */
1258                 if (!*s) return (1);
1259
1260                 /* Get the index */
1261                 i = atoi(buf + 2);
1262
1263                 /* Verify information */
1264                 if (i <= error_idx) return (4);
1265
1266                 /* Verify information */
1267                 if (i >= head->info_num) return (2);
1268
1269                 /* Save the index */
1270                 error_idx = i;
1271
1272                 /* Point at the "info" */
1273                 v_ptr = &v_info[i];
1274
1275                 /* Store the name */
1276                 if (!add_name(&v_ptr->name, head, s)) return (7);
1277         }
1278
1279         /* There better be a current v_ptr */
1280         else if (!v_ptr) return (3);
1281
1282         /* Process 'D' for "Description" */
1283         else if (buf[0] == 'D')
1284         {
1285                 /* Acquire the text */
1286                 s = buf + 2;
1287
1288                 /* Store the text */
1289                 if (!add_text(&v_ptr->text, head, s, FALSE)) return (7);
1290         }
1291
1292         /* Process 'X' for "Extra info" (one line only) */
1293         else if (buf[0] == 'X')
1294         {
1295                 EFFECT_ID typ, rat, hgt, wid;
1296
1297                 /* Scan for the values */
1298                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1299                         &typ, &rat, &hgt, &wid)) return (1);
1300
1301                 /* Save the values */
1302                 v_ptr->typ = (ROOM_IDX)typ;
1303                 v_ptr->rat = (PROB)rat;
1304                 v_ptr->hgt = (POSITION)hgt;
1305                 v_ptr->wid = (POSITION)wid;
1306         }
1307
1308         else    return (6);
1309
1310         /* Success */
1311         return (0);
1312 }
1313
1314
1315 /*!
1316  * @brief 職業技能情報(s_info)のパース関数 /
1317  * Initialize the "s_info" array, by parsing an ascii "template" file
1318  * @param buf テキスト列
1319  * @param head ヘッダ構造体
1320  * @return エラーコード
1321  */
1322 errr parse_s_info(char *buf, header *head)
1323 {
1324         int i;
1325
1326         /* Current entry */
1327         static skill_table *s_ptr = NULL;
1328
1329
1330         /* Process 'N' for "New/Number/Name" */
1331         if (buf[0] == 'N')
1332         {
1333                 /* Get the index */
1334                 i = atoi(buf + 2);
1335
1336                 /* Verify information */
1337                 if (i <= error_idx) return (4);
1338
1339                 /* Verify information */
1340                 if (i >= head->info_num) return (2);
1341
1342                 /* Save the index */
1343                 error_idx = i;
1344
1345                 /* Point at the "info" */
1346                 s_ptr = &s_info[i];
1347         }
1348
1349         /* There better be a current s_ptr */
1350         else if (!s_ptr) return (3);
1351
1352         /* Process 'W' for "Weapon exp" */
1353         else if (buf[0] == 'W')
1354         {
1355                 int tval, sval, start, max;
1356                 const s16b exp_conv_table[] =
1357                 {
1358                         WEAPON_EXP_UNSKILLED, WEAPON_EXP_BEGINNER, WEAPON_EXP_SKILLED,
1359                         WEAPON_EXP_EXPERT, WEAPON_EXP_MASTER
1360                 };
1361
1362                 /* Scan for the values */
1363                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1364                         &tval, &sval, &start, &max)) return (1);
1365
1366                 if (start < EXP_LEVEL_UNSKILLED || start > EXP_LEVEL_MASTER
1367                         || max < EXP_LEVEL_UNSKILLED || max > EXP_LEVEL_MASTER) return (8);
1368
1369                 /* Save the values */
1370                 s_ptr->w_start[tval][sval] = exp_conv_table[start];
1371                 s_ptr->w_max[tval][sval] = exp_conv_table[max];
1372         }
1373
1374         /* Process 'S' for "Skill exp" */
1375         else if (buf[0] == 'S')
1376         {
1377                 int num, start, max;
1378
1379                 /* Scan for the values */
1380                 if (3 != sscanf(buf + 2, "%d:%d:%d",
1381                         &num, &start, &max)) return (1);
1382
1383                 if (start < WEAPON_EXP_UNSKILLED || start > WEAPON_EXP_MASTER
1384                         || max < WEAPON_EXP_UNSKILLED || max > WEAPON_EXP_MASTER) return (8);
1385
1386                 /* Save the values */
1387                 s_ptr->s_start[num] = (SUB_EXP)start;
1388                 s_ptr->s_max[num] = (SUB_EXP)max;
1389         }
1390
1391
1392         else return (6);
1393
1394         /* Success */
1395         return (0);
1396 }
1397
1398
1399 /*!
1400  * @brief 職業魔法情報(m_info)のパース関数 /
1401  * Initialize the "m_info" array, by parsing an ascii "template" file
1402  * @param buf テキスト列
1403  * @param head ヘッダ構造体
1404  * @return エラーコード
1405  */
1406 errr parse_m_info(char *buf, header *head)
1407 {
1408         int i;
1409
1410         char *s;
1411
1412         /* Current entry */
1413         static player_magic *m_ptr = NULL;
1414
1415         /* ---Hack--- */
1416         static int realm, magic_idx = 0, readable = 0;
1417
1418
1419         /* Process 'N' for "New/Number/Name" */
1420         if (buf[0] == 'N')
1421         {
1422                 /* Get the index */
1423                 i = atoi(buf + 2);
1424
1425                 /* Verify information */
1426                 if (i <= error_idx) return (4);
1427
1428                 /* Verify information */
1429                 if (i >= head->info_num) return (2);
1430
1431                 /* Save the index */
1432                 error_idx = i;
1433
1434                 /* Point at the "info" */
1435                 m_ptr = &m_info[i];
1436         }
1437
1438         /* There better be a current m_ptr */
1439         else if (!m_ptr) return (3);
1440
1441         /* Process 'I' for "Info" (one line only) */
1442         else if (buf[0] == 'I')
1443         {
1444                 char *book, *stat;
1445                 int xtra, type, first, weight;
1446
1447                 /* Find the colon before the name */
1448                 s = my_strchr(buf + 2, ':');
1449
1450                 /* Verify that colon */
1451                 if (!s) return (1);
1452
1453                 /* Nuke the colon, advance to the name */
1454                 *s++ = '\0';
1455
1456                 book = buf + 2;
1457
1458                 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1459                 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1460                 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1461                 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1462                 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1463                 else return (5);
1464
1465                 stat = s;
1466
1467                 /* Find the colon before the name */
1468                 s = my_strchr(s, ':');
1469
1470                 /* Verify that colon */
1471                 if (!s) return (1);
1472
1473                 /* Nuke the colon, advance to the name */
1474                 *s++ = '\0';
1475
1476                 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1477                 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1478                 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1479                 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1480                 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1481                 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1482                 else return (5);
1483
1484
1485                 /* Scan for the values */
1486                 if (4 != sscanf(s, "%x:%d:%d:%d",
1487                         (uint *)&xtra, &type, &first, &weight)) return (1);
1488
1489                 m_ptr->spell_xtra = xtra;
1490                 m_ptr->spell_type = type;
1491                 m_ptr->spell_first = first;
1492                 m_ptr->spell_weight = weight;
1493         }
1494
1495
1496         /* Process 'R' for "Realm" (one line only) */
1497         else if (buf[0] == 'R')
1498         {
1499                 /* Scan for the values */
1500                 if (2 != sscanf(buf + 2, "%d:%d",
1501                         &realm, &readable)) return (1);
1502
1503                 magic_idx = 0;
1504         }
1505
1506         else if (buf[0] == 'T')
1507         {
1508                 int level, mana, fail, exp;
1509
1510                 if (!readable) return (1);
1511                 /* Scan for the values */
1512                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1513                         &level, &mana, &fail, &exp)) return (1);
1514
1515                 m_ptr->info[realm][magic_idx].slevel = (PLAYER_LEVEL)level;
1516                 m_ptr->info[realm][magic_idx].smana = (MANA_POINT)mana;
1517                 m_ptr->info[realm][magic_idx].sfail = (PERCENTAGE)fail;
1518                 m_ptr->info[realm][magic_idx].sexp = (EXP)exp;
1519                 magic_idx++;
1520         }
1521
1522
1523         else return (6);
1524
1525         /* Success */
1526         return (0);
1527 }
1528
1529
1530 /*!
1531  * @brief テキストトークンを走査してフラグを一つ得る(汎用) /
1532  * Grab one flag from a textual string
1533  * @param flags ビットフラグを追加する先の参照ポインタ
1534  * @param names トークン定義配列
1535  * @param what 参照元の文字列ポインタ
1536  * @return エラーコード
1537  */
1538 static errr grab_one_flag(u32b *flags, concptr names[], concptr what)
1539 {
1540         int i;
1541
1542         /* Check flags */
1543         for (i = 0; i < 32; i++)
1544         {
1545                 if (streq(what, names[i]))
1546                 {
1547                         *flags |= (1L << i);
1548                         return 0;
1549                 }
1550         }
1551
1552         return -1;
1553 }
1554
1555
1556 /*!
1557  * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
1558  * Grab one flag in an feature_type from a textual string
1559  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1560  * @param what 参照元の文字列ポインタ
1561  * @return エラーコード
1562  */
1563 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
1564 {
1565         int i;
1566
1567         /* Check flags */
1568         for (i = 0; i < FF_FLAG_MAX; i++)
1569         {
1570                 if (streq(what, f_info_flags[i]))
1571                 {
1572                         add_flag(f_ptr->flags, i);
1573                         return 0;
1574                 }
1575         }
1576
1577         msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
1578
1579         /* Error */
1580         return PARSE_ERROR_GENERIC;
1581 }
1582
1583
1584 /*!
1585  * @brief テキストトークンを走査してフラグ(ステート)を一つ得る(地形情報向け2) /
1586  * Grab an action in an feature_type from a textual string
1587  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1588  * @param what 参照元の文字列ポインタ
1589  * @param count ステートの保存先ID
1590  * @return エラーコード
1591  */
1592 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
1593 {
1594         FF_FLAGS_IDX i;
1595
1596         /* Check flags */
1597         for (i = 0; i < FF_FLAG_MAX; i++)
1598         {
1599                 if (streq(what, f_info_flags[i]))
1600                 {
1601                         f_ptr->state[count].action = i;
1602                         return 0;
1603                 }
1604         }
1605
1606         msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
1607
1608         /* Error */
1609         return PARSE_ERROR_GENERIC;
1610 }
1611
1612
1613 /*!
1614  * @brief 地形情報(f_info)のパース関数 /
1615  * Initialize the "f_info" array, by parsing an ascii "template" file
1616  * @param buf テキスト列
1617  * @param head ヘッダ構造体
1618  * @return エラーコード
1619  */
1620 errr parse_f_info(char *buf, header *head)
1621 {
1622         int i;
1623
1624         char *s, *t;
1625
1626         /* Current entry */
1627         static feature_type *f_ptr = NULL;
1628
1629
1630         /* Process 'N' for "New/Number/Name" */
1631         if (buf[0] == 'N')
1632         {
1633                 /* Find the colon before the name */
1634                 s = my_strchr(buf + 2, ':');
1635
1636                 if (s)
1637                 {
1638                         /* Nuke the colon, advance to the name */
1639                         *s++ = '\0';
1640                 }
1641
1642                 /* Get the index */
1643                 i = atoi(buf + 2);
1644
1645                 /* Verify information */
1646                 if (i <= error_idx) return (4);
1647
1648                 /* Verify information */
1649                 if (i >= head->info_num) return (2);
1650
1651                 /* Save the index */
1652                 error_idx = i;
1653
1654                 /* Point at the "info" */
1655                 f_ptr = &f_info[i];
1656
1657                 /* Tag name is given */
1658                 if (s)
1659                 {
1660                         /* Store the tag */
1661                         if (!add_tag(&f_ptr->tag, head, s)) return (7);
1662                 }
1663
1664                 /* Default "mimic" */
1665                 f_ptr->mimic = (FEAT_IDX)i;
1666
1667                 /* Default "destroyed state" -- if not specified */
1668                 f_ptr->destroyed = (FEAT_IDX)i;
1669
1670                 /* Default "states" */
1671                 for (i = 0; i < MAX_FEAT_STATES; i++) f_ptr->state[i].action = FF_FLAG_MAX;
1672         }
1673
1674         /* There better be a current f_ptr */
1675         else if (!f_ptr) return (3);
1676
1677 #ifdef JP
1678         else if (buf[0] == 'J')
1679         {
1680                 /* Store the name */
1681                 if (!add_name(&f_ptr->name, head, buf + 2)) return (7);
1682         }
1683
1684         else if (buf[0] == 'E')
1685         {
1686                 /* Ignore english name */
1687         }
1688 #else
1689         else if (buf[0] == 'J')
1690         {
1691                 /* Ignore Japanese name */
1692         }
1693
1694         else if (buf[0] == 'E')
1695         {
1696                 /* Acquire the Text */
1697                 s = buf + 2;
1698
1699                 /* Store the name */
1700                 if (!add_name(&f_ptr->name, head, s)) return (7);
1701         }
1702 #endif
1703
1704
1705         /* Process 'M' for "Mimic" (one line only) */
1706         else if (buf[0] == 'M')
1707         {
1708                 STR_OFFSET offset;
1709
1710                 if (!add_tag(&offset, head, buf + 2)) return PARSE_ERROR_OUT_OF_MEMORY;
1711
1712                 /* Record a fake tag index */
1713                 f_ptr->mimic_tag = offset;
1714         }
1715
1716
1717         /* Process 'G' for "Graphics" (one line only) */
1718         else if (buf[0] == 'G')
1719         {
1720                 int j;
1721                 byte s_attr;
1722                 char char_tmp[F_LIT_MAX];
1723                 if (buf[1] != ':') return (1);
1724                 if (!buf[2]) return (1);
1725                 if (buf[3] != ':') return (1);
1726                 if (!buf[4]) return (1);
1727
1728                 /* Extract the char */
1729                 char_tmp[F_LIT_STANDARD] = buf[2];
1730
1731                 /* Extract the color */
1732                 s_attr = color_char_to_attr(buf[4]);
1733                 if (s_attr > 127) return (1);
1734
1735                 /* Save the standard values */
1736                 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
1737                 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
1738
1739                 /* Is this feature supports lighting? */
1740                 if (buf[5] == ':')
1741                 {
1742                         /* G:c:a:LIT (default) */
1743                         apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
1744
1745                         /* G:c:a:lc:la:dc:da */
1746                         if (!streq(buf + 6, "LIT"))
1747                         {
1748                                 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
1749
1750                                 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
1751                                         &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
1752                                         &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
1753                                 if (buf[F_LIT_MAX * 4 + 1]) return 1;
1754
1755                                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1756                                 {
1757                                         switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
1758                                         {
1759                                         case '*':
1760                                                 /* Use default lighting */
1761                                                 break;
1762                                         case '-':
1763                                                 /* No lighting support */
1764                                                 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
1765                                                 break;
1766                                         default:
1767                                                 /* Extract the color */
1768                                                 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
1769                                                 if (f_ptr->d_attr[j] > 127) return 1;
1770                                                 break;
1771                                         }
1772                                         f_ptr->d_char[j] = char_tmp[j];
1773                                 }
1774                         }
1775                 }
1776                 else if (!buf[5])
1777                 {
1778                         for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1779                         {
1780                                 f_ptr->d_attr[j] = s_attr;
1781                                 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
1782                         }
1783                 }
1784                 else return 1;
1785         }
1786
1787         /* Hack -- Process 'F' for flags */
1788         else if (buf[0] == 'F')
1789         {
1790                 /* Parse every entry textually */
1791                 for (s = buf + 2; *s; )
1792                 {
1793                         /* Find the end of this entry */
1794                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1795
1796                         /* Nuke and skip any dividers */
1797                         if (*t)
1798                         {
1799                                 *t++ = '\0';
1800                                 while (*t == ' ' || *t == '|') t++;
1801                         }
1802
1803                         /* Hack -- Read feature subtype */
1804                         if (1 == sscanf(s, "SUBTYPE_%d", &i))
1805                         {
1806                                 /* Extract a "subtype" */
1807                                 f_ptr->subtype = (FEAT_SUBTYPE)i;
1808
1809                                 /* Start at next entry */
1810                                 s = t;
1811
1812                                 continue;
1813                         }
1814
1815                         /* Hack -- Read feature power */
1816                         if (1 == sscanf(s, "POWER_%d", &i))
1817                         {
1818                                 /* Extract a "power" */
1819                                 f_ptr->power = (FEAT_POWER)i;
1820
1821                                 /* Start at next entry */
1822                                 s = t;
1823                                 continue;
1824                         }
1825
1826                         /* Parse this entry */
1827                         if (0 != grab_one_feat_flag(f_ptr, s)) return (PARSE_ERROR_INVALID_FLAG);
1828
1829                         /* Start the next entry */
1830                         s = t;
1831                 }
1832         }
1833
1834         /* Process 'W' for "More Info" (one line only) */
1835         else if (buf[0] == 'W')
1836         {
1837                 int priority;
1838
1839                 /* Scan for the value */
1840                 if (1 != sscanf(buf + 2, "%d", &priority)) return (PARSE_ERROR_GENERIC);
1841
1842                 /* Save the value */
1843                 f_ptr->priority = (FEAT_PRIORITY)priority;
1844         }
1845
1846         /* Process 'K' for "States" (up to four lines + default (which cannot be last)) */
1847         else if (buf[0] == 'K')
1848         {
1849                 STR_OFFSET offset;
1850
1851                 /* Find the next empty state slot (if any) */
1852                 for (i = 0; i < MAX_FEAT_STATES; i++) if (f_ptr->state[i].action == FF_FLAG_MAX) break;
1853
1854                 /* Oops, no more slots */
1855                 if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
1856
1857                 /* Analyze the first field */
1858                 for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
1859
1860                 /* Terminate the field (if necessary) */
1861                 if (*t == ':') *t++ = '\0';
1862
1863                 /* Is this default entry? */
1864                 if (streq(s, "DESTROYED"))
1865                 {
1866                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1867
1868                         /* Record a fake tag index */
1869                         f_ptr->destroyed_tag = offset;
1870                 }
1871                 else
1872                 {
1873                         /* Reset */
1874                         f_ptr->state[i].action = 0;
1875
1876                         /* Parse this entry */
1877                         if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
1878
1879                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1880
1881                         /* Record a fake tag index */
1882                         f_ptr->state[i].result_tag = offset;
1883                 }
1884         }
1885
1886         else return (6);
1887
1888         /* Success */
1889         return (0);
1890 }
1891
1892
1893 /*!
1894  * @brief 地形タグからIDを得る /
1895  * Convert a fake tag to a real feat index
1896  * @param str タグ文字列
1897  * @return 地形ID
1898  */
1899 s16b f_tag_to_index(concptr str)
1900 {
1901         u16b i;
1902
1903         /* Search for real index corresponding to this fake tag */
1904         for (i = 0; i < f_head.info_num; i++)
1905         {
1906                 if (streq(f_tag + f_info[i].tag, str))
1907                 {
1908                         /* Return the index */
1909                         return (s16b)i;
1910                 }
1911         }
1912
1913         /* Not found */
1914         return -1;
1915 }
1916
1917
1918 /*!
1919  * @brief 地形タグからIDを得る /
1920  * Search for real index corresponding to this fake tag
1921  * @param feat タグ文字列のオフセット
1922  * @return 地形ID。該当がないなら-1
1923  */
1924 static FEAT_IDX search_real_feat(STR_OFFSET feat)
1925 {
1926         FEAT_IDX i;
1927
1928         /* Don't convert non-fake tag */
1929         if (feat <= 0)
1930         {
1931                 return -1;
1932         }
1933
1934         /* Search for real index corresponding to this fake tag */
1935         for (i = 0; i < f_head.info_num; i++)
1936         {
1937                 if (feat == f_info[i].tag)
1938                 {
1939                         /* Record real index */
1940                         return i;
1941                 }
1942         }
1943
1944         /* Undefined tag */
1945         msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
1946         return -1;
1947 }
1948
1949
1950 /*!
1951  * @brief 地形情報の各種タグからIDへ変換して結果を収める /
1952  * Retouch fake tags of f_info
1953  * @param head ヘッダ構造体
1954  * @return なし
1955  */
1956 void retouch_f_info(header *head)
1957 {
1958         int i;
1959
1960         /* Convert fake tags to real feat indices */
1961         for (i = 0; i < head->info_num; i++)
1962         {
1963                 feature_type *f_ptr = &f_info[i];
1964                 FEAT_IDX j, k;
1965
1966                 k = search_real_feat(f_ptr->mimic_tag);
1967                 f_ptr->mimic = k < 0 ? f_ptr->mimic : k;
1968                 k = search_real_feat(f_ptr->destroyed_tag);
1969                 f_ptr->destroyed = k < 0 ? f_ptr->destroyed : k;
1970                 for (j = 0; j < MAX_FEAT_STATES; j++)
1971                 {
1972                         k = search_real_feat(f_ptr->state[j].result_tag);
1973                         f_ptr->state[j].result = k < 0 ? f_ptr->state[j].result : k;
1974                 }
1975         }
1976 }
1977
1978
1979 /*!
1980  * @brief テキストトークンを走査してフラグを一つ得る(ベースアイテム用) /
1981  * Grab one flag in an object_kind from a textual string
1982  * @param k_ptr 保管先のベースアイテム構造体参照ポインタ
1983  * @param what 参照元の文字列ポインタ
1984  * @return エラーコード
1985  */
1986 static errr grab_one_kind_flag(object_kind *k_ptr, concptr what)
1987 {
1988         int i;
1989
1990         /* Check flags */
1991         for (i = 0; i < TR_FLAG_MAX; i++)
1992         {
1993                 if (streq(what, k_info_flags[i]))
1994                 {
1995                         add_flag(k_ptr->flags, i);
1996                         return (0);
1997                 }
1998         }
1999
2000         if (grab_one_flag(&k_ptr->gen_flags, k_info_gen_flags, what) == 0)
2001                 return 0;
2002
2003         msg_format(_("未知のアイテム・フラグ '%s'。", "Unknown object flag '%s'."), what);
2004
2005         /* Error */
2006         return (1);
2007 }
2008
2009 /*!
2010  * @brief テキストトークンを走査してフラグを一つ得る(発動能力用) /
2011  * Grab one activation index flag
2012  * @param what 参照元の文字列ポインタ
2013  * @return 発動能力ID
2014  */
2015 static byte grab_one_activation_flag(concptr what)
2016 {
2017         int i;
2018
2019         for (i = 0; ; i++)
2020         {
2021                 if (activation_info[i].flag == NULL) break;
2022
2023                 if (streq(what, activation_info[i].flag))
2024                 {
2025                         return activation_info[i].index;
2026                 }
2027         }
2028
2029         i = atoi(what);
2030         if (i > 0)
2031         {
2032                 return ((byte)i);
2033         }
2034
2035         msg_format(_("未知の発動・フラグ '%s'。", "Unknown activation flag '%s'."), what);
2036
2037         /* Error */
2038         return (0);
2039 }
2040
2041
2042 /*!
2043  * @brief ベースアイテム(k_info)のパース関数 /
2044  * Initialize the "k_info" array, by parsing an ascii "template" file
2045  * @param buf テキスト列
2046  * @param head ヘッダ構造体
2047  * @return エラーコード
2048  */
2049 errr parse_k_info(char *buf, header *head)
2050 {
2051         int i;
2052
2053         char *s, *t;
2054
2055         /* Current entry */
2056         static object_kind *k_ptr = NULL;
2057
2058
2059         /* Process 'N' for "New/Number/Name" */
2060         if (buf[0] == 'N')
2061         {
2062 #ifdef JP
2063                 char *flavor;
2064 #endif
2065
2066                 /* Find the colon before the name */
2067                 s = my_strchr(buf + 2, ':');
2068
2069                 /* Verify that colon */
2070                 if (!s) return (1);
2071
2072                 /* Nuke the colon, advance to the name */
2073                 *s++ = '\0';
2074
2075                 /* Get the index */
2076                 i = atoi(buf + 2);
2077
2078                 /* Verify information */
2079                 if (i <= error_idx) return (4);
2080
2081                 /* Verify information */
2082                 if (i >= head->info_num) return (2);
2083
2084                 /* Save the index */
2085                 error_idx = i;
2086
2087                 /* Point at the "info" */
2088                 k_ptr = &k_info[i];
2089
2090 #ifdef JP
2091                 /* Paranoia -- require a name */
2092                 if (!*s) return (1);
2093
2094                 /* Find the colon before the flavor */
2095                 flavor = my_strchr(s, ':');
2096
2097                 /* Verify that colon */
2098                 if (flavor)
2099                 {
2100                         /* Nuke the colon, advance to the flavor */
2101                         *flavor++ = '\0';
2102
2103                         /* Store the flavor */
2104                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return (7);
2105                 }
2106
2107                 /* Store the name */
2108                 if (!add_name(&k_ptr->name, head, s)) return (7);
2109 #endif
2110         }
2111
2112         /* There better be a current k_ptr */
2113         else if (!k_ptr) return (3);
2114
2115
2116 #ifdef JP
2117         /* 英語名を読むルーチンを追加 */
2118         /* 'E' から始まる行は英語名としている */
2119         else if (buf[0] == 'E')
2120         {
2121                 /* nothing to do */
2122         }
2123 #else
2124         else if (buf[0] == 'E')
2125         {
2126                 char *flavor;
2127
2128                 /* Acquire the name */
2129                 s = buf + 2;
2130
2131                 /* Find the colon before the flavor */
2132                 flavor = my_strchr(s, ':');
2133
2134                 /* Verify that colon */
2135                 if (flavor)
2136                 {
2137                         /* Nuke the colon, advance to the flavor */
2138                         *flavor++ = '\0';
2139
2140                         /* Store the flavor */
2141                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return (7);
2142                 }
2143
2144                 /* Store the name */
2145                 if (!add_name(&k_ptr->name, head, s)) return (7);
2146         }
2147 #endif
2148
2149         /* Process 'D' for "Description" */
2150         else if (buf[0] == 'D')
2151         {
2152 #ifdef JP
2153                 if (buf[2] == '$')
2154                         return (0);
2155                 /* Acquire the text */
2156                 s = buf + 2;
2157 #else
2158                 if (buf[2] != '$')
2159                         return (0);
2160                 /* Acquire the text */
2161                 s = buf + 3;
2162 #endif
2163
2164                 /* Store the text */
2165                 if (!add_text(&k_ptr->text, head, s, TRUE)) return (7);
2166         }
2167
2168         /* Process 'G' for "Graphics" (one line only) */
2169         else if (buf[0] == 'G')
2170         {
2171                 char sym;
2172                 byte tmp;
2173                 if (buf[1] != ':') return (1);
2174                 if (!buf[2]) return (1);
2175                 if (buf[3] != ':') return (1);
2176                 if (!buf[4]) return (1);
2177
2178                 /* Extract the char */
2179                 sym = buf[2];
2180
2181                 /* Extract the attr */
2182                 tmp = color_char_to_attr(buf[4]);
2183                 if (tmp > 127) return (1);
2184
2185                 /* Save the values */
2186                 k_ptr->d_attr = tmp;
2187                 k_ptr->d_char = sym;
2188         }
2189
2190         /* Process 'I' for "Info" (one line only) */
2191         else if (buf[0] == 'I')
2192         {
2193                 int tval, sval, pval;
2194
2195                 /* Scan for the values */
2196                 if (3 != sscanf(buf + 2, "%d:%d:%d",
2197                         &tval, &sval, &pval)) return (1);
2198
2199                 /* Save the values */
2200                 k_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2201                 k_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2202                 k_ptr->pval = (PARAMETER_VALUE)pval;
2203         }
2204
2205         /* Process 'W' for "More Info" (one line only) */
2206         else if (buf[0] == 'W')
2207         {
2208                 int level, extra, wgt;
2209                 long cost;
2210
2211                 /* Scan for the values */
2212                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2213                         &level, &extra, &wgt, &cost)) return (1);
2214
2215                 /* Save the values */
2216                 k_ptr->level = (DEPTH)level;
2217                 k_ptr->extra = (BIT_FLAGS8)extra;
2218                 k_ptr->weight = (WEIGHT)wgt;
2219                 k_ptr->cost = (PRICE)cost;
2220         }
2221
2222         /* Process 'A' for "Allocation" (one line only) */
2223         else if (buf[0] == 'A')
2224         {
2225
2226                 /* Simply read each number following a colon */
2227                 for (i = 0, s = buf + 1; s && (s[0] == ':') && s[1]; ++i)
2228                 {
2229                         /* Default chance */
2230                         k_ptr->chance[i] = 1;
2231
2232                         /* Store the attack damage index */
2233                         k_ptr->locale[i] = atoi(s + 1);
2234
2235                         /* Find the slash */
2236                         t = my_strchr(s + 1, '/');
2237
2238                         /* Find the next colon */
2239                         s = my_strchr(s + 1, ':');
2240
2241                         /* If the slash is "nearby", use it */
2242                         if (t && (!s || t < s))
2243                         {
2244                                 int chance = atoi(t + 1);
2245                                 if (chance > 0) k_ptr->chance[i] = (PROB)chance;
2246                         }
2247                 }
2248         }
2249
2250         /* Hack -- Process 'P' for "power" and such */
2251         else if (buf[0] == 'P')
2252         {
2253                 int ac, hd1, hd2, th, td, ta;
2254
2255                 /* Scan for the values */
2256                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2257                         &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2258
2259                 k_ptr->ac = (ARMOUR_CLASS)ac;
2260                 k_ptr->dd = (DICE_NUMBER)hd1;
2261                 k_ptr->ds = (DICE_SID)hd2;
2262                 k_ptr->to_h = (HIT_PROB)th;
2263                 k_ptr->to_d = (HIT_POINT)td;
2264                 k_ptr->to_a = (ARMOUR_CLASS)ta;
2265         }
2266
2267         /* Hack -- Process 'U' for activation index */
2268         else if (buf[0] == 'U')
2269         {
2270                 byte n;
2271                 n = grab_one_activation_flag(buf + 2);
2272                 if (n > 0)
2273                 {
2274                         k_ptr->act_idx = n;
2275                 }
2276                 else
2277                 {
2278                         return (5);
2279                 }
2280         }
2281
2282         /* Hack -- Process 'F' for flags */
2283         else if (buf[0] == 'F')
2284         {
2285                 /* Parse every entry textually */
2286                 for (s = buf + 2; *s; )
2287                 {
2288                         /* Find the end of this entry */
2289                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2290
2291                         /* Nuke and skip any dividers */
2292                         if (*t)
2293                         {
2294                                 *t++ = '\0';
2295                                 while (*t == ' ' || *t == '|') t++;
2296                         }
2297
2298                         /* Parse this entry */
2299                         if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
2300
2301                         /* Start the next entry */
2302                         s = t;
2303                 }
2304         }
2305
2306
2307         else return (6);
2308
2309
2310         /* Success */
2311         return (0);
2312 }
2313
2314 /*!
2315  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2316  * Grab one activation index flag
2317  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
2318  * @param what 参照元の文字列ポインタ
2319  * @return エラーがあった場合1、エラーがない場合0を返す
2320  */
2321 static errr grab_one_artifact_flag(artifact_type *a_ptr, concptr what)
2322 {
2323         int i;
2324
2325         /* Check flags */
2326         for (i = 0; i < TR_FLAG_MAX; i++)
2327         {
2328                 if (streq(what, k_info_flags[i]))
2329                 {
2330                         add_flag(a_ptr->flags, i);
2331                         return (0);
2332                 }
2333         }
2334
2335         if (grab_one_flag(&a_ptr->gen_flags, k_info_gen_flags, what) == 0)
2336                 return 0;
2337
2338         msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what);
2339
2340         /* Error */
2341         return (1);
2342 }
2343
2344
2345 /*!
2346  * @brief 固定アーティファクト情報(a_info)のパース関数 /
2347  * Initialize the "a_info" array, by parsing an ascii "template" file
2348  * @param buf テキスト列
2349  * @param head ヘッダ構造体
2350  * @return エラーコード
2351  */
2352 errr parse_a_info(char *buf, header *head)
2353 {
2354         int i;
2355
2356         char *s, *t;
2357
2358         /* Current entry */
2359         static artifact_type *a_ptr = NULL;
2360
2361
2362         /* Process 'N' for "New/Number/Name" */
2363         if (buf[0] == 'N')
2364         {
2365                 /* Find the colon before the name */
2366                 s = my_strchr(buf + 2, ':');
2367
2368                 /* Verify that colon */
2369                 if (!s) return (1);
2370
2371                 /* Nuke the colon, advance to the name */
2372                 *s++ = '\0';
2373 #ifdef JP
2374                 /* Paranoia -- require a name */
2375                 if (!*s) return (1);
2376 #endif
2377                 /* Get the index */
2378                 i = atoi(buf + 2);
2379
2380                 /* Verify information */
2381                 if (i < error_idx) return (4);
2382
2383                 /* Verify information */
2384                 if (i >= head->info_num) return (2);
2385
2386                 /* Save the index */
2387                 error_idx = i;
2388
2389                 /* Point at the "info" */
2390                 a_ptr = &a_info[i];
2391
2392                 /* Ignore everything */
2393                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
2394                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
2395                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
2396                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
2397 #ifdef JP
2398                 /* Store the name */
2399                 if (!add_name(&a_ptr->name, head, s)) return (7);
2400 #endif
2401         }
2402
2403         /* There better be a current a_ptr */
2404         else if (!a_ptr) return (3);
2405
2406
2407 #ifdef JP
2408         /* 英語名を読むルーチンを追加 */
2409         /* 'E' から始まる行は英語名としている */
2410         else if (buf[0] == 'E')
2411         {
2412                 /* nothing to do */
2413         }
2414 #else
2415         else if (buf[0] == 'E')
2416         {
2417                 /* Acquire the Text */
2418                 s = buf + 2;
2419
2420                 /* Store the name */
2421                 if (!add_name(&a_ptr->name, head, s)) return (7);
2422         }
2423 #endif
2424
2425         /* Process 'D' for "Description" */
2426         else if (buf[0] == 'D')
2427         {
2428 #ifdef JP
2429                 if (buf[2] == '$')
2430                         return (0);
2431                 /* Acquire the text */
2432                 s = buf + 2;
2433 #else
2434                 if (buf[2] != '$')
2435                         return (0);
2436                 /* Acquire the text */
2437                 s = buf + 3;
2438 #endif
2439
2440                 /* Store the text */
2441                 if (!add_text(&a_ptr->text, head, s, TRUE)) return (7);
2442         }
2443
2444
2445         /* Process 'I' for "Info" (one line only) */
2446         else if (buf[0] == 'I')
2447         {
2448                 int tval, sval, pval;
2449
2450                 /* Scan for the values */
2451                 if (3 != sscanf(buf + 2, "%d:%d:%d",
2452                         &tval, &sval, &pval)) return (1);
2453
2454                 /* Save the values */
2455                 a_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2456                 a_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2457                 a_ptr->pval = (PARAMETER_VALUE)pval;
2458         }
2459
2460         /* Process 'W' for "More Info" (one line only) */
2461         else if (buf[0] == 'W')
2462         {
2463                 int level, rarity, wgt;
2464                 long cost;
2465
2466                 /* Scan for the values */
2467                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2468                         &level, &rarity, &wgt, &cost)) return (1);
2469
2470                 /* Save the values */
2471                 a_ptr->level = (DEPTH)level;
2472                 a_ptr->rarity = (RARITY)rarity;
2473                 a_ptr->weight = (WEIGHT)wgt;
2474                 a_ptr->cost = (PRICE)cost;
2475         }
2476
2477         /* Hack -- Process 'P' for "power" and such */
2478         else if (buf[0] == 'P')
2479         {
2480                 int ac, hd1, hd2, th, td, ta;
2481
2482                 /* Scan for the values */
2483                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2484                         &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2485
2486                 a_ptr->ac = (ARMOUR_CLASS)ac;
2487                 a_ptr->dd = (DICE_NUMBER)hd1;
2488                 a_ptr->ds = (DICE_SID)hd2;
2489                 a_ptr->to_h = (HIT_PROB)th;
2490                 a_ptr->to_d = (HIT_POINT)td;
2491                 a_ptr->to_a = (ARMOUR_CLASS)ta;
2492         }
2493
2494         /* Hack -- Process 'U' for activation index */
2495         else if (buf[0] == 'U')
2496         {
2497                 byte n;
2498                 n = grab_one_activation_flag(buf + 2);
2499                 if (n > 0)
2500                 {
2501                         a_ptr->act_idx = n;
2502                 }
2503                 else
2504                 {
2505                         return (5);
2506                 }
2507         }
2508
2509         /* Hack -- Process 'F' for flags */
2510         else if (buf[0] == 'F')
2511         {
2512                 /* Parse every entry textually */
2513                 for (s = buf + 2; *s; )
2514                 {
2515                         /* Find the end of this entry */
2516                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2517
2518                         /* Nuke and skip any dividers */
2519                         if (*t)
2520                         {
2521                                 *t++ = '\0';
2522                                 while ((*t == ' ') || (*t == '|')) t++;
2523                         }
2524
2525                         /* Parse this entry */
2526                         if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
2527
2528                         /* Start the next entry */
2529                         s = t;
2530                 }
2531         }
2532
2533
2534         else return (6);
2535
2536
2537         /* Success */
2538         return (0);
2539 }
2540
2541
2542 /*!
2543  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2544  * Grab one flag in a ego-item_type from a textual string
2545  * @param e_ptr 保管先のエゴ構造体参照ポインタ
2546  * @param what 参照元の文字列ポインタ
2547  * @return エラーがあった場合1、エラーがない場合0を返す
2548  */
2549 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
2550 {
2551         int i;
2552
2553         /* Check flags */
2554         for (i = 0; i < TR_FLAG_MAX; i++)
2555         {
2556                 if (streq(what, k_info_flags[i]))
2557                 {
2558                         add_flag(e_ptr->flags, i);
2559                         return (0);
2560                 }
2561         }
2562
2563         if (grab_one_flag(&e_ptr->gen_flags, k_info_gen_flags, what) == 0)
2564                 return 0;
2565
2566         msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what);
2567
2568         /* Error */
2569         return (1);
2570 }
2571
2572
2573 /*!
2574  * @brief アイテムエゴ情報(e_info)のパース関数 /
2575  * Initialize the "e_info" array, by parsing an ascii "template" file
2576  * @param buf テキスト列
2577  * @param head ヘッダ構造体
2578  * @return エラーコード
2579  */
2580 errr parse_e_info(char *buf, header *head)
2581 {
2582         int i;
2583         char *s, *t;
2584
2585         /* Current entry */
2586         static ego_item_type *e_ptr = NULL;
2587
2588         /* Just before the first record */
2589         error_idx = -1;
2590
2591         /* Just before the first line */
2592         error_line = -1;
2593
2594         /* Process 'N' for "New/Number/Name" */
2595         if (buf[0] == 'N')
2596         {
2597                 /* Find the colon before the name */
2598                 s = my_strchr(buf + 2, ':');
2599
2600                 /* Verify that colon */
2601                 if (!s) return (1);
2602
2603                 /* Nuke the colon, advance to the name */
2604                 *s++ = '\0';
2605 #ifdef JP
2606                 /* Paranoia -- require a name */
2607                 if (!*s) return (1);
2608 #endif
2609                 /* Get the index */
2610                 i = atoi(buf + 2);
2611
2612                 /* Verify information */
2613                 if (i < error_idx) return (4);
2614
2615                 /* Verify information */
2616                 if (i >= head->info_num) return (2);
2617
2618                 /* Save the index */
2619                 error_idx = i;
2620
2621                 /* Point at the "info" */
2622                 e_ptr = &e_info[i];
2623 #ifdef JP
2624                 /* Store the name */
2625                 if (!add_name(&e_ptr->name, head, s)) return (7);
2626 #endif
2627         }
2628
2629         /* There better be a current e_ptr */
2630         else if (!e_ptr) return (3);
2631
2632
2633 #ifdef JP
2634         /* 英語名を読むルーチンを追加 */
2635         /* 'E' から始まる行は英語名 */
2636         else if (buf[0] == 'E')
2637         {
2638                 /* nothing to do */
2639         }
2640 #else
2641         else if (buf[0] == 'E')
2642         {
2643                 /* Acquire the Text */
2644                 s = buf + 2;
2645
2646                 /* Store the name */
2647                 if (!add_name(&e_ptr->name, head, s)) return (7);
2648         }
2649 #endif
2650 #if 0
2651
2652         /* Process 'D' for "Description" */
2653         else if (buf[0] == 'D')
2654         {
2655                 /* Acquire the text */
2656                 s = buf + 2;
2657
2658                 /* Store the text */
2659                 if (!add_text(&e_ptr->text, head, s, TRUE)) return (7);
2660         }
2661
2662 #endif
2663
2664         /* Process 'X' for "Xtra" (one line only) */
2665         else if (buf[0] == 'X')
2666         {
2667                 int slot, rating;
2668
2669                 /* Scan for the values */
2670                 if (2 != sscanf(buf + 2, "%d:%d",
2671                         &slot, &rating)) return (1);
2672
2673                 /* Save the values */
2674                 e_ptr->slot = (INVENTORY_IDX)slot;
2675                 e_ptr->rating = (PRICE)rating;
2676         }
2677
2678         /* Process 'W' for "More Info" (one line only) */
2679         else if (buf[0] == 'W')
2680         {
2681                 int level, rarity, pad2;
2682                 long cost;
2683
2684                 /* Scan for the values */
2685                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2686                         &level, &rarity, &pad2, &cost)) return (1);
2687
2688                 /* Save the values */
2689                 e_ptr->level = level;
2690                 e_ptr->rarity = (RARITY)rarity;
2691                 /* e_ptr->weight = wgt; */
2692                 e_ptr->cost = cost;
2693         }
2694
2695         /* Hack -- Process 'C' for "creation" */
2696         else if (buf[0] == 'C')
2697         {
2698                 int th, td, ta, pval;
2699
2700                 /* Scan for the values */
2701                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
2702                         &th, &td, &ta, &pval)) return (1);
2703
2704                 e_ptr->max_to_h = (HIT_PROB)th;
2705                 e_ptr->max_to_d = (HIT_POINT)td;
2706                 e_ptr->max_to_a = (ARMOUR_CLASS)ta;
2707                 e_ptr->max_pval = (PARAMETER_VALUE)pval;
2708         }
2709
2710         /* Hack -- Process 'U' for activation index */
2711         else if (buf[0] == 'U')
2712         {
2713                 byte n;
2714                 n = grab_one_activation_flag(buf + 2);
2715                 if (n > 0)
2716                 {
2717                         e_ptr->act_idx = n;
2718                 }
2719                 else
2720                 {
2721                         return (5);
2722                 }
2723         }
2724
2725         /* Hack -- Process 'F' for flags */
2726         else if (buf[0] == 'F')
2727         {
2728                 /* Parse every entry textually */
2729                 for (s = buf + 2; *s; )
2730                 {
2731                         /* Find the end of this entry */
2732                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2733
2734                         /* Nuke and skip any dividers */
2735                         if (*t)
2736                         {
2737                                 *t++ = '\0';
2738                                 while ((*t == ' ') || (*t == '|')) t++;
2739                         }
2740
2741                         /* Parse this entry */
2742                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2743
2744                         /* Start the next entry */
2745                         s = t;
2746                 }
2747         }
2748
2749         else return (6);
2750
2751         /* Success */
2752         return (0);
2753 }
2754
2755
2756 /*!
2757  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用1) /
2758  * Grab one (basic) flag in a monster_race from a textual string
2759  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2760  * @param what 参照元の文字列ポインタ
2761  * @return エラーコード
2762  */
2763 static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
2764 {
2765         if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
2766                 return 0;
2767
2768         if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
2769                 return 0;
2770
2771         if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
2772                 return 0;
2773
2774         if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
2775                 return 0;
2776
2777         if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
2778                 return 0;
2779
2780         if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
2781                 return 0;
2782
2783         if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
2784                 return 0;
2785
2786         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2787
2788         /* Failure */
2789         return (1);
2790 }
2791
2792
2793 /*!
2794  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用2) /
2795  * Grab one (spell) flag in a monster_race from a textual string
2796  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2797  * @param what 参照元の文字列ポインタ
2798  * @return エラーコード
2799  */
2800 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
2801 {
2802         if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
2803                 return 0;
2804
2805         if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
2806                 return 0;
2807
2808         if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
2809                 return 0;
2810
2811         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2812
2813         /* Failure */
2814         return (1);
2815 }
2816
2817
2818 /*!
2819  * @brief モンスター種族情報(r_info)のパース関数 /
2820  * Initialize the "r_info" array, by parsing an ascii "template" file
2821  * @param buf テキスト列
2822  * @param head ヘッダ構造体
2823  * @return エラーコード
2824  */
2825 errr parse_r_info(char *buf, header *head)
2826 {
2827         int i;
2828         char *s, *t;
2829
2830         /* Current entry */
2831         static monster_race *r_ptr = NULL;
2832
2833
2834         /* Process 'N' for "New/Number/Name" */
2835         if (buf[0] == 'N')
2836         {
2837                 /* Find the colon before the name */
2838                 s = my_strchr(buf + 2, ':');
2839
2840                 /* Verify that colon */
2841                 if (!s) return (1);
2842
2843                 /* Nuke the colon, advance to the name */
2844                 *s++ = '\0';
2845 #ifdef JP
2846                 /* Paranoia -- require a name */
2847                 if (!*s) return (1);
2848 #endif
2849                 /* Get the index */
2850                 i = atoi(buf + 2);
2851
2852                 /* Verify information */
2853                 if (i < error_idx) return (4);
2854
2855                 /* Verify information */
2856                 if (i >= head->info_num) return (2);
2857
2858                 /* Save the index */
2859                 error_idx = i;
2860
2861                 /* Point at the "info" */
2862                 r_ptr = &r_info[i];
2863 #ifdef JP
2864                 /* Store the name */
2865                 if (!add_name(&r_ptr->name, head, s)) return (7);
2866 #endif
2867         }
2868
2869         /* There better be a current r_ptr */
2870         else if (!r_ptr) return (3);
2871
2872
2873 #ifdef JP
2874         /* 英語名を読むルーチンを追加 */
2875         /* 'E' から始まる行は英語名 */
2876         else if (buf[0] == 'E')
2877         {
2878                 /* Acquire the Text */
2879                 s = buf + 2;
2880
2881                 /* Store the name */
2882                 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2883         }
2884 #else
2885         else if (buf[0] == 'E')
2886         {
2887                 /* Acquire the Text */
2888                 s = buf + 2;
2889
2890                 /* Store the name */
2891                 if (!add_name(&r_ptr->name, head, s)) return (7);
2892         }
2893 #endif
2894         /* Process 'D' for "Description" */
2895         else if (buf[0] == 'D')
2896         {
2897 #ifdef JP
2898                 if (buf[2] == '$')
2899                         return (0);
2900                 /* Acquire the text */
2901                 s = buf + 2;
2902 #else
2903                 if (buf[2] != '$')
2904                         return (0);
2905                 /* Acquire the text */
2906                 s = buf + 3;
2907 #endif
2908
2909                 /* Store the text */
2910                 if (!add_text(&r_ptr->text, head, s, TRUE)) return (7);
2911         }
2912
2913         /* Process 'G' for "Graphics" (one line only) */
2914         else if (buf[0] == 'G')
2915         {
2916                 char sym;
2917                 byte tmp;
2918                 if (buf[1] != ':') return (1);
2919                 if (!buf[2]) return (1);
2920                 if (buf[3] != ':') return (1);
2921                 if (!buf[4]) return (1);
2922
2923                 /* Extract the char */
2924                 sym = buf[2];
2925
2926                 /* Extract the attr */
2927                 tmp = color_char_to_attr(buf[4]);
2928                 if (tmp > 127) return (1);
2929
2930                 /* Save the values */
2931                 r_ptr->d_char = sym;
2932                 r_ptr->d_attr = tmp;
2933         }
2934
2935         /* Process 'I' for "Info" (one line only) */
2936         else if (buf[0] == 'I')
2937         {
2938                 int spd, hp1, hp2, aaf, ac, slp;
2939
2940                 /* Scan for the other values */
2941                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2942                         &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2943
2944                 /* Save the values */
2945                 r_ptr->speed = (SPEED)spd;
2946                 r_ptr->hdice = (DICE_NUMBER)MAX(hp1, 1);
2947                 r_ptr->hside = (DICE_SID)MAX(hp2, 1);
2948                 r_ptr->aaf = (POSITION)aaf;
2949                 r_ptr->ac = (ARMOUR_CLASS)ac;
2950                 r_ptr->sleep = (SLEEP_DEGREE)slp;
2951         }
2952
2953         /* Process 'W' for "More Info" (one line only) */
2954         else if (buf[0] == 'W')
2955         {
2956                 int lev, rar, pad;
2957                 long exp;
2958                 long nextexp;
2959                 int nextmon;
2960
2961                 /* Scan for the values */
2962                 if (6 != sscanf(buf + 2, "%d:%d:%d:%ld:%ld:%d",
2963                         &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2964
2965                 /* Save the values */
2966                 r_ptr->level = (DEPTH)lev;
2967                 r_ptr->rarity = (RARITY)rar;
2968                 r_ptr->extra = (BIT_FLAGS16)pad;
2969                 r_ptr->mexp = (EXP)exp;
2970                 r_ptr->next_exp = (EXP)nextexp;
2971                 r_ptr->next_r_idx = (IDX)nextmon;
2972         }
2973
2974         /* Process 'R' for "Reinforcement" (up to six lines) */
2975         else if (buf[0] == 'R')
2976         {
2977                 int id, ds, dd;
2978                 /* Find the next empty blow slot (if any) */
2979                 for (i = 0; i < A_MAX; i++) if (r_ptr->reinforce_id[i] == 0) break;
2980
2981                 /* Oops, no more slots */
2982                 if (i == 6) return (1);
2983
2984                 /* Scan for the values */
2985                 if (3 != sscanf(buf + 2, "%d:%dd%d", &id, &dd, &ds)) return (1);
2986                 r_ptr->reinforce_id[i] = (MONRACE_IDX)id;
2987                 r_ptr->reinforce_dd[i] = (DICE_NUMBER)dd;
2988                 r_ptr->reinforce_ds[i] = (DICE_SID)ds;
2989         }
2990
2991         /* Process 'B' for "Blows" (up to four lines) */
2992         else if (buf[0] == 'B')
2993         {
2994                 int n1, n2;
2995
2996                 /* Find the next empty blow slot (if any) */
2997                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2998
2999                 /* Oops, no more slots */
3000                 if (i == 4) return (1);
3001
3002                 /* Analyze the first field */
3003                 for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
3004
3005                 /* Terminate the field (if necessary) */
3006                 if (*t == ':') *t++ = '\0';
3007
3008                 /* Analyze the method */
3009                 for (n1 = 0; r_info_blow_method[n1]; n1++)
3010                 {
3011                         if (streq(s, r_info_blow_method[n1])) break;
3012                 }
3013
3014                 /* Invalid method */
3015                 if (!r_info_blow_method[n1]) return (1);
3016
3017                 /* Analyze the second field */
3018                 for (s = t; *t && (*t != ':'); t++) /* loop */;
3019
3020                 /* Terminate the field (if necessary) */
3021                 if (*t == ':') *t++ = '\0';
3022
3023                 /* Analyze effect */
3024                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
3025                 {
3026                         if (streq(s, r_info_blow_effect[n2])) break;
3027                 }
3028
3029                 /* Invalid effect */
3030                 if (!r_info_blow_effect[n2]) return (1);
3031
3032                 /* Analyze the third field */
3033                 for (s = t; *t && (*t != 'd'); t++) /* loop */;
3034
3035                 /* Terminate the field (if necessary) */
3036                 if (*t == 'd') *t++ = '\0';
3037
3038                 /* Save the method */
3039                 r_ptr->blow[i].method = (BLOW_METHOD)n1;
3040
3041                 /* Save the effect */
3042                 r_ptr->blow[i].effect = (BLOW_EFFECT)n2;
3043
3044                 /* Extract the damage dice and sides */
3045                 r_ptr->blow[i].d_dice = atoi(s);
3046                 r_ptr->blow[i].d_side = atoi(t);
3047         }
3048
3049         /* Process 'F' for "Basic Flags" (multiple lines) */
3050         else if (buf[0] == 'F')
3051         {
3052                 /* Parse every entry */
3053                 for (s = buf + 2; *s; )
3054                 {
3055                         /* Find the end of this entry */
3056                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3057
3058                         /* Nuke and skip any dividers */
3059                         if (*t)
3060                         {
3061                                 *t++ = '\0';
3062                                 while (*t == ' ' || *t == '|') t++;
3063                         }
3064
3065                         /* Parse this entry */
3066                         if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
3067
3068                         /* Start the next entry */
3069                         s = t;
3070                 }
3071         }
3072
3073         /* Process 'S' for "Spell Flags" (multiple lines) */
3074         else if (buf[0] == 'S')
3075         {
3076                 /* Parse every entry */
3077                 for (s = buf + 2; *s; )
3078                 {
3079                         /* Find the end of this entry */
3080                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3081
3082                         /* Nuke and skip any dividers */
3083                         if (*t)
3084                         {
3085                                 *t++ = '\0';
3086                                 while ((*t == ' ') || (*t == '|')) t++;
3087                         }
3088
3089                         /* Hack -- Read spell frequency */
3090                         if (1 == sscanf(s, "1_IN_%d", &i))
3091                         {
3092                                 /* Extract a "frequency" */
3093                                 r_ptr->freq_spell = 100 / i;
3094
3095                                 /* Start at next entry */
3096                                 s = t;
3097                                 continue;
3098                         }
3099
3100                         /* Parse this entry */
3101                         if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
3102
3103                         /* Start the next entry */
3104                         s = t;
3105                 }
3106         }
3107
3108         /* Process 'A' for "Artifact Flags" (multiple lines) */
3109         else if (buf[0] == 'A')
3110         {
3111                 int id, per, rarity;
3112
3113                 /* Find the next empty blow slot (if any) */
3114                 for (i = 0; i < 4; i++) if (!r_ptr->artifact_id[i]) break;
3115
3116                 /* Oops, no more slots */
3117                 if (i == 4) return (1);
3118
3119                 if (3 != sscanf(buf + 2, "%d:%d:%d", &id, &rarity, &per)) return (1);
3120                 r_ptr->artifact_id[i] = (ARTIFACT_IDX)id;
3121                 r_ptr->artifact_rarity[i] = (RARITY)rarity;
3122                 r_ptr->artifact_percent[i] = (PERCENTAGE)per;
3123         }
3124
3125         /* Process 'V' for "Arena power value ratio" */
3126         else if (buf[0] == 'V')
3127         {
3128                 int val;
3129                 if (3 != sscanf(buf + 2, "%d", &val)) return (1);
3130                 r_ptr->arena_ratio = (PERCENTAGE)val;
3131         }
3132
3133         else return (6);
3134
3135
3136         /* Success */
3137         return (0);
3138 }
3139
3140
3141 /*!
3142  * @brief テキストトークンを走査してフラグを一つ得る(ダンジョン用) /
3143  * Grab one flag for a dungeon type from a textual string
3144  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3145  * @param what 参照元の文字列ポインタ
3146  * @return エラーコード
3147  */
3148 static errr grab_one_dungeon_flag(dungeon_type *d_ptr, concptr what)
3149 {
3150         if (grab_one_flag(&d_ptr->flags1, d_info_flags1, what) == 0)
3151                 return 0;
3152
3153         msg_format(_("未知のダンジョン・フラグ '%s'。", "Unknown dungeon type flag '%s'."), what);
3154
3155         /* Failure */
3156         return (1);
3157 }
3158
3159 /*!
3160  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用1) /
3161  * Grab one (basic) flag in a monster_race from a textual string
3162  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3163  * @param what 参照元の文字列ポインタ
3164  * @return エラーコード
3165  */
3166 static errr grab_one_basic_monster_flag(dungeon_type *d_ptr, concptr what)
3167 {
3168         if (grab_one_flag(&d_ptr->mflags1, r_info_flags1, what) == 0)
3169                 return 0;
3170
3171         if (grab_one_flag(&d_ptr->mflags2, r_info_flags2, what) == 0)
3172                 return 0;
3173
3174         if (grab_one_flag(&d_ptr->mflags3, r_info_flags3, what) == 0)
3175                 return 0;
3176
3177         if (grab_one_flag(&d_ptr->mflags7, r_info_flags7, what) == 0)
3178                 return 0;
3179
3180         if (grab_one_flag(&d_ptr->mflags8, r_info_flags8, what) == 0)
3181                 return 0;
3182
3183         if (grab_one_flag(&d_ptr->mflags9, r_info_flags9, what) == 0)
3184                 return 0;
3185
3186         if (grab_one_flag(&d_ptr->mflagsr, r_info_flagsr, what) == 0)
3187                 return 0;
3188
3189         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3190         /* Failure */
3191         return (1);
3192 }
3193
3194
3195 /*!
3196  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用2) /
3197  * Grab one (spell) flag in a monster_race from a textual string
3198  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3199  * @param what 参照元の文字列ポインタ
3200  * @return エラーコード
3201  */
3202 static errr grab_one_spell_monster_flag(dungeon_type *d_ptr, concptr what)
3203 {
3204         if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
3205                 return 0;
3206
3207         if (grab_one_flag(&d_ptr->m_a_ability_flags1, r_a_ability_flags1, what) == 0)
3208                 return 0;
3209
3210         if (grab_one_flag(&d_ptr->m_a_ability_flags2, r_a_ability_flags2, what) == 0)
3211                 return 0;
3212
3213         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3214
3215         /* Failure */
3216         return (1);
3217 }
3218
3219 /*!
3220  * @brief ダンジョン情報(d_info)のパース関数 /
3221  * Initialize the "d_info" array, by parsing an ascii "template" file
3222  * @param buf テキスト列
3223  * @param head ヘッダ構造体
3224  * @return エラーコード
3225  */
3226 errr parse_d_info(char *buf, header *head)
3227 {
3228         int i;
3229         char *s, *t;
3230
3231         /* Current entry */
3232         static dungeon_type *d_ptr = NULL;
3233
3234         /* Process 'N' for "New/Number/Name" */
3235         if (buf[0] == 'N')
3236         {
3237                 /* Find the colon before the name */
3238                 s = my_strchr(buf + 2, ':');
3239
3240                 /* Verify that colon */
3241                 if (!s) return (1);
3242
3243                 /* Nuke the colon, advance to the name */
3244                 *s++ = '\0';
3245 #ifdef JP
3246                 /* Paranoia -- require a name */
3247                 if (!*s) return (1);
3248 #endif
3249                 /* Get the index */
3250                 i = atoi(buf + 2);
3251
3252                 /* Verify information */
3253                 if (i < error_idx) return (4);
3254
3255                 /* Verify information */
3256                 if (i >= head->info_num) return (2);
3257
3258                 /* Save the index */
3259                 error_idx = i;
3260
3261                 /* Point at the "info" */
3262                 d_ptr = &d_info[i];
3263 #ifdef JP
3264                 /* Store the name */
3265                 if (!add_name(&d_ptr->name, head, s)) return (7);
3266 #endif
3267         }
3268
3269 #ifdef JP
3270         else if (buf[0] == 'E') return (0);
3271 #else
3272         else if (buf[0] == 'E')
3273         {
3274                 /* Acquire the Text */
3275                 s = buf + 2;
3276
3277                 /* Store the name */
3278                 if (!add_name(&d_ptr->name, head, s)) return (7);
3279         }
3280 #endif
3281
3282         /* Process 'D' for "Description */
3283         else if (buf[0] == 'D')
3284         {
3285 #ifdef JP
3286                 if (buf[2] == '$')
3287                         return (0);
3288                 /* Acquire the text */
3289                 s = buf + 2;
3290 #else
3291                 if (buf[2] != '$')
3292                         return (0);
3293                 /* Acquire the text */
3294                 s = buf + 3;
3295 #endif
3296
3297                 /* Store the text */
3298                 if (!add_text(&d_ptr->text, head, s, TRUE)) return (7);
3299         }
3300
3301         /* Process 'W' for "More Info" (one line only) */
3302         else if (buf[0] == 'W')
3303         {
3304                 int min_lev, max_lev;
3305                 int min_plev, mode;
3306                 int min_alloc, max_chance;
3307                 int obj_good, obj_great;
3308                 int pit, nest;
3309
3310                 /* Scan for the values */
3311                 if (10 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
3312                         &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
3313
3314                 /* Save the values */
3315                 d_ptr->mindepth = (DEPTH)min_lev;
3316                 d_ptr->maxdepth = (DEPTH)max_lev;
3317                 d_ptr->min_plev = (PLAYER_LEVEL)min_plev;
3318                 d_ptr->mode = (BIT_FLAGS8)mode;
3319                 d_ptr->min_m_alloc_level = min_alloc;
3320                 d_ptr->max_m_alloc_chance = max_chance;
3321                 d_ptr->obj_good = obj_good;
3322                 d_ptr->obj_great = obj_great;
3323                 d_ptr->pit = (BIT_FLAGS16)pit;
3324                 d_ptr->nest = (BIT_FLAGS16)nest;
3325         }
3326
3327         /* Process 'P' for "Place Info" */
3328         else if (buf[0] == 'P')
3329         {
3330                 int dy, dx;
3331
3332                 /* Scan for the values */
3333                 if (2 != sscanf(buf + 2, "%d:%d", &dy, &dx)) return (1);
3334
3335                 /* Save the values */
3336                 d_ptr->dy = dy;
3337                 d_ptr->dx = dx;
3338         }
3339
3340         /* Process 'L' for "fLoor type" (one line only) */
3341         else if (buf[0] == 'L')
3342         {
3343                 char *zz[16];
3344
3345                 /* Scan for the values */
3346                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 1, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 1)) return (1);
3347
3348                 /* Save the values */
3349                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3350                 {
3351                         d_ptr->floor[i].feat = f_tag_to_index(zz[i * 2]);
3352                         if (d_ptr->floor[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3353
3354                         d_ptr->floor[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3355                 }
3356                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3357         }
3358
3359         /* Process 'A' for "wAll type" (one line only) */
3360         else if (buf[0] == 'A')
3361         {
3362                 char *zz[16];
3363
3364                 /* Scan for the values */
3365                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return (1);
3366
3367                 /* Save the values */
3368                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3369                 {
3370                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
3371                         if (d_ptr->fill[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3372
3373                         d_ptr->fill[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3374                 }
3375
3376                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3377                 if (d_ptr->outer_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3378
3379                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
3380                 if (d_ptr->inner_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3381
3382                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
3383                 if (d_ptr->stream1 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3384
3385                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
3386                 if (d_ptr->stream2 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3387         }
3388
3389         /* Process 'F' for "Dungeon Flags" (multiple lines) */
3390         else if (buf[0] == 'F')
3391         {
3392                 int artif = 0, monst = 0;
3393
3394                 /* Parse every entry */
3395                 for (s = buf + 2; *s; )
3396                 {
3397                         /* Find the end of this entry */
3398                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3399
3400                         /* Nuke and skip any dividers */
3401                         if (*t)
3402                         {
3403                                 *t++ = '\0';
3404                                 while (*t == ' ' || *t == '|') t++;
3405                         }
3406
3407                         /* Hack -- Read Final Artifact */
3408                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3409                         {
3410                                 /* Extract a "Final Artifact" */
3411                                 d_ptr->final_artifact = (ARTIFACT_IDX)artif;
3412
3413                                 /* Start at next entry */
3414                                 s = t;
3415                                 continue;
3416                         }
3417
3418                         /* Hack -- Read Final Object */
3419                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3420                         {
3421                                 /* Extract a "Final Artifact" */
3422                                 d_ptr->final_object = (KIND_OBJECT_IDX)artif;
3423
3424                                 /* Start at next entry */
3425                                 s = t;
3426                                 continue;
3427                         }
3428
3429                         /* Hack -- Read Artifact Guardian */
3430                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3431                         {
3432                                 /* Extract a "Artifact Guardian" */
3433                                 d_ptr->final_guardian = (MONRACE_IDX)monst;
3434
3435                                 /* Start at next entry */
3436                                 s = t;
3437                                 continue;
3438                         }
3439
3440                         /* Hack -- Read Special Percentage */
3441                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3442                         {
3443                                 /* Extract a "Special %" */
3444                                 d_ptr->special_div = (PROB)monst;
3445
3446                                 /* Start at next entry */
3447                                 s = t;
3448                                 continue;
3449                         }
3450
3451                         /* Parse this entry */
3452                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3453
3454                         /* Start the next entry */
3455                         s = t;
3456                 }
3457         }
3458
3459         /* Process 'M' for "Basic Flags" (multiple lines) */
3460         else if (buf[0] == 'M')
3461         {
3462                 /* Parse every entry */
3463                 for (s = buf + 2; *s; )
3464                 {
3465                         /* Find the end of this entry */
3466                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3467
3468                         /* Nuke and skip any dividers */
3469                         if (*t)
3470                         {
3471                                 *t++ = '\0';
3472                                 while (*t == ' ' || *t == '|') t++;
3473                         }
3474
3475                         /* Hack -- Read monster symbols */
3476                         if (!strncmp(s, "R_CHAR_", 7))
3477                         {
3478                                 /* Skip "R_CHAR_" */
3479                                 s += 7;
3480
3481                                 /* Read a string */
3482                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
3483
3484                                 /* Start at next entry */
3485                                 s = t;
3486                                 continue;
3487                         }
3488
3489                         /* Parse this entry */
3490                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3491
3492                         /* Start the next entry */
3493                         s = t;
3494                 }
3495         }
3496
3497         /* Process 'S' for "Spell Flags" (multiple lines) */
3498         else if (buf[0] == 'S')
3499         {
3500                 /* Parse every entry */
3501                 for (s = buf + 2; *s; )
3502                 {
3503                         /* Find the end of this entry */
3504                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3505
3506                         /* Nuke and skip any dividers */
3507                         if (*t)
3508                         {
3509                                 *t++ = '\0';
3510                                 while ((*t == ' ') || (*t == '|')) t++;
3511                         }
3512
3513                         /* Hack -- Read spell frequency */
3514                         if (1 == sscanf(s, "1_IN_%d", &i))
3515                         {
3516                                 /* Start at next entry */
3517                                 s = t;
3518                                 continue;
3519                         }
3520
3521                         /* Parse this entry */
3522                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3523
3524                         /* Start the next entry */
3525                         s = t;
3526                 }
3527         }
3528
3529         else return (6);
3530
3531         /* Success */
3532         return (0);
3533 }
3534
3535
3536 #else   /* ALLOW_TEMPLATES */
3537
3538 #ifdef MACINTOSH
3539 static int i = 0;
3540 #endif
3541
3542 #endif  /* ALLOW_TEMPLATES */
3543
3544
3545 /*!
3546  * @brief 地形情報の「F:」情報をパースする
3547  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3548  * @param buf 解析文字列
3549  * @return エラーコード
3550  */
3551 static errr parse_line_feature(char *buf)
3552 {
3553         int num;
3554         char *zz[9];
3555
3556         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3557
3558         /* Tokenize the line */
3559         if ((num = tokenize(buf + 2, 9, zz, 0)) > 1)
3560         {
3561                 /* Letter to assign */
3562                 int index = zz[0][0];
3563
3564                 /* Reset the info for the letter */
3565                 letter[index].feature = feat_none;
3566                 letter[index].monster = 0;
3567                 letter[index].object = 0;
3568                 letter[index].ego = 0;
3569                 letter[index].artifact = 0;
3570                 letter[index].trap = feat_none;
3571                 letter[index].cave_info = 0;
3572                 letter[index].special = 0;
3573                 letter[index].random = RANDOM_NONE;
3574
3575                 switch (num)
3576                 {
3577                         /* Special */
3578                 case 9:
3579                         letter[index].special = (s16b)atoi(zz[8]);
3580                         /* Fall through */
3581                 /* Trap */
3582                 case 8:
3583                         if ((zz[7][0] == '*') && !zz[7][1])
3584                         {
3585                                 letter[index].random |= RANDOM_TRAP;
3586                         }
3587                         else
3588                         {
3589                                 letter[index].trap = f_tag_to_index(zz[7]);
3590                                 if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3591                         }
3592                         /* Fall through */
3593                 /* Artifact */
3594                 case 7:
3595                         if (zz[6][0] == '*')
3596                         {
3597                                 letter[index].random |= RANDOM_ARTIFACT;
3598                                 if (zz[6][1]) letter[index].artifact = (IDX)atoi(zz[6] + 1);
3599                         }
3600                         else if (zz[6][0] == '!')
3601                         {
3602                                 if (p_ptr->inside_quest)
3603                                 {
3604                                         letter[index].artifact = quest[p_ptr->inside_quest].k_idx;
3605                                 }
3606                         }
3607                         else
3608                         {
3609                                 letter[index].artifact = (IDX)atoi(zz[6]);
3610                         }
3611                         /* Fall through */
3612                 /* Ego-item */
3613                 case 6:
3614                         if (zz[5][0] == '*')
3615                         {
3616                                 letter[index].random |= RANDOM_EGO;
3617                                 if (zz[5][1]) letter[index].ego = (IDX)atoi(zz[5] + 1);
3618                         }
3619                         else
3620                         {
3621                                 letter[index].ego = (IDX)atoi(zz[5]);
3622                         }
3623                         /* Fall through */
3624                 /* Object */
3625                 case 5:
3626                         if (zz[4][0] == '*')
3627                         {
3628                                 letter[index].random |= RANDOM_OBJECT;
3629                                 if (zz[4][1]) letter[index].object = (IDX)atoi(zz[4] + 1);
3630                         }
3631                         else if (zz[4][0] == '!')
3632                         {
3633                                 if (p_ptr->inside_quest)
3634                                 {
3635                                         ARTIFACT_IDX a_idx = quest[p_ptr->inside_quest].k_idx;
3636                                         if (a_idx)
3637                                         {
3638                                                 artifact_type *a_ptr = &a_info[a_idx];
3639                                                 if (!(a_ptr->gen_flags & TRG_INSTA_ART))
3640                                                 {
3641                                                         letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
3642                                                 }
3643                                         }
3644                                 }
3645                         }
3646                         else
3647                         {
3648                                 letter[index].object = (IDX)atoi(zz[4]);
3649                         }
3650                         /* Fall through */
3651                 /* Monster */
3652                 case 4:
3653                         if (zz[3][0] == '*')
3654                         {
3655                                 letter[index].random |= RANDOM_MONSTER;
3656                                 if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1);
3657                         }
3658                         else if (zz[3][0] == 'c')
3659                         {
3660                                 if (!zz[3][1]) return PARSE_ERROR_GENERIC;
3661                                 letter[index].monster = -atoi(zz[3] + 1);
3662                         }
3663                         else
3664                         {
3665                                 letter[index].monster = (IDX)atoi(zz[3]);
3666                         }
3667                         /* Fall through */
3668                 /* Cave info */
3669                 case 3:
3670                         letter[index].cave_info = atoi(zz[2]);
3671                         /* Fall through */
3672                 /* Feature */
3673                 case 2:
3674                         if ((zz[1][0] == '*') && !zz[1][1])
3675                         {
3676                                 letter[index].random |= RANDOM_FEATURE;
3677                         }
3678                         else
3679                         {
3680                                 letter[index].feature = f_tag_to_index(zz[1]);
3681                                 if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3682                         }
3683                         break;
3684                 }
3685
3686                 return (0);
3687         }
3688
3689         return (1);
3690 }
3691
3692
3693 /*!
3694  * @brief 地形情報の「B:」情報をパースする
3695  * Process "B:<Index>:<Command>:..." -- Building definition
3696  * @param buf 解析文字列
3697  * @return エラーコード
3698  */
3699 static errr parse_line_building(char *buf)
3700 {
3701         int i;
3702         char *zz[1000];
3703         int index;
3704         char *s;
3705
3706 #ifdef JP
3707         if (buf[2] == '$')
3708                 return 0;
3709         s = buf + 2;
3710 #else
3711         if (buf[2] != '$')
3712                 return 0;
3713         s = buf + 3;
3714 #endif
3715         /* Get the building number */
3716         index = atoi(s);
3717
3718         /* Find the colon after the building number */
3719         s = my_strchr(s, ':');
3720
3721         /* Verify that colon */
3722         if (!s) return (1);
3723
3724         /* Nuke the colon, advance to the sub-index */
3725         *s++ = '\0';
3726
3727         /* Paranoia -- require a sub-index */
3728         if (!*s) return (1);
3729
3730         /* Building definition sub-index */
3731         switch (s[0])
3732         {
3733                 /* Building name, owner, race */
3734         case 'N':
3735         {
3736                 if (tokenize(s + 2, 3, zz, 0) == 3)
3737                 {
3738                         /* Name of the building */
3739                         strcpy(building[index].name, zz[0]);
3740
3741                         /* Name of the owner */
3742                         strcpy(building[index].owner_name, zz[1]);
3743
3744                         /* Race of the owner */
3745                         strcpy(building[index].owner_race, zz[2]);
3746
3747                         break;
3748                 }
3749
3750                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3751         }
3752
3753         /* Building Action */
3754         case 'A':
3755         {
3756                 if (tokenize(s + 2, 8, zz, 0) >= 7)
3757                 {
3758                         /* Index of the action */
3759                         int action_index = atoi(zz[0]);
3760
3761                         /* Name of the action */
3762                         strcpy(building[index].act_names[action_index], zz[1]);
3763
3764                         /* Cost of the action for members */
3765                         building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
3766
3767                         /* Cost of the action for non-members */
3768                         building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
3769
3770                         /* Letter assigned to the action */
3771                         building[index].letters[action_index] = zz[4][0];
3772
3773                         /* Action code */
3774                         building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]);
3775
3776                         /* Action restriction */
3777                         building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]);
3778
3779                         break;
3780                 }
3781
3782                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3783         }
3784
3785         /* Building Classes */
3786         case 'C':
3787         {
3788                 int n;
3789                 n = tokenize(s + 2, MAX_CLASS, zz, 0);
3790                 for (i = 0; i < MAX_CLASS; i++)
3791                 {
3792                         building[index].member_class[i] = ((i < n) ? (CLASS_IDX)atoi(zz[i]) : 1);
3793                 }
3794                 break;
3795         }
3796
3797         /* Building Races */
3798         case 'R':
3799         {
3800                 int n;
3801                 n = tokenize(s + 2, MAX_RACES, zz, 0);
3802                 for (i = 0; i < MAX_RACES; i++)
3803                 {
3804                         building[index].member_race[i] = ((i < n) ? (RACE_IDX)atoi(zz[i]) : 1);
3805                 }
3806                 break;
3807         }
3808
3809         /* Building Realms */
3810         case 'M':
3811         {
3812                 int n;
3813                 n = tokenize(s + 2, MAX_MAGIC, zz, 0);
3814                 for (i = 0; i < MAX_MAGIC; i++)
3815                 {
3816                         building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1);
3817                 }
3818                 break;
3819         }
3820
3821         case 'Z':
3822         {
3823                 /* Ignore scripts */
3824                 break;
3825         }
3826
3827         default:
3828         {
3829                 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3830         }
3831         }
3832
3833         return (0);
3834 }
3835
3836
3837 /*!
3838  * @brief フロアの所定のマスにオブジェクトを配置する
3839  * Place the object j_ptr to a grid
3840  * @param j_ptr オブジェクト構造体の参照ポインタ
3841  * @param y 配置先Y座標
3842  * @param x 配置先X座標
3843  * @return エラーコード
3844  */
3845 static void drop_here(object_type *j_ptr, POSITION y, POSITION x)
3846 {
3847         grid_type *g_ptr = &current_floor_ptr->grid_array[y][x];
3848         object_type *o_ptr;
3849
3850         OBJECT_IDX o_idx = o_pop();
3851
3852         /* Access new object */
3853         o_ptr = &current_floor_ptr->o_list[o_idx];
3854
3855         /* Structure copy */
3856         object_copy(o_ptr, j_ptr);
3857
3858         /* Locate */
3859         o_ptr->iy = y;
3860         o_ptr->ix = x;
3861
3862         /* No monster */
3863         o_ptr->held_m_idx = 0;
3864
3865         /* Build a stack */
3866         o_ptr->next_o_idx = g_ptr->o_idx;
3867
3868         g_ptr->o_idx = o_idx;
3869 }
3870
3871 /*!
3872  * @brief クエスト用固定ダンジョンをフロアに生成する
3873  * Parse a sub-file of the "extra info"
3874  * @param buf 文字列
3875  * @param ymin 詳細不明
3876  * @param xmin 詳細不明
3877  * @param ymax 詳細不明
3878  * @param xmax 詳細不明
3879  * @param y 詳細不明
3880  * @param x 詳細不明
3881  * @return エラーコード
3882  */
3883 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3884 {
3885         int i;
3886         char *zz[33];
3887
3888         /* Skip "empty" lines */
3889         if (!buf[0]) return (0);
3890
3891         /* Skip "blank" lines */
3892         if (iswspace(buf[0])) return (0);
3893
3894         /* Skip comments */
3895         if (buf[0] == '#') return (0);
3896
3897         /* Require "?:*" format */
3898         if (buf[1] != ':') return (1);
3899
3900
3901         /* Process "%:<fname>" */
3902         if (buf[0] == '%')
3903         {
3904                 /* Attempt to Process the given file */
3905                 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3906         }
3907
3908         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3909         if (buf[0] == 'F')
3910         {
3911                 return parse_line_feature(buf);
3912         }
3913
3914         /* Process "D:<dungeon>" -- info for the current_floor_ptr->grid_array grids */
3915         else if (buf[0] == 'D')
3916         {
3917                 object_type object_type_body;
3918
3919                 /* Acquire the text */
3920                 char *s = buf + 2;
3921
3922                 /* Length of the text */
3923                 int len = strlen(s);
3924
3925                 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3926
3927                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3928                 {
3929                         grid_type *g_ptr = &current_floor_ptr->grid_array[*y][*x];
3930
3931                         int idx = s[0];
3932
3933                         OBJECT_IDX object_index = letter[idx].object;
3934                         MONSTER_IDX monster_index = letter[idx].monster;
3935                         int random = letter[idx].random;
3936                         ARTIFACT_IDX artifact_index = letter[idx].artifact;
3937
3938                         /* Lay down a floor */
3939                         g_ptr->feat = conv_dungeon_feat(letter[idx].feature);
3940
3941                         /* Only the features */
3942                         if (init_flags & INIT_ONLY_FEATURES) continue;
3943
3944                         /* Cave info */
3945                         g_ptr->info = letter[idx].cave_info;
3946
3947                         /* Create a monster */
3948                         if (random & RANDOM_MONSTER)
3949                         {
3950                                 current_floor_ptr->monster_level = current_floor_ptr->base_level + monster_index;
3951
3952                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3953
3954                                 current_floor_ptr->monster_level = current_floor_ptr->base_level;
3955                         }
3956                         else if (monster_index)
3957                         {
3958                                 int old_cur_num, old_max_num;
3959                                 bool clone = FALSE;
3960
3961                                 if (monster_index < 0)
3962                                 {
3963                                         monster_index = -monster_index;
3964                                         clone = TRUE;
3965                                 }
3966                                 old_cur_num = r_info[monster_index].cur_num;
3967                                 old_max_num = r_info[monster_index].max_num;
3968
3969                                 /* Make alive again */
3970                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3971                                 {
3972                                         r_info[monster_index].cur_num = 0;
3973                                         r_info[monster_index].max_num = 1;
3974                                 }
3975
3976                                 /* Make alive again */
3977                                 /* Hack -- Non-unique Nazguls are semi-unique */
3978                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3979                                 {
3980                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3981                                         {
3982                                                 r_info[monster_index].max_num++;
3983                                         }
3984                                 }
3985
3986                                 /* Place it */
3987                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3988                                 if (clone)
3989                                 {
3990                                         /* clone */
3991                                         current_floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
3992
3993                                         /* Make alive again for real unique monster */
3994                                         r_info[monster_index].cur_num = old_cur_num;
3995                                         r_info[monster_index].max_num = old_max_num;
3996                                 }
3997                         }
3998
3999                         /* Object (and possible trap) */
4000                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
4001                         {
4002                                 current_floor_ptr->object_level = current_floor_ptr->base_level + object_index;
4003
4004                                 /*
4005                                  * Random trap and random treasure defined
4006                                  * 25% chance for trap and 75% chance for object
4007                                  */
4008                                 if (randint0(100) < 75)
4009                                 {
4010                                         place_object(*y, *x, 0L);
4011                                 }
4012                                 else
4013                                 {
4014                                         place_trap(*y, *x);
4015                                 }
4016
4017                                 current_floor_ptr->object_level = current_floor_ptr->base_level;
4018                         }
4019                         else if (random & RANDOM_OBJECT)
4020                         {
4021                                 current_floor_ptr->object_level = current_floor_ptr->base_level + object_index;
4022
4023                                 /* Create an out of deep object */
4024                                 if (randint0(100) < 75)
4025                                         place_object(*y, *x, 0L);
4026                                 else if (randint0(100) < 80)
4027                                         place_object(*y, *x, AM_GOOD);
4028                                 else
4029                                         place_object(*y, *x, AM_GOOD | AM_GREAT);
4030
4031                                 current_floor_ptr->object_level = current_floor_ptr->base_level;
4032                         }
4033                         /* Random trap */
4034                         else if (random & RANDOM_TRAP)
4035                         {
4036                                 place_trap(*y, *x);
4037                         }
4038                         /* Hidden trap (or door) */
4039                         else if (letter[idx].trap)
4040                         {
4041                                 g_ptr->mimic = g_ptr->feat;
4042                                 g_ptr->feat = conv_dungeon_feat(letter[idx].trap);
4043                         }
4044                         else if (object_index)
4045                         {
4046                                 object_type *o_ptr = &object_type_body;
4047                                 object_prep(o_ptr, object_index);
4048
4049                                 if (o_ptr->tval == TV_GOLD)
4050                                 {
4051                                         coin_type = object_index - OBJ_GOLD_LIST;
4052                                         make_gold(o_ptr);
4053                                         coin_type = 0;
4054                                 }
4055
4056                                 /* Apply magic (no messages, no artifacts) */
4057                                 apply_magic(o_ptr, current_floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
4058
4059                                 drop_here(o_ptr, *y, *x);
4060                         }
4061
4062                         /* Artifact */
4063                         if (artifact_index)
4064                         {
4065                                 if (a_info[artifact_index].cur_num)
4066                                 {
4067                                         KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
4068                                         object_type forge;
4069                                         object_type *q_ptr = &forge;
4070
4071                                         object_prep(q_ptr, k_idx);
4072                                         drop_here(q_ptr, *y, *x);
4073                                 }
4074                                 else
4075                                 {
4076                                         if (create_named_art(artifact_index, *y, *x))
4077                                                 a_info[artifact_index].cur_num = 1;
4078                                 }
4079                         }
4080
4081                         /* Terrain special */
4082                         g_ptr->special = letter[idx].special;
4083                 }
4084
4085                 (*y)++;
4086
4087                 return (0);
4088         }
4089
4090         /* Process "Q:<number>:<command>:... -- quest info */
4091         else if (buf[0] == 'Q')
4092         {
4093                 int num;
4094                 quest_type *q_ptr;
4095 #ifdef JP
4096                 if (buf[2] == '$')
4097                         return 0;
4098                 num = tokenize(buf + 2, 33, zz, 0);
4099 #else
4100                 if (buf[2] != '$')
4101                         return 0;
4102                 num = tokenize(buf + 3, 33, zz, 0);
4103 #endif
4104
4105                 /* Have we enough parameters? */
4106                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4107
4108                 /* Get the quest */
4109                 q_ptr = &(quest[atoi(zz[0])]);
4110
4111                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
4112                 if (zz[1][0] == 'Q')
4113                 {
4114                         if (init_flags & INIT_ASSIGN)
4115                         {
4116                                 monster_race *r_ptr;
4117                                 artifact_type *a_ptr;
4118
4119                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4120
4121                                 q_ptr->type = (QUEST_TYPE)atoi(zz[2]);
4122                                 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
4123                                 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
4124                                 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
4125                                 q_ptr->level = (DEPTH)atoi(zz[6]);
4126                                 q_ptr->r_idx = (IDX)atoi(zz[7]);
4127                                 q_ptr->k_idx = (IDX)atoi(zz[8]);
4128                                 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
4129
4130                                 if (num > 10) q_ptr->flags = atoi(zz[10]);
4131
4132                                 r_ptr = &r_info[q_ptr->r_idx];
4133                                 if (r_ptr->flags1 & RF1_UNIQUE)
4134                                         r_ptr->flags1 |= RF1_QUESTOR;
4135
4136                                 a_ptr = &a_info[q_ptr->k_idx];
4137                                 a_ptr->gen_flags |= TRG_QUESTITEM;
4138                         }
4139                         return (0);
4140                 }
4141
4142                 else if (zz[1][0] == 'R')
4143                 {
4144                         if (init_flags & INIT_ASSIGN)
4145                         {
4146                                 int count = 0;
4147                                 IDX idx, reward_idx = 0;
4148
4149                                 for (idx = 2; idx < num; idx++)
4150                                 {
4151                                         IDX a_idx = (IDX)atoi(zz[idx]);
4152                                         if (a_idx < 1) continue;
4153                                         if (a_info[a_idx].cur_num > 0) continue;
4154                                         count++;
4155                                         if (one_in_(count)) reward_idx = a_idx;
4156                                 }
4157
4158                                 if (reward_idx)
4159                                 {
4160                                         /* Set quest's rewarding artifact */
4161                                         q_ptr->k_idx = reward_idx;
4162                                         a_info[reward_idx].gen_flags |= TRG_QUESTITEM;
4163                                 }
4164                                 else
4165                                 {
4166                                         /* Change a quest type to KILL_ALL when all artifact of reward list are got */
4167                                         q_ptr->type = QUEST_TYPE_KILL_ALL;
4168                                 }
4169                         }
4170
4171                         return (0);
4172                 }
4173
4174                 /* Process "Q:<q_index>:N:<name>" -- quest name */
4175                 else if (zz[1][0] == 'N')
4176                 {
4177                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY))
4178                         {
4179                                 strcpy(q_ptr->name, zz[2]);
4180                         }
4181
4182                         return (0);
4183                 }
4184
4185                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
4186                 else if (zz[1][0] == 'T')
4187                 {
4188                         if (init_flags & INIT_SHOW_TEXT)
4189                         {
4190                                 strcpy(quest_text[quest_text_line], zz[2]);
4191                                 quest_text_line++;
4192                         }
4193
4194                         return (0);
4195                 }
4196         }
4197
4198         /* Process "W:<command>: ..." -- info for the wilderness */
4199         else if (buf[0] == 'W')
4200         {
4201                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
4202         }
4203
4204         /* Process "P:<y>:<x>" -- player position */
4205         else if (buf[0] == 'P')
4206         {
4207                 if (init_flags & INIT_CREATE_DUNGEON)
4208                 {
4209                         if (tokenize(buf + 2, 2, zz, 0) == 2)
4210                         {
4211                                 int panels_x, panels_y;
4212
4213                                 /* Hack - Set the dungeon size */
4214                                 panels_y = (*y / SCREEN_HGT);
4215                                 if (*y % SCREEN_HGT) panels_y++;
4216                                 current_floor_ptr->height = panels_y * SCREEN_HGT;
4217
4218                                 panels_x = (*x / SCREEN_WID);
4219                                 if (*x % SCREEN_WID) panels_x++;
4220                                 current_floor_ptr->width = panels_x * SCREEN_WID;
4221
4222                                 /* Assume illegal panel */
4223                                 panel_row_min = current_floor_ptr->height;
4224                                 panel_col_min = current_floor_ptr->width;
4225
4226                                 /* Place player in a quest level */
4227                                 if (p_ptr->inside_quest)
4228                                 {
4229                                         POSITION py, px;
4230
4231                                         /* Delete the monster (if any) */
4232                                         delete_monster(p_ptr->y, p_ptr->x);
4233
4234                                         py = atoi(zz[0]);
4235                                         px = atoi(zz[1]);
4236
4237                                         p_ptr->y = py;
4238                                         p_ptr->x = px;
4239                                 }
4240                                 /* Place player in the town */
4241                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
4242                                 {
4243                                         p_ptr->oldpy = atoi(zz[0]);
4244                                         p_ptr->oldpx = atoi(zz[1]);
4245                                 }
4246                         }
4247                 }
4248
4249                 return (0);
4250         }
4251
4252         /* Process "B:<Index>:<Command>:..." -- Building definition */
4253         else if (buf[0] == 'B')
4254         {
4255                 return parse_line_building(buf);
4256         }
4257
4258         /* Process "M:<type>:<maximum>" -- set maximum values */
4259         else if (buf[0] == 'M')
4260         {
4261                 if (tokenize(buf + 2, 2, zz, 0) == 2)
4262                 {
4263                         /* Maximum towns */
4264                         if (zz[0][0] == 'T')
4265                         {
4266                                 max_towns = (TOWN_IDX)atoi(zz[1]);
4267                         }
4268
4269                         /* Maximum quests */
4270                         else if (zz[0][0] == 'Q')
4271                         {
4272                                 max_q_idx = (QUEST_IDX)atoi(zz[1]);
4273                         }
4274
4275                         /* Maximum r_idx */
4276                         else if (zz[0][0] == 'R')
4277                         {
4278                                 max_r_idx = (IDX)atoi(zz[1]);
4279                         }
4280
4281                         /* Maximum k_idx */
4282                         else if (zz[0][0] == 'K')
4283                         {
4284                                 max_k_idx = (IDX)atoi(zz[1]);
4285                         }
4286
4287                         /* Maximum v_idx */
4288                         else if (zz[0][0] == 'V')
4289                         {
4290                                 max_v_idx = (IDX)atoi(zz[1]);
4291                         }
4292
4293                         /* Maximum f_idx */
4294                         else if (zz[0][0] == 'F')
4295                         {
4296                                 max_f_idx = (IDX)atoi(zz[1]);
4297                         }
4298
4299                         /* Maximum a_idx */
4300                         else if (zz[0][0] == 'A')
4301                         {
4302                                 max_a_idx = (IDX)atoi(zz[1]);
4303                         }
4304
4305                         /* Maximum e_idx */
4306                         else if (zz[0][0] == 'E')
4307                         {
4308                                 max_e_idx = (IDX)atoi(zz[1]);
4309                         }
4310
4311                         /* Maximum d_idx */
4312                         else if (zz[0][0] == 'D')
4313                         {
4314                                 max_d_idx = (IDX)atoi(zz[1]);
4315                         }
4316
4317                         /* Maximum o_idx */
4318                         else if (zz[0][0] == 'O')
4319                         {
4320                                 current_floor_ptr->max_o_idx = (IDX)atoi(zz[1]);
4321                         }
4322
4323                         /* Maximum m_idx */
4324                         else if (zz[0][0] == 'M')
4325                         {
4326                                 current_floor_ptr->max_m_idx = (IDX)atoi(zz[1]);
4327                         }
4328
4329                         /* Wilderness size */
4330                         else if (zz[0][0] == 'W')
4331                         {
4332                                 /* Maximum wild_x_size */
4333                                 if (zz[0][1] == 'X')
4334                                         current_world_ptr->max_wild_x = atoi(zz[1]);
4335                                 /* Maximum wild_y_size */
4336                                 if (zz[0][1] == 'Y')
4337                                         current_world_ptr->max_wild_y = atoi(zz[1]);
4338                         }
4339
4340                         return (0);
4341                 }
4342         }
4343
4344
4345         /* Failure */
4346         return (1);
4347 }
4348
4349
4350 static char tmp[8];
4351 static concptr variant = "ZANGBAND";
4352
4353
4354 /*!
4355  * @brief クエスト用固定ダンジョン生成時の分岐処理
4356  * Helper function for "process_dungeon_file()"
4357  * @param sp
4358  * @param fp
4359  * @return エラーコード
4360  */
4361 static concptr process_dungeon_file_expr(char **sp, char *fp)
4362 {
4363         concptr v;
4364
4365         char *b;
4366         char *s;
4367
4368         char b1 = '[';
4369         char b2 = ']';
4370
4371         char f = ' ';
4372
4373         /* Initial */
4374         s = (*sp);
4375
4376         /* Skip spaces */
4377         while (iswspace(*s)) s++;
4378
4379         /* Save start */
4380         b = s;
4381
4382         /* Default */
4383         v = "?o?o?";
4384
4385         /* Analyze */
4386         if (*s == b1)
4387         {
4388                 concptr p;
4389                 concptr t;
4390
4391                 /* Skip b1 */
4392                 s++;
4393
4394                 /* First */
4395                 t = process_dungeon_file_expr(&s, &f);
4396
4397                 if (!*t)
4398                 {
4399                         /* Nothing */
4400                 }
4401
4402                 /* Function: IOR */
4403                 else if (streq(t, "IOR"))
4404                 {
4405                         v = "0";
4406                         while (*s && (f != b2))
4407                         {
4408                                 t = process_dungeon_file_expr(&s, &f);
4409                                 if (*t && !streq(t, "0")) v = "1";
4410                         }
4411                 }
4412
4413                 /* Function: AND */
4414                 else if (streq(t, "AND"))
4415                 {
4416                         v = "1";
4417                         while (*s && (f != b2))
4418                         {
4419                                 t = process_dungeon_file_expr(&s, &f);
4420                                 if (*t && streq(t, "0")) v = "0";
4421                         }
4422                 }
4423
4424                 /* Function: NOT */
4425                 else if (streq(t, "NOT"))
4426                 {
4427                         v = "1";
4428                         while (*s && (f != b2))
4429                         {
4430                                 t = process_dungeon_file_expr(&s, &f);
4431                                 if (*t && streq(t, "1")) v = "0";
4432                         }
4433                 }
4434
4435                 /* Function: EQU */
4436                 else if (streq(t, "EQU"))
4437                 {
4438                         v = "0";
4439                         if (*s && (f != b2))
4440                         {
4441                                 t = process_dungeon_file_expr(&s, &f);
4442                         }
4443                         while (*s && (f != b2))
4444                         {
4445                                 p = process_dungeon_file_expr(&s, &f);
4446                                 if (streq(t, p)) v = "1";
4447                         }
4448                 }
4449
4450                 /* Function: LEQ */
4451                 else if (streq(t, "LEQ"))
4452                 {
4453                         v = "1";
4454                         if (*s && (f != b2))
4455                         {
4456                                 t = process_dungeon_file_expr(&s, &f);
4457                         }
4458                         while (*s && (f != b2))
4459                         {
4460                                 p = t;
4461                                 t = process_dungeon_file_expr(&s, &f);
4462                                 if (*t && atoi(p) > atoi(t)) v = "0";
4463                         }
4464                 }
4465
4466                 /* Function: GEQ */
4467                 else if (streq(t, "GEQ"))
4468                 {
4469                         v = "1";
4470                         if (*s && (f != b2))
4471                         {
4472                                 t = process_dungeon_file_expr(&s, &f);
4473                         }
4474                         while (*s && (f != b2))
4475                         {
4476                                 p = t;
4477                                 t = process_dungeon_file_expr(&s, &f);
4478
4479                                 /* Compare two numbers instead of string */
4480                                 if (*t && atoi(p) < atoi(t)) v = "0";
4481                         }
4482                 }
4483
4484                 else
4485                 {
4486                         while (*s && (f != b2))
4487                         {
4488                                 t = process_dungeon_file_expr(&s, &f);
4489                         }
4490                 }
4491
4492                 /* Verify ending */
4493                 if (f != b2) v = "?x?x?";
4494
4495                 /* Extract final and Terminate */
4496                 if ((f = *s) != '\0') *s++ = '\0';
4497         }
4498
4499         /* Other */
4500         else
4501         {
4502                 /* Accept all printables except spaces and brackets */
4503 #ifdef JP
4504                 while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
4505                 {
4506                         if (iskanji(*s)) s++;
4507                         s++;
4508                 }
4509 #else
4510                 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
4511 #endif
4512
4513                 /* Extract final and Terminate */
4514                 if ((f = *s) != '\0') *s++ = '\0';
4515
4516                 /* Variable */
4517                 if (*b == '$')
4518                 {
4519                         /* System */
4520                         if (streq(b + 1, "SYS"))
4521                         {
4522                                 v = ANGBAND_SYS;
4523                         }
4524
4525                         /* Graphics */
4526                         else if (streq(b + 1, "GRAF"))
4527                         {
4528                                 v = ANGBAND_GRAF;
4529                         }
4530
4531                         else if (streq(b + 1, "MONOCHROME"))
4532                         {
4533                                 if (arg_monochrome)
4534                                         v = "ON";
4535                                 else
4536                                         v = "OFF";
4537                         }
4538
4539                         /* Race */
4540                         else if (streq(b + 1, "RACE"))
4541                         {
4542                                 v = _(rp_ptr->E_title, rp_ptr->title);
4543                         }
4544
4545                         /* Class */
4546                         else if (streq(b + 1, "CLASS"))
4547                         {
4548                                 v = _(cp_ptr->E_title, cp_ptr->title);
4549                         }
4550
4551                         /* First realm */
4552                         else if (streq(b + 1, "REALM1"))
4553                         {
4554                                 v = _(E_realm_names[p_ptr->realm1], realm_names[p_ptr->realm1]);
4555                         }
4556
4557                         /* Second realm */
4558                         else if (streq(b + 1, "REALM2"))
4559                         {
4560                                 v = _(E_realm_names[p_ptr->realm2], realm_names[p_ptr->realm2]);
4561                         }
4562
4563                         /* Player name */
4564                         else if (streq(b + 1, "PLAYER"))
4565                         {
4566                                 static char tmp_player_name[32];
4567                                 char *pn, *tpn;
4568                                 for (pn = p_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
4569                                 {
4570 #ifdef JP
4571                                         if (iskanji(*pn))
4572                                         {
4573                                                 *(tpn++) = *(pn++);
4574                                                 *tpn = *pn;
4575                                                 continue;
4576                                         }
4577 #endif
4578                                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
4579                                 }
4580                                 *tpn = '\0';
4581                                 v = tmp_player_name;
4582                         }
4583
4584                         /* Town */
4585                         else if (streq(b + 1, "TOWN"))
4586                         {
4587                                 sprintf(tmp, "%d", p_ptr->town_num);
4588                                 v = tmp;
4589                         }
4590
4591                         /* Level */
4592                         else if (streq(b + 1, "LEVEL"))
4593                         {
4594                                 sprintf(tmp, "%d", p_ptr->lev);
4595                                 v = tmp;
4596                         }
4597
4598                         /* Current quest number */
4599                         else if (streq(b + 1, "QUEST_NUMBER"))
4600                         {
4601                                 sprintf(tmp, "%d", p_ptr->inside_quest);
4602                                 v = tmp;
4603                         }
4604
4605                         /* Number of last quest */
4606                         else if (streq(b + 1, "LEAVING_QUEST"))
4607                         {
4608                                 sprintf(tmp, "%d", leaving_quest);
4609                                 v = tmp;
4610                         }
4611
4612                         /* Quest type */
4613                         else if (prefix(b + 1, "QUEST_TYPE"))
4614                         {
4615                                 /* "QUEST_TYPE" uses a special parameter to determine the type of the quest */
4616                                 sprintf(tmp, "%d", quest[atoi(b + 11)].type);
4617                                 v = tmp;
4618                         }
4619
4620                         /* Quest status */
4621                         else if (prefix(b + 1, "QUEST"))
4622                         {
4623                                 /* "QUEST" uses a special parameter to determine the number of the quest */
4624                                 sprintf(tmp, "%d", quest[atoi(b + 6)].status);
4625                                 v = tmp;
4626                         }
4627
4628                         /* Random */
4629                         else if (prefix(b + 1, "RANDOM"))
4630                         {
4631                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
4632                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b + 7)));
4633                                 v = tmp;
4634                         }
4635
4636                         /* Variant name */
4637                         else if (streq(b + 1, "VARIANT"))
4638                         {
4639                                 v = variant;
4640                         }
4641
4642                         /* Wilderness */
4643                         else if (streq(b + 1, "WILDERNESS"))
4644                         {
4645                                 if (vanilla_town)
4646                                         sprintf(tmp, "NONE");
4647                                 else if (lite_town)
4648                                         sprintf(tmp, "LITE");
4649                                 else
4650                                         sprintf(tmp, "NORMAL");
4651                                 v = tmp;
4652                         }
4653                 }
4654
4655                 /* Constant */
4656                 else
4657                 {
4658                         v = b;
4659                 }
4660         }
4661
4662         /* Save */
4663         (*fp) = f;
4664         (*sp) = s;
4665         return (v);
4666 }
4667
4668 #if 0
4669 void write_r_info_txt(void)
4670 {
4671         int i, j, z, fc, bc;
4672         int dlen;
4673
4674         concptr flags[32 * 10];
4675
4676         u32b f_ptr[10];
4677         concptr *n_ptr[10];
4678
4679         monster_race *r_ptr;
4680
4681         monster_blow *b_ptr;
4682
4683         FILE *fff = fopen("output.txt", "wt");
4684
4685         concptr desc;
4686
4687         BIT_FLAGS mode = -1;
4688
4689         if (!fff) return;
4690
4691         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4692
4693         fprintf(fff, "# Version stamp (required)\n\n");
4694
4695         /* Write Version */
4696         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4697
4698         /* Write a note */
4699         fprintf(fff, "##### The Player #####\n\n");
4700
4701         for (z = -1; z < alloc_race_size; z++)
4702         {
4703                 /* Output the monsters in order */
4704                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4705
4706                 /* Acquire the monster */
4707                 r_ptr = &r_info[i];
4708
4709                 /* Ignore empty monsters */
4710                 if (!strlen(r_name + r_ptr->name)) continue;
4711
4712                 /* Ignore useless monsters */
4713                 if (i && !r_ptr->speed) continue;
4714
4715                 /* Write a note if necessary */
4716                 if (i && (!r_ptr->level != !mode))
4717                 {
4718                         /* Note the town */
4719                         if (!r_ptr->level)
4720                         {
4721                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4722                         }
4723                         /* Note the dungeon */
4724                         else
4725                         {
4726                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4727                         }
4728
4729                         /* Record the change */
4730                         mode = r_ptr->level;
4731                 }
4732
4733                 /* Acquire the flags */
4734                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4735                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4736                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4737                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4738                 f_ptr[4] = r_ptr->a_ability_flags1; n_ptr[4] = r_a_ability_flags1;
4739                 f_ptr[5] = r_ptr->a_ability_flags2; n_ptr[5] = r_a_ability_flags2;
4740                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4741                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4742                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4743                 f_ptr[9] = r_ptr->flagsr; n_ptr[9] = r_info_flagsr;
4744
4745                 /* Write New/Number/Name */
4746                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4747
4748                 /* Write Graphic */
4749                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4750
4751                 /* Write Information */
4752                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4753                         r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4754
4755                 /* Write more information */
4756                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4757
4758                 /* Write Blows */
4759                 for (j = 0; j < 4; j++)
4760                 {
4761                         b_ptr = &(r_ptr->blow[j]);
4762
4763                         /* Stop when done */
4764                         if (!b_ptr->method) break;
4765
4766                         /* Write the blows */
4767                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4768                                 r_info_blow_effect[b_ptr->effect],
4769                                 b_ptr->d_dice, b_ptr->d_side);
4770                 }
4771                 for (fc = 0, j = 0; j < 32 * 3; j++)
4772                 {
4773                         /* Check this flag */
4774                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4775                 }
4776
4777                 /* Extract the extra flags */
4778                 for (j = 32 * 6; j < 32 * 10; j++)
4779                 {
4780                         /* Check this flag */
4781                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4782                 }
4783
4784                 /* Write the flags */
4785                 for (j = 0; j < fc;)
4786                 {
4787                         char buf[160];
4788
4789                         /* Start the line */
4790                         sprintf(buf, "F:");
4791
4792                         for (bc = 0; (bc < 60) && (j < fc); j++)
4793                         {
4794                                 char t[80];
4795
4796                                 /* Format the flag */
4797                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4798
4799                                 /* Add it to the buffer */
4800                                 strcat(buf, t);
4801
4802                                 /* Note the length */
4803                                 bc += strlen(t);
4804                         }
4805
4806                         /* Done with this line; write it */
4807                         fprintf(fff, "%s\n", buf);
4808                 }
4809
4810                 /* Write Spells if applicable */
4811                 if (r_ptr->freq_spell)
4812                 {
4813                         /* Write the frequency */
4814                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4815
4816                         /* Extract the spell flags */
4817                         for (fc = 0, j = 96; j < 192; j++)
4818                         {
4819                                 /* Check this flag */
4820                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4821                         }
4822
4823                         /* Write the flags */
4824                         for (j = 0; j < fc;)
4825                         {
4826                                 char buf[160], *t;
4827
4828                                 /* Start the line */
4829                                 sprintf(buf, "S:");
4830
4831                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4832                                 {
4833                                         int tlen;
4834
4835                                         /* Format the flag */
4836                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4837
4838                                         tlen = strlen(t);
4839
4840                                         /* Note the length */
4841                                         bc += tlen;
4842
4843                                         /* Advance */
4844                                         t += tlen;
4845                                 }
4846
4847                                 /* Done with this line; write it */
4848                                 fprintf(fff, "%s\n", buf);
4849                         }
4850                 }
4851
4852                 /* Acquire the description */
4853                 desc = r_text + r_ptr->text;
4854                 dlen = strlen(desc);
4855
4856                 /* Write Description */
4857                 for (j = 0; j < dlen;)
4858                 {
4859                         char buf[160], *t;
4860
4861                         /* Start the line */
4862                         sprintf(buf, "D:");
4863
4864                         for (bc = 0, t = buf + 2; ((bc < 60) || !iswspace(desc[j])) && (j < dlen); j++, bc++, t++)
4865                         {
4866                                 *t = desc[j];
4867                         }
4868
4869                         /* Terminate it */
4870                         *t = '\0';
4871
4872                         /* Done with this line; write it */
4873                         fprintf(fff, "%s\n", buf);
4874                 }
4875
4876                 /* Space between entries */
4877                 fprintf(fff, "\n");
4878         }
4879
4880         fclose(fff);
4881 }
4882
4883 #endif
4884
4885
4886 /*!
4887  * @brief クエスト用固定ダンジョン生成時のメインルーチン
4888  * Helper function for "process_dungeon_file()"
4889  * @param name ファイル名
4890  * @param ymin 詳細不明
4891  * @param xmin 詳細不明
4892  * @param ymax 詳細不明
4893  * @param xmax 詳細不明
4894  * @return エラーコード
4895  */
4896 errr process_dungeon_file(concptr name, int ymin, int xmin, int ymax, int xmax)
4897 {
4898         FILE *fp;
4899         char buf[1024];
4900         int num = -1;
4901         errr err = 0;
4902         bool bypass = FALSE;
4903         int x = xmin, y = ymin;
4904
4905
4906         /* Build the filename */
4907         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
4908
4909         /* Open the file */
4910         fp = my_fopen(buf, "r");
4911
4912         /* No such file */
4913         if (!fp) return (-1);
4914
4915
4916         /* Process the file */
4917         while (0 == my_fgets(fp, buf, sizeof(buf)))
4918         {
4919                 /* Count lines */
4920                 num++;
4921
4922
4923                 /* Skip "empty" lines */
4924                 if (!buf[0]) continue;
4925
4926                 /* Skip "blank" lines */
4927                 if (iswspace(buf[0])) continue;
4928
4929                 /* Skip comments */
4930                 if (buf[0] == '#') continue;
4931
4932
4933                 /* Process "?:<expr>" */
4934                 if ((buf[0] == '?') && (buf[1] == ':'))
4935                 {
4936                         char f;
4937                         concptr v;
4938                         char *s;
4939
4940                         /* Start */
4941                         s = buf + 2;
4942
4943                         /* Parse the expr */
4944                         v = process_dungeon_file_expr(&s, &f);
4945
4946                         /* Set flag */
4947                         bypass = (streq(v, "0") ? TRUE : FALSE);
4948                         continue;
4949                 }
4950
4951                 /* Apply conditionals */
4952                 if (bypass) continue;
4953
4954                 /* Process the line */
4955                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4956
4957                 if (err) break;
4958         }
4959
4960         /* Errors */
4961         if (err)
4962         {
4963                 concptr oops;
4964
4965                 /* Error string */
4966                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4967
4968                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4969                 msg_format(_("'%s'を解析中。", "Parsing '%s'."), buf);
4970
4971                 msg_print(NULL);
4972         }
4973
4974         my_fclose(fp);
4975         return (err);
4976 }
4977
4978