OSDN Git Service

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