OSDN Git Service

Merge remote-tracking branch 'remotes/origin/MERFOLK'
[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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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 concptr 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         "LAKE_ACID",
967         "LAKE_POISONOUS",
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         "ACID_RIVER",
984         "POISONOUS_RIVER"
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, concptr 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, concptr 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, concptr 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, parse_info_txt_func parse_info_txt_line)
1181 {
1182         errr err;
1183
1184         /* Just before the first record */
1185         error_idx = -1;
1186
1187         /* Just before the first line */
1188         error_line = 0;
1189
1190
1191         /* Prepare the "fake" stuff */
1192         head->name_size = 0;
1193         head->text_size = 0;
1194         head->tag_size = 0;
1195
1196         /* Parse */
1197         while (0 == my_fgets(fp, buf, 1024))
1198         {
1199                 /* Advance the line number */
1200                 error_line++;
1201
1202                 /* Skip comments and blank lines */
1203                 if (!buf[0] || (buf[0] == '#')) continue;
1204
1205                 /* Verify correct "colon" format */
1206                 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
1207
1208
1209                 /* Hack -- Process 'V' for "Version" */
1210                 if (buf[0] == 'V')
1211                 {
1212                         /* ignore */
1213                         continue;
1214                 }
1215
1216                 /* Mega Hack -- Calculate Check Sum */
1217                 if (buf[0] != 'N' && buf[0] != 'D')
1218                 {
1219                         int i;
1220                         for (i = 0; buf[i]; i++)
1221                         {
1222                                 head->v_extra += (byte)buf[i];
1223                                 head->v_extra ^= (1 << (i % 8));
1224                         }
1225                 }
1226
1227                 /* Parse the line */
1228                 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
1229                         return (err);
1230         }
1231
1232
1233         /* Complete the "name" and "text" sizes */
1234         if (head->name_size) head->name_size++;
1235         if (head->text_size) head->text_size++;
1236
1237         /* Success */
1238         return (0);
1239 }
1240
1241
1242 /*!
1243  * @brief Vault情報(v_info)のパース関数 /
1244  * Initialize the "v_info" array, by parsing an ascii "template" file
1245  * @param buf テキスト列
1246  * @param head ヘッダ構造体
1247  * @return エラーコード
1248  */
1249 errr parse_v_info(char *buf, header *head)
1250 {
1251         int i;
1252         char *s;
1253
1254         /* Current entry */
1255         static vault_type *v_ptr = NULL;
1256
1257         /* Process 'N' for "New/Number/Name" */
1258         if (buf[0] == 'N')
1259         {
1260                 /* Find the colon before the name */
1261                 s = my_strchr(buf+2, ':');
1262
1263                 /* Verify that colon */
1264                 if (!s) return (1);
1265
1266                 /* Nuke the colon, advance to the name */
1267                 *s++ = '\0';
1268
1269                 /* Paranoia -- require a name */
1270                 if (!*s) return (1);
1271
1272                 /* Get the index */
1273                 i = atoi(buf+2);
1274
1275                 /* Verify information */
1276                 if (i <= error_idx) return (4);
1277
1278                 /* Verify information */
1279                 if (i >= head->info_num) return (2);
1280
1281                 /* Save the index */
1282                 error_idx = i;
1283
1284                 /* Point at the "info" */
1285                 v_ptr = &v_info[i];
1286
1287                 /* Store the name */
1288                 if (!add_name(&v_ptr->name, head, s)) return (7);
1289         }
1290
1291         /* There better be a current v_ptr */
1292         else if (!v_ptr) return (3);
1293
1294         /* Process 'D' for "Description" */
1295         else if (buf[0] == 'D')
1296         {
1297                 /* Acquire the text */
1298                 s = buf+2;
1299
1300                 /* Store the text */
1301                 if (!add_text(&v_ptr->text, head, s, FALSE)) return (7);
1302         }
1303
1304         /* Process 'X' for "Extra info" (one line only) */
1305         else if (buf[0] == 'X')
1306         {
1307                 EFFECT_ID typ, rat, hgt, wid;
1308
1309                 /* Scan for the values */
1310                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1311                         &typ, &rat, &hgt, &wid)) return (1);
1312
1313                 /* Save the values */
1314                 v_ptr->typ = (ROOM_IDX)typ;
1315                 v_ptr->rat = (PROB)rat;
1316                 v_ptr->hgt = (POSITION)hgt;
1317                 v_ptr->wid = (POSITION)wid;
1318         }
1319
1320         else    return (6);
1321
1322         /* Success */
1323         return (0);
1324 }
1325
1326
1327 /*!
1328  * @brief 職業技能情報(s_info)のパース関数 /
1329  * Initialize the "s_info" array, by parsing an ascii "template" file
1330  * @param buf テキスト列
1331  * @param head ヘッダ構造体
1332  * @return エラーコード
1333  */
1334 errr parse_s_info(char *buf, header *head)
1335 {
1336         int i;
1337
1338         /* Current entry */
1339         static skill_table *s_ptr = NULL;
1340
1341
1342         /* Process 'N' for "New/Number/Name" */
1343         if (buf[0] == 'N')
1344         {
1345                 /* Get the index */
1346                 i = atoi(buf+2);
1347
1348                         /* Verify information */
1349                 if (i <= error_idx) return (4);
1350
1351                 /* Verify information */
1352                 if (i >= head->info_num) return (2);
1353
1354                 /* Save the index */
1355                 error_idx = i;
1356
1357                 /* Point at the "info" */
1358                 s_ptr = &s_info[i];
1359         }
1360
1361         /* There better be a current s_ptr */
1362         else if (!s_ptr) return (3);
1363
1364         /* Process 'W' for "Weapon exp" */
1365         else if (buf[0] == 'W')
1366         {
1367                 int tval, sval, start, max;
1368                 const s16b exp_conv_table[] =
1369                 {
1370                         WEAPON_EXP_UNSKILLED, WEAPON_EXP_BEGINNER, WEAPON_EXP_SKILLED,
1371                         WEAPON_EXP_EXPERT, WEAPON_EXP_MASTER
1372                 };
1373
1374                 /* Scan for the values */
1375                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1376                                 &tval, &sval, &start, &max)) return (1);
1377
1378                 if (start < EXP_LEVEL_UNSKILLED || start > EXP_LEVEL_MASTER
1379                         || max < EXP_LEVEL_UNSKILLED || max > EXP_LEVEL_MASTER) return (8);
1380
1381                 /* Save the values */
1382                 s_ptr->w_start[tval][sval] = exp_conv_table[start];
1383                 s_ptr->w_max[tval][sval] = exp_conv_table[max];
1384         }
1385
1386         /* Process 'S' for "Skill exp" */
1387         else if (buf[0] == 'S')
1388         {
1389                 int num, start, max;
1390
1391                 /* Scan for the values */
1392                 if (3 != sscanf(buf+2, "%d:%d:%d",
1393                                 &num, &start, &max)) return (1);
1394
1395                 if (start < WEAPON_EXP_UNSKILLED || start > WEAPON_EXP_MASTER
1396                         || max < WEAPON_EXP_UNSKILLED || max > WEAPON_EXP_MASTER) return (8);
1397
1398                 /* Save the values */
1399                 s_ptr->s_start[num] = (SUB_EXP)start;
1400                 s_ptr->s_max[num] = (SUB_EXP)max;
1401         }
1402
1403
1404         else return (6);
1405
1406         /* Success */
1407         return (0);
1408 }
1409
1410
1411 /*!
1412  * @brief 職業魔法情報(m_info)のパース関数 /
1413  * Initialize the "m_info" array, by parsing an ascii "template" file
1414  * @param buf テキスト列
1415  * @param head ヘッダ構造体
1416  * @return エラーコード
1417  */
1418 errr parse_m_info(char *buf, header *head)
1419 {
1420         int i;
1421
1422         char *s;
1423
1424         /* Current entry */
1425         static player_magic *m_ptr = NULL;
1426
1427         /* ---Hack--- */
1428         static int realm, magic_idx = 0, readable = 0;
1429
1430
1431         /* Process 'N' for "New/Number/Name" */
1432         if (buf[0] == 'N')
1433         {
1434                 /* Get the index */
1435                 i = atoi(buf+2);
1436
1437                         /* Verify information */
1438                 if (i <= error_idx) return (4);
1439
1440                 /* Verify information */
1441                 if (i >= head->info_num) return (2);
1442
1443                 /* Save the index */
1444                 error_idx = i;
1445
1446                 /* Point at the "info" */
1447                 m_ptr = &m_info[i];
1448         }
1449
1450         /* There better be a current m_ptr */
1451         else if (!m_ptr) return (3);
1452
1453         /* Process 'I' for "Info" (one line only) */
1454         else if (buf[0] == 'I')
1455         {
1456                 char *book, *stat;
1457                 int xtra, type, first, weight;
1458
1459                 /* Find the colon before the name */
1460                 s = my_strchr(buf+2, ':');
1461
1462                 /* Verify that colon */
1463                 if (!s) return (1);
1464
1465                 /* Nuke the colon, advance to the name */
1466                 *s++ = '\0';
1467
1468                 book = buf+2;
1469
1470                 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1471                 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1472                 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1473                 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1474                 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1475                 else return (5);
1476
1477                 stat = s;
1478
1479                 /* Find the colon before the name */
1480                 s = my_strchr(s, ':');
1481
1482                 /* Verify that colon */
1483                 if (!s) return (1);
1484
1485                 /* Nuke the colon, advance to the name */
1486                 *s++ = '\0';
1487
1488                 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1489                 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1490                 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1491                 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1492                 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1493                 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1494                 else return (5);
1495
1496
1497                 /* Scan for the values */
1498                 if (4 != sscanf(s, "%x:%d:%d:%d",
1499                                 (uint *)&xtra, &type, &first, &weight)) return (1);
1500
1501                 m_ptr->spell_xtra = xtra;
1502                 m_ptr->spell_type = type;
1503                 m_ptr->spell_first = first;
1504                 m_ptr->spell_weight = weight;
1505         }
1506
1507
1508         /* Process 'R' for "Realm" (one line only) */
1509         else if (buf[0] == 'R')
1510         {
1511                 /* Scan for the values */
1512                 if (2 != sscanf(buf+2, "%d:%d",
1513                                 &realm, &readable)) return (1);
1514
1515                 magic_idx = 0;
1516         }
1517
1518         else if (buf[0] == 'T')
1519         {
1520                 int level, mana, fail, exp;
1521
1522                 if (!readable) return (1);
1523                 /* Scan for the values */
1524                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1525                                 &level, &mana, &fail, &exp)) return (1);
1526
1527                 m_ptr->info[realm][magic_idx].slevel = (PLAYER_LEVEL)level;
1528                 m_ptr->info[realm][magic_idx].smana = (MANA_POINT)mana;
1529                 m_ptr->info[realm][magic_idx].sfail = (PERCENTAGE)fail;
1530                 m_ptr->info[realm][magic_idx].sexp = (EXP)exp;
1531                 magic_idx ++;
1532         }
1533
1534
1535         else return (6);
1536
1537         /* Success */
1538         return (0);
1539 }
1540
1541
1542 /*!
1543  * @brief テキストトークンを走査してフラグを一つ得る(汎用) /
1544  * Grab one flag from a textual string
1545  * @param flags ビットフラグを追加する先の参照ポインタ
1546  * @param names トークン定義配列
1547  * @param what 参照元の文字列ポインタ
1548  * @return エラーコード
1549  */
1550 static errr grab_one_flag(u32b *flags, concptr names[], concptr what)
1551 {
1552         int i;
1553
1554         /* Check flags */
1555         for (i = 0; i < 32; i++)
1556         {
1557                 if (streq(what, names[i]))
1558                 {
1559                         *flags |= (1L << i);
1560                         return 0;
1561                 }
1562         }
1563
1564         return -1;
1565 }
1566
1567
1568 /*!
1569  * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
1570  * Grab one flag in an feature_type from a textual string
1571  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1572  * @param what 参照元の文字列ポインタ
1573  * @return エラーコード
1574  */
1575 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
1576 {
1577         int i;
1578
1579         /* Check flags */
1580         for (i = 0; i < FF_FLAG_MAX; i++)
1581         {
1582                 if (streq(what, f_info_flags[i]))
1583                 {
1584                         add_flag(f_ptr->flags, i);
1585                         return 0;
1586                 }
1587         }
1588
1589         msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
1590
1591         /* Error */
1592         return PARSE_ERROR_GENERIC;
1593 }
1594
1595
1596 /*!
1597  * @brief テキストトークンを走査してフラグ(ステート)を一つ得る(地形情報向け2) /
1598  * Grab an action in an feature_type from a textual string
1599  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1600  * @param what 参照元の文字列ポインタ
1601  * @param count ステートの保存先ID
1602  * @return エラーコード
1603  */
1604 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
1605 {
1606         FF_FLAGS_IDX i;
1607
1608         /* Check flags */
1609         for (i = 0; i < FF_FLAG_MAX; i++)
1610         {
1611                 if (streq(what, f_info_flags[i]))
1612                 {
1613                         f_ptr->state[count].action = i;
1614                         return 0;
1615                 }
1616         }
1617
1618         msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
1619
1620         /* Error */
1621         return PARSE_ERROR_GENERIC;
1622 }
1623
1624
1625 /*!
1626  * @brief 地形情報(f_info)のパース関数 /
1627  * Initialize the "f_info" array, by parsing an ascii "template" file
1628  * @param buf テキスト列
1629  * @param head ヘッダ構造体
1630  * @return エラーコード
1631  */
1632 errr parse_f_info(char *buf, header *head)
1633 {
1634         int i;
1635
1636         char *s, *t;
1637
1638         /* Current entry */
1639         static feature_type *f_ptr = NULL;
1640
1641
1642         /* Process 'N' for "New/Number/Name" */
1643         if (buf[0] == 'N')
1644         {
1645                 /* Find the colon before the name */
1646                 s = my_strchr(buf+2, ':');
1647
1648                 if (s)
1649                 {
1650                         /* Nuke the colon, advance to the name */
1651                         *s++ = '\0';
1652                 }
1653
1654                 /* Get the index */
1655                 i = atoi(buf+2);
1656
1657                 /* Verify information */
1658                 if (i <= error_idx) return (4);
1659
1660                 /* Verify information */
1661                 if (i >= head->info_num) return (2);
1662
1663                 /* Save the index */
1664                 error_idx = i;
1665
1666                 /* Point at the "info" */
1667                 f_ptr = &f_info[i];
1668
1669                 /* Tag name is given */
1670                 if (s)
1671                 {
1672                         /* Store the tag */
1673                         if (!add_tag(&f_ptr->tag, head, s)) return (7);
1674                 }
1675
1676                 /* Default "mimic" */
1677                 f_ptr->mimic = (FEAT_IDX)i;
1678
1679                 /* Default "destroyed state" -- if not specified */
1680                 f_ptr->destroyed = (FEAT_IDX)i;
1681
1682                 /* Default "states" */
1683                 for (i = 0; i < MAX_FEAT_STATES; i++) f_ptr->state[i].action = FF_FLAG_MAX;
1684         }
1685
1686         /* There better be a current f_ptr */
1687         else if (!f_ptr) return (3);
1688
1689 #ifdef JP
1690         else if (buf[0] == 'J')
1691         {
1692                 /* Store the name */
1693                 if (!add_name(&f_ptr->name, head, buf+2)) return (7);
1694         }
1695
1696         else if (buf[0] == 'E')
1697         {
1698                 /* Ignore english name */
1699         }
1700 #else
1701         else if (buf[0] == 'J')
1702         {
1703                 /* Ignore Japanese name */
1704         }
1705
1706         else if (buf[0] == 'E')
1707         {
1708                 /* Acquire the Text */
1709                 s = buf+2;
1710
1711                 /* Store the name */
1712                 if (!add_name(&f_ptr->name, head, s)) return (7);
1713         }
1714 #endif
1715
1716
1717         /* Process 'M' for "Mimic" (one line only) */
1718         else if (buf[0] == 'M')
1719         {
1720                 STR_OFFSET offset;
1721
1722                 if (!add_tag(&offset, head, buf + 2)) return PARSE_ERROR_OUT_OF_MEMORY;
1723
1724                 /* Record a fake tag index */
1725                 f_ptr->mimic_tag = offset;
1726         }
1727
1728
1729         /* Process 'G' for "Graphics" (one line only) */
1730         else if (buf[0] == 'G')
1731         {
1732                 int j;
1733                 byte s_attr;
1734                 char char_tmp[F_LIT_MAX];
1735
1736                 /* Paranoia */
1737                 if (buf[1] != ':') return (1);
1738                 if (!buf[2]) return (1);
1739                 if (buf[3] != ':') return (1);
1740                 if (!buf[4]) return (1);
1741
1742                 /* Extract the char */
1743                 char_tmp[F_LIT_STANDARD] = buf[2];
1744
1745                 /* Extract the color */
1746                 s_attr = color_char_to_attr(buf[4]);
1747
1748                 /* Paranoia */
1749                 if (s_attr > 127) return (1);
1750
1751                 /* Save the standard values */
1752                 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
1753                 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
1754
1755                 /* Is this feature supports lighting? */
1756                 if (buf[5] == ':')
1757                 {
1758                         /* G:c:a:LIT (default) */
1759                         apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
1760
1761                         /* G:c:a:lc:la:dc:da */
1762                         if (!streq(buf + 6, "LIT"))
1763                         {
1764                                 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
1765
1766                                 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
1767                                         &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
1768                                         &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
1769                                 if (buf[F_LIT_MAX * 4 + 1]) return 1;
1770
1771                                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1772                                 {
1773                                         switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
1774                                         {
1775                                         case '*':
1776                                                 /* Use default lighting */
1777                                                 break;
1778                                         case '-':
1779                                                 /* No lighting support */
1780                                                 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
1781                                                 break;
1782                                         default:
1783                                                 /* Extract the color */
1784                                                 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
1785                                                 if (f_ptr->d_attr[j] > 127) return 1;
1786                                                 break;
1787                                         }
1788                                         f_ptr->d_char[j] = char_tmp[j];
1789                                 }
1790                         }
1791                 }
1792                 else if (!buf[5])
1793                 {
1794                         for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1795                         {
1796                                 f_ptr->d_attr[j] = s_attr;
1797                                 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
1798                         }
1799                 }
1800                 else return 1;
1801         }
1802
1803         /* Hack -- Process 'F' for flags */
1804         else if (buf[0] == 'F')
1805         {
1806                 /* Parse every entry textually */
1807                 for (s = buf + 2; *s; )
1808                 {
1809                         /* Find the end of this entry */
1810                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1811
1812                         /* Nuke and skip any dividers */
1813                         if (*t)
1814                         {
1815                                 *t++ = '\0';
1816                                 while (*t == ' ' || *t == '|') t++;
1817                         }
1818
1819                         /* Hack -- Read feature subtype */
1820                         if (1 == sscanf(s, "SUBTYPE_%d", &i))
1821                         {
1822                                 /* Extract a "subtype" */
1823                                 f_ptr->subtype = (FEAT_SUBTYPE)i;
1824
1825                                 /* Start at next entry */
1826                                 s = t;
1827
1828                                 continue;
1829                         }
1830
1831                         /* Hack -- Read feature power */
1832                         if (1 == sscanf(s, "POWER_%d", &i))
1833                         {
1834                                 /* Extract a "power" */
1835                                 f_ptr->power = (FEAT_POWER)i;
1836
1837                                 /* Start at next entry */
1838                                 s = t;
1839                                 continue;
1840                         }
1841
1842                         /* Parse this entry */
1843                         if (0 != grab_one_feat_flag(f_ptr, s)) return (PARSE_ERROR_INVALID_FLAG);
1844
1845                         /* Start the next entry */
1846                         s = t;
1847                 }
1848         }
1849
1850         /* Process 'W' for "More Info" (one line only) */
1851         else if (buf[0] == 'W')
1852         {
1853                 int priority;
1854
1855                 /* Scan for the value */
1856                 if (1 != sscanf(buf+2, "%d", &priority)) return (PARSE_ERROR_GENERIC);
1857
1858                 /* Save the value */
1859                 f_ptr->priority = (FEAT_PRIORITY)priority;
1860         }
1861
1862         /* Process 'K' for "States" (up to four lines + default (which cannot be last)) */
1863         else if (buf[0] == 'K')
1864         {
1865                 STR_OFFSET offset;
1866
1867                 /* Find the next empty state slot (if any) */
1868                 for (i = 0; i < MAX_FEAT_STATES; i++) if (f_ptr->state[i].action == FF_FLAG_MAX) break;
1869
1870                 /* Oops, no more slots */
1871                 if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
1872
1873                 /* Analyze the first field */
1874                 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
1875
1876                 /* Terminate the field (if necessary) */
1877                 if (*t == ':') *t++ = '\0';
1878
1879                 /* Is this default entry? */
1880                 if (streq(s, "DESTROYED"))
1881                 {
1882                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1883
1884                         /* Record a fake tag index */
1885                         f_ptr->destroyed_tag = offset;
1886                 }
1887                 else
1888                 {
1889                         /* Reset */
1890                         f_ptr->state[i].action = 0;
1891
1892                         /* Parse this entry */
1893                         if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
1894
1895                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1896
1897                         /* Record a fake tag index */
1898                         f_ptr->state[i].result_tag = offset;
1899                 }
1900         }
1901
1902         else return (6);
1903
1904         /* Success */
1905         return (0);
1906 }
1907
1908
1909 /*!
1910  * @brief 地形タグからIDを得る /
1911  * Convert a fake tag to a real feat index
1912  * @param str タグ文字列
1913  * @return 地形ID
1914  */
1915 s16b f_tag_to_index(concptr str)
1916 {
1917         u16b i;
1918
1919         /* Search for real index corresponding to this fake tag */
1920         for (i = 0; i < f_head.info_num; i++)
1921         {
1922                 if (streq(f_tag + f_info[i].tag, str))
1923                 {
1924                         /* Return the index */
1925                         return (s16b)i;
1926                 }
1927         }
1928
1929         /* Not found */
1930         return -1;
1931 }
1932
1933
1934 /*!
1935  * @brief 地形タグからIDを得る /
1936  * Search for real index corresponding to this fake tag
1937  * @param feat タグ文字列のオフセット
1938  * @return 地形ID。該当がないなら-1
1939  */
1940 static FEAT_IDX search_real_feat(STR_OFFSET feat)
1941 {
1942         FEAT_IDX i;
1943
1944         /* Don't convert non-fake tag */
1945         if (feat <= 0)
1946         {
1947                 return -1;
1948         }
1949
1950         /* Search for real index corresponding to this fake tag */
1951         for (i = 0; i < f_head.info_num; i++)
1952         {
1953                 if (feat == f_info[i].tag)
1954                 {
1955                         /* Record real index */
1956                         return i;
1957                 }
1958         }
1959
1960         /* Undefined tag */
1961         msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
1962         return -1;
1963 }
1964
1965
1966 /*!
1967  * @brief 地形情報の各種タグからIDへ変換して結果を収める /
1968  * Retouch fake tags of f_info
1969  * @param head ヘッダ構造体
1970  * @return なし
1971  */
1972 void retouch_f_info(header *head)
1973 {
1974         int i;
1975
1976         /* Convert fake tags to real feat indices */
1977         for (i = 0; i < head->info_num; i++)
1978         {
1979                 feature_type *f_ptr = &f_info[i];
1980                 FEAT_IDX j, k;
1981
1982                 k = search_real_feat(f_ptr->mimic_tag);
1983                 f_ptr->mimic = k < 0 ? f_ptr->mimic : k;
1984                 k = search_real_feat(f_ptr->destroyed_tag);
1985                 f_ptr->destroyed = k < 0 ? f_ptr->destroyed : k;
1986                 for (j = 0; j < MAX_FEAT_STATES; j++)
1987                 {
1988                         k = search_real_feat(f_ptr->state[j].result_tag);
1989                         f_ptr->state[j].result = k < 0 ? f_ptr->state[j].result : k;
1990                 }
1991         }
1992 }
1993
1994
1995 /*!
1996  * @brief テキストトークンを走査してフラグを一つ得る(ベースアイテム用) /
1997  * Grab one flag in an object_kind from a textual string
1998  * @param k_ptr 保管先のベースアイテム構造体参照ポインタ
1999  * @param what 参照元の文字列ポインタ
2000  * @return エラーコード
2001  */
2002 static errr grab_one_kind_flag(object_kind *k_ptr, concptr what)
2003 {
2004         int i;
2005
2006         /* Check flags */
2007         for (i = 0; i < TR_FLAG_MAX; i++)
2008         {
2009                 if (streq(what, k_info_flags[i]))
2010                 {
2011                         add_flag(k_ptr->flags, i);
2012                         return (0);
2013                 }
2014         }
2015
2016         if (grab_one_flag(&k_ptr->gen_flags, k_info_gen_flags, what) == 0)
2017                 return 0;
2018
2019         msg_format(_("未知のアイテム・フラグ '%s'。", "Unknown object flag '%s'."), what);
2020
2021         /* Error */
2022         return (1);
2023 }
2024
2025 /*!
2026  * @brief テキストトークンを走査してフラグを一つ得る(発動能力用) /
2027  * Grab one activation index flag
2028  * @param what 参照元の文字列ポインタ
2029  * @return 発動能力ID
2030  */
2031 static byte grab_one_activation_flag(concptr what)
2032 {
2033         int i;
2034
2035         for (i = 0; ; i++)
2036         {
2037                 if (activation_info[i].flag == NULL) break;
2038
2039                 if (streq(what, activation_info[i].flag))
2040                 {
2041                         return activation_info[i].index;
2042                 }
2043         }
2044
2045         i = atoi(what);
2046          if (i > 0)
2047          {
2048                  return ((byte) i);
2049          }
2050
2051         msg_format(_("未知の発動・フラグ '%s'。", "Unknown activation flag '%s'."), what);
2052
2053         /* Error */
2054         return (0);
2055 }
2056
2057
2058 /*!
2059  * @brief ベースアイテム(k_info)のパース関数 /
2060  * Initialize the "k_info" array, by parsing an ascii "template" file
2061  * @param buf テキスト列
2062  * @param head ヘッダ構造体
2063  * @return エラーコード
2064  */
2065 errr parse_k_info(char *buf, header *head)
2066 {
2067         int i;
2068
2069         char *s, *t;
2070
2071         /* Current entry */
2072         static object_kind *k_ptr = NULL;
2073
2074
2075         /* Process 'N' for "New/Number/Name" */
2076         if (buf[0] == 'N')
2077         {
2078 #ifdef JP
2079                 char *flavor;
2080 #endif
2081
2082                 /* Find the colon before the name */
2083                 s = my_strchr(buf+2, ':');
2084
2085                 /* Verify that colon */
2086                 if (!s) return (1);
2087
2088                 /* Nuke the colon, advance to the name */
2089                 *s++ = '\0';
2090
2091                 /* Get the index */
2092                 i = atoi(buf+2);
2093
2094                 /* Verify information */
2095                 if (i <= error_idx) return (4);
2096
2097                 /* Verify information */
2098                 if (i >= head->info_num) return (2);
2099
2100                 /* Save the index */
2101                 error_idx = i;
2102
2103                 /* Point at the "info" */
2104                 k_ptr = &k_info[i];
2105
2106 #ifdef JP
2107                 /* Paranoia -- require a name */
2108                 if (!*s) return (1);
2109
2110                 /* Find the colon before the flavor */
2111                 flavor = my_strchr(s, ':');
2112
2113                 /* Verify that colon */
2114                 if (flavor)
2115                 {
2116                         /* Nuke the colon, advance to the flavor */
2117                         *flavor++ = '\0';
2118
2119                         /* Store the flavor */
2120                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return (7);
2121                 }
2122
2123                 /* Store the name */
2124                 if (!add_name(&k_ptr->name, head, s)) return (7);
2125 #endif
2126         }
2127
2128         /* There better be a current k_ptr */
2129         else if (!k_ptr) return (3);
2130
2131
2132 #ifdef JP
2133         /* 英語名を読むルーチンを追加 */
2134         /* 'E' から始まる行は英語名としている */
2135         else if (buf[0] == 'E')
2136         {
2137                 /* nothing to do */
2138         }
2139 #else
2140         else if (buf[0] == 'E')
2141         {
2142                 char *flavor;
2143
2144                 /* Acquire the name */
2145                 s = buf+2;
2146
2147                 /* Find the colon before the flavor */
2148                 flavor = my_strchr(s, ':');
2149
2150                 /* Verify that colon */
2151                 if (flavor)
2152                 {
2153                         /* Nuke the colon, advance to the flavor */
2154                         *flavor++ = '\0';
2155
2156                         /* Store the flavor */
2157                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return (7);
2158                 }
2159
2160                 /* Store the name */
2161                 if (!add_name(&k_ptr->name, head, s)) return (7);
2162         }
2163 #endif
2164
2165         /* Process 'D' for "Description" */
2166         else if (buf[0] == 'D')
2167         {
2168 #ifdef JP
2169                 if (buf[2] == '$')
2170                         return (0);
2171                 /* Acquire the text */
2172                 s = buf+2;
2173 #else
2174                 if (buf[2] != '$')
2175                         return (0);
2176                 /* Acquire the text */
2177                 s = buf+3;
2178 #endif
2179
2180                 /* Store the text */
2181                 if (!add_text(&k_ptr->text, head, s, TRUE)) return (7);
2182         }
2183
2184         /* Process 'G' for "Graphics" (one line only) */
2185         else if (buf[0] == 'G')
2186         {
2187                 char sym;
2188                 byte tmp;
2189
2190                 /* Paranoia */
2191                 if (buf[1] != ':') return (1);
2192                 if (!buf[2]) return (1);
2193                 if (buf[3] != ':') return (1);
2194                 if (!buf[4]) return (1);
2195
2196                 /* Extract the char */
2197                 sym = buf[2];
2198
2199                 /* Extract the attr */
2200                 tmp = color_char_to_attr(buf[4]);
2201
2202                 /* Paranoia */
2203                 if (tmp > 127) return (1);
2204
2205                 /* Save the values */
2206                 k_ptr->d_attr = tmp;
2207                 k_ptr->d_char = sym;
2208         }
2209
2210         /* Process 'I' for "Info" (one line only) */
2211         else if (buf[0] == 'I')
2212         {
2213                 int tval, sval, pval;
2214
2215                 /* Scan for the values */
2216                 if (3 != sscanf(buf+2, "%d:%d:%d",
2217                                 &tval, &sval, &pval)) return (1);
2218
2219                 /* Save the values */
2220                 k_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2221                 k_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2222                 k_ptr->pval = (PARAMETER_VALUE)pval;
2223         }
2224
2225         /* Process 'W' for "More Info" (one line only) */
2226         else if (buf[0] == 'W')
2227         {
2228                 int level, extra, wgt;
2229                 long cost;
2230
2231                 /* Scan for the values */
2232                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2233                                 &level, &extra, &wgt, &cost)) return (1);
2234
2235                 /* Save the values */
2236                 k_ptr->level = (DEPTH)level;
2237                 k_ptr->extra = (BIT_FLAGS8)extra;
2238                 k_ptr->weight = (WEIGHT)wgt;
2239                 k_ptr->cost = (PRICE)cost;
2240         }
2241
2242         /* Process 'A' for "Allocation" (one line only) */
2243         else if (buf[0] == 'A')
2244         {
2245
2246                 /* Simply read each number following a colon */
2247                 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
2248                 {
2249                                 /* Default chance */
2250                         k_ptr->chance[i] = 1;
2251
2252                                 /* Store the attack damage index */
2253                         k_ptr->locale[i] = atoi(s+1);
2254
2255                                 /* Find the slash */
2256                         t = my_strchr(s+1, '/');
2257
2258                                 /* Find the next colon */
2259                         s = my_strchr(s+1, ':');
2260
2261                                 /* If the slash is "nearby", use it */
2262                         if (t && (!s || t < s))
2263                         {
2264                                 int chance = atoi(t+1);
2265                                 if (chance > 0) k_ptr->chance[i] = (PROB)chance;
2266                         }
2267                 }
2268         }
2269
2270         /* Hack -- Process 'P' for "power" and such */
2271         else if (buf[0] == 'P')
2272         {
2273                 int ac, hd1, hd2, th, td, ta;
2274
2275                 /* Scan for the values */
2276                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2277                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2278
2279                 k_ptr->ac = (ARMOUR_CLASS)ac;
2280                 k_ptr->dd = (DICE_NUMBER)hd1;
2281                 k_ptr->ds = (DICE_SID)hd2;
2282                 k_ptr->to_h = (HIT_PROB)th;
2283                 k_ptr->to_d = (HIT_POINT)td;
2284                 k_ptr->to_a = (ARMOUR_CLASS)ta;
2285         }
2286
2287         /* Hack -- Process 'U' for activation index */
2288         else if (buf[0] == 'U')
2289         {
2290                 byte n;
2291                 n = grab_one_activation_flag(buf + 2);
2292                 if (n > 0)
2293                 {
2294                         k_ptr->act_idx = n;
2295                 }
2296                 else
2297                 {
2298                         return (5);
2299                 }
2300         }
2301
2302         /* Hack -- Process 'F' for flags */
2303         else if (buf[0] == 'F')
2304         {
2305                 /* Parse every entry textually */
2306                 for (s = buf + 2; *s; )
2307                 {
2308                                 /* Find the end of this entry */
2309                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2310
2311                                 /* Nuke and skip any dividers */
2312                         if (*t)
2313                         {
2314                                 *t++ = '\0';
2315                                 while (*t == ' ' || *t == '|') t++;
2316                         }
2317
2318                                 /* Parse this entry */
2319                         if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
2320
2321                                 /* Start the next entry */
2322                         s = t;
2323                 }
2324         }
2325
2326
2327         else return (6);
2328
2329
2330         /* Success */
2331         return (0);
2332 }
2333
2334 /*!
2335  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2336  * Grab one activation index flag
2337  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
2338  * @param what 参照元の文字列ポインタ
2339  * @return エラーがあった場合1、エラーがない場合0を返す
2340  */
2341 static errr grab_one_artifact_flag(artifact_type *a_ptr, concptr what)
2342 {
2343         int i;
2344
2345         /* Check flags */
2346         for (i = 0; i < TR_FLAG_MAX; i++)
2347         {
2348                 if (streq(what, k_info_flags[i]))
2349                 {
2350                         add_flag(a_ptr->flags, i);
2351                         return (0);
2352                 }
2353         }
2354
2355         if (grab_one_flag(&a_ptr->gen_flags, k_info_gen_flags, what) == 0)
2356                 return 0;
2357
2358         msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what);
2359
2360         /* Error */
2361         return (1);
2362 }
2363
2364
2365 /*!
2366  * @brief 固定アーティファクト情報(a_info)のパース関数 /
2367  * Initialize the "a_info" array, by parsing an ascii "template" file
2368  * @param buf テキスト列
2369  * @param head ヘッダ構造体
2370  * @return エラーコード
2371  */
2372 errr parse_a_info(char *buf, header *head)
2373 {
2374         int i;
2375
2376         char *s, *t;
2377
2378         /* Current entry */
2379         static artifact_type *a_ptr = NULL;
2380
2381
2382         /* Process 'N' for "New/Number/Name" */
2383         if (buf[0] == 'N')
2384         {
2385                 /* Find the colon before the name */
2386                 s = my_strchr(buf+2, ':');
2387
2388                         /* Verify that colon */
2389                 if (!s) return (1);
2390
2391                 /* Nuke the colon, advance to the name */
2392                 *s++ = '\0';
2393 #ifdef JP
2394                 /* Paranoia -- require a name */
2395                 if (!*s) return (1);
2396 #endif
2397                 /* Get the index */
2398                 i = atoi(buf+2);
2399
2400                 /* Verify information */
2401                 if (i < error_idx) return (4);
2402
2403                 /* Verify information */
2404                 if (i >= head->info_num) return (2);
2405
2406                 /* Save the index */
2407                 error_idx = i;
2408
2409                 /* Point at the "info" */
2410                 a_ptr = &a_info[i];
2411
2412                 /* Ignore everything */
2413                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
2414                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
2415                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
2416                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
2417 #ifdef JP
2418                 /* Store the name */
2419                 if (!add_name(&a_ptr->name, head, s)) return (7);
2420 #endif
2421         }
2422
2423         /* There better be a current a_ptr */
2424         else if (!a_ptr) return (3);
2425
2426
2427 #ifdef JP
2428         /* 英語名を読むルーチンを追加 */
2429         /* 'E' から始まる行は英語名としている */
2430         else if (buf[0] == 'E')
2431         {
2432                 /* nothing to do */
2433         }
2434 #else
2435         else if (buf[0] == 'E')
2436         {
2437                 /* Acquire the Text */
2438                 s = buf+2;
2439
2440                 /* Store the name */
2441                 if (!add_name(&a_ptr->name, head, s)) return (7);
2442         }
2443 #endif
2444
2445         /* Process 'D' for "Description" */
2446         else if (buf[0] == 'D')
2447         {
2448 #ifdef JP
2449                 if (buf[2] == '$')
2450                         return (0);
2451                 /* Acquire the text */
2452                 s = buf+2;
2453 #else
2454                 if (buf[2] != '$')
2455                         return (0);
2456                 /* Acquire the text */
2457                 s = buf+3;
2458 #endif
2459
2460                 /* Store the text */
2461                 if (!add_text(&a_ptr->text, head, s, TRUE)) return (7);
2462         }
2463
2464
2465         /* Process 'I' for "Info" (one line only) */
2466         else if (buf[0] == 'I')
2467         {
2468                 int tval, sval, pval;
2469
2470                 /* Scan for the values */
2471                 if (3 != sscanf(buf+2, "%d:%d:%d",
2472                                 &tval, &sval, &pval)) return (1);
2473
2474                 /* Save the values */
2475                 a_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2476                 a_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2477                 a_ptr->pval = (PARAMETER_VALUE)pval;
2478         }
2479
2480         /* Process 'W' for "More Info" (one line only) */
2481         else if (buf[0] == 'W')
2482         {
2483                 int level, rarity, wgt;
2484                 long cost;
2485
2486                 /* Scan for the values */
2487                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2488                                 &level, &rarity, &wgt, &cost)) return (1);
2489
2490                 /* Save the values */
2491                 a_ptr->level = (DEPTH)level;
2492                 a_ptr->rarity = (RARITY)rarity;
2493                 a_ptr->weight = (WEIGHT)wgt;
2494                 a_ptr->cost = (PRICE)cost;
2495         }
2496
2497         /* Hack -- Process 'P' for "power" and such */
2498         else if (buf[0] == 'P')
2499         {
2500                 int ac, hd1, hd2, th, td, ta;
2501
2502                 /* Scan for the values */
2503                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2504                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2505
2506                 a_ptr->ac = (ARMOUR_CLASS)ac;
2507                 a_ptr->dd = (DICE_NUMBER)hd1;
2508                 a_ptr->ds = (DICE_SID)hd2;
2509                 a_ptr->to_h = (HIT_PROB)th;
2510                 a_ptr->to_d = (HIT_POINT)td;
2511                 a_ptr->to_a = (ARMOUR_CLASS)ta;
2512         }
2513
2514         /* Hack -- Process 'U' for activation index */
2515         else if (buf[0] == 'U')
2516         {
2517                 byte n;
2518                 n = grab_one_activation_flag(buf + 2);
2519                 if (n > 0)
2520                 {
2521                         a_ptr->act_idx = n;
2522                 }
2523                 else
2524                 {
2525                         return (5);
2526                 }
2527         }
2528
2529         /* Hack -- Process 'F' for flags */
2530         else if (buf[0] == 'F')
2531         {
2532                 /* Parse every entry textually */
2533                 for (s = buf + 2; *s; )
2534                 {
2535                                 /* Find the end of this entry */
2536                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2537
2538                                 /* Nuke and skip any dividers */
2539                         if (*t)
2540                         {
2541                                 *t++ = '\0';
2542                                 while ((*t == ' ') || (*t == '|')) t++;
2543                         }
2544
2545                                 /* Parse this entry */
2546                         if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
2547
2548                                 /* Start the next entry */
2549                         s = t;
2550                 }
2551         }
2552
2553
2554         else return (6);
2555
2556
2557         /* Success */
2558         return (0);
2559 }
2560
2561
2562 /*!
2563  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2564  * Grab one flag in a ego-item_type from a textual string
2565  * @param e_ptr 保管先のエゴ構造体参照ポインタ
2566  * @param what 参照元の文字列ポインタ
2567  * @return エラーがあった場合1、エラーがない場合0を返す
2568  */
2569 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
2570 {
2571         int i;
2572
2573         /* Check flags */
2574         for (i = 0; i < TR_FLAG_MAX; i++)
2575         {
2576                 if (streq(what, k_info_flags[i]))
2577                 {
2578                         add_flag(e_ptr->flags, i);
2579                         return (0);
2580                 }
2581         }
2582
2583         if (grab_one_flag(&e_ptr->gen_flags, k_info_gen_flags, what) == 0)
2584                 return 0;
2585
2586         msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what);
2587
2588         /* Error */
2589         return (1);
2590 }
2591
2592
2593 /*!
2594  * @brief アイテムエゴ情報(e_info)のパース関数 /
2595  * Initialize the "e_info" array, by parsing an ascii "template" file
2596  * @param buf テキスト列
2597  * @param head ヘッダ構造体
2598  * @return エラーコード
2599  */
2600 errr parse_e_info(char *buf, header *head)
2601 {
2602         int i;
2603         char *s, *t;
2604
2605         /* Current entry */
2606         static ego_item_type *e_ptr = NULL;
2607
2608         /* Just before the first record */
2609         error_idx = -1;
2610
2611         /* Just before the first line */
2612         error_line = -1;
2613
2614         /* Process 'N' for "New/Number/Name" */
2615         if (buf[0] == 'N')
2616         {
2617                 /* Find the colon before the name */
2618                 s = my_strchr(buf+2, ':');
2619
2620                 /* Verify that colon */
2621                 if (!s) return (1);
2622
2623                 /* Nuke the colon, advance to the name */
2624                 *s++ = '\0';
2625 #ifdef JP
2626                 /* Paranoia -- require a name */
2627                 if (!*s) return (1);
2628 #endif
2629                 /* Get the index */
2630                 i = atoi(buf+2);
2631
2632                 /* Verify information */
2633                 if (i < error_idx) return (4);
2634
2635                 /* Verify information */
2636                 if (i >= head->info_num) return (2);
2637
2638                 /* Save the index */
2639                 error_idx = i;
2640
2641                 /* Point at the "info" */
2642                 e_ptr = &e_info[i];
2643 #ifdef JP
2644                 /* Store the name */
2645                 if (!add_name(&e_ptr->name, head, s)) return (7);
2646 #endif
2647         }
2648
2649         /* There better be a current e_ptr */
2650         else if (!e_ptr) return (3);
2651
2652
2653 #ifdef JP
2654         /* 英語名を読むルーチンを追加 */
2655         /* 'E' から始まる行は英語名 */
2656         else if (buf[0] == 'E')
2657         {
2658                 /* nothing to do */
2659         }
2660 #else
2661         else if (buf[0] == 'E')
2662         {
2663                 /* Acquire the Text */
2664                 s = buf+2;
2665
2666                 /* Store the name */
2667                 if (!add_name(&e_ptr->name, head, s)) return (7);
2668         }
2669 #endif
2670 #if 0
2671
2672         /* Process 'D' for "Description" */
2673         else if (buf[0] == 'D')
2674         {
2675                 /* Acquire the text */
2676                 s = buf+2;
2677
2678                 /* Store the text */
2679                 if (!add_text(&e_ptr->text, head, s, TRUE)) return (7);
2680         }
2681
2682 #endif
2683
2684         /* Process 'X' for "Xtra" (one line only) */
2685         else if (buf[0] == 'X')
2686         {
2687                 int slot, rating;
2688
2689                 /* Scan for the values */
2690                 if (2 != sscanf(buf+2, "%d:%d",
2691                                 &slot, &rating)) return (1);
2692
2693                 /* Save the values */
2694                 e_ptr->slot = (INVENTORY_IDX)slot;
2695                 e_ptr->rating = (PRICE)rating;
2696         }
2697
2698         /* Process 'W' for "More Info" (one line only) */
2699         else if (buf[0] == 'W')
2700         {
2701                 int level, rarity, pad2;
2702                 long cost;
2703
2704                 /* Scan for the values */
2705                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2706                                 &level, &rarity, &pad2, &cost)) return (1);
2707
2708                 /* Save the values */
2709                 e_ptr->level = level;
2710                 e_ptr->rarity = (RARITY)rarity;
2711                 /* e_ptr->weight = wgt; */
2712                 e_ptr->cost = cost;
2713         }
2714
2715         /* Hack -- Process 'C' for "creation" */
2716         else if (buf[0] == 'C')
2717         {
2718                 int th, td, ta, pval;
2719
2720                 /* Scan for the values */
2721                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
2722                                 &th, &td, &ta, &pval)) return (1);
2723
2724                 e_ptr->max_to_h = (HIT_PROB)th;
2725                 e_ptr->max_to_d = (HIT_POINT)td;
2726                 e_ptr->max_to_a = (ARMOUR_CLASS)ta;
2727                 e_ptr->max_pval = (PARAMETER_VALUE)pval;
2728         }
2729
2730         /* Hack -- Process 'U' for activation index */
2731         else if (buf[0] == 'U')
2732         {
2733                 byte n;
2734                 n = grab_one_activation_flag(buf + 2);
2735                 if (n > 0)
2736                 {
2737                         e_ptr->act_idx = n;
2738                 }
2739                 else
2740                 {
2741                         return (5);
2742                 }
2743         }
2744
2745         /* Hack -- Process 'F' for flags */
2746         else if (buf[0] == 'F')
2747         {
2748                 /* Parse every entry textually */
2749                 for (s = buf + 2; *s; )
2750                 {
2751                                 /* Find the end of this entry */
2752                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2753
2754                                 /* Nuke and skip any dividers */
2755                         if (*t)
2756                         {
2757                                 *t++ = '\0';
2758                                 while ((*t == ' ') || (*t == '|')) t++;
2759                         }
2760
2761                                 /* Parse this entry */
2762                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2763
2764                                 /* Start the next entry */
2765                         s = t;
2766                 }
2767         }
2768
2769         else return (6);
2770
2771         /* Success */
2772         return (0);
2773 }
2774
2775
2776 /*!
2777  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用1) /
2778  * Grab one (basic) flag in a monster_race from a textual string
2779  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2780  * @param what 参照元の文字列ポインタ
2781  * @return エラーコード
2782  */
2783 static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
2784 {
2785         if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
2786                 return 0;
2787
2788         if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
2789                 return 0;
2790
2791         if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
2792                 return 0;
2793
2794         if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
2795                 return 0;
2796
2797         if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
2798                 return 0;
2799
2800         if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
2801                 return 0;
2802
2803         if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
2804                 return 0;
2805
2806         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2807
2808         /* Failure */
2809         return (1);
2810 }
2811
2812
2813 /*!
2814  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用2) /
2815  * Grab one (spell) flag in a monster_race from a textual string
2816  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2817  * @param what 参照元の文字列ポインタ
2818  * @return エラーコード
2819  */
2820 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
2821 {
2822         if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
2823                 return 0;
2824
2825         if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
2826                 return 0;
2827
2828         if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
2829                 return 0;
2830
2831         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2832
2833         /* Failure */
2834         return (1);
2835 }
2836
2837
2838 /*!
2839  * @brief モンスター種族情報(r_info)のパース関数 /
2840  * Initialize the "r_info" array, by parsing an ascii "template" file
2841  * @param buf テキスト列
2842  * @param head ヘッダ構造体
2843  * @return エラーコード
2844  */
2845 errr parse_r_info(char *buf, header *head)
2846 {
2847         int i;
2848         char *s, *t;
2849
2850         /* Current entry */
2851         static monster_race *r_ptr = NULL;
2852
2853
2854         /* Process 'N' for "New/Number/Name" */
2855         if (buf[0] == 'N')
2856         {
2857                 /* Find the colon before the name */
2858                 s = my_strchr(buf+2, ':');
2859
2860                         /* Verify that colon */
2861                 if (!s) return (1);
2862
2863                 /* Nuke the colon, advance to the name */
2864                 *s++ = '\0';
2865 #ifdef JP
2866                 /* Paranoia -- require a name */
2867                 if (!*s) return (1);
2868 #endif
2869                 /* Get the index */
2870                 i = atoi(buf+2);
2871
2872                 /* Verify information */
2873                 if (i < error_idx) return (4);
2874
2875                 /* Verify information */
2876                 if (i >= head->info_num) return (2);
2877
2878                 /* Save the index */
2879                 error_idx = i;
2880
2881                 /* Point at the "info" */
2882                 r_ptr = &r_info[i];
2883 #ifdef JP
2884                 /* Store the name */
2885                 if (!add_name(&r_ptr->name, head, s)) return (7);
2886 #endif
2887         }
2888
2889         /* There better be a current r_ptr */
2890         else if (!r_ptr) return (3);
2891
2892
2893 #ifdef JP
2894         /* 英語名を読むルーチンを追加 */
2895         /* 'E' から始まる行は英語名 */
2896         else if (buf[0] == 'E')
2897         {
2898                 /* Acquire the Text */
2899                 s = buf+2;
2900
2901                 /* Store the name */
2902                 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2903         }
2904 #else
2905         else if (buf[0] == 'E')
2906         {
2907                 /* Acquire the Text */
2908                 s = buf+2;
2909
2910                 /* Store the name */
2911                 if (!add_name(&r_ptr->name, head, s)) return (7);
2912         }
2913 #endif
2914         /* Process 'D' for "Description" */
2915         else if (buf[0] == 'D')
2916         {
2917 #ifdef JP
2918                 if (buf[2] == '$')
2919                         return (0);
2920                 /* Acquire the text */
2921                 s = buf+2;
2922 #else
2923                 if (buf[2] != '$')
2924                         return (0);
2925                 /* Acquire the text */
2926                 s = buf+3;
2927 #endif
2928
2929                 /* Store the text */
2930                 if (!add_text(&r_ptr->text, head, s, TRUE)) return (7);
2931         }
2932
2933         /* Process 'G' for "Graphics" (one line only) */
2934         else if (buf[0] == 'G')
2935         {
2936                 char sym;
2937                 byte tmp;
2938
2939                 /* Paranoia */
2940                 if (buf[1] != ':') return (1);
2941                 if (!buf[2]) return (1);
2942                 if (buf[3] != ':') return (1);
2943                 if (!buf[4]) return (1);
2944
2945                 /* Extract the char */
2946                 sym = buf[2];
2947
2948                 /* Extract the attr */
2949                 tmp = color_char_to_attr(buf[4]);
2950
2951                 /* Paranoia */
2952                 if (tmp > 127) return (1);
2953
2954                 /* Save the values */
2955                 r_ptr->d_char = sym;
2956                 r_ptr->d_attr = tmp;
2957         }
2958
2959         /* Process 'I' for "Info" (one line only) */
2960         else if (buf[0] == 'I')
2961         {
2962                 int spd, hp1, hp2, aaf, ac, slp;
2963
2964                 /* Scan for the other values */
2965                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2966                                 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2967
2968                 /* Save the values */
2969                 r_ptr->speed = (SPEED)spd;
2970                 r_ptr->hdice = (DICE_NUMBER)MAX(hp1, 1);
2971                 r_ptr->hside = (DICE_SID)MAX(hp2, 1);
2972                 r_ptr->aaf = (POSITION)aaf;
2973                 r_ptr->ac = (ARMOUR_CLASS)ac;
2974                 r_ptr->sleep = (SLEEP_DEGREE)slp;
2975         }
2976
2977         /* Process 'W' for "More Info" (one line only) */
2978         else if (buf[0] == 'W')
2979         {
2980                 int lev, rar, pad;
2981                 long exp;
2982                 long nextexp;
2983                 int nextmon;
2984
2985                 /* Scan for the values */
2986                 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2987                                 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2988
2989                 /* Save the values */
2990                 r_ptr->level = (DEPTH)lev;
2991                 r_ptr->rarity = (RARITY)rar;
2992                 r_ptr->extra = (BIT_FLAGS16)pad;
2993                 r_ptr->mexp = (EXP)exp;
2994                 r_ptr->next_exp = (EXP)nextexp;
2995                 r_ptr->next_r_idx = (IDX)nextmon;
2996         }
2997
2998         /* Process 'R' for "Reinforcement" (up to six lines) */
2999         else if (buf[0] == 'R')
3000         {
3001                 int id, ds, dd;
3002                 /* Find the next empty blow slot (if any) */
3003                 for (i = 0; i < A_MAX; i++) if (r_ptr->reinforce_id[i] == 0) break;
3004
3005                 /* Oops, no more slots */
3006                 if (i == 6) return (1);
3007
3008                 /* Scan for the values */
3009                 if (3 != sscanf(buf+2, "%d:%dd%d", &id, &dd, &ds)) return (1);
3010                 r_ptr->reinforce_id[i] = (MONRACE_IDX)id;
3011                 r_ptr->reinforce_dd[i] = (DICE_NUMBER)dd;
3012                 r_ptr->reinforce_ds[i] = (DICE_SID)ds;
3013         }
3014
3015         /* Process 'B' for "Blows" (up to four lines) */
3016         else if (buf[0] == 'B')
3017         {
3018                 int n1, n2;
3019
3020                 /* Find the next empty blow slot (if any) */
3021                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
3022
3023                 /* Oops, no more slots */
3024                 if (i == 4) return (1);
3025
3026                 /* Analyze the first field */
3027                 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
3028
3029                 /* Terminate the field (if necessary) */
3030                 if (*t == ':') *t++ = '\0';
3031
3032                 /* Analyze the method */
3033                 for (n1 = 0; r_info_blow_method[n1]; n1++)
3034                 {
3035                         if (streq(s, r_info_blow_method[n1])) break;
3036                 }
3037
3038                 /* Invalid method */
3039                 if (!r_info_blow_method[n1]) return (1);
3040
3041                 /* Analyze the second field */
3042                 for (s = t; *t && (*t != ':'); t++) /* loop */;
3043
3044                 /* Terminate the field (if necessary) */
3045                 if (*t == ':') *t++ = '\0';
3046
3047                 /* Analyze effect */
3048                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
3049                 {
3050                         if (streq(s, r_info_blow_effect[n2])) break;
3051                 }
3052
3053                 /* Invalid effect */
3054                 if (!r_info_blow_effect[n2]) return (1);
3055
3056                 /* Analyze the third field */
3057                 for (s = t; *t && (*t != 'd'); t++) /* loop */;
3058
3059                 /* Terminate the field (if necessary) */
3060                 if (*t == 'd') *t++ = '\0';
3061
3062                 /* Save the method */
3063                 r_ptr->blow[i].method = (BLOW_METHOD)n1;
3064
3065                 /* Save the effect */
3066                 r_ptr->blow[i].effect = (BLOW_EFFECT)n2;
3067
3068                 /* Extract the damage dice and sides */
3069                 r_ptr->blow[i].d_dice = atoi(s);
3070                 r_ptr->blow[i].d_side = atoi(t);
3071         }
3072
3073         /* Process 'F' for "Basic Flags" (multiple lines) */
3074         else if (buf[0] == 'F')
3075         {
3076                 /* Parse every entry */
3077                 for (s = buf + 2; *s; )
3078                 {
3079                                 /* Find the end of this entry */
3080                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3081
3082                                 /* Nuke and skip any dividers */
3083                         if (*t)
3084                         {
3085                                 *t++ = '\0';
3086                                 while (*t == ' ' || *t == '|') t++;
3087                         }
3088
3089                                 /* Parse this entry */
3090                         if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
3091
3092                                 /* Start the next entry */
3093                         s = t;
3094                 }
3095         }
3096
3097         /* Process 'S' for "Spell Flags" (multiple lines) */
3098         else if (buf[0] == 'S')
3099         {
3100                 /* Parse every entry */
3101                 for (s = buf + 2; *s; )
3102                 {
3103                                 /* Find the end of this entry */
3104                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3105
3106                                 /* Nuke and skip any dividers */
3107                         if (*t)
3108                         {
3109                                 *t++ = '\0';
3110                                 while ((*t == ' ') || (*t == '|')) t++;
3111                         }
3112
3113                                 /* Hack -- Read spell frequency */
3114                         if (1 == sscanf(s, "1_IN_%d", &i))
3115                         {
3116                                 /* Extract a "frequency" */
3117                                 r_ptr->freq_spell = 100 / i;
3118
3119                                         /* Start at next entry */
3120                                 s = t;
3121                                 continue;
3122                         }
3123
3124                                 /* Parse this entry */
3125                         if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
3126
3127                                 /* Start the next entry */
3128                         s = t;
3129                 }
3130         }
3131
3132         /* Process 'A' for "Artifact Flags" (multiple lines) */
3133         else if (buf[0] == 'A')
3134         {
3135                 int id, per, rarity;
3136
3137                 /* Find the next empty blow slot (if any) */
3138                 for (i = 0; i < 4; i++) if (!r_ptr->artifact_id[i]) break;
3139
3140                 /* Oops, no more slots */
3141                 if (i == 4) return (1);
3142
3143                 if (3 != sscanf(buf+2, "%d:%d:%d", &id, &rarity, &per)) return (1);
3144                 r_ptr->artifact_id[i] = (ARTIFACT_IDX)id;
3145                 r_ptr->artifact_rarity[i] = (RARITY)rarity;
3146                 r_ptr->artifact_percent[i] = (PERCENTAGE)per;
3147         }
3148
3149         /* Process 'V' for "Arena power value ratio" */
3150         else if (buf[0] == 'V')
3151         {
3152                 int val;
3153                 if (3 != sscanf(buf+2, "%d", &val)) return (1);
3154                 r_ptr->arena_ratio = (PERCENTAGE)val;
3155         }
3156
3157         else return (6);
3158
3159
3160         /* Success */
3161         return (0);
3162 }
3163
3164
3165 /*!
3166  * @brief テキストトークンを走査してフラグを一つ得る(ダンジョン用) /
3167  * Grab one flag for a dungeon type from a textual string
3168  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3169  * @param what 参照元の文字列ポインタ
3170  * @return エラーコード
3171  */
3172 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, concptr what)
3173 {
3174         if (grab_one_flag(&d_ptr->flags1, d_info_flags1, what) == 0)
3175                 return 0;
3176
3177         msg_format(_("未知のダンジョン・フラグ '%s'。", "Unknown dungeon type flag '%s'."), what);
3178
3179         /* Failure */
3180         return (1);
3181 }
3182
3183 /*!
3184  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用1) /
3185  * Grab one (basic) flag in a monster_race from a textual string
3186  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3187  * @param what 参照元の文字列ポインタ
3188  * @return エラーコード
3189  */
3190 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, concptr what)
3191 {
3192         if (grab_one_flag(&d_ptr->mflags1, r_info_flags1, what) == 0)
3193                 return 0;
3194
3195         if (grab_one_flag(&d_ptr->mflags2, r_info_flags2, what) == 0)
3196                 return 0;
3197
3198         if (grab_one_flag(&d_ptr->mflags3, r_info_flags3, what) == 0)
3199                 return 0;
3200
3201         if (grab_one_flag(&d_ptr->mflags7, r_info_flags7, what) == 0)
3202                 return 0;
3203
3204         if (grab_one_flag(&d_ptr->mflags8, r_info_flags8, what) == 0)
3205                 return 0;
3206
3207         if (grab_one_flag(&d_ptr->mflags9, r_info_flags9, what) == 0)
3208                 return 0;
3209
3210         if (grab_one_flag(&d_ptr->mflagsr, r_info_flagsr, what) == 0)
3211                 return 0;
3212
3213         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3214         /* Failure */
3215         return (1);
3216 }
3217
3218
3219 /*!
3220  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用2) /
3221  * Grab one (spell) flag in a monster_race from a textual string
3222  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3223  * @param what 参照元の文字列ポインタ
3224  * @return エラーコード
3225  */
3226 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, concptr what)
3227 {
3228         if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
3229                 return 0;
3230
3231         if (grab_one_flag(&d_ptr->m_a_ability_flags1, r_a_ability_flags1, what) == 0)
3232                 return 0;
3233
3234         if (grab_one_flag(&d_ptr->m_a_ability_flags2, r_a_ability_flags2, what) == 0)
3235                 return 0;
3236
3237         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3238
3239         /* Failure */
3240         return (1);
3241 }
3242
3243 /*!
3244  * @brief ダンジョン情報(d_info)のパース関数 /
3245  * Initialize the "d_info" array, by parsing an ascii "template" file
3246  * @param buf テキスト列
3247  * @param head ヘッダ構造体
3248  * @return エラーコード
3249  */
3250 errr parse_d_info(char *buf, header *head)
3251 {
3252         int i;
3253         char *s, *t;
3254
3255         /* Current entry */
3256         static dungeon_info_type *d_ptr = NULL;
3257
3258         /* Process 'N' for "New/Number/Name" */
3259         if (buf[0] == 'N')
3260         {
3261                 /* Find the colon before the name */
3262                 s = my_strchr(buf+2, ':');
3263
3264                 /* Verify that colon */
3265                 if (!s) return (1);
3266
3267                 /* Nuke the colon, advance to the name */
3268                 *s++ = '\0';
3269 #ifdef JP
3270                 /* Paranoia -- require a name */
3271                 if (!*s) return (1);
3272 #endif
3273                 /* Get the index */
3274                 i = atoi(buf+2);
3275
3276                 /* Verify information */
3277                 if (i < error_idx) return (4);
3278
3279                 /* Verify information */
3280                 if (i >= head->info_num) return (2);
3281
3282                 /* Save the index */
3283                 error_idx = i;
3284
3285                 /* Point at the "info" */
3286                 d_ptr = &d_info[i];
3287 #ifdef JP
3288                 /* Store the name */
3289                 if (!add_name(&d_ptr->name, head, s)) return (7);
3290 #endif
3291         }
3292
3293 #ifdef JP
3294         else if (buf[0] == 'E') return (0);
3295 #else
3296         else if (buf[0] == 'E')
3297         {
3298                 /* Acquire the Text */
3299                 s = buf+2;
3300
3301                 /* Store the name */
3302                 if (!add_name(&d_ptr->name, head, s)) return (7);
3303         }
3304 #endif
3305
3306         /* Process 'D' for "Description */
3307         else if (buf[0] == 'D')
3308         {
3309 #ifdef JP
3310                 if (buf[2] == '$')
3311                         return (0);
3312                 /* Acquire the text */
3313                 s = buf+2;
3314 #else
3315                 if (buf[2] != '$')
3316                         return (0);
3317                 /* Acquire the text */
3318                 s = buf+3;
3319 #endif
3320
3321                 /* Store the text */
3322                 if (!add_text(&d_ptr->text, head, s, TRUE)) return (7);
3323         }
3324
3325         /* Process 'W' for "More Info" (one line only) */
3326         else if (buf[0] == 'W')
3327         {
3328                 int min_lev, max_lev;
3329                 int min_plev, mode;
3330                 int min_alloc, max_chance;
3331                 int obj_good, obj_great;
3332                 int pit, nest;
3333
3334                 /* Scan for the values */
3335                 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
3336                                  &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
3337
3338                 /* Save the values */
3339                 d_ptr->mindepth = (DEPTH)min_lev;
3340                 d_ptr->maxdepth = (DEPTH)max_lev;
3341                 d_ptr->min_plev = (PLAYER_LEVEL)min_plev;
3342                 d_ptr->mode = (BIT_FLAGS8)mode;
3343                 d_ptr->min_m_alloc_level = min_alloc;
3344                 d_ptr->max_m_alloc_chance = max_chance;
3345                 d_ptr->obj_good = obj_good;
3346                 d_ptr->obj_great = obj_great;
3347                 d_ptr->pit = (BIT_FLAGS16)pit;
3348                 d_ptr->nest = (BIT_FLAGS16)nest;
3349         }
3350
3351         /* Process 'P' for "Place Info" */
3352         else if (buf[0] == 'P')
3353         {
3354                 int dy, dx;
3355
3356                 /* Scan for the values */
3357                 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
3358
3359                 /* Save the values */
3360                 d_ptr->dy = dy;
3361                 d_ptr->dx = dx;
3362         }
3363
3364         /* Process 'L' for "fLoor type" (one line only) */
3365         else if (buf[0] == 'L')
3366         {
3367                 char *zz[16];
3368
3369                 /* Scan for the values */
3370                 if (tokenize(buf+2, DUNGEON_FEAT_PROB_NUM * 2 + 1, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 1)) return (1);
3371
3372                 /* Save the values */
3373                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3374                 {
3375                         d_ptr->floor[i].feat = f_tag_to_index(zz[i * 2]);
3376                         if (d_ptr->floor[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3377
3378                         d_ptr->floor[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3379                 }
3380                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3381         }
3382
3383         /* Process 'A' for "wAll type" (one line only) */
3384         else if (buf[0] == 'A')
3385         {
3386                 char *zz[16];
3387
3388                 /* Scan for the values */
3389                 if (tokenize(buf+2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return (1);
3390
3391                 /* Save the values */
3392                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3393                 {
3394                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
3395                         if (d_ptr->fill[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3396
3397                         d_ptr->fill[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3398                 }
3399
3400                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3401                 if (d_ptr->outer_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3402
3403                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
3404                 if (d_ptr->inner_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3405
3406                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
3407                 if (d_ptr->stream1 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3408
3409                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
3410                 if (d_ptr->stream2 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3411         }
3412
3413         /* Process 'F' for "Dungeon Flags" (multiple lines) */
3414         else if (buf[0] == 'F')
3415         {
3416                 int artif = 0, monst = 0;
3417
3418                 /* Parse every entry */
3419                 for (s = buf + 2; *s; )
3420                 {
3421                         /* Find the end of this entry */
3422                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3423
3424                         /* Nuke and skip any dividers */
3425                         if (*t)
3426                         {
3427                                 *t++ = '\0';
3428                                 while (*t == ' ' || *t == '|') t++;
3429                         }
3430
3431                         /* Hack -- Read Final Artifact */
3432                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3433                         {
3434                                 /* Extract a "Final Artifact" */
3435                                 d_ptr->final_artifact = (ARTIFACT_IDX)artif;
3436
3437                                 /* Start at next entry */
3438                                 s = t;
3439                                 continue;
3440                         }
3441
3442                         /* Hack -- Read Final Object */
3443                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3444                         {
3445                                 /* Extract a "Final Artifact" */
3446                                 d_ptr->final_object = (KIND_OBJECT_IDX)artif;
3447
3448                                 /* Start at next entry */
3449                                 s = t;
3450                                 continue;
3451                         }
3452
3453                         /* Hack -- Read Artifact Guardian */
3454                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3455                         {
3456                                 /* Extract a "Artifact Guardian" */
3457                                 d_ptr->final_guardian = (MONRACE_IDX)monst;
3458
3459                                 /* Start at next entry */
3460                                 s = t;
3461                                 continue;
3462                         }
3463
3464                         /* Hack -- Read Special Percentage */
3465                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3466                         {
3467                                 /* Extract a "Special %" */
3468                                 d_ptr->special_div = (PROB)monst;
3469
3470                                 /* Start at next entry */
3471                                 s = t;
3472                                 continue;
3473                         }
3474
3475                         /* Parse this entry */
3476                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3477
3478                         /* Start the next entry */
3479                         s = t;
3480                 }
3481         }
3482
3483         /* Process 'M' for "Basic Flags" (multiple lines) */
3484         else if (buf[0] == 'M')
3485         {
3486                 /* Parse every entry */
3487                 for (s = buf + 2; *s; )
3488                 {
3489                         /* Find the end of this entry */
3490                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3491
3492                         /* Nuke and skip any dividers */
3493                         if (*t)
3494                         {
3495                                 *t++ = '\0';
3496                                 while (*t == ' ' || *t == '|') t++;
3497                         }
3498
3499                         /* Hack -- Read monster symbols */
3500                         if (!strncmp(s, "R_CHAR_", 7))
3501                         {
3502                                 /* Skip "R_CHAR_" */
3503                                 s += 7;
3504
3505                                 /* Read a string */
3506                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
3507
3508                                 /* Start at next entry */
3509                                 s = t;
3510                                 continue;
3511                         }
3512
3513                         /* Parse this entry */
3514                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3515
3516                         /* Start the next entry */
3517                         s = t;
3518                 }
3519         }
3520
3521         /* Process 'S' for "Spell Flags" (multiple lines) */
3522         else if (buf[0] == 'S')
3523         {
3524                 /* Parse every entry */
3525                 for (s = buf + 2; *s; )
3526                 {
3527                                 /* Find the end of this entry */
3528                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3529
3530                                 /* Nuke and skip any dividers */
3531                         if (*t)
3532                         {
3533                                 *t++ = '\0';
3534                                 while ((*t == ' ') || (*t == '|')) t++;
3535                         }
3536
3537                                 /* Hack -- Read spell frequency */
3538                         if (1 == sscanf(s, "1_IN_%d", &i))
3539                         {
3540                                 /* Start at next entry */
3541                                 s = t;
3542                                 continue;
3543                         }
3544
3545                                 /* Parse this entry */
3546                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3547
3548                                 /* Start the next entry */
3549                         s = t;
3550                 }
3551         }
3552
3553         else return (6);
3554
3555         /* Success */
3556         return (0);
3557 }
3558
3559
3560 #else   /* ALLOW_TEMPLATES */
3561
3562 #ifdef MACINTOSH
3563 static int i = 0;
3564 #endif
3565
3566 #endif  /* ALLOW_TEMPLATES */
3567
3568
3569 /* Random dungeon grid effects */
3570 #define RANDOM_NONE         0x00000000
3571 #define RANDOM_FEATURE      0x00000001
3572 #define RANDOM_MONSTER      0x00000002
3573 #define RANDOM_OBJECT       0x00000004
3574 #define RANDOM_EGO          0x00000008
3575 #define RANDOM_ARTIFACT     0x00000010
3576 #define RANDOM_TRAP         0x00000020
3577
3578
3579 typedef struct dungeon_grid dungeon_grid;
3580
3581 struct dungeon_grid
3582 {
3583         FEAT_IDX feature;               /* Terrain feature */
3584         MONSTER_IDX     monster;                /* Monster */
3585         OBJECT_IDX object;                      /* Object */
3586         EGO_IDX ego;                    /* Ego-Item */
3587         ARTIFACT_IDX artifact;          /* Artifact */
3588         IDX trap;                       /* Trap */
3589         BIT_FLAGS cave_info;            /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3590         s16b special; /* Reserved for special terrain info */
3591         int random;                     /* Number of the random effect */
3592 };
3593
3594
3595 static dungeon_grid letter[255];
3596
3597
3598 /*!
3599  * @brief 地形情報の「F:」情報をパースする
3600  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3601  * @param buf 解析文字列
3602  * @return エラーコード
3603  */
3604 static errr parse_line_feature(char *buf)
3605 {
3606         int num;
3607         char *zz[9];
3608
3609         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3610
3611         /* Tokenize the line */
3612         if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3613         {
3614                 /* Letter to assign */
3615                 int index = zz[0][0];
3616
3617                 /* Reset the info for the letter */
3618                 letter[index].feature = feat_none;
3619                 letter[index].monster = 0;
3620                 letter[index].object = 0;
3621                 letter[index].ego = 0;
3622                 letter[index].artifact = 0;
3623                 letter[index].trap = feat_none;
3624                 letter[index].cave_info = 0;
3625                 letter[index].special = 0;
3626                 letter[index].random = RANDOM_NONE;
3627
3628                 switch (num)
3629                 {
3630                         /* Special */
3631                         case 9:
3632                                 letter[index].special = (s16b)atoi(zz[8]);
3633                                 /* Fall through */
3634                         /* Trap */
3635                         case 8:
3636                                 if ((zz[7][0] == '*') && !zz[7][1])
3637                                 {
3638                                         letter[index].random |= RANDOM_TRAP;
3639                                 }
3640                                 else
3641                                 {
3642                                         letter[index].trap = f_tag_to_index(zz[7]);
3643                                         if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3644                                 }
3645                                 /* Fall through */
3646                         /* Artifact */
3647                         case 7:
3648                                 if (zz[6][0] == '*')
3649                                 {
3650                                         letter[index].random |= RANDOM_ARTIFACT;
3651                                         if (zz[6][1]) letter[index].artifact = (IDX)atoi(zz[6] + 1);
3652                                 }
3653                                 else if (zz[6][0] == '!')
3654                                 {
3655                                         if (p_ptr->inside_quest)
3656                                         {
3657                                                 letter[index].artifact = quest[p_ptr->inside_quest].k_idx;
3658                                         }
3659                                 }
3660                                 else
3661                                 {
3662                                         letter[index].artifact = (IDX)atoi(zz[6]);
3663                                 }
3664                                 /* Fall through */
3665                         /* Ego-item */
3666                         case 6:
3667                                 if (zz[5][0] == '*')
3668                                 {
3669                                         letter[index].random |= RANDOM_EGO;
3670                                         if (zz[5][1]) letter[index].ego = (IDX)atoi(zz[5] + 1);
3671                                 }
3672                                 else
3673                                 {
3674                                         letter[index].ego = (IDX)atoi(zz[5]);
3675                                 }
3676                                 /* Fall through */
3677                         /* Object */
3678                         case 5:
3679                                 if (zz[4][0] == '*')
3680                                 {
3681                                         letter[index].random |= RANDOM_OBJECT;
3682                                         if (zz[4][1]) letter[index].object = (IDX)atoi(zz[4] + 1);
3683                                 }
3684                                 else if (zz[4][0] == '!')
3685                                 {
3686                                         if (p_ptr->inside_quest)
3687                                         {
3688                                                 ARTIFACT_IDX a_idx = quest[p_ptr->inside_quest].k_idx;
3689                                                 if (a_idx)
3690                                                 {
3691                                                         artifact_type *a_ptr = &a_info[a_idx];
3692                                                         if (!(a_ptr->gen_flags & TRG_INSTA_ART))
3693                                                         {
3694                                                                 letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
3695                                                         }
3696                                                 }
3697                                         }
3698                                 }
3699                                 else
3700                                 {
3701                                         letter[index].object = (IDX)atoi(zz[4]);
3702                                 }
3703                                 /* Fall through */
3704                         /* Monster */
3705                         case 4:
3706                                 if (zz[3][0] == '*')
3707                                 {
3708                                         letter[index].random |= RANDOM_MONSTER;
3709                                         if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1);
3710                                 }
3711                                 else if (zz[3][0] == 'c')
3712                                 {
3713                                         if (!zz[3][1]) return PARSE_ERROR_GENERIC;
3714                                         letter[index].monster = - atoi(zz[3] + 1);
3715                                 }
3716                                 else
3717                                 {
3718                                         letter[index].monster = (IDX)atoi(zz[3]);
3719                                 }
3720                                 /* Fall through */
3721                         /* Cave info */
3722                         case 3:
3723                                 letter[index].cave_info = atoi(zz[2]);
3724                                 /* Fall through */
3725                         /* Feature */
3726                         case 2:
3727                                 if ((zz[1][0] == '*') && !zz[1][1])
3728                                 {
3729                                         letter[index].random |= RANDOM_FEATURE;
3730                                 }
3731                                 else
3732                                 {
3733                                         letter[index].feature = f_tag_to_index(zz[1]);
3734                                         if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3735                                 }
3736                                 break;
3737                 }
3738
3739                 return (0);
3740         }
3741
3742         return (1);
3743 }
3744
3745
3746 /*!
3747  * @brief 地形情報の「B:」情報をパースする
3748  * Process "B:<Index>:<Command>:..." -- Building definition
3749  * @param buf 解析文字列
3750  * @return エラーコード
3751  */
3752 static errr parse_line_building(char *buf)
3753 {
3754         int i;
3755         char *zz[1000];
3756         int index;
3757         char *s;
3758
3759 #ifdef JP
3760         if (buf[2] == '$')
3761                 return 0;
3762         s = buf + 2;
3763 #else
3764         if (buf[2] != '$')
3765                 return 0;
3766         s = buf + 3;
3767 #endif
3768         /* Get the building number */
3769         index = atoi(s);
3770
3771         /* Find the colon after the building number */
3772         s = my_strchr(s, ':');
3773
3774         /* Verify that colon */
3775         if (!s) return (1);
3776
3777         /* Nuke the colon, advance to the sub-index */
3778         *s++ = '\0';
3779
3780         /* Paranoia -- require a sub-index */
3781         if (!*s) return (1);
3782
3783         /* Building definition sub-index */
3784         switch (s[0])
3785         {
3786                 /* Building name, owner, race */
3787                 case 'N':
3788                 {
3789                         if (tokenize(s + 2, 3, zz, 0) == 3)
3790                         {
3791                                 /* Name of the building */
3792                                 strcpy(building[index].name, zz[0]);
3793
3794                                 /* Name of the owner */
3795                                 strcpy(building[index].owner_name, zz[1]);
3796
3797                                 /* Race of the owner */
3798                                 strcpy(building[index].owner_race, zz[2]);
3799
3800                                 break;
3801                         }
3802
3803                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3804                 }
3805
3806                 /* Building Action */
3807                 case 'A':
3808                 {
3809                         if (tokenize(s + 2, 8, zz, 0) >= 7)
3810                         {
3811                                 /* Index of the action */
3812                                 int action_index = atoi(zz[0]);
3813
3814                                 /* Name of the action */
3815                                 strcpy(building[index].act_names[action_index], zz[1]);
3816
3817                                 /* Cost of the action for members */
3818                                 building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
3819
3820                                 /* Cost of the action for non-members */
3821                                 building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
3822
3823                                 /* Letter assigned to the action */
3824                                 building[index].letters[action_index] = zz[4][0];
3825
3826                                 /* Action code */
3827                                 building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]);
3828
3829                                 /* Action restriction */
3830                                 building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]);
3831
3832                                 break;
3833                         }
3834
3835                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3836                 }
3837
3838                 /* Building Classes */
3839                 case 'C':
3840                 {
3841                         int n;
3842                         n = tokenize(s + 2, MAX_CLASS, zz, 0);
3843                         if (n <= MAX_CLASS)
3844                         {
3845                                 for (i = 0; i < MAX_CLASS; i++)
3846                                 {       
3847                                         building[index].member_class[i] = ((i > n) ? (CLASS_IDX)atoi(zz[i]) : 1);
3848                                 }
3849
3850                                 break;
3851                         }
3852
3853                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3854                 }
3855
3856                 /* Building Races */
3857                 case 'R':
3858                 {
3859                         int n;
3860                         n = tokenize(s + 2, MAX_RACES, zz, 0);
3861                         if (n <= MAX_RACES)
3862                         {
3863                                 for (i = 0; i < MAX_RACES; i++)
3864                                 {
3865                                         building[index].member_race[i] = ((i > n) ? (RACE_IDX)atoi(zz[i]) : 1);
3866                                 }
3867
3868                                 break;
3869                         }
3870
3871                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3872                 }
3873
3874                 /* Building Realms */
3875                 case 'M':
3876                 {
3877                         int n;
3878                         n = tokenize(s + 2, MAX_MAGIC, zz, 0);
3879                         if (n <= MAX_MAGIC)
3880                         {
3881                                 for (i = 0; i < MAX_MAGIC; i++)
3882                                 {
3883                                         building[index].member_realm[i+1] = ((i > n) ? (REALM_IDX)atoi(zz[i]) : 1);
3884                                 }
3885
3886                                 break;
3887                         }
3888
3889                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3890                 }
3891
3892                 case 'Z':
3893                 {
3894                         /* Ignore scripts */
3895                         break;
3896                 }
3897
3898                 default:
3899                 {
3900                         return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3901                 }
3902         }
3903
3904         return (0);
3905 }
3906
3907
3908 /*!
3909  * @brief フロアの所定のマスにオブジェクトを配置する
3910  * Place the object j_ptr to a grid
3911  * @param j_ptr オブジェクト構造体の参照ポインタ
3912  * @param y 配置先Y座標
3913  * @param x 配置先X座標
3914  * @return エラーコード
3915  */
3916 static void drop_here(object_type *j_ptr, POSITION y, POSITION x)
3917 {
3918         cave_type *c_ptr = &cave[y][x];
3919         object_type *o_ptr;
3920
3921         OBJECT_IDX o_idx = o_pop();
3922
3923         /* Access new object */
3924         o_ptr = &o_list[o_idx];
3925
3926         /* Structure copy */
3927         object_copy(o_ptr, j_ptr);
3928
3929         /* Locate */
3930         o_ptr->iy = y;
3931         o_ptr->ix = x;
3932
3933         /* No monster */
3934         o_ptr->held_m_idx = 0;
3935
3936         /* Build a stack */
3937         o_ptr->next_o_idx = c_ptr->o_idx;
3938
3939         /* Place the object */
3940         c_ptr->o_idx = o_idx;
3941 }
3942
3943
3944 /*!
3945  * @brief クエスト用固定ダンジョンをフロアに生成する
3946  * Parse a sub-file of the "extra info"
3947  * @param buf 文字列
3948  * @param ymin 詳細不明
3949  * @param xmin 詳細不明
3950  * @param ymax 詳細不明
3951  * @param xmax 詳細不明
3952  * @param y 詳細不明
3953  * @param x 詳細不明
3954  * @return エラーコード
3955  */
3956 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3957 {
3958         int i;
3959         char *zz[33];
3960
3961         /* Skip "empty" lines */
3962         if (!buf[0]) return (0);
3963
3964         /* Skip "blank" lines */
3965         if (iswspace(buf[0])) return (0);
3966
3967         /* Skip comments */
3968         if (buf[0] == '#') return (0);
3969
3970         /* Require "?:*" format */
3971         if (buf[1] != ':') return (1);
3972
3973
3974         /* Process "%:<fname>" */
3975         if (buf[0] == '%')
3976         {
3977                 /* Attempt to Process the given file */
3978                 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3979         }
3980
3981         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3982         if (buf[0] == 'F')
3983         {
3984                 return parse_line_feature(buf);
3985         }
3986
3987         /* Process "D:<dungeon>" -- info for the cave grids */
3988         else if (buf[0] == 'D')
3989         {
3990                 object_type object_type_body;
3991
3992                 /* Acquire the text */
3993                 char *s = buf + 2;
3994
3995                 /* Length of the text */
3996                 int len = strlen(s);
3997
3998                 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3999
4000                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
4001                 {
4002                         cave_type *c_ptr = &cave[*y][*x];
4003
4004                         int idx = s[0];
4005
4006                         OBJECT_IDX object_index = letter[idx].object;
4007                         MONSTER_IDX monster_index = letter[idx].monster;
4008                         int random = letter[idx].random;
4009                         ARTIFACT_IDX artifact_index = letter[idx].artifact;
4010
4011                         /* Lay down a floor */
4012                         c_ptr->feat = conv_dungeon_feat(letter[idx].feature);
4013
4014                         /* Only the features */
4015                         if (init_flags & INIT_ONLY_FEATURES) continue;
4016
4017                         /* Cave info */
4018                         c_ptr->info = letter[idx].cave_info;
4019
4020                         /* Create a monster */
4021                         if (random & RANDOM_MONSTER)
4022                         {
4023                                 monster_level = base_level + monster_index;
4024
4025                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4026
4027                                 monster_level = base_level;
4028                         }
4029                         else if (monster_index)
4030                         {
4031                                 int old_cur_num, old_max_num;
4032                                 bool clone = FALSE;
4033
4034                                 if (monster_index < 0)
4035                                 {
4036                                         monster_index = -monster_index;
4037                                         clone = TRUE;
4038                                 }
4039                                 old_cur_num = r_info[monster_index].cur_num;
4040                                 old_max_num = r_info[monster_index].max_num;
4041
4042                                 /* Make alive again */
4043                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
4044                                 {
4045                                         r_info[monster_index].cur_num = 0;
4046                                         r_info[monster_index].max_num = 1;
4047                                 }
4048
4049                                 /* Make alive again */
4050                                 /* Hack -- Non-unique Nazguls are semi-unique */
4051                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
4052                                 {
4053                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
4054                                         {
4055                                                 r_info[monster_index].max_num++;
4056                                         }
4057                                 }
4058
4059                                 /* Place it */
4060                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
4061                                 if (clone)
4062                                 {
4063                                         /* clone */
4064                                         m_list[hack_m_idx_ii].smart |= SM_CLONED;
4065
4066                                         /* Make alive again for real unique monster */
4067                                         r_info[monster_index].cur_num = old_cur_num;
4068                                         r_info[monster_index].max_num = old_max_num;
4069                                 }
4070                         }
4071
4072                         /* Object (and possible trap) */
4073                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
4074                         {
4075                                 object_level = base_level + object_index;
4076
4077                                 /*
4078                                  * Random trap and random treasure defined
4079                                  * 25% chance for trap and 75% chance for object
4080                                  */
4081                                 if (randint0(100) < 75)
4082                                 {
4083                                         place_object(*y, *x, 0L);
4084                                 }
4085                                 else
4086                                 {
4087                                         place_trap(*y, *x);
4088                                 }
4089
4090                                 object_level = base_level;
4091                         }
4092                         else if (random & RANDOM_OBJECT)
4093                         {
4094                                 object_level = base_level + object_index;
4095
4096                                 /* Create an out of deep object */
4097                                 if (randint0(100) < 75)
4098                                         place_object(*y, *x, 0L);
4099                                 else if (randint0(100) < 80)
4100                                         place_object(*y, *x, AM_GOOD);
4101                                 else
4102                                         place_object(*y, *x, AM_GOOD | AM_GREAT);
4103
4104                                 object_level = base_level;
4105                         }
4106                         /* Random trap */
4107                         else if (random & RANDOM_TRAP)
4108                         {
4109                                 place_trap(*y, *x);
4110                         }
4111                         /* Hidden trap (or door) */
4112                         else if (letter[idx].trap)
4113                         {
4114                                 c_ptr->mimic = c_ptr->feat;
4115                                 c_ptr->feat = conv_dungeon_feat(letter[idx].trap);
4116                         }
4117                         else if (object_index)
4118                         {
4119                                 object_type *o_ptr = &object_type_body;
4120                                 object_prep(o_ptr, object_index);
4121
4122                                 if (o_ptr->tval == TV_GOLD)
4123                                 {
4124                                         coin_type = object_index - OBJ_GOLD_LIST;
4125                                         make_gold(o_ptr);
4126                                         coin_type = 0;
4127                                 }
4128
4129                                 /* Apply magic (no messages, no artifacts) */
4130                                 apply_magic(o_ptr, base_level, AM_NO_FIXED_ART | AM_GOOD);
4131
4132                                 drop_here(o_ptr, *y, *x);
4133                         }
4134
4135                         /* Artifact */
4136                         if (artifact_index)
4137                         {
4138                                 if (a_info[artifact_index].cur_num)
4139                                 {
4140                                         KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
4141                                         object_type forge;
4142                                         object_type *q_ptr = &forge;
4143
4144                                         object_prep(q_ptr, k_idx);
4145                                         drop_here(q_ptr, *y, *x);
4146                                 }
4147                                 else
4148                                 {
4149                                         /* Create the artifact */
4150                                         if (create_named_art(artifact_index, *y, *x))
4151                                                 a_info[artifact_index].cur_num = 1;
4152                                 }
4153                         }
4154
4155                         /* Terrain special */
4156                         c_ptr->special = letter[idx].special;
4157                 }
4158
4159                 (*y)++;
4160
4161                 return (0);
4162         }
4163
4164         /* Process "Q:<number>:<command>:... -- quest info */
4165         else if (buf[0] == 'Q')
4166         {
4167                 int num;
4168                 quest_type *q_ptr;
4169 #ifdef JP
4170                 if (buf[2] == '$')
4171                         return 0;
4172                 num = tokenize(buf + 2, 33, zz, 0);
4173 #else
4174                 if (buf[2] != '$')
4175                         return 0;
4176                 num = tokenize(buf + 3, 33, zz, 0);
4177 #endif
4178
4179                 /* Have we enough parameters? */
4180                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4181
4182                 /* Get the quest */
4183                 q_ptr = &(quest[atoi(zz[0])]);
4184
4185                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
4186                 if (zz[1][0] == 'Q')
4187                 {
4188                         if (init_flags & INIT_ASSIGN)
4189                         {
4190                                 monster_race *r_ptr;
4191                                 artifact_type *a_ptr;
4192
4193                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4194
4195                                 q_ptr->type    = (QUEST_TYPE)atoi(zz[2]);
4196                                 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
4197                                 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
4198                                 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
4199                                 q_ptr->level   = (DEPTH)atoi(zz[6]);
4200                                 q_ptr->r_idx   = (IDX)atoi(zz[7]);
4201                                 q_ptr->k_idx   = (IDX)atoi(zz[8]);
4202                                 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
4203
4204                                 if (num > 10) q_ptr->flags  = atoi(zz[10]);
4205
4206                                 r_ptr = &r_info[q_ptr->r_idx];
4207                                 if (r_ptr->flags1 & RF1_UNIQUE)
4208                                         r_ptr->flags1 |= RF1_QUESTOR;
4209
4210                                 a_ptr = &a_info[q_ptr->k_idx];
4211                                 a_ptr->gen_flags |= TRG_QUESTITEM;
4212                         }
4213                         return (0);
4214                 }
4215
4216                 else if (zz[1][0] == 'R')
4217                 {
4218                         if (init_flags & INIT_ASSIGN)
4219                         {
4220                                 int count = 0;
4221                                 IDX idx, reward_idx = 0;
4222
4223                                 for (idx = 2; idx < num; idx++)
4224                                 {
4225                                         IDX a_idx = (IDX)atoi(zz[idx]);
4226                                         if (a_idx < 1) continue;
4227                                         if (a_info[a_idx].cur_num > 0) continue;
4228                                         count++;
4229                                         if (one_in_(count)) reward_idx = a_idx;
4230                                 }
4231
4232                                 if (reward_idx)
4233                                 {
4234                                         /* Set quest's rewarding artifact */
4235                                         q_ptr->k_idx = reward_idx;
4236                                         a_info[reward_idx].gen_flags |= TRG_QUESTITEM;
4237                                 }
4238                                 else
4239                                 {
4240                                         /* Change a quest type to KILL_ALL when all artifact of reward list are got */
4241                                         q_ptr->type = QUEST_TYPE_KILL_ALL;
4242                                 }
4243                         }
4244
4245                         return (0);
4246                 }
4247
4248                 /* Process "Q:<q_index>:N:<name>" -- quest name */
4249                 else if (zz[1][0] == 'N')
4250                 {
4251                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY))
4252                         {
4253                                 strcpy(q_ptr->name, zz[2]);
4254                         }
4255
4256                         return (0);
4257                 }
4258
4259                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
4260                 else if (zz[1][0] == 'T')
4261                 {
4262                         if (init_flags & INIT_SHOW_TEXT)
4263                         {
4264                                 strcpy(quest_text[quest_text_line], zz[2]);
4265                                 quest_text_line++;
4266                         }
4267
4268                         return (0);
4269                 }
4270         }
4271
4272         /* Process "W:<command>: ..." -- info for the wilderness */
4273         else if (buf[0] == 'W')
4274         {
4275                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
4276         }
4277
4278         /* Process "P:<y>:<x>" -- player position */
4279         else if (buf[0] == 'P')
4280         {
4281                 if (init_flags & INIT_CREATE_DUNGEON)
4282                 {
4283                         if (tokenize(buf + 2, 2, zz, 0) == 2)
4284                         {
4285                                 int panels_x, panels_y;
4286
4287                                 /* Hack - Set the dungeon size */
4288                                 panels_y = (*y / SCREEN_HGT);
4289                                 if (*y % SCREEN_HGT) panels_y++;
4290                                 cur_hgt = panels_y * SCREEN_HGT;
4291
4292                                 panels_x = (*x / SCREEN_WID);
4293                                 if (*x % SCREEN_WID) panels_x++;
4294                                 cur_wid = panels_x * SCREEN_WID;
4295
4296                                 /* Assume illegal panel */
4297                                 panel_row_min = cur_hgt;
4298                                 panel_col_min = cur_wid;
4299
4300                                 /* Place player in a quest level */
4301                                 if (p_ptr->inside_quest)
4302                                 {
4303                                         POSITION py, px;
4304
4305                                         /* Delete the monster (if any) */
4306                                         delete_monster(p_ptr->y, p_ptr->x);
4307
4308                                         py = atoi(zz[0]);
4309                                         px = atoi(zz[1]);
4310
4311                                         p_ptr->y = py;
4312                                         p_ptr->x = px;
4313                                 }
4314                                 /* Place player in the town */
4315                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
4316                                 {
4317                                         p_ptr->oldpy = atoi(zz[0]);
4318                                         p_ptr->oldpx = atoi(zz[1]);
4319                                 }
4320                         }
4321                 }
4322
4323                 return (0);
4324         }
4325
4326         /* Process "B:<Index>:<Command>:..." -- Building definition */
4327         else if (buf[0] == 'B')
4328         {
4329                 return parse_line_building(buf);
4330         }
4331
4332         /* Process "M:<type>:<maximum>" -- set maximum values */
4333         else if (buf[0] == 'M')
4334         {
4335                 if (tokenize(buf+2, 2, zz, 0) == 2)
4336                 {
4337                         /* Maximum towns */
4338                         if (zz[0][0] == 'T')
4339                         {
4340                                 max_towns = (IDX)atoi(zz[1]);
4341                         }
4342
4343                         /* Maximum quests */
4344                         else if (zz[0][0] == 'Q')
4345                         {
4346                                 max_q_idx = (IDX)atoi(zz[1]);
4347                         }
4348
4349                         /* Maximum r_idx */
4350                         else if (zz[0][0] == 'R')
4351                         {
4352                                 max_r_idx = (IDX)atoi(zz[1]);
4353                         }
4354
4355                         /* Maximum k_idx */
4356                         else if (zz[0][0] == 'K')
4357                         {
4358                                 max_k_idx = (IDX)atoi(zz[1]);
4359                         }
4360
4361                         /* Maximum v_idx */
4362                         else if (zz[0][0] == 'V')
4363                         {
4364                                 max_v_idx = (IDX)atoi(zz[1]);
4365                         }
4366
4367                         /* Maximum f_idx */
4368                         else if (zz[0][0] == 'F')
4369                         {
4370                                 max_f_idx = (IDX)atoi(zz[1]);
4371                         }
4372
4373                         /* Maximum a_idx */
4374                         else if (zz[0][0] == 'A')
4375                         {
4376                                 max_a_idx = (IDX)atoi(zz[1]);
4377                         }
4378
4379                         /* Maximum e_idx */
4380                         else if (zz[0][0] == 'E')
4381                         {
4382                                 max_e_idx = (IDX)atoi(zz[1]);
4383                         }
4384
4385                         /* Maximum d_idx */
4386                         else if (zz[0][0] == 'D')
4387                         {
4388                                 max_d_idx = (IDX)atoi(zz[1]);
4389                         }
4390
4391                         /* Maximum o_idx */
4392                         else if (zz[0][0] == 'O')
4393                         {
4394                                 max_o_idx = (IDX)atoi(zz[1]);
4395                         }
4396
4397                         /* Maximum m_idx */
4398                         else if (zz[0][0] == 'M')
4399                         {
4400                                 max_m_idx = (IDX)atoi(zz[1]);
4401                         }
4402
4403                         /* Wilderness size */
4404                         else if (zz[0][0] == 'W')
4405                         {
4406                                 /* Maximum wild_x_size */
4407                                 if (zz[0][1] == 'X')
4408                                         max_wild_x = atoi(zz[1]);
4409                                 /* Maximum wild_y_size */
4410                                 if (zz[0][1] == 'Y')
4411                                         max_wild_y = atoi(zz[1]);
4412                         }
4413
4414                         return (0);
4415                 }
4416         }
4417
4418
4419         /* Failure */
4420         return (1);
4421 }
4422
4423
4424 static char tmp[8];
4425 static concptr variant = "ZANGBAND";
4426
4427
4428 /*!
4429  * @brief クエスト用固定ダンジョン生成時の分岐処理
4430  * Helper function for "process_dungeon_file()"
4431  * @param sp
4432  * @param fp
4433  * @return エラーコード
4434  */
4435 static concptr process_dungeon_file_expr(char **sp, char *fp)
4436 {
4437         concptr v;
4438
4439         char *b;
4440         char *s;
4441
4442         char b1 = '[';
4443         char b2 = ']';
4444
4445         char f = ' ';
4446
4447         /* Initial */
4448         s = (*sp);
4449
4450         /* Skip spaces */
4451         while (iswspace(*s)) s++;
4452
4453         /* Save start */
4454         b = s;
4455
4456         /* Default */
4457         v = "?o?o?";
4458
4459         /* Analyze */
4460         if (*s == b1)
4461         {
4462                 concptr p;
4463                 concptr t;
4464
4465                 /* Skip b1 */
4466                 s++;
4467
4468                 /* First */
4469                 t = process_dungeon_file_expr(&s, &f);
4470
4471                 if (!*t)
4472                 {
4473                         /* Nothing */
4474                 }
4475
4476                 /* Function: IOR */
4477                 else if (streq(t, "IOR"))
4478                 {
4479                         v = "0";
4480                         while (*s && (f != b2))
4481                         {
4482                                 t = process_dungeon_file_expr(&s, &f);
4483                                 if (*t && !streq(t, "0")) v = "1";
4484                         }
4485                 }
4486
4487                 /* Function: AND */
4488                 else if (streq(t, "AND"))
4489                 {
4490                         v = "1";
4491                         while (*s && (f != b2))
4492                         {
4493                                 t = process_dungeon_file_expr(&s, &f);
4494                                 if (*t && streq(t, "0")) v = "0";
4495                         }
4496                 }
4497
4498                 /* Function: NOT */
4499                 else if (streq(t, "NOT"))
4500                 {
4501                         v = "1";
4502                         while (*s && (f != b2))
4503                         {
4504                                 t = process_dungeon_file_expr(&s, &f);
4505                                 if (*t && streq(t, "1")) v = "0";
4506                         }
4507                 }
4508
4509                 /* Function: EQU */
4510                 else if (streq(t, "EQU"))
4511                 {
4512                         v = "0";
4513                         if (*s && (f != b2))
4514                         {
4515                                 t = process_dungeon_file_expr(&s, &f);
4516                         }
4517                         while (*s && (f != b2))
4518                         {
4519                                 p = process_dungeon_file_expr(&s, &f);
4520                                 if (streq(t, p)) v = "1";
4521                         }
4522                 }
4523
4524                 /* Function: LEQ */
4525                 else if (streq(t, "LEQ"))
4526                 {
4527                         v = "1";
4528                         if (*s && (f != b2))
4529                         {
4530                                 t = process_dungeon_file_expr(&s, &f);
4531                         }
4532                         while (*s && (f != b2))
4533                         {
4534                                 p = t;
4535                                 t = process_dungeon_file_expr(&s, &f);
4536                                 if (*t && atoi(p) > atoi(t)) v = "0";
4537                         }
4538                 }
4539
4540                 /* Function: GEQ */
4541                 else if (streq(t, "GEQ"))
4542                 {
4543                         v = "1";
4544                         if (*s && (f != b2))
4545                         {
4546                                 t = process_dungeon_file_expr(&s, &f);
4547                         }
4548                         while (*s && (f != b2))
4549                         {
4550                                 p = t;
4551                                 t = process_dungeon_file_expr(&s, &f);
4552
4553                                 /* Compare two numbers instead of string */
4554                                 if (*t && atoi(p) < atoi(t)) v = "0";
4555                         }
4556                 }
4557
4558                 else
4559                 {
4560                         while (*s && (f != b2))
4561                         {
4562                                 t = process_dungeon_file_expr(&s, &f);
4563                         }
4564                 }
4565
4566                 /* Verify ending */
4567                 if (f != b2) v = "?x?x?";
4568
4569                 /* Extract final and Terminate */
4570                 if ((f = *s) != '\0') *s++ = '\0';
4571         }
4572
4573         /* Other */
4574         else
4575         {
4576                 /* Accept all printables except spaces and brackets */
4577 #ifdef JP
4578                 while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
4579                 {
4580                         if (iskanji(*s)) s++;
4581                         s++;
4582                 }
4583 #else
4584                 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
4585 #endif
4586
4587                 /* Extract final and Terminate */
4588                 if ((f = *s) != '\0') *s++ = '\0';
4589
4590                 /* Variable */
4591                 if (*b == '$')
4592                 {
4593                         /* System */
4594                         if (streq(b+1, "SYS"))
4595                         {
4596                                 v = ANGBAND_SYS;
4597                         }
4598
4599                         /* Graphics */
4600                         else if (streq(b+1, "GRAF"))
4601                         {
4602                                 v = ANGBAND_GRAF;
4603                         }
4604
4605                         else if (streq(b+1, "MONOCHROME"))
4606                         {
4607                                 if (arg_monochrome)
4608                                         v = "ON";
4609                                 else
4610                                         v = "OFF";
4611                         }
4612
4613                         /* Race */
4614                         else if (streq(b+1, "RACE"))
4615                         {
4616                                 v = _(rp_ptr->E_title, rp_ptr->title);
4617                         }
4618
4619                         /* Class */
4620                         else if (streq(b+1, "CLASS"))
4621                         {
4622                                 v = _(cp_ptr->E_title, cp_ptr->title);
4623                         }
4624
4625                         /* First realm */
4626                         else if (streq(b+1, "REALM1"))
4627                         {
4628                                 v = _(E_realm_names[p_ptr->realm1], realm_names[p_ptr->realm1]);
4629                         }
4630
4631                         /* Second realm */
4632                         else if (streq(b+1, "REALM2"))
4633                         {
4634                                 v = _(E_realm_names[p_ptr->realm2], realm_names[p_ptr->realm2]);
4635                         }
4636
4637                         /* Player name */
4638                         else if (streq(b+1, "PLAYER"))
4639                         {
4640                                 static char tmp_player_name[32];
4641                                 char *pn, *tpn;
4642                                 for (pn = p_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
4643                                 {
4644 #ifdef JP
4645                                         if (iskanji(*pn))
4646                                         {
4647                                                 *(tpn++) = *(pn++);
4648                                                 *tpn = *pn;
4649                                                 continue;
4650                                         }
4651 #endif
4652                                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
4653                                 }
4654                                 *tpn = '\0';
4655                                 v = tmp_player_name;
4656                         }
4657
4658                         /* Town */
4659                         else if (streq(b+1, "TOWN"))
4660                         {
4661                                 sprintf(tmp, "%d", p_ptr->town_num);
4662                                 v = tmp;
4663                         }
4664
4665                         /* Level */
4666                         else if (streq(b+1, "LEVEL"))
4667                         {
4668                                 sprintf(tmp, "%d", p_ptr->lev);
4669                                 v = tmp;
4670                         }
4671
4672                         /* Current quest number */
4673                         else if (streq(b+1, "QUEST_NUMBER"))
4674                         {
4675                                 sprintf(tmp, "%d", p_ptr->inside_quest);
4676                                 v = tmp;
4677                         }
4678
4679                         /* Number of last quest */
4680                         else if (streq(b+1, "LEAVING_QUEST"))
4681                         {
4682                                 sprintf(tmp, "%d", leaving_quest);
4683                                 v = tmp;
4684                         }
4685
4686                         /* Quest type */
4687                         else if (prefix(b+1, "QUEST_TYPE"))
4688                         {
4689                                 /* "QUEST_TYPE" uses a special parameter to determine the type of the quest */
4690                                 sprintf(tmp, "%d", quest[atoi(b+11)].type);
4691                                 v = tmp;
4692                         }
4693
4694                         /* Quest status */
4695                         else if (prefix(b+1, "QUEST"))
4696                         {
4697                                 /* "QUEST" uses a special parameter to determine the number of the quest */
4698                                 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4699                                 v = tmp;
4700                         }
4701
4702                         /* Random */
4703                         else if (prefix(b+1, "RANDOM"))
4704                         {
4705                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
4706                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4707                                 v = tmp;
4708                         }
4709
4710                         /* Variant name */
4711                         else if (streq(b+1, "VARIANT"))
4712                         {
4713                                 v = variant;
4714                         }
4715
4716                         /* Wilderness */
4717                         else if (streq(b+1, "WILDERNESS"))
4718                         {
4719                                 if (vanilla_town)
4720                                         sprintf(tmp, "NONE");
4721                                 else if (lite_town)
4722                                         sprintf(tmp, "LITE");
4723                                 else
4724                                         sprintf(tmp, "NORMAL");
4725                                 v = tmp;
4726                         }
4727                 }
4728
4729                 /* Constant */
4730                 else
4731                 {
4732                         v = b;
4733                 }
4734         }
4735
4736         /* Save */
4737         (*fp) = f;
4738         (*sp) = s;
4739         return (v);
4740 }
4741
4742
4743 /*!
4744  * @brief クエスト用固定ダンジョン生成時のメインルーチン
4745  * Helper function for "process_dungeon_file()"
4746  * @param name ファイル名
4747  * @param ymin 詳細不明
4748  * @param xmin 詳細不明
4749  * @param ymax 詳細不明
4750  * @param xmax 詳細不明
4751  * @return エラーコード
4752  */
4753 errr process_dungeon_file(concptr name, int ymin, int xmin, int ymax, int xmax)
4754 {
4755         FILE *fp;
4756         char buf[1024];
4757         int num = -1;
4758         errr err = 0;
4759         bool bypass = FALSE;
4760         int x = xmin, y = ymin;
4761
4762
4763         /* Build the filename */
4764         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
4765
4766         /* Open the file */
4767         fp = my_fopen(buf, "r");
4768
4769         /* No such file */
4770         if (!fp) return (-1);
4771
4772
4773         /* Process the file */
4774         while (0 == my_fgets(fp, buf, sizeof(buf)))
4775         {
4776                 /* Count lines */
4777                 num++;
4778
4779
4780                 /* Skip "empty" lines */
4781                 if (!buf[0]) continue;
4782
4783                 /* Skip "blank" lines */
4784                 if (iswspace(buf[0])) continue;
4785
4786                 /* Skip comments */
4787                 if (buf[0] == '#') continue;
4788
4789
4790                 /* Process "?:<expr>" */
4791                 if ((buf[0] == '?') && (buf[1] == ':'))
4792                 {
4793                         char f;
4794                         concptr v;
4795                         char *s;
4796
4797                         /* Start */
4798                         s = buf + 2;
4799
4800                         /* Parse the expr */
4801                         v = process_dungeon_file_expr(&s, &f);
4802
4803                         /* Set flag */
4804                         bypass = (streq(v, "0") ? TRUE : FALSE);
4805                         continue;
4806                 }
4807
4808                 /* Apply conditionals */
4809                 if (bypass) continue;
4810
4811                 /* Process the line */
4812                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4813
4814                 if (err) break;
4815         }
4816
4817         /* Errors */
4818         if (err)
4819         {
4820                 concptr oops;
4821
4822                 /* Error string */
4823                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4824
4825                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4826                 msg_format(_("'%s'を解析中。", "Parsing '%s'."), buf);
4827
4828                 msg_print(NULL);
4829         }
4830
4831         my_fclose(fp);
4832         return (err);
4833 }
4834
4835
4836
4837 #if 0
4838 void write_r_info_txt(void)
4839 {
4840         int i, j, z, fc, bc;
4841         int dlen;
4842
4843         concptr flags[32 * 10];
4844
4845         u32b f_ptr[10];
4846         concptr *n_ptr[10];
4847
4848         monster_race *r_ptr;
4849
4850         monster_blow *b_ptr;
4851
4852         FILE *fff = fopen("output.txt", "wt");
4853
4854         concptr desc;
4855
4856         BIT_FLAGS mode = -1;
4857
4858         if (!fff) return;
4859
4860         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4861
4862         fprintf(fff, "# Version stamp (required)\n\n");
4863
4864         /* Write Version */
4865         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4866
4867         /* Write a note */
4868         fprintf(fff, "##### The Player #####\n\n");
4869
4870         for (z = -1; z < alloc_race_size; z++)
4871         {
4872                 /* Output the monsters in order */
4873                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4874
4875                 /* Acquire the monster */
4876                 r_ptr = &r_info[i];
4877
4878                 /* Ignore empty monsters */
4879                 if (!strlen(r_name + r_ptr->name)) continue;
4880
4881                 /* Ignore useless monsters */
4882                 if (i && !r_ptr->speed) continue;
4883
4884                 /* Write a note if necessary */
4885                 if (i && (!r_ptr->level != !mode))
4886                 {
4887                         /* Note the town */
4888                         if (!r_ptr->level)
4889                         {
4890                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4891                         }
4892                         /* Note the dungeon */
4893                         else
4894                         {
4895                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4896                         }
4897
4898                         /* Record the change */
4899                         mode = r_ptr->level;
4900                 }
4901
4902                 /* Acquire the flags */
4903                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4904                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4905                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4906                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4907                 f_ptr[4] = r_ptr->a_ability_flags1; n_ptr[4] = r_a_ability_flags1;
4908                 f_ptr[5] = r_ptr->a_ability_flags2; n_ptr[5] = r_a_ability_flags2;
4909                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4910                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4911                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4912                 f_ptr[9] = r_ptr->flagsr; n_ptr[9] = r_info_flagsr;
4913
4914                 /* Write New/Number/Name */
4915                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4916
4917                 /* Write Graphic */
4918                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4919
4920                 /* Write Information */
4921                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4922                                                                                                                   r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4923
4924                 /* Write more information */
4925                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4926
4927                 /* Write Blows */
4928                 for(j = 0; j < 4; j++)
4929                 {
4930                         b_ptr = &(r_ptr->blow[j]);
4931
4932                         /* Stop when done */
4933                         if (!b_ptr->method) break;
4934
4935                         /* Write the blows */
4936                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4937                                                                                                           r_info_blow_effect[b_ptr->effect],
4938                                                                                                           b_ptr->d_dice, b_ptr->d_side);
4939                 }
4940                 for (fc = 0, j = 0; j < 32 * 3; j++)
4941                 {
4942                         /* Check this flag */
4943                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4944                 }
4945
4946                 /* Extract the extra flags */
4947                 for (j = 32 * 6; j < 32 * 10; j++)
4948                 {
4949                         /* Check this flag */
4950                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4951                 }
4952
4953                 /* Write the flags */
4954                 for (j = 0; j < fc;)
4955                 {
4956                         char buf[160];
4957
4958                         /* Start the line */
4959                         sprintf(buf, "F:");
4960
4961                         for (bc = 0; (bc < 60) && (j < fc); j++)
4962                         {
4963                                 char t[80];
4964
4965                                 /* Format the flag */
4966                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4967
4968                                 /* Add it to the buffer */
4969                                 strcat(buf, t);
4970
4971                                 /* Note the length */
4972                                 bc += strlen(t);
4973                         }
4974
4975                         /* Done with this line; write it */
4976                         fprintf(fff, "%s\n", buf);
4977                 }
4978
4979                 /* Write Spells if applicable */
4980                 if (r_ptr->freq_spell)
4981                 {
4982                         /* Write the frequency */
4983                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4984
4985                         /* Extract the spell flags */
4986                         for (fc = 0, j = 96; j < 192; j++)
4987                         {
4988                                 /* Check this flag */
4989                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4990                         }
4991
4992                         /* Write the flags */
4993                         for (j = 0; j < fc;)
4994                         {
4995                                 char buf[160], *t;
4996
4997                                 /* Start the line */
4998                                 sprintf(buf, "S:");
4999
5000                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
5001                                 {
5002                                         int tlen;
5003
5004                                         /* Format the flag */
5005                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
5006
5007                                         tlen = strlen(t);
5008
5009                                         /* Note the length */
5010                                         bc += tlen;
5011
5012                                         /* Advance */
5013                                         t += tlen;
5014                                 }
5015
5016                                 /* Done with this line; write it */
5017                                 fprintf(fff, "%s\n", buf);
5018                         }
5019                 }
5020
5021                 /* Acquire the description */
5022                 desc = r_text + r_ptr->text;
5023                 dlen = strlen(desc);
5024
5025                 /* Write Description */
5026                 for (j = 0; j < dlen;)
5027                 {
5028                         char buf[160], *t;
5029
5030                         /* Start the line */
5031                         sprintf(buf, "D:");
5032
5033                         for (bc = 0, t = buf + 2; ((bc < 60) || !iswspace(desc[j])) && (j < dlen); j++, bc++, t++)
5034                         {
5035                                 *t = desc[j];
5036                         }
5037
5038                         /* Terminate it */
5039                         *t = '\0';
5040
5041                         /* Done with this line; write it */
5042                         fprintf(fff, "%s\n", buf);
5043                 }
5044
5045                 /* Space between entries */
5046                 fprintf(fff, "\n");
5047         }
5048
5049         fclose(fff);
5050 }
5051
5052 #endif