OSDN Git Service

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