OSDN Git Service

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