OSDN Git Service

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