OSDN Git Service

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