OSDN Git Service

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