OSDN Git Service

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