OSDN Git Service

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