OSDN Git Service

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