OSDN Git Service

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