OSDN Git Service

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