OSDN Git Service

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