OSDN Git Service

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