OSDN Git Service

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