OSDN Git Service

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