OSDN Git Service

Reworded for clarity some of the English messages which record why named pets were...
[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 /*!
541  * モンスター特性トークンの定義7 /
542  * Monster race flags
543  */
544 static concptr r_info_flags7[] =
545 {
546         "AQUATIC",
547         "CAN_SWIM",
548         "CAN_FLY",
549         "FRIENDLY",
550         "NAZGUL",
551         "UNIQUE2",
552         "RIDING",
553         "KAGE",
554         "HAS_LITE_1",
555         "SELF_LITE_1",
556         "HAS_LITE_2",
557         "SELF_LITE_2",
558         "GUARDIAN",
559         "CHAMELEON",
560         "XXXX4XXX",
561         "TANUKI",
562         "HAS_DARK_1",
563         "SELF_DARK_1",
564         "HAS_DARK_2",
565         "SELF_DARK_2",
566         "XXX7X20",
567         "XXX7X21",
568         "XXX7X22",
569         "XXX7X23",
570         "XXX7X24",
571         "XXX7X25",
572         "XXX7X26",
573         "XXX7X27",
574         "XXX7X28",
575         "XXX7X29",
576         "XXX7X30",
577         "XXX7X31",
578 };
579
580 /*!
581  * モンスター特性トークンの定義8 /
582  * Monster race flags
583  */
584 static concptr r_info_flags8[] =
585 {
586         "WILD_ONLY",
587         "WILD_TOWN",
588         "XXX8X02",
589         "WILD_SHORE",
590         "WILD_OCEAN",
591         "WILD_WASTE",
592         "WILD_WOOD",
593         "WILD_VOLCANO",
594         "XXX8X08",
595         "WILD_MOUNTAIN",
596         "WILD_GRASS",
597         "XXX8X11",
598         "XXX8X12",
599         "XXX8X13",
600         "XXX8X14",
601         "XXX8X15",
602         "XXX8X16",
603         "XXX8X17",
604         "XXX8X18",
605         "XXX8X19",
606         "XXX8X20",
607         "XXX8X21",
608         "XXX8X22",
609         "XXX8X23",
610         "XXX8X24",
611         "XXX8X25",
612         "XXX8X26",
613         "XXX8X27",
614         "XXX8X28",
615         "XXX8X29",
616         "WILD_SWAMP",   /* ToDo: Implement Swamp */
617         "WILD_ALL",
618 };
619
620 /*!
621  * モンスター特性トークンの定義9 /
622  * Monster race flags
623  */
624 static concptr r_info_flags9[] =
625 {
626         "DROP_CORPSE",
627         "DROP_SKELETON",
628         "EAT_BLIND",
629         "EAT_CONF",
630         "EAT_MANA",
631         "EAT_NEXUS",
632         "EAT_BLINK",
633         "EAT_SLEEP",
634         "EAT_BERSERKER",
635         "EAT_ACIDIC",
636         "EAT_SPEED",
637         "EAT_CURE",
638         "EAT_FIRE_RES",
639         "EAT_COLD_RES",
640         "EAT_ACID_RES",
641         "EAT_ELEC_RES",
642         "EAT_POIS_RES",
643         "EAT_INSANITY",
644         "EAT_DRAIN_EXP",
645         "EAT_POISONOUS",
646         "EAT_GIVE_STR",
647         "EAT_GIVE_INT",
648         "EAT_GIVE_WIS",
649         "EAT_GIVE_DEX",
650         "EAT_GIVE_CON",
651         "EAT_GIVE_CHR",
652         "EAT_LOSE_STR",
653         "EAT_LOSE_INT",
654         "EAT_LOSE_WIS",
655         "EAT_LOSE_DEX",
656         "EAT_LOSE_CON",
657         "EAT_LOSE_CHR",
658         "EAT_DRAIN_MANA",
659 };
660
661 /*!
662  * モンスター特性トークンの定義R(耐性) /
663  * Monster race flags
664  */
665 static concptr r_info_flagsr[] =
666 {
667         "IM_ACID",
668         "IM_ELEC",
669         "IM_FIRE",
670         "IM_COLD",
671         "IM_POIS",
672         "RES_LITE",
673         "RES_DARK",
674         "RES_NETH",
675         "RES_WATE",
676         "RES_PLAS",
677         "RES_SHAR",
678         "RES_SOUN",
679         "RES_CHAO",
680         "RES_NEXU",
681         "RES_DISE",
682         "RES_WALL",
683         "RES_INER",
684         "RES_TIME",
685         "RES_GRAV",
686         "RES_ALL",
687         "RES_TELE",
688         "XXX",
689         "XXX",
690         "XXX",
691         "XXX",
692         "XXX",
693         "XXX",
694         "XXX",
695         "XXX",
696         "XXX",
697         "XXX",
698         "XXX",
699 };
700
701 /*!
702  * オブジェクト基本特性トークンの定義 /
703  * Object flags
704  */
705 static concptr k_info_flags[] =
706 {
707         "STR",
708         "INT",
709         "WIS",
710         "DEX",
711         "CON",
712         "CHR",
713         "MAGIC_MASTERY",
714         "FORCE_WEAPON",
715         "STEALTH",
716         "SEARCH",
717         "INFRA",
718         "TUNNEL",
719         "SPEED",
720         "BLOWS",
721         "CHAOTIC",
722         "VAMPIRIC",
723         "SLAY_ANIMAL",
724         "SLAY_EVIL",
725         "SLAY_UNDEAD",
726         "SLAY_DEMON",
727         "SLAY_ORC",
728         "SLAY_TROLL",
729         "SLAY_GIANT",
730         "SLAY_DRAGON",
731         "KILL_DRAGON",
732         "VORPAL",
733         "IMPACT",
734         "BRAND_POIS",
735         "BRAND_ACID",
736         "BRAND_ELEC",
737         "BRAND_FIRE",
738         "BRAND_COLD",
739
740         "SUST_STR",
741         "SUST_INT",
742         "SUST_WIS",
743         "SUST_DEX",
744         "SUST_CON",
745         "SUST_CHR",
746         "RIDING",
747         "EASY_SPELL",
748         "IM_ACID",
749         "IM_ELEC",
750         "IM_FIRE",
751         "IM_COLD",
752         "THROW",
753         "REFLECT",
754         "FREE_ACT",
755         "HOLD_EXP",
756         "RES_ACID",
757         "RES_ELEC",
758         "RES_FIRE",
759         "RES_COLD",
760         "RES_POIS",
761         "RES_FEAR",
762         "RES_LITE",
763         "RES_DARK",
764         "RES_BLIND",
765         "RES_CONF",
766         "RES_SOUND",
767         "RES_SHARDS",
768         "RES_NETHER",
769         "RES_NEXUS",
770         "RES_CHAOS",
771         "RES_DISEN",
772
773         "SH_FIRE",
774         "SH_ELEC",
775         "SLAY_HUMAN",
776         "SH_COLD",
777         "NO_TELE",
778         "NO_MAGIC",
779         "DEC_MANA",
780         "TY_CURSE",
781         "WARNING",
782         "HIDE_TYPE",
783         "SHOW_MODS",
784         "SLAY_GOOD",
785         "LEVITATION",
786         "LITE",
787         "SEE_INVIS",
788         "TELEPATHY",
789         "SLOW_DIGEST",
790         "REGEN",
791         "XTRA_MIGHT",
792         "XTRA_SHOTS",
793         "IGNORE_ACID",
794         "IGNORE_ELEC",
795         "IGNORE_FIRE",
796         "IGNORE_COLD",
797         "ACTIVATE",
798         "DRAIN_EXP",
799         "TELEPORT",
800         "AGGRAVATE",
801         "BLESSED",
802         "XXX3", /* Fake flag for Smith */
803         "XXX4", /* Fake flag for Smith */
804         "KILL_GOOD",
805
806         "KILL_ANIMAL",
807         "KILL_EVIL",
808         "KILL_UNDEAD",
809         "KILL_DEMON",
810         "KILL_ORC",
811         "KILL_TROLL",
812         "KILL_GIANT",
813         "KILL_HUMAN",
814         "ESP_ANIMAL",
815         "ESP_UNDEAD",
816         "ESP_DEMON",
817         "ESP_ORC",
818         "ESP_TROLL",
819         "ESP_GIANT",
820         "ESP_DRAGON",
821         "ESP_HUMAN",
822         "ESP_EVIL",
823         "ESP_GOOD",
824         "ESP_NONLIVING",
825         "ESP_UNIQUE",
826         "FULL_NAME",
827         "FIXED_FLAVOR",
828         "ADD_L_CURSE",
829         "ADD_H_CURSE",
830         "DRAIN_HP",
831         "DRAIN_MANA",
832
833         "LITE_2",
834         "LITE_3",
835         "LITE_M1",
836         "LITE_M2",
837         "LITE_M3",
838         "LITE_FUEL",
839
840         "CALL_ANIMAL",
841         "CALL_DEMON",
842         "CALL_DRAGON",
843         "CALL_UNDEAD",
844         "COWARDICE",
845         "LOW_MELEE",
846         "LOW_AC",
847         "LOW_MAGIC",
848         "FAST_DIGEST",
849         "SLOW_REGEN",
850 };
851
852 /*!
853  * オブジェクト生成特性トークンの定義 /
854  * Object flags
855  */
856 static concptr k_info_gen_flags[] =
857 {
858         "INSTA_ART",
859         "QUESTITEM",
860         "XTRA_POWER",
861         "ONE_SUSTAIN",
862         "XTRA_RES_OR_POWER",
863         "XTRA_H_RES",
864         "XTRA_E_RES",
865         "XTRA_L_RES",
866         "XTRA_D_RES",
867         "XTRA_RES",
868         "CURSED",
869         "HEAVY_CURSE",
870         "PERMA_CURSE",
871         "RANDOM_CURSE0",
872         "RANDOM_CURSE1",
873         "RANDOM_CURSE2",
874         "XTRA_DICE",
875         "POWERFUL",
876         "XXX",
877         "XXX",
878         "XXX",
879         "XXX",
880         "XXX",
881         "XXX",
882         "XXX",
883         "XXX",
884         "XXX",
885         "XXX",
886         "XXX",
887         "XXX",
888         "XXX",
889         "XXX",
890 };
891
892 /*!
893  * ダンジョン特性トークンの定義 /
894  * Dungeon flags
895  */
896 static concptr d_info_flags1[] =
897 {
898         "WINNER",
899         "MAZE",
900         "SMALLEST",
901         "BEGINNER",
902         "BIG",
903         "NO_DOORS",
904         "WATER_RIVER",
905         "LAVA_RIVER",
906         "CURTAIN",
907         "GLASS_DOOR",
908         "CAVE",
909         "CAVERN",
910         "ARCADE",
911         "LAKE_ACID",
912         "LAKE_POISONOUS",
913         "XXX",
914         "FORGET",
915         "LAKE_WATER",
916         "LAKE_LAVA",
917         "LAKE_RUBBLE",
918         "LAKE_TREE",
919         "NO_VAULT",
920         "ARENA",
921         "DESTROY",
922         "GLASS_ROOM",
923         "NO_CAVE",
924         "NO_MAGIC",
925         "NO_MELEE",
926         "CHAMELEON",
927         "DARKNESS",
928         "ACID_RIVER",
929         "POISONOUS_RIVER"
930 };
931
932 /*!
933  * @brief データの可変文字列情報をテキストとして保管する /
934  * Add a text to the text-storage and store offset to it.
935  * @param offset 文字列保管ポインタからのオフセット
936  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
937  * @param buf 保管文字列
938  * @param normal_text テキストの正規化を行う
939  * @return
940  * 無事保管ができたらTRUEを返す。
941  * Returns FALSE when there isn't enough space available to store
942  * the text.
943  */
944 static bool add_text(u32b *offset, header *head, concptr buf, bool normal_text)
945 {
946         /* Hack -- Verify space */
947         if (head->text_size + strlen(buf) + 8 > FAKE_TEXT_SIZE)
948                 return FALSE;
949
950         /* New text? */
951         if (*offset == 0)
952         {
953                 /* Advance and save the text index */
954                 *offset = ++head->text_size;
955         }
956
957         /* Additional text */
958         else if (normal_text)
959         {
960                 /*
961                  * If neither the end of the last line nor
962                  * the beginning of current line is not a space,
963                  * fill up a space as a correct separator of two words.
964                  */
965                 if (head->text_size > 0 &&
966 #ifdef JP
967                 (*(head->text_ptr + head->text_size - 1) != ' ') &&
968                         ((head->text_size == 1) || !iskanji(*(head->text_ptr + head->text_size - 2))) &&
969                         (buf[0] != ' ') && !iskanji(buf[0])
970 #else
971                         (*(head->text_ptr + head->text_size - 1) != ' ') &&
972                         (buf[0] != ' ')
973 #endif
974                         )
975                 {
976                         /* Append a space */
977                         *(head->text_ptr + head->text_size) = ' ';
978
979                         /* Advance the index */
980                         head->text_size++;
981                 }
982         }
983
984         strcpy(head->text_ptr + head->text_size, buf);
985         head->text_size += strlen(buf);
986         return TRUE;
987 }
988
989
990 /*!
991  * @brief データの可変文字列情報を名前として保管する /
992  * Add a name to the name-storage and return an offset to it.
993  * @param offset 文字列保管ポインタからのオフセット
994  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
995  * @param buf 保管文字列
996  * @return
997  * 無事保管ができたらTRUEを返す。
998  * Returns FALSE when there isn't enough space available to store
999  * the text.
1000  */
1001 static bool add_name(u32b *offset, header *head, concptr buf)
1002 {
1003         /* Hack -- Verify space */
1004         if (head->name_size + strlen(buf) + 8 > FAKE_NAME_SIZE)
1005                 return FALSE;
1006
1007         /* New name? */
1008         if (*offset == 0)
1009         {
1010                 /* Advance and save the name index */
1011                 *offset = ++head->name_size;
1012         }
1013
1014         /* Append chars to the names */
1015         strcpy(head->name_ptr + head->name_size, buf);
1016
1017         /* Advance the index */
1018         head->name_size += strlen(buf);
1019
1020         /* Success */
1021         return TRUE;
1022 }
1023
1024
1025 /*!
1026  * @brief データの可変文字列情報をタグとして保管する /
1027  * Add a tag to the tag-storage and return an offset to it.
1028  * @param offset 文字列保管ポインタからのオフセット
1029  * @param head テキスト保管ヘッダ情報の構造体参照ポインタ
1030  * @param buf 保管文字列
1031  * @return
1032  * 無事保管ができたらTRUEを返す。
1033  * Returns FALSE when there isn't enough space available to store
1034  * the text.
1035  */
1036 static bool add_tag(STR_OFFSET *offset, header *head, concptr buf)
1037 {
1038         u32b i;
1039
1040         /* Search for an existing (fake) tag */
1041         for (i = 1; i < head->tag_size; i += strlen(&head->tag_ptr[i]) + 1)
1042         {
1043                 /* Found it */
1044                 if (streq(&head->tag_ptr[i], buf)) break;
1045         }
1046
1047         /* There was no existing tag */
1048         if (i >= head->tag_size)
1049         {
1050                 /* Hack -- Verify space */
1051                 if (head->tag_size + strlen(buf) + 8 > FAKE_TAG_SIZE)
1052                         return FALSE;
1053
1054                 /* Append chars to the tags */
1055                 strcpy(head->tag_ptr + head->tag_size, buf);
1056
1057                 /* Point the new tag */
1058                 i = head->tag_size;
1059
1060                 /* Advance the index */
1061                 head->tag_size += strlen(buf) + 1;
1062         }
1063
1064         *offset = (s16b)i;
1065         return TRUE;
1066 }
1067
1068
1069 /*** Initialize from ascii template files ***/
1070
1071
1072 /*!
1073  * @brief パース関数に基づいてデータファイルからデータを読み取る /
1074  * Initialize an "*_info" array, by parsing an ascii "template" file
1075  * @param fp 読み取りに使うファイルポインタ
1076  * @param buf 読み取りに使うバッファ領域
1077  * @param head ヘッダ構造体
1078  * @param parse_info_txt_line パース関数
1079  * @return エラーコード
1080  */
1081 errr init_info_txt(FILE *fp, char *buf, header *head, parse_info_txt_func parse_info_txt_line)
1082 {
1083         /* Just before the first record */
1084         error_idx = -1;
1085
1086         /* Just before the first line */
1087         error_line = 0;
1088
1089         /* Prepare the "fake" stuff */
1090         head->name_size = 0;
1091         head->text_size = 0;
1092         head->tag_size = 0;
1093
1094         /* Parse */
1095         errr err;
1096         while (my_fgets(fp, buf, 1024) == 0)
1097         {
1098                 /* Advance the line number */
1099                 error_line++;
1100
1101                 /* Skip comments and blank lines */
1102                 if (!buf[0] || (buf[0] == '#')) continue;
1103
1104                 /* Verify correct "colon" format */
1105                 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
1106
1107
1108                 /* Hack -- Process 'V' for "Version" */
1109                 if (buf[0] == 'V')
1110                 {
1111                         /* ignore */
1112                         continue;
1113                 }
1114
1115                 /* Mega Hack -- Calculate Check Sum */
1116                 if (buf[0] != 'N' && buf[0] != 'D')
1117                 {
1118                         int i;
1119                         for (i = 0; buf[i]; i++)
1120                         {
1121                                 head->v_extra += (byte)buf[i];
1122                                 head->v_extra ^= (1 << (i % 8));
1123                         }
1124                 }
1125
1126                 /* Parse the line */
1127                 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
1128                         return (err);
1129         }
1130
1131
1132         /* Complete the "name" and "text" sizes */
1133         if (head->name_size) head->name_size++;
1134         if (head->text_size) head->text_size++;
1135
1136         /* Success */
1137         return 0;
1138 }
1139
1140
1141 /*!
1142  * @brief Vault情報(v_info)のパース関数 /
1143  * Initialize the "v_info" array, by parsing an ascii "template" file
1144  * @param buf テキスト列
1145  * @param head ヘッダ構造体
1146  * @return エラーコード
1147  */
1148 errr parse_v_info(char *buf, header *head)
1149 {
1150         int i;
1151         char *s;
1152
1153         /* Current entry */
1154         static vault_type *v_ptr = NULL;
1155
1156         /* Process 'N' for "New/Number/Name" */
1157         if (buf[0] == 'N')
1158         {
1159                 /* Find the colon before the name */
1160                 s = my_strchr(buf + 2, ':');
1161
1162                 /* Verify that colon */
1163                 if (!s) return 1;
1164
1165                 /* Nuke the colon, advance to the name */
1166                 *s++ = '\0';
1167
1168                 /* Paranoia -- require a name */
1169                 if (!*s) return 1;
1170
1171                 /* Get the index */
1172                 i = atoi(buf + 2);
1173
1174                 /* Verify information */
1175                 if (i <= error_idx) return 4;
1176
1177                 /* Verify information */
1178                 if (i >= head->info_num) return 2;
1179
1180                 /* Save the index */
1181                 error_idx = i;
1182
1183                 /* Point at the "info" */
1184                 v_ptr = &v_info[i];
1185
1186                 /* Store the name */
1187                 if (!add_name(&v_ptr->name, head, s)) return 7;
1188         }
1189
1190         /* There better be a current v_ptr */
1191         else if (!v_ptr) return 3;
1192
1193         /* Process 'D' for "Description" */
1194         else if (buf[0] == 'D')
1195         {
1196                 /* Acquire the text */
1197                 s = buf + 2;
1198
1199                 /* Store the text */
1200                 if (!add_text(&v_ptr->text, head, s, FALSE)) return 7;
1201         }
1202
1203         /* Process 'X' for "Extra info" (one line only) */
1204         else if (buf[0] == 'X')
1205         {
1206                 EFFECT_ID typ, rat, hgt, wid;
1207
1208                 /* Scan for the values */
1209                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1210                         &typ, &rat, &hgt, &wid)) return 1;
1211
1212                 /* Save the values */
1213                 v_ptr->typ = (ROOM_IDX)typ;
1214                 v_ptr->rat = (PROB)rat;
1215                 v_ptr->hgt = (POSITION)hgt;
1216                 v_ptr->wid = (POSITION)wid;
1217         }
1218
1219         else    return 6;
1220
1221         /* Success */
1222         return 0;
1223 }
1224
1225
1226 /*!
1227  * @brief 職業技能情報(s_info)のパース関数 /
1228  * Initialize the "s_info" array, by parsing an ascii "template" file
1229  * @param buf テキスト列
1230  * @param head ヘッダ構造体
1231  * @return エラーコード
1232  */
1233 errr parse_s_info(char *buf, header *head)
1234 {
1235         int i;
1236
1237         /* Current entry */
1238         static skill_table *s_ptr = NULL;
1239
1240
1241         /* Process 'N' for "New/Number/Name" */
1242         if (buf[0] == 'N')
1243         {
1244                 /* Get the index */
1245                 i = atoi(buf + 2);
1246
1247                 /* Verify information */
1248                 if (i <= error_idx) return 4;
1249
1250                 /* Verify information */
1251                 if (i >= head->info_num) return 2;
1252
1253                 /* Save the index */
1254                 error_idx = i;
1255
1256                 /* Point at the "info" */
1257                 s_ptr = &s_info[i];
1258         }
1259
1260         /* There better be a current s_ptr */
1261         else if (!s_ptr) return 3;
1262
1263         /* Process 'W' for "Weapon exp" */
1264         else if (buf[0] == 'W')
1265         {
1266                 int tval, sval, start, max;
1267                 const s16b exp_conv_table[] =
1268                 {
1269                         WEAPON_EXP_UNSKILLED, WEAPON_EXP_BEGINNER, WEAPON_EXP_SKILLED,
1270                         WEAPON_EXP_EXPERT, WEAPON_EXP_MASTER
1271                 };
1272
1273                 /* Scan for the values */
1274                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1275                         &tval, &sval, &start, &max)) return 1;
1276
1277                 if (start < EXP_LEVEL_UNSKILLED || start > EXP_LEVEL_MASTER
1278                         || max < EXP_LEVEL_UNSKILLED || max > EXP_LEVEL_MASTER) return 8;
1279
1280                 /* Save the values */
1281                 s_ptr->w_start[tval][sval] = exp_conv_table[start];
1282                 s_ptr->w_max[tval][sval] = exp_conv_table[max];
1283         }
1284
1285         /* Process 'S' for "Skill exp" */
1286         else if (buf[0] == 'S')
1287         {
1288                 int num, start, max;
1289
1290                 /* Scan for the values */
1291                 if (3 != sscanf(buf + 2, "%d:%d:%d",
1292                         &num, &start, &max)) return 1;
1293
1294                 if (start < WEAPON_EXP_UNSKILLED || start > WEAPON_EXP_MASTER
1295                         || max < WEAPON_EXP_UNSKILLED || max > WEAPON_EXP_MASTER) return 8;
1296
1297                 /* Save the values */
1298                 s_ptr->s_start[num] = (SUB_EXP)start;
1299                 s_ptr->s_max[num] = (SUB_EXP)max;
1300         }
1301
1302
1303         else return 6;
1304
1305         /* Success */
1306         return 0;
1307 }
1308
1309
1310 /*!
1311  * @brief 職業魔法情報(m_info)のパース関数 /
1312  * Initialize the "m_info" array, by parsing an ascii "template" file
1313  * @param buf テキスト列
1314  * @param head ヘッダ構造体
1315  * @return エラーコード
1316  */
1317 errr parse_m_info(char *buf, header *head)
1318 {
1319         int i;
1320
1321         char *s;
1322
1323         /* Current entry */
1324         static player_magic *m_ptr = NULL;
1325
1326         /* ---Hack--- */
1327         static int realm, magic_idx = 0, readable = 0;
1328
1329
1330         /* Process 'N' for "New/Number/Name" */
1331         if (buf[0] == 'N')
1332         {
1333                 /* Get the index */
1334                 i = atoi(buf + 2);
1335
1336                 /* Verify information */
1337                 if (i <= error_idx) return 4;
1338
1339                 /* Verify information */
1340                 if (i >= head->info_num) return 2;
1341
1342                 /* Save the index */
1343                 error_idx = i;
1344
1345                 /* Point at the "info" */
1346                 m_ptr = &m_info[i];
1347         }
1348
1349         /* There better be a current m_ptr */
1350         else if (!m_ptr) return 3;
1351
1352         /* Process 'I' for "Info" (one line only) */
1353         else if (buf[0] == 'I')
1354         {
1355                 char *book, *stat;
1356                 int xtra, type, first, weight;
1357
1358                 /* Find the colon before the name */
1359                 s = my_strchr(buf + 2, ':');
1360
1361                 /* Verify that colon */
1362                 if (!s) return 1;
1363
1364                 /* Nuke the colon, advance to the name */
1365                 *s++ = '\0';
1366
1367                 book = buf + 2;
1368
1369                 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1370                 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1371                 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1372                 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1373                 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1374                 else return 5;
1375
1376                 stat = s;
1377
1378                 /* Find the colon before the name */
1379                 s = my_strchr(s, ':');
1380
1381                 /* Verify that colon */
1382                 if (!s) return 1;
1383
1384                 /* Nuke the colon, advance to the name */
1385                 *s++ = '\0';
1386
1387                 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1388                 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1389                 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1390                 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1391                 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1392                 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1393                 else return 5;
1394
1395
1396                 /* Scan for the values */
1397                 if (4 != sscanf(s, "%x:%d:%d:%d",
1398                         (uint *)&xtra, &type, &first, &weight)) return 1;
1399
1400                 m_ptr->spell_xtra = xtra;
1401                 m_ptr->spell_type = type;
1402                 m_ptr->spell_first = first;
1403                 m_ptr->spell_weight = weight;
1404         }
1405
1406
1407         /* Process 'R' for "Realm" (one line only) */
1408         else if (buf[0] == 'R')
1409         {
1410                 /* Scan for the values */
1411                 if (2 != sscanf(buf + 2, "%d:%d",
1412                         &realm, &readable)) return 1;
1413
1414                 magic_idx = 0;
1415         }
1416
1417         else if (buf[0] == 'T')
1418         {
1419                 int level, mana, fail, exp;
1420
1421                 if (!readable) return 1;
1422                 /* Scan for the values */
1423                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1424                         &level, &mana, &fail, &exp)) return 1;
1425
1426                 m_ptr->info[realm][magic_idx].slevel = (PLAYER_LEVEL)level;
1427                 m_ptr->info[realm][magic_idx].smana = (MANA_POINT)mana;
1428                 m_ptr->info[realm][magic_idx].sfail = (PERCENTAGE)fail;
1429                 m_ptr->info[realm][magic_idx].sexp = (EXP)exp;
1430                 magic_idx++;
1431         }
1432         else return 6;
1433
1434         return 0;
1435 }
1436
1437
1438 /*!
1439  * @brief テキストトークンを走査してフラグを一つ得る(汎用) /
1440  * Grab one flag from a textual string
1441  * @param flags ビットフラグを追加する先の参照ポインタ
1442  * @param names トークン定義配列
1443  * @param what 参照元の文字列ポインタ
1444  * @return エラーコード
1445  */
1446 static errr grab_one_flag(u32b *flags, concptr names[], concptr what)
1447 {
1448         for (int i = 0; i < 32; i++)
1449         {
1450                 if (streq(what, names[i]))
1451                 {
1452                         *flags |= (1L << i);
1453                         return 0;
1454                 }
1455         }
1456
1457         return -1;
1458 }
1459
1460
1461 /*!
1462  * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) /
1463  * Grab one flag in an feature_type from a textual string
1464  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1465  * @param what 参照元の文字列ポインタ
1466  * @return エラーコード
1467  */
1468 static errr grab_one_feat_flag(feature_type *f_ptr, concptr what)
1469 {
1470         /* Check flags */
1471         for (int i = 0; i < FF_FLAG_MAX; i++)
1472         {
1473                 if (streq(what, f_info_flags[i]))
1474                 {
1475                         add_flag(f_ptr->flags, i);
1476                         return 0;
1477                 }
1478         }
1479
1480         msg_format(_("未知の地形フラグ '%s'。", "Unknown feature flag '%s'."), what);
1481         return PARSE_ERROR_GENERIC;
1482 }
1483
1484
1485 /*!
1486  * @brief テキストトークンを走査してフラグ(ステート)を一つ得る(地形情報向け2) /
1487  * Grab an action in an feature_type from a textual string
1488  * @param f_ptr 地形情報を保管する先の構造体参照ポインタ
1489  * @param what 参照元の文字列ポインタ
1490  * @param count ステートの保存先ID
1491  * @return エラーコード
1492  */
1493 static errr grab_one_feat_action(feature_type *f_ptr, concptr what, int count)
1494 {
1495         /* Check flags */
1496         for (FF_FLAGS_IDX i = 0; i < FF_FLAG_MAX; i++)
1497         {
1498                 if (streq(what, f_info_flags[i]))
1499                 {
1500                         f_ptr->state[count].action = i;
1501                         return 0;
1502                 }
1503         }
1504
1505         msg_format(_("未知の地形アクション '%s'。", "Unknown feature action '%s'."), what);
1506         return PARSE_ERROR_GENERIC;
1507 }
1508
1509
1510 /*!
1511  * @brief 地形情報(f_info)のパース関数 /
1512  * Initialize the "f_info" array, by parsing an ascii "template" file
1513  * @param buf テキスト列
1514  * @param head ヘッダ構造体
1515  * @return エラーコード
1516  */
1517 errr parse_f_info(char *buf, header *head)
1518 {
1519         /* Current entry */
1520         static feature_type *f_ptr = NULL;
1521
1522         /* Process 'N' for "New/Number/Name" */
1523         int i;
1524         char *s, *t;
1525         if (buf[0] == 'N')
1526         {
1527                 /* Find the colon before the name */
1528                 s = my_strchr(buf + 2, ':');
1529
1530                 if (s)
1531                 {
1532                         /* Nuke the colon, advance to the name */
1533                         *s++ = '\0';
1534                 }
1535
1536                 /* Get the index */
1537                 i = atoi(buf + 2);
1538
1539                 /* Verify information */
1540                 if (i <= error_idx) return 4;
1541
1542                 /* Verify information */
1543                 if (i >= head->info_num) return 2;
1544
1545                 /* Save the index */
1546                 error_idx = i;
1547
1548                 /* Point at the "info" */
1549                 f_ptr = &f_info[i];
1550
1551                 /* Tag name is given */
1552                 if (s)
1553                 {
1554                         /* Store the tag */
1555                         if (!add_tag(&f_ptr->tag, head, s)) return 7;
1556                 }
1557
1558                 /* Default "mimic" */
1559                 f_ptr->mimic = (FEAT_IDX)i;
1560
1561                 /* Default "destroyed state" -- if not specified */
1562                 f_ptr->destroyed = (FEAT_IDX)i;
1563
1564                 /* Default "states" */
1565                 for (i = 0; i < MAX_FEAT_STATES; i++) f_ptr->state[i].action = FF_FLAG_MAX;
1566         }
1567
1568         /* There better be a current f_ptr */
1569         else if (!f_ptr) return 3;
1570
1571 #ifdef JP
1572         else if (buf[0] == 'J')
1573         {
1574                 /* Store the name */
1575                 if (!add_name(&f_ptr->name, head, buf + 2)) return 7;
1576         }
1577
1578         else if (buf[0] == 'E')
1579         {
1580                 /* Ignore english name */
1581         }
1582 #else
1583         else if (buf[0] == 'J')
1584         {
1585                 /* Ignore Japanese name */
1586         }
1587
1588         else if (buf[0] == 'E')
1589         {
1590                 /* Acquire the Text */
1591                 s = buf + 2;
1592
1593                 /* Store the name */
1594                 if (!add_name(&f_ptr->name, head, s)) return 7;
1595         }
1596 #endif
1597
1598
1599         /* Process 'M' for "Mimic" (one line only) */
1600         else if (buf[0] == 'M')
1601         {
1602                 STR_OFFSET offset;
1603
1604                 if (!add_tag(&offset, head, buf + 2)) return PARSE_ERROR_OUT_OF_MEMORY;
1605
1606                 /* Record a fake tag index */
1607                 f_ptr->mimic_tag = offset;
1608         }
1609
1610
1611         /* Process 'G' for "Graphics" (one line only) */
1612         else if (buf[0] == 'G')
1613         {
1614                 int j;
1615                 byte s_attr;
1616                 char char_tmp[F_LIT_MAX];
1617                 if (buf[1] != ':') return 1;
1618                 if (!buf[2]) return 1;
1619                 if (buf[3] != ':') return 1;
1620                 if (!buf[4]) return 1;
1621
1622                 /* Extract the char */
1623                 char_tmp[F_LIT_STANDARD] = buf[2];
1624
1625                 /* Extract the color */
1626                 s_attr = color_char_to_attr(buf[4]);
1627                 if (s_attr > 127) return 1;
1628
1629                 /* Save the standard values */
1630                 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
1631                 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
1632
1633                 /* Is this feature supports lighting? */
1634                 if (buf[5] == ':')
1635                 {
1636                         /* G:c:a:LIT (default) */
1637                         apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
1638
1639                         /* G:c:a:lc:la:dc:da */
1640                         if (!streq(buf + 6, "LIT"))
1641                         {
1642                                 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
1643
1644                                 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
1645                                         &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
1646                                         &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
1647                                 if (buf[F_LIT_MAX * 4 + 1]) return 1;
1648
1649                                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1650                                 {
1651                                         switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
1652                                         {
1653                                         case '*':
1654                                                 /* Use default lighting */
1655                                                 break;
1656                                         case '-':
1657                                                 /* No lighting support */
1658                                                 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
1659                                                 break;
1660                                         default:
1661                                                 /* Extract the color */
1662                                                 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
1663                                                 if (f_ptr->d_attr[j] > 127) return 1;
1664                                                 break;
1665                                         }
1666                                         f_ptr->d_char[j] = char_tmp[j];
1667                                 }
1668                         }
1669                 }
1670                 else if (!buf[5])
1671                 {
1672                         for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1673                         {
1674                                 f_ptr->d_attr[j] = s_attr;
1675                                 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
1676                         }
1677                 }
1678                 else return 1;
1679         }
1680
1681         /* Hack -- Process 'F' for flags */
1682         else if (buf[0] == 'F')
1683         {
1684                 /* Parse every entry textually */
1685                 for (s = buf + 2; *s; )
1686                 {
1687                         /* Find the end of this entry */
1688                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1689
1690                         /* Nuke and skip any dividers */
1691                         if (*t)
1692                         {
1693                                 *t++ = '\0';
1694                                 while (*t == ' ' || *t == '|') t++;
1695                         }
1696
1697                         /* Hack -- Read feature subtype */
1698                         if (1 == sscanf(s, "SUBTYPE_%d", &i))
1699                         {
1700                                 /* Extract a "subtype" */
1701                                 f_ptr->subtype = (FEAT_SUBTYPE)i;
1702
1703                                 /* Start at next entry */
1704                                 s = t;
1705
1706                                 continue;
1707                         }
1708
1709                         /* Hack -- Read feature power */
1710                         if (1 == sscanf(s, "POWER_%d", &i))
1711                         {
1712                                 /* Extract a "power" */
1713                                 f_ptr->power = (FEAT_POWER)i;
1714
1715                                 /* Start at next entry */
1716                                 s = t;
1717                                 continue;
1718                         }
1719
1720                         /* Parse this entry */
1721                         if (0 != grab_one_feat_flag(f_ptr, s)) return (PARSE_ERROR_INVALID_FLAG);
1722
1723                         /* Start the next entry */
1724                         s = t;
1725                 }
1726         }
1727
1728         /* Process 'W' for "More Info" (one line only) */
1729         else if (buf[0] == 'W')
1730         {
1731                 int priority;
1732
1733                 /* Scan for the value */
1734                 if (1 != sscanf(buf + 2, "%d", &priority)) return (PARSE_ERROR_GENERIC);
1735
1736                 /* Save the value */
1737                 f_ptr->priority = (FEAT_PRIORITY)priority;
1738         }
1739
1740         /* Process 'K' for "States" (up to four lines + default (which cannot be last)) */
1741         else if (buf[0] == 'K')
1742         {
1743                 STR_OFFSET offset;
1744
1745                 /* Find the next empty state slot (if any) */
1746                 for (i = 0; i < MAX_FEAT_STATES; i++) if (f_ptr->state[i].action == FF_FLAG_MAX) break;
1747
1748                 /* Oops, no more slots */
1749                 if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
1750
1751                 /* Analyze the first field */
1752                 for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
1753
1754                 /* Terminate the field (if necessary) */
1755                 if (*t == ':') *t++ = '\0';
1756
1757                 /* Is this default entry? */
1758                 if (streq(s, "DESTROYED"))
1759                 {
1760                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1761
1762                         /* Record a fake tag index */
1763                         f_ptr->destroyed_tag = offset;
1764                 }
1765                 else
1766                 {
1767                         /* Reset */
1768                         f_ptr->state[i].action = 0;
1769
1770                         /* Parse this entry */
1771                         if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
1772
1773                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1774
1775                         /* Record a fake tag index */
1776                         f_ptr->state[i].result_tag = offset;
1777                 }
1778         }
1779         else return 6;
1780
1781         return 0;
1782 }
1783
1784
1785 /*!
1786  * @brief 地形タグからIDを得る /
1787  * Convert a fake tag to a real feat index
1788  * @param str タグ文字列
1789  * @return 地形ID
1790  */
1791 s16b f_tag_to_index(concptr str)
1792 {
1793         u16b i;
1794
1795         /* Search for real index corresponding to this fake tag */
1796         for (i = 0; i < f_head.info_num; i++)
1797         {
1798                 if (streq(f_tag + f_info[i].tag, str))
1799                 {
1800                         /* Return the index */
1801                         return (s16b)i;
1802                 }
1803         }
1804
1805         /* Not found */
1806         return -1;
1807 }
1808
1809
1810 /*!
1811  * @brief 地形タグからIDを得る /
1812  * Search for real index corresponding to this fake tag
1813  * @param feat タグ文字列のオフセット
1814  * @return 地形ID。該当がないなら-1
1815  */
1816 static FEAT_IDX search_real_feat(STR_OFFSET feat)
1817 {
1818         /* Don't convert non-fake tag */
1819         if (feat <= 0)
1820         {
1821                 return -1;
1822         }
1823
1824         /* Search for real index corresponding to this fake tag */
1825         for (FEAT_IDX i = 0; i < f_head.info_num; i++)
1826         {
1827                 if (feat == f_info[i].tag)
1828                 {
1829                         /* Record real index */
1830                         return i;
1831                 }
1832         }
1833
1834         /* Undefined tag */
1835         msg_format(_("未定義のタグ '%s'。", "%s is undefined."), f_tag + feat);
1836         return -1;
1837 }
1838
1839
1840 /*!
1841  * @brief 地形情報の各種タグからIDへ変換して結果を収める /
1842  * Retouch fake tags of f_info
1843  * @param head ヘッダ構造体
1844  * @return なし
1845  */
1846 void retouch_f_info(header *head)
1847 {
1848         /* Convert fake tags to real feat indices */
1849         for (int i = 0; i < head->info_num; i++)
1850         {
1851                 feature_type *f_ptr = &f_info[i];
1852                 FEAT_IDX j, k;
1853
1854                 k = search_real_feat(f_ptr->mimic_tag);
1855                 f_ptr->mimic = k < 0 ? f_ptr->mimic : k;
1856                 k = search_real_feat(f_ptr->destroyed_tag);
1857                 f_ptr->destroyed = k < 0 ? f_ptr->destroyed : k;
1858                 for (j = 0; j < MAX_FEAT_STATES; j++)
1859                 {
1860                         k = search_real_feat(f_ptr->state[j].result_tag);
1861                         f_ptr->state[j].result = k < 0 ? f_ptr->state[j].result : k;
1862                 }
1863         }
1864 }
1865
1866
1867 /*!
1868  * @brief テキストトークンを走査してフラグを一つ得る(ベースアイテム用) /
1869  * Grab one flag in an object_kind from a textual string
1870  * @param k_ptr 保管先のベースアイテム構造体参照ポインタ
1871  * @param what 参照元の文字列ポインタ
1872  * @return エラーコード
1873  */
1874 static errr grab_one_kind_flag(object_kind *k_ptr, concptr what)
1875 {
1876         /* Check flags */
1877         for (int i = 0; i < TR_FLAG_MAX; i++)
1878         {
1879                 if (streq(what, k_info_flags[i]))
1880                 {
1881                         add_flag(k_ptr->flags, i);
1882                         return 0;
1883                 }
1884         }
1885
1886         if (grab_one_flag(&k_ptr->gen_flags, k_info_gen_flags, what) == 0)
1887                 return 0;
1888
1889         msg_format(_("未知のアイテム・フラグ '%s'。", "Unknown object flag '%s'."), what);
1890         return 1;
1891 }
1892
1893
1894 /*!
1895  * @brief テキストトークンを走査してフラグを一つ得る(発動能力用) /
1896  * Grab one activation index flag
1897  * @param what 参照元の文字列ポインタ
1898  * @return 発動能力ID
1899  */
1900 static byte grab_one_activation_flag(concptr what)
1901 {
1902         for (int i = 0; ; i++)
1903         {
1904                 if (activation_info[i].flag == NULL) break;
1905
1906                 if (streq(what, activation_info[i].flag))
1907                 {
1908                         return activation_info[i].index;
1909                 }
1910         }
1911
1912         int j = atoi(what);
1913         if (j > 0)
1914         {
1915                 return ((byte)j);
1916         }
1917
1918         msg_format(_("未知の発動・フラグ '%s'。", "Unknown activation flag '%s'."), what);
1919         return 0;
1920 }
1921
1922
1923 /*!
1924  * @brief ベースアイテム(k_info)のパース関数 /
1925  * Initialize the "k_info" array, by parsing an ascii "template" file
1926  * @param buf テキスト列
1927  * @param head ヘッダ構造体
1928  * @return エラーコード
1929  */
1930 errr parse_k_info(char *buf, header *head)
1931 {
1932         /* Current entry */
1933         static object_kind *k_ptr = NULL;
1934
1935         /* Process 'N' for "New/Number/Name" */
1936         int i;
1937         char *s, *t;
1938         if (buf[0] == 'N')
1939         {
1940 #ifdef JP
1941                 char *flavor;
1942 #endif
1943
1944                 /* Find the colon before the name */
1945                 s = my_strchr(buf + 2, ':');
1946
1947                 /* Verify that colon */
1948                 if (!s) return 1;
1949
1950                 /* Nuke the colon, advance to the name */
1951                 *s++ = '\0';
1952
1953                 /* Get the index */
1954                 i = atoi(buf + 2);
1955
1956                 /* Verify information */
1957                 if (i <= error_idx) return 4;
1958
1959                 /* Verify information */
1960                 if (i >= head->info_num) return 2;
1961
1962                 /* Save the index */
1963                 error_idx = i;
1964
1965                 /* Point at the "info" */
1966                 k_ptr = &k_info[i];
1967
1968 #ifdef JP
1969                 /* Paranoia -- require a name */
1970                 if (!*s) return 1;
1971
1972                 /* Find the colon before the flavor */
1973                 flavor = my_strchr(s, ':');
1974
1975                 /* Verify that colon */
1976                 if (flavor)
1977                 {
1978                         /* Nuke the colon, advance to the flavor */
1979                         *flavor++ = '\0';
1980
1981                         /* Store the flavor */
1982                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return 7;
1983                 }
1984
1985                 /* Store the name */
1986                 if (!add_name(&k_ptr->name, head, s)) return 7;
1987 #endif
1988         }
1989
1990         /* There better be a current k_ptr */
1991         else if (!k_ptr) return 3;
1992
1993
1994 #ifdef JP
1995         /* 英語名を読むルーチンを追加 */
1996         /* 'E' から始まる行は英語名としている */
1997         else if (buf[0] == 'E')
1998         {
1999                 /* nothing to do */
2000         }
2001 #else
2002         else if (buf[0] == 'E')
2003         {
2004                 char *flavor;
2005
2006                 /* Acquire the name */
2007                 s = buf + 2;
2008
2009                 /* Find the colon before the flavor */
2010                 flavor = my_strchr(s, ':');
2011
2012                 /* Verify that colon */
2013                 if (flavor)
2014                 {
2015                         /* Nuke the colon, advance to the flavor */
2016                         *flavor++ = '\0';
2017
2018                         /* Store the flavor */
2019                         if (!add_name(&k_ptr->flavor_name, head, flavor)) return 7;
2020                 }
2021
2022                 /* Store the name */
2023                 if (!add_name(&k_ptr->name, head, s)) return 7;
2024         }
2025 #endif
2026
2027         /* Process 'D' for "Description" */
2028         else if (buf[0] == 'D')
2029         {
2030 #ifdef JP
2031                 if (buf[2] == '$')
2032                         return 0;
2033                 /* Acquire the text */
2034                 s = buf + 2;
2035 #else
2036                 if (buf[2] != '$')
2037                         return 0;
2038                 /* Acquire the text */
2039                 s = buf + 3;
2040 #endif
2041
2042                 /* Store the text */
2043                 if (!add_text(&k_ptr->text, head, s, TRUE)) return 7;
2044         }
2045
2046         /* Process 'G' for "Graphics" (one line only) */
2047         else if (buf[0] == 'G')
2048         {
2049                 char sym;
2050                 byte tmp;
2051                 if (buf[1] != ':') return 1;
2052                 if (!buf[2]) return 1;
2053                 if (buf[3] != ':') return 1;
2054                 if (!buf[4]) return 1;
2055
2056                 /* Extract the char */
2057                 sym = buf[2];
2058
2059                 /* Extract the attr */
2060                 tmp = color_char_to_attr(buf[4]);
2061                 if (tmp > 127) return 1;
2062
2063                 /* Save the values */
2064                 k_ptr->d_attr = tmp;
2065                 k_ptr->d_char = sym;
2066         }
2067
2068         /* Process 'I' for "Info" (one line only) */
2069         else if (buf[0] == 'I')
2070         {
2071                 int tval, sval, pval;
2072
2073                 /* Scan for the values */
2074                 if (3 != sscanf(buf + 2, "%d:%d:%d",
2075                         &tval, &sval, &pval)) return 1;
2076
2077                 /* Save the values */
2078                 k_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2079                 k_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2080                 k_ptr->pval = (PARAMETER_VALUE)pval;
2081         }
2082
2083         /* Process 'W' for "More Info" (one line only) */
2084         else if (buf[0] == 'W')
2085         {
2086                 int level, extra, wgt;
2087                 long cost;
2088
2089                 /* Scan for the values */
2090                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2091                         &level, &extra, &wgt, &cost)) return 1;
2092
2093                 /* Save the values */
2094                 k_ptr->level = (DEPTH)level;
2095                 k_ptr->extra = (BIT_FLAGS8)extra;
2096                 k_ptr->weight = (WEIGHT)wgt;
2097                 k_ptr->cost = (PRICE)cost;
2098         }
2099
2100         /* Process 'A' for "Allocation" (one line only) */
2101         else if (buf[0] == 'A')
2102         {
2103
2104                 /* Simply read each number following a colon */
2105                 for (i = 0, s = buf + 1; s && (s[0] == ':') && s[1]; ++i)
2106                 {
2107                         /* Default chance */
2108                         k_ptr->chance[i] = 1;
2109
2110                         /* Store the attack damage index */
2111                         k_ptr->locale[i] = atoi(s + 1);
2112
2113                         /* Find the slash */
2114                         t = my_strchr(s + 1, '/');
2115
2116                         /* Find the next colon */
2117                         s = my_strchr(s + 1, ':');
2118
2119                         /* If the slash is "nearby", use it */
2120                         if (t && (!s || t < s))
2121                         {
2122                                 int chance = atoi(t + 1);
2123                                 if (chance > 0) k_ptr->chance[i] = (PROB)chance;
2124                         }
2125                 }
2126         }
2127
2128         /* Hack -- Process 'P' for "power" and such */
2129         else if (buf[0] == 'P')
2130         {
2131                 int ac, hd1, hd2, th, td, ta;
2132
2133                 /* Scan for the values */
2134                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2135                         &ac, &hd1, &hd2, &th, &td, &ta)) return 1;
2136
2137                 k_ptr->ac = (ARMOUR_CLASS)ac;
2138                 k_ptr->dd = (DICE_NUMBER)hd1;
2139                 k_ptr->ds = (DICE_SID)hd2;
2140                 k_ptr->to_h = (HIT_PROB)th;
2141                 k_ptr->to_d = (HIT_POINT)td;
2142                 k_ptr->to_a = (ARMOUR_CLASS)ta;
2143         }
2144
2145         /* Hack -- Process 'U' for activation index */
2146         else if (buf[0] == 'U')
2147         {
2148                 byte n;
2149                 n = grab_one_activation_flag(buf + 2);
2150                 if (n > 0)
2151                 {
2152                         k_ptr->act_idx = n;
2153                 }
2154                 else
2155                 {
2156                         return 5;
2157                 }
2158         }
2159
2160         /* Hack -- Process 'F' for flags */
2161         else if (buf[0] == 'F')
2162         {
2163                 /* Parse every entry textually */
2164                 for (s = buf + 2; *s; )
2165                 {
2166                         /* Find the end of this entry */
2167                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2168
2169                         /* Nuke and skip any dividers */
2170                         if (*t)
2171                         {
2172                                 *t++ = '\0';
2173                                 while (*t == ' ' || *t == '|') t++;
2174                         }
2175
2176                         /* Parse this entry */
2177                         if (0 != grab_one_kind_flag(k_ptr, s)) return 5;
2178
2179                         /* Start the next entry */
2180                         s = t;
2181                 }
2182         }
2183         else return 6;
2184
2185         return 0;
2186 }
2187
2188
2189 /*!
2190  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2191  * Grab one activation index flag
2192  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
2193  * @param what 参照元の文字列ポインタ
2194  * @return エラーがあった場合1、エラーがない場合0を返す
2195  */
2196 static errr grab_one_artifact_flag(artifact_type *a_ptr, concptr what)
2197 {
2198         /* Check flags */
2199         for (int i = 0; i < TR_FLAG_MAX; i++)
2200         {
2201                 if (streq(what, k_info_flags[i]))
2202                 {
2203                         add_flag(a_ptr->flags, i);
2204                         return 0;
2205                 }
2206         }
2207
2208         if (grab_one_flag(&a_ptr->gen_flags, k_info_gen_flags, what) == 0)
2209                 return 0;
2210
2211         msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what);
2212         return 1;
2213 }
2214
2215
2216 /*!
2217  * @brief 固定アーティファクト情報(a_info)のパース関数 /
2218  * Initialize the "a_info" array, by parsing an ascii "template" file
2219  * @param buf テキスト列
2220  * @param head ヘッダ構造体
2221  * @return エラーコード
2222  */
2223 errr parse_a_info(char *buf, header *head)
2224 {
2225         /* Current entry */
2226         static artifact_type *a_ptr = NULL;
2227
2228         /* Process 'N' for "New/Number/Name" */
2229         int i;
2230         char *s, *t;
2231         if (buf[0] == 'N')
2232         {
2233                 /* Find the colon before the name */
2234                 s = my_strchr(buf + 2, ':');
2235
2236                 /* Verify that colon */
2237                 if (!s) return 1;
2238
2239                 /* Nuke the colon, advance to the name */
2240                 *s++ = '\0';
2241 #ifdef JP
2242                 /* Paranoia -- require a name */
2243                 if (!*s) return 1;
2244 #endif
2245                 /* Get the index */
2246                 i = atoi(buf + 2);
2247
2248                 /* Verify information */
2249                 if (i < error_idx) return 4;
2250
2251                 /* Verify information */
2252                 if (i >= head->info_num) return 2;
2253
2254                 /* Save the index */
2255                 error_idx = i;
2256
2257                 /* Point at the "info" */
2258                 a_ptr = &a_info[i];
2259
2260                 /* Ignore everything */
2261                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
2262                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
2263                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
2264                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
2265 #ifdef JP
2266                 /* Store the name */
2267                 if (!add_name(&a_ptr->name, head, s)) return 7;
2268 #endif
2269         }
2270
2271         /* There better be a current a_ptr */
2272         else if (!a_ptr) return 3;
2273
2274
2275 #ifdef JP
2276         /* 英語名を読むルーチンを追加 */
2277         /* 'E' から始まる行は英語名としている */
2278         else if (buf[0] == 'E')
2279         {
2280                 /* nothing to do */
2281         }
2282 #else
2283         else if (buf[0] == 'E')
2284         {
2285                 /* Acquire the Text */
2286                 s = buf + 2;
2287
2288                 /* Store the name */
2289                 if (!add_name(&a_ptr->name, head, s)) return 7;
2290         }
2291 #endif
2292
2293         /* Process 'D' for "Description" */
2294         else if (buf[0] == 'D')
2295         {
2296 #ifdef JP
2297                 if (buf[2] == '$')
2298                         return 0;
2299                 /* Acquire the text */
2300                 s = buf + 2;
2301 #else
2302                 if (buf[2] != '$')
2303                         return 0;
2304                 /* Acquire the text */
2305                 s = buf + 3;
2306 #endif
2307
2308                 /* Store the text */
2309                 if (!add_text(&a_ptr->text, head, s, TRUE)) return 7;
2310         }
2311
2312
2313         /* Process 'I' for "Info" (one line only) */
2314         else if (buf[0] == 'I')
2315         {
2316                 int tval, sval, pval;
2317
2318                 /* Scan for the values */
2319                 if (3 != sscanf(buf + 2, "%d:%d:%d",
2320                         &tval, &sval, &pval)) return 1;
2321
2322                 /* Save the values */
2323                 a_ptr->tval = (OBJECT_TYPE_VALUE)tval;
2324                 a_ptr->sval = (OBJECT_SUBTYPE_VALUE)sval;
2325                 a_ptr->pval = (PARAMETER_VALUE)pval;
2326         }
2327
2328         /* Process 'W' for "More Info" (one line only) */
2329         else if (buf[0] == 'W')
2330         {
2331                 int level, rarity, wgt;
2332                 long cost;
2333
2334                 /* Scan for the values */
2335                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2336                         &level, &rarity, &wgt, &cost)) return 1;
2337
2338                 /* Save the values */
2339                 a_ptr->level = (DEPTH)level;
2340                 a_ptr->rarity = (RARITY)rarity;
2341                 a_ptr->weight = (WEIGHT)wgt;
2342                 a_ptr->cost = (PRICE)cost;
2343         }
2344
2345         /* Hack -- Process 'P' for "power" and such */
2346         else if (buf[0] == 'P')
2347         {
2348                 int ac, hd1, hd2, th, td, ta;
2349
2350                 /* Scan for the values */
2351                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2352                         &ac, &hd1, &hd2, &th, &td, &ta)) return 1;
2353
2354                 a_ptr->ac = (ARMOUR_CLASS)ac;
2355                 a_ptr->dd = (DICE_NUMBER)hd1;
2356                 a_ptr->ds = (DICE_SID)hd2;
2357                 a_ptr->to_h = (HIT_PROB)th;
2358                 a_ptr->to_d = (HIT_POINT)td;
2359                 a_ptr->to_a = (ARMOUR_CLASS)ta;
2360         }
2361
2362         /* Hack -- Process 'U' for activation index */
2363         else if (buf[0] == 'U')
2364         {
2365                 byte n;
2366                 n = grab_one_activation_flag(buf + 2);
2367                 if (n > 0)
2368                 {
2369                         a_ptr->act_idx = n;
2370                 }
2371                 else
2372                 {
2373                         return 5;
2374                 }
2375         }
2376
2377         /* Hack -- Process 'F' for flags */
2378         else if (buf[0] == 'F')
2379         {
2380                 /* Parse every entry textually */
2381                 for (s = buf + 2; *s; )
2382                 {
2383                         /* Find the end of this entry */
2384                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2385
2386                         /* Nuke and skip any dividers */
2387                         if (*t)
2388                         {
2389                                 *t++ = '\0';
2390                                 while ((*t == ' ') || (*t == '|')) t++;
2391                         }
2392
2393                         /* Parse this entry */
2394                         if (0 != grab_one_artifact_flag(a_ptr, s)) return 5;
2395
2396                         /* Start the next entry */
2397                         s = t;
2398                 }
2399         }
2400         else return 6;
2401
2402         return 0;
2403 }
2404
2405
2406 /*!
2407  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
2408  * Grab one flag in a ego-item_type from a textual string
2409  * @param e_ptr 保管先のエゴ構造体参照ポインタ
2410  * @param what 参照元の文字列ポインタ
2411  * @return エラーがあった場合1、エラーがない場合0を返す
2412  */
2413 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
2414 {
2415         /* Check flags */
2416         for (int i = 0; i < TR_FLAG_MAX; i++)
2417         {
2418                 if (streq(what, k_info_flags[i]))
2419                 {
2420                         add_flag(e_ptr->flags, i);
2421                         return 0;
2422                 }
2423         }
2424
2425         if (grab_one_flag(&e_ptr->gen_flags, k_info_gen_flags, what) == 0)
2426                 return 0;
2427
2428         msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what);
2429         return 1;
2430 }
2431
2432
2433 /*!
2434  * @brief アイテムエゴ情報(e_info)のパース関数 /
2435  * Initialize the "e_info" array, by parsing an ascii "template" file
2436  * @param buf テキスト列
2437  * @param head ヘッダ構造体
2438  * @return エラーコード
2439  */
2440 errr parse_e_info(char *buf, header *head)
2441 {
2442         /* Current entry */
2443         static ego_item_type *e_ptr = NULL;
2444
2445         /* Just before the first record */
2446         error_idx = -1;
2447
2448         /* Just before the first line */
2449         error_line = -1;
2450
2451         /* Process 'N' for "New/Number/Name" */
2452         int i;
2453         char *s, *t;
2454         if (buf[0] == 'N')
2455         {
2456                 /* Find the colon before the name */
2457                 s = my_strchr(buf + 2, ':');
2458
2459                 /* Verify that colon */
2460                 if (!s) return 1;
2461
2462                 /* Nuke the colon, advance to the name */
2463                 *s++ = '\0';
2464 #ifdef JP
2465                 /* Paranoia -- require a name */
2466                 if (!*s) return 1;
2467 #endif
2468                 /* Get the index */
2469                 i = atoi(buf + 2);
2470
2471                 /* Verify information */
2472                 if (i < error_idx) return 4;
2473
2474                 /* Verify information */
2475                 if (i >= head->info_num) return 2;
2476
2477                 /* Save the index */
2478                 error_idx = i;
2479
2480                 /* Point at the "info" */
2481                 e_ptr = &e_info[i];
2482 #ifdef JP
2483                 /* Store the name */
2484                 if (!add_name(&e_ptr->name, head, s)) return 7;
2485 #endif
2486         }
2487
2488         /* There better be a current e_ptr */
2489         else if (!e_ptr) return 3;
2490
2491
2492 #ifdef JP
2493         /* 英語名を読むルーチンを追加 */
2494         /* 'E' から始まる行は英語名 */
2495         else if (buf[0] == 'E')
2496         {
2497                 /* nothing to do */
2498         }
2499 #else
2500         else if (buf[0] == 'E')
2501         {
2502                 /* Acquire the Text */
2503                 s = buf + 2;
2504
2505                 /* Store the name */
2506                 if (!add_name(&e_ptr->name, head, s)) return 7;
2507         }
2508 #endif
2509         /* Process 'X' for "Xtra" (one line only) */
2510         else if (buf[0] == 'X')
2511         {
2512                 int slot, rating;
2513
2514                 /* Scan for the values */
2515                 if (2 != sscanf(buf + 2, "%d:%d",
2516                         &slot, &rating)) return 1;
2517
2518                 /* Save the values */
2519                 e_ptr->slot = (INVENTORY_IDX)slot;
2520                 e_ptr->rating = (PRICE)rating;
2521         }
2522
2523         /* Process 'W' for "More Info" (one line only) */
2524         else if (buf[0] == 'W')
2525         {
2526                 int level, rarity, pad2;
2527                 long cost;
2528
2529                 /* Scan for the values */
2530                 if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
2531                         &level, &rarity, &pad2, &cost)) return 1;
2532
2533                 /* Save the values */
2534                 e_ptr->level = level;
2535                 e_ptr->rarity = (RARITY)rarity;
2536                 /* e_ptr->weight = wgt; */
2537                 e_ptr->cost = cost;
2538         }
2539
2540         /* Hack -- Process 'C' for "creation" */
2541         else if (buf[0] == 'C')
2542         {
2543                 int th, td, ta, pval;
2544
2545                 /* Scan for the values */
2546                 if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
2547                         &th, &td, &ta, &pval)) return 1;
2548
2549                 e_ptr->max_to_h = (HIT_PROB)th;
2550                 e_ptr->max_to_d = (HIT_POINT)td;
2551                 e_ptr->max_to_a = (ARMOUR_CLASS)ta;
2552                 e_ptr->max_pval = (PARAMETER_VALUE)pval;
2553         }
2554
2555         /* Hack -- Process 'U' for activation index */
2556         else if (buf[0] == 'U')
2557         {
2558                 byte n;
2559                 n = grab_one_activation_flag(buf + 2);
2560                 if (n > 0)
2561                 {
2562                         e_ptr->act_idx = n;
2563                 }
2564                 else
2565                 {
2566                         return 5;
2567                 }
2568         }
2569
2570         /* Hack -- Process 'F' for flags */
2571         else if (buf[0] == 'F')
2572         {
2573                 /* Parse every entry textually */
2574                 for (s = buf + 2; *s; )
2575                 {
2576                         /* Find the end of this entry */
2577                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2578
2579                         /* Nuke and skip any dividers */
2580                         if (*t)
2581                         {
2582                                 *t++ = '\0';
2583                                 while ((*t == ' ') || (*t == '|')) t++;
2584                         }
2585
2586                         /* Parse this entry */
2587                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return 5;
2588
2589                         /* Start the next entry */
2590                         s = t;
2591                 }
2592         }
2593         else return 6;
2594
2595         return 0;
2596 }
2597
2598
2599 /*!
2600  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用1) /
2601  * Grab one (basic) flag in a monster_race from a textual string
2602  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2603  * @param what 参照元の文字列ポインタ
2604  * @return エラーコード
2605  */
2606 static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
2607 {
2608         if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
2609                 return 0;
2610
2611         if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
2612                 return 0;
2613
2614         if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
2615                 return 0;
2616
2617         if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
2618                 return 0;
2619
2620         if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
2621                 return 0;
2622
2623         if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
2624                 return 0;
2625
2626         if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
2627                 return 0;
2628
2629         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2630         return 1;
2631 }
2632
2633
2634 /*!
2635  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用2) /
2636  * Grab one (spell) flag in a monster_race from a textual string
2637  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
2638  * @param what 参照元の文字列ポインタ
2639  * @return エラーコード
2640  */
2641 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
2642 {
2643         if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
2644                 return 0;
2645
2646         if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
2647                 return 0;
2648
2649         if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
2650                 return 0;
2651
2652         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
2653         return 1;
2654 }
2655
2656
2657 /*!
2658  * @brief モンスター種族情報(r_info)のパース関数 /
2659  * Initialize the "r_info" array, by parsing an ascii "template" file
2660  * @param buf テキスト列
2661  * @param head ヘッダ構造体
2662  * @return エラーコード
2663  */
2664 errr parse_r_info(char *buf, header *head)
2665 {
2666         /* Current entry */
2667         static monster_race *r_ptr = NULL;
2668
2669         /* Process 'N' for "New/Number/Name" */
2670         int i;
2671         char *s, *t;
2672         if (buf[0] == 'N')
2673         {
2674                 /* Find the colon before the name */
2675                 s = my_strchr(buf + 2, ':');
2676
2677                 /* Verify that colon */
2678                 if (!s) return 1;
2679
2680                 /* Nuke the colon, advance to the name */
2681                 *s++ = '\0';
2682 #ifdef JP
2683                 /* Paranoia -- require a name */
2684                 if (!*s) return 1;
2685 #endif
2686                 /* Get the index */
2687                 i = atoi(buf + 2);
2688
2689                 /* Verify information */
2690                 if (i < error_idx) return 4;
2691
2692                 /* Verify information */
2693                 if (i >= head->info_num) return 2;
2694
2695                 /* Save the index */
2696                 error_idx = i;
2697
2698                 /* Point at the "info" */
2699                 r_ptr = &r_info[i];
2700 #ifdef JP
2701                 /* Store the name */
2702                 if (!add_name(&r_ptr->name, head, s)) return 7;
2703 #endif
2704         }
2705
2706         /* There better be a current r_ptr */
2707         else if (!r_ptr) return 3;
2708
2709
2710 #ifdef JP
2711         /* 英語名を読むルーチンを追加 */
2712         /* 'E' から始まる行は英語名 */
2713         else if (buf[0] == 'E')
2714         {
2715                 /* Acquire the Text */
2716                 s = buf + 2;
2717
2718                 /* Store the name */
2719                 if (!add_name(&r_ptr->E_name, head, s)) return 7;
2720         }
2721 #else
2722         else if (buf[0] == 'E')
2723         {
2724                 /* Acquire the Text */
2725                 s = buf + 2;
2726
2727                 /* Store the name */
2728                 if (!add_name(&r_ptr->name, head, s)) return 7;
2729         }
2730 #endif
2731         /* Process 'D' for "Description" */
2732         else if (buf[0] == 'D')
2733         {
2734 #ifdef JP
2735                 if (buf[2] == '$')
2736                         return 0;
2737                 /* Acquire the text */
2738                 s = buf + 2;
2739 #else
2740                 if (buf[2] != '$')
2741                         return 0;
2742                 /* Acquire the text */
2743                 s = buf + 3;
2744 #endif
2745
2746                 /* Store the text */
2747                 if (!add_text(&r_ptr->text, head, s, TRUE)) return 7;
2748         }
2749
2750         /* Process 'G' for "Graphics" (one line only) */
2751         else if (buf[0] == 'G')
2752         {
2753                 char sym;
2754                 byte tmp;
2755                 if (buf[1] != ':') return 1;
2756                 if (!buf[2]) return 1;
2757                 if (buf[3] != ':') return 1;
2758                 if (!buf[4]) return 1;
2759
2760                 /* Extract the char */
2761                 sym = buf[2];
2762
2763                 /* Extract the attr */
2764                 tmp = color_char_to_attr(buf[4]);
2765                 if (tmp > 127) return 1;
2766
2767                 /* Save the values */
2768                 r_ptr->d_char = sym;
2769                 r_ptr->d_attr = tmp;
2770         }
2771
2772         /* Process 'I' for "Info" (one line only) */
2773         else if (buf[0] == 'I')
2774         {
2775                 int spd, hp1, hp2, aaf, ac, slp;
2776
2777                 /* Scan for the other values */
2778                 if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2779                         &spd, &hp1, &hp2, &aaf, &ac, &slp)) return 1;
2780
2781                 /* Save the values */
2782                 r_ptr->speed = (SPEED)spd;
2783                 r_ptr->hdice = (DICE_NUMBER)MAX(hp1, 1);
2784                 r_ptr->hside = (DICE_SID)MAX(hp2, 1);
2785                 r_ptr->aaf = (POSITION)aaf;
2786                 r_ptr->ac = (ARMOUR_CLASS)ac;
2787                 r_ptr->sleep = (SLEEP_DEGREE)slp;
2788         }
2789
2790         /* Process 'W' for "More Info" (one line only) */
2791         else if (buf[0] == 'W')
2792         {
2793                 int lev, rar, pad;
2794                 long exp;
2795                 long nextexp;
2796                 int nextmon;
2797
2798                 /* Scan for the values */
2799                 if (6 != sscanf(buf + 2, "%d:%d:%d:%ld:%ld:%d",
2800                         &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return 1;
2801
2802                 /* Save the values */
2803                 r_ptr->level = (DEPTH)lev;
2804                 r_ptr->rarity = (RARITY)rar;
2805                 r_ptr->extra = (BIT_FLAGS16)pad;
2806                 r_ptr->mexp = (EXP)exp;
2807                 r_ptr->next_exp = (EXP)nextexp;
2808                 r_ptr->next_r_idx = (MONRACE_IDX)nextmon;
2809         }
2810
2811         /* Process 'R' for "Reinforcement" (up to six lines) */
2812         else if (buf[0] == 'R')
2813         {
2814                 int id, ds, dd;
2815                 /* Find the next empty blow slot (if any) */
2816                 for (i = 0; i < A_MAX; i++) if (r_ptr->reinforce_id[i] == 0) break;
2817
2818                 /* Oops, no more slots */
2819                 if (i == 6) return 1;
2820
2821                 /* Scan for the values */
2822                 if (3 != sscanf(buf + 2, "%d:%dd%d", &id, &dd, &ds)) return 1;
2823                 r_ptr->reinforce_id[i] = (MONRACE_IDX)id;
2824                 r_ptr->reinforce_dd[i] = (DICE_NUMBER)dd;
2825                 r_ptr->reinforce_ds[i] = (DICE_SID)ds;
2826         }
2827
2828         /* Process 'B' for "Blows" (up to four lines) */
2829         else if (buf[0] == 'B')
2830         {
2831                 int n1, n2;
2832
2833                 /* Find the next empty blow slot (if any) */
2834                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2835
2836                 /* Oops, no more slots */
2837                 if (i == 4) return 1;
2838
2839                 /* Analyze the first field */
2840                 for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
2841
2842                 /* Terminate the field (if necessary) */
2843                 if (*t == ':') *t++ = '\0';
2844
2845                 /* Analyze the method */
2846                 for (n1 = 0; r_info_blow_method[n1]; n1++)
2847                 {
2848                         if (streq(s, r_info_blow_method[n1])) break;
2849                 }
2850
2851                 /* Invalid method */
2852                 if (!r_info_blow_method[n1]) return 1;
2853
2854                 /* Analyze the second field */
2855                 for (s = t; *t && (*t != ':'); t++) /* loop */;
2856
2857                 /* Terminate the field (if necessary) */
2858                 if (*t == ':') *t++ = '\0';
2859
2860                 /* Analyze effect */
2861                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2862                 {
2863                         if (streq(s, r_info_blow_effect[n2])) break;
2864                 }
2865
2866                 /* Invalid effect */
2867                 if (!r_info_blow_effect[n2]) return 1;
2868
2869                 /* Analyze the third field */
2870                 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2871
2872                 /* Terminate the field (if necessary) */
2873                 if (*t == 'd') *t++ = '\0';
2874
2875                 /* Save the method */
2876                 r_ptr->blow[i].method = (BLOW_METHOD)n1;
2877
2878                 /* Save the effect */
2879                 r_ptr->blow[i].effect = (BLOW_EFFECT)n2;
2880
2881                 /* Extract the damage dice and sides */
2882                 r_ptr->blow[i].d_dice = atoi(s);
2883                 r_ptr->blow[i].d_side = atoi(t);
2884         }
2885
2886         /* Process 'F' for "Basic Flags" (multiple lines) */
2887         else if (buf[0] == 'F')
2888         {
2889                 /* Parse every entry */
2890                 for (s = buf + 2; *s; )
2891                 {
2892                         /* Find the end of this entry */
2893                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2894
2895                         /* Nuke and skip any dividers */
2896                         if (*t)
2897                         {
2898                                 *t++ = '\0';
2899                                 while (*t == ' ' || *t == '|') t++;
2900                         }
2901
2902                         /* Parse this entry */
2903                         if (0 != grab_one_basic_flag(r_ptr, s)) return 5;
2904
2905                         /* Start the next entry */
2906                         s = t;
2907                 }
2908         }
2909
2910         /* Process 'S' for "Spell Flags" (multiple lines) */
2911         else if (buf[0] == 'S')
2912         {
2913                 /* Parse every entry */
2914                 for (s = buf + 2; *s; )
2915                 {
2916                         /* Find the end of this entry */
2917                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2918
2919                         /* Nuke and skip any dividers */
2920                         if (*t)
2921                         {
2922                                 *t++ = '\0';
2923                                 while ((*t == ' ') || (*t == '|')) t++;
2924                         }
2925
2926                         /* Hack -- Read spell frequency */
2927                         if (1 == sscanf(s, "1_IN_%d", &i))
2928                         {
2929                                 /* Extract a "frequency" */
2930                                 r_ptr->freq_spell = 100 / i;
2931
2932                                 /* Start at next entry */
2933                                 s = t;
2934                                 continue;
2935                         }
2936
2937                         /* Parse this entry */
2938                         if (0 != grab_one_spell_flag(r_ptr, s)) return 5;
2939
2940                         /* Start the next entry */
2941                         s = t;
2942                 }
2943         }
2944
2945         /* Process 'A' for "Artifact Flags" (multiple lines) */
2946         else if (buf[0] == 'A')
2947         {
2948                 int id, per, rarity;
2949
2950                 /* Find the next empty blow slot (if any) */
2951                 for (i = 0; i < 4; i++) if (!r_ptr->artifact_id[i]) break;
2952
2953                 /* Oops, no more slots */
2954                 if (i == 4) return 1;
2955
2956                 if (3 != sscanf(buf + 2, "%d:%d:%d", &id, &rarity, &per)) return 1;
2957                 r_ptr->artifact_id[i] = (ARTIFACT_IDX)id;
2958                 r_ptr->artifact_rarity[i] = (RARITY)rarity;
2959                 r_ptr->artifact_percent[i] = (PERCENTAGE)per;
2960         }
2961
2962         /* Process 'V' for "Arena power value ratio" */
2963         else if (buf[0] == 'V')
2964         {
2965                 int val;
2966                 if (3 != sscanf(buf + 2, "%d", &val)) return 1;
2967                 r_ptr->arena_ratio = (PERCENTAGE)val;
2968         }
2969         else return 6;
2970
2971         return 0;
2972 }
2973
2974
2975 /*!
2976  * @brief テキストトークンを走査してフラグを一つ得る(ダンジョン用) /
2977  * Grab one flag for a dungeon type from a textual string
2978  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
2979  * @param what 参照元の文字列ポインタ
2980  * @return エラーコード
2981  */
2982 static errr grab_one_dungeon_flag(dungeon_type *d_ptr, concptr what)
2983 {
2984         if (grab_one_flag(&d_ptr->flags1, d_info_flags1, what) == 0)
2985                 return 0;
2986
2987         msg_format(_("未知のダンジョン・フラグ '%s'。", "Unknown dungeon type flag '%s'."), what);
2988         return 1;
2989 }
2990
2991
2992 /*!
2993  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用1) /
2994  * Grab one (basic) flag in a monster_race from a textual string
2995  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
2996  * @param what 参照元の文字列ポインタ
2997  * @return エラーコード
2998  */
2999 static errr grab_one_basic_monster_flag(dungeon_type *d_ptr, concptr what)
3000 {
3001         if (grab_one_flag(&d_ptr->mflags1, r_info_flags1, what) == 0)
3002                 return 0;
3003
3004         if (grab_one_flag(&d_ptr->mflags2, r_info_flags2, what) == 0)
3005                 return 0;
3006
3007         if (grab_one_flag(&d_ptr->mflags3, r_info_flags3, what) == 0)
3008                 return 0;
3009
3010         if (grab_one_flag(&d_ptr->mflags7, r_info_flags7, what) == 0)
3011                 return 0;
3012
3013         if (grab_one_flag(&d_ptr->mflags8, r_info_flags8, what) == 0)
3014                 return 0;
3015
3016         if (grab_one_flag(&d_ptr->mflags9, r_info_flags9, what) == 0)
3017                 return 0;
3018
3019         if (grab_one_flag(&d_ptr->mflagsr, r_info_flagsr, what) == 0)
3020                 return 0;
3021
3022         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3023         return 1;
3024 }
3025
3026
3027 /*!
3028  * @brief テキストトークンを走査してフラグを一つ得る(モンスターのダンジョン出現条件用2) /
3029  * Grab one (spell) flag in a monster_race from a textual string
3030  * @param d_ptr 保管先のダンジョン構造体参照ポインタ
3031  * @param what 参照元の文字列ポインタ
3032  * @return エラーコード
3033  */
3034 static errr grab_one_spell_monster_flag(dungeon_type *d_ptr, concptr what)
3035 {
3036         if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
3037                 return 0;
3038
3039         if (grab_one_flag(&d_ptr->m_a_ability_flags1, r_a_ability_flags1, what) == 0)
3040                 return 0;
3041
3042         if (grab_one_flag(&d_ptr->m_a_ability_flags2, r_a_ability_flags2, what) == 0)
3043                 return 0;
3044
3045         msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
3046         return 1;
3047 }
3048
3049
3050 /*!
3051  * @brief ダンジョン情報(d_info)のパース関数 /
3052  * Initialize the "d_info" array, by parsing an ascii "template" file
3053  * @param buf テキスト列
3054  * @param head ヘッダ構造体
3055  * @return エラーコード
3056  */
3057 errr parse_d_info(char *buf, header *head)
3058 {
3059         /* Current entry */
3060         static dungeon_type *d_ptr = NULL;
3061
3062         /* Process 'N' for "New/Number/Name" */
3063         int i;
3064         char *s, *t;
3065         if (buf[0] == 'N')
3066         {
3067                 /* Find the colon before the name */
3068                 s = my_strchr(buf + 2, ':');
3069
3070                 /* Verify that colon */
3071                 if (!s) return 1;
3072
3073                 /* Nuke the colon, advance to the name */
3074                 *s++ = '\0';
3075 #ifdef JP
3076                 /* Paranoia -- require a name */
3077                 if (!*s) return 1;
3078 #endif
3079                 /* Get the index */
3080                 i = atoi(buf + 2);
3081
3082                 /* Verify information */
3083                 if (i < error_idx) return 4;
3084
3085                 /* Verify information */
3086                 if (i >= head->info_num) return 2;
3087
3088                 /* Save the index */
3089                 error_idx = i;
3090
3091                 /* Point at the "info" */
3092                 d_ptr = &d_info[i];
3093 #ifdef JP
3094                 /* Store the name */
3095                 if (!add_name(&d_ptr->name, head, s)) return 7;
3096 #endif
3097         }
3098
3099 #ifdef JP
3100         else if (buf[0] == 'E') return 0;
3101 #else
3102         else if (buf[0] == 'E')
3103         {
3104                 /* Acquire the Text */
3105                 s = buf + 2;
3106
3107                 /* Store the name */
3108                 if (!add_name(&d_ptr->name, head, s)) return 7;
3109         }
3110 #endif
3111
3112         /* Process 'D' for "Description */
3113         else if (buf[0] == 'D')
3114         {
3115 #ifdef JP
3116                 if (buf[2] == '$')
3117                         return 0;
3118                 /* Acquire the text */
3119                 s = buf + 2;
3120 #else
3121                 if (buf[2] != '$')
3122                         return 0;
3123                 /* Acquire the text */
3124                 s = buf + 3;
3125 #endif
3126
3127                 /* Store the text */
3128                 if (!add_text(&d_ptr->text, head, s, TRUE)) return 7;
3129         }
3130
3131         /* Process 'W' for "More Info" (one line only) */
3132         else if (buf[0] == 'W')
3133         {
3134                 int min_lev, max_lev;
3135                 int min_plev, mode;
3136                 int min_alloc, max_chance;
3137                 int obj_good, obj_great;
3138                 int pit, nest;
3139
3140                 /* Scan for the values */
3141                 if (10 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
3142                         &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return 1;
3143
3144                 /* Save the values */
3145                 d_ptr->mindepth = (DEPTH)min_lev;
3146                 d_ptr->maxdepth = (DEPTH)max_lev;
3147                 d_ptr->min_plev = (PLAYER_LEVEL)min_plev;
3148                 d_ptr->mode = (BIT_FLAGS8)mode;
3149                 d_ptr->min_m_alloc_level = min_alloc;
3150                 d_ptr->max_m_alloc_chance = max_chance;
3151                 d_ptr->obj_good = obj_good;
3152                 d_ptr->obj_great = obj_great;
3153                 d_ptr->pit = (BIT_FLAGS16)pit;
3154                 d_ptr->nest = (BIT_FLAGS16)nest;
3155         }
3156
3157         /* Process 'P' for "Place Info" */
3158         else if (buf[0] == 'P')
3159         {
3160                 int dy, dx;
3161
3162                 /* Scan for the values */
3163                 if (2 != sscanf(buf + 2, "%d:%d", &dy, &dx)) return 1;
3164
3165                 /* Save the values */
3166                 d_ptr->dy = dy;
3167                 d_ptr->dx = dx;
3168         }
3169
3170         /* Process 'L' for "fLoor type" (one line only) */
3171         else if (buf[0] == 'L')
3172         {
3173                 char *zz[16];
3174
3175                 /* Scan for the values */
3176                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 1, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 1)) return 1;
3177
3178                 /* Save the values */
3179                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3180                 {
3181                         d_ptr->floor[i].feat = f_tag_to_index(zz[i * 2]);
3182                         if (d_ptr->floor[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3183
3184                         d_ptr->floor[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3185                 }
3186                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3187         }
3188
3189         /* Process 'A' for "wAll type" (one line only) */
3190         else if (buf[0] == 'A')
3191         {
3192                 char *zz[16];
3193
3194                 /* Scan for the values */
3195                 if (tokenize(buf + 2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return 1;
3196
3197                 /* Save the values */
3198                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3199                 {
3200                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
3201                         if (d_ptr->fill[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3202
3203                         d_ptr->fill[i].percent = (PERCENTAGE)atoi(zz[i * 2 + 1]);
3204                 }
3205
3206                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3207                 if (d_ptr->outer_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3208
3209                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
3210                 if (d_ptr->inner_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3211
3212                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
3213                 if (d_ptr->stream1 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3214
3215                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
3216                 if (d_ptr->stream2 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3217         }
3218
3219         /* Process 'F' for "Dungeon Flags" (multiple lines) */
3220         else if (buf[0] == 'F')
3221         {
3222                 int artif = 0, monst = 0;
3223
3224                 /* Parse every entry */
3225                 for (s = buf + 2; *s; )
3226                 {
3227                         /* Find the end of this entry */
3228                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3229
3230                         /* Nuke and skip any dividers */
3231                         if (*t)
3232                         {
3233                                 *t++ = '\0';
3234                                 while (*t == ' ' || *t == '|') t++;
3235                         }
3236
3237                         /* Hack -- Read Final Artifact */
3238                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3239                         {
3240                                 /* Extract a "Final Artifact" */
3241                                 d_ptr->final_artifact = (ARTIFACT_IDX)artif;
3242
3243                                 /* Start at next entry */
3244                                 s = t;
3245                                 continue;
3246                         }
3247
3248                         /* Hack -- Read Final Object */
3249                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3250                         {
3251                                 /* Extract a "Final Artifact" */
3252                                 d_ptr->final_object = (KIND_OBJECT_IDX)artif;
3253
3254                                 /* Start at next entry */
3255                                 s = t;
3256                                 continue;
3257                         }
3258
3259                         /* Hack -- Read Artifact Guardian */
3260                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3261                         {
3262                                 /* Extract a "Artifact Guardian" */
3263                                 d_ptr->final_guardian = (MONRACE_IDX)monst;
3264
3265                                 /* Start at next entry */
3266                                 s = t;
3267                                 continue;
3268                         }
3269
3270                         /* Hack -- Read Special Percentage */
3271                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3272                         {
3273                                 /* Extract a "Special %" */
3274                                 d_ptr->special_div = (PROB)monst;
3275
3276                                 /* Start at next entry */
3277                                 s = t;
3278                                 continue;
3279                         }
3280
3281                         /* Parse this entry */
3282                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return 5;
3283
3284                         /* Start the next entry */
3285                         s = t;
3286                 }
3287         }
3288
3289         /* Process 'M' for "Basic Flags" (multiple lines) */
3290         else if (buf[0] == 'M')
3291         {
3292                 /* Parse every entry */
3293                 for (s = buf + 2; *s; )
3294                 {
3295                         /* Find the end of this entry */
3296                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3297
3298                         /* Nuke and skip any dividers */
3299                         if (*t)
3300                         {
3301                                 *t++ = '\0';
3302                                 while (*t == ' ' || *t == '|') t++;
3303                         }
3304
3305                         /* Hack -- Read monster symbols */
3306                         if (!strncmp(s, "R_CHAR_", 7))
3307                         {
3308                                 /* Skip "R_CHAR_" */
3309                                 s += 7;
3310
3311                                 /* Read a string */
3312                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
3313
3314                                 /* Start at next entry */
3315                                 s = t;
3316                                 continue;
3317                         }
3318
3319                         /* Parse this entry */
3320                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return 5;
3321
3322                         /* Start the next entry */
3323                         s = t;
3324                 }
3325         }
3326
3327         /* Process 'S' for "Spell Flags" (multiple lines) */
3328         else if (buf[0] == 'S')
3329         {
3330                 /* Parse every entry */
3331                 for (s = buf + 2; *s; )
3332                 {
3333                         /* Find the end of this entry */
3334                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3335
3336                         /* Nuke and skip any dividers */
3337                         if (*t)
3338                         {
3339                                 *t++ = '\0';
3340                                 while ((*t == ' ') || (*t == '|')) t++;
3341                         }
3342
3343                         /* Hack -- Read spell frequency */
3344                         if (1 == sscanf(s, "1_IN_%d", &i))
3345                         {
3346                                 /* Start at next entry */
3347                                 s = t;
3348                                 continue;
3349                         }
3350
3351                         /* Parse this entry */
3352                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return 5;
3353
3354                         /* Start the next entry */
3355                         s = t;
3356                 }
3357         }
3358         else return 6;
3359
3360         return 0;
3361 }
3362
3363
3364 #else   /* ALLOW_TEMPLATES */
3365
3366 #ifdef MACINTOSH
3367 static int i = 0;
3368 #endif
3369
3370 #endif  /* ALLOW_TEMPLATES */
3371
3372
3373 /*!
3374  * @brief 地形情報の「F:」情報をパースする
3375  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3376  * @param floor_ptr 現在フロアへの参照ポインタ
3377  * @param buf 解析文字列
3378  * @return エラーコード
3379  */
3380 static errr parse_line_feature(floor_type *floor_ptr, char *buf)
3381 {
3382         if (init_flags & INIT_ONLY_BUILDINGS) return 0;
3383
3384         /* Tokenize the line */
3385         char *zz[9];
3386         int num = tokenize(buf + 2, 9, zz, 0);
3387         if (num <= 1) return 1;
3388
3389         /* Letter to assign */
3390         int index = zz[0][0];
3391
3392         /* Reset the info for the letter */
3393         letter[index].feature = feat_none;
3394         letter[index].monster = 0;
3395         letter[index].object = 0;
3396         letter[index].ego = 0;
3397         letter[index].artifact = 0;
3398         letter[index].trap = feat_none;
3399         letter[index].cave_info = 0;
3400         letter[index].special = 0;
3401         letter[index].random = RANDOM_NONE;
3402
3403         switch (num)
3404         {
3405                 /* Special */
3406         case 9:
3407                 letter[index].special = (s16b)atoi(zz[8]);
3408                 /* Fall through */
3409         /* Trap */
3410         case 8:
3411                 if ((zz[7][0] == '*') && !zz[7][1])
3412                 {
3413                         letter[index].random |= RANDOM_TRAP;
3414                 }
3415                 else
3416                 {
3417                         letter[index].trap = f_tag_to_index(zz[7]);
3418                         if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3419                 }
3420                 /* Fall through */
3421         /* Artifact */
3422         case 7:
3423                 if (zz[6][0] == '*')
3424                 {
3425                         letter[index].random |= RANDOM_ARTIFACT;
3426                         if (zz[6][1]) letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6] + 1);
3427                 }
3428                 else if (zz[6][0] == '!')
3429                 {
3430                         if (floor_ptr->inside_quest)
3431                         {
3432                                 letter[index].artifact = quest[floor_ptr->inside_quest].k_idx;
3433                         }
3434                 }
3435                 else
3436                 {
3437                         letter[index].artifact = (ARTIFACT_IDX)atoi(zz[6]);
3438                 }
3439                 /* Fall through */
3440         /* Ego-item */
3441         case 6:
3442                 if (zz[5][0] == '*')
3443                 {
3444                         letter[index].random |= RANDOM_EGO;
3445                         if (zz[5][1]) letter[index].ego = (EGO_IDX)atoi(zz[5] + 1);
3446                 }
3447                 else
3448                 {
3449                         letter[index].ego = (EGO_IDX)atoi(zz[5]);
3450                 }
3451                 /* Fall through */
3452         /* Object */
3453         case 5:
3454                 if (zz[4][0] == '*')
3455                 {
3456                         letter[index].random |= RANDOM_OBJECT;
3457                         if (zz[4][1]) letter[index].object = (OBJECT_IDX)atoi(zz[4] + 1);
3458                 }
3459                 else if (zz[4][0] == '!')
3460                 {
3461                         if (floor_ptr->inside_quest)
3462                         {
3463                                 ARTIFACT_IDX a_idx = quest[floor_ptr->inside_quest].k_idx;
3464                                 if (a_idx)
3465                                 {
3466                                         artifact_type *a_ptr = &a_info[a_idx];
3467                                         if (!(a_ptr->gen_flags & TRG_INSTA_ART))
3468                                         {
3469                                                 letter[index].object = lookup_kind(a_ptr->tval, a_ptr->sval);
3470                                         }
3471                                 }
3472                         }
3473                 }
3474                 else
3475                 {
3476                         letter[index].object = (IDX)atoi(zz[4]);
3477                 }
3478                 /* Fall through */
3479         /* Monster */
3480         case 4:
3481                 if (zz[3][0] == '*')
3482                 {
3483                         letter[index].random |= RANDOM_MONSTER;
3484                         if (zz[3][1]) letter[index].monster = (IDX)atoi(zz[3] + 1);
3485                 }
3486                 else if (zz[3][0] == 'c')
3487                 {
3488                         if (!zz[3][1]) return PARSE_ERROR_GENERIC;
3489                         letter[index].monster = -atoi(zz[3] + 1);
3490                 }
3491                 else
3492                 {
3493                         letter[index].monster = (IDX)atoi(zz[3]);
3494                 }
3495                 /* Fall through */
3496         /* Cave info */
3497         case 3:
3498                 letter[index].cave_info = atoi(zz[2]);
3499                 /* Fall through */
3500         /* Feature */
3501         case 2:
3502                 if ((zz[1][0] == '*') && !zz[1][1])
3503                 {
3504                         letter[index].random |= RANDOM_FEATURE;
3505                 }
3506                 else
3507                 {
3508                         letter[index].feature = f_tag_to_index(zz[1]);
3509                         if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3510                 }
3511                 break;
3512         }
3513
3514         return 0;
3515 }
3516
3517
3518 /*!
3519  * @brief 地形情報の「B:」情報をパースする
3520  * Process "B:<Index>:<Command>:..." -- Building definition
3521  * @param buf 解析文字列
3522  * @return エラーコード
3523  */
3524 static errr parse_line_building(char *buf)
3525 {
3526         int i;
3527         char *zz[1000];
3528         int index;
3529         char *s;
3530
3531 #ifdef JP
3532         if (buf[2] == '$')
3533                 return 0;
3534         s = buf + 2;
3535 #else
3536         if (buf[2] != '$')
3537                 return 0;
3538         s = buf + 3;
3539 #endif
3540         /* Get the building number */
3541         index = atoi(s);
3542
3543         /* Find the colon after the building number */
3544         s = my_strchr(s, ':');
3545
3546         /* Verify that colon */
3547         if (!s) return 1;
3548
3549         /* Nuke the colon, advance to the sub-index */
3550         *s++ = '\0';
3551
3552         /* Paranoia -- require a sub-index */
3553         if (!*s) return 1;
3554
3555         /* Building definition sub-index */
3556         switch (s[0])
3557         {
3558                 /* Building name, owner, race */
3559         case 'N':
3560         {
3561                 if (tokenize(s + 2, 3, zz, 0) == 3)
3562                 {
3563                         /* Name of the building */
3564                         strcpy(building[index].name, zz[0]);
3565
3566                         /* Name of the owner */
3567                         strcpy(building[index].owner_name, zz[1]);
3568
3569                         /* Race of the owner */
3570                         strcpy(building[index].owner_race, zz[2]);
3571
3572                         break;
3573                 }
3574
3575                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3576         }
3577
3578         /* Building Action */
3579         case 'A':
3580         {
3581                 if (tokenize(s + 2, 8, zz, 0) >= 7)
3582                 {
3583                         /* Index of the action */
3584                         int action_index = atoi(zz[0]);
3585
3586                         /* Name of the action */
3587                         strcpy(building[index].act_names[action_index], zz[1]);
3588
3589                         /* Cost of the action for members */
3590                         building[index].member_costs[action_index] = (PRICE)atoi(zz[2]);
3591
3592                         /* Cost of the action for non-members */
3593                         building[index].other_costs[action_index] = (PRICE)atoi(zz[3]);
3594
3595                         /* Letter assigned to the action */
3596                         building[index].letters[action_index] = zz[4][0];
3597
3598                         /* Action code */
3599                         building[index].actions[action_index] = (BACT_IDX)atoi(zz[5]);
3600
3601                         /* Action restriction */
3602                         building[index].action_restr[action_index] = (BACT_RESTRICT_IDX)atoi(zz[6]);
3603
3604                         break;
3605                 }
3606
3607                 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3608         }
3609
3610         /* Building Classes */
3611         case 'C':
3612         {
3613                 int n;
3614                 n = tokenize(s + 2, MAX_CLASS, zz, 0);
3615                 for (i = 0; i < MAX_CLASS; i++)
3616                 {
3617                         building[index].member_class[i] = ((i < n) ? (CLASS_IDX)atoi(zz[i]) : 1);
3618                 }
3619                 break;
3620         }
3621
3622         /* Building Races */
3623         case 'R':
3624         {
3625                 int n;
3626                 n = tokenize(s + 2, MAX_RACES, zz, 0);
3627                 for (i = 0; i < MAX_RACES; i++)
3628                 {
3629                         building[index].member_race[i] = ((i < n) ? (RACE_IDX)atoi(zz[i]) : 1);
3630                 }
3631                 break;
3632         }
3633
3634         /* Building Realms */
3635         case 'M':
3636         {
3637                 int n;
3638                 n = tokenize(s + 2, MAX_MAGIC, zz, 0);
3639                 for (i = 0; i < MAX_MAGIC; i++)
3640                 {
3641                         building[index].member_realm[i + 1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1);
3642                 }
3643                 break;
3644         }
3645
3646         case 'Z':
3647         {
3648                 /* Ignore scripts */
3649                 break;
3650         }
3651
3652         default:
3653         {
3654                 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3655         }
3656         }
3657
3658         return 0;
3659 }
3660
3661
3662 /*!
3663  * @brief フロアの所定のマスにオブジェクトを配置する
3664  * Place the object j_ptr to a grid
3665  * @param floor_ptr 現在フロアへの参照ポインタ
3666  * @param j_ptr オブジェクト構造体の参照ポインタ
3667  * @param y 配置先Y座標
3668  * @param x 配置先X座標
3669  * @return エラーコード
3670  */
3671 static void drop_here(floor_type *floor_ptr, object_type *j_ptr, POSITION y, POSITION x)
3672 {
3673         OBJECT_IDX o_idx = o_pop(floor_ptr);
3674         object_type *o_ptr;
3675         o_ptr = &floor_ptr->o_list[o_idx];
3676         object_copy(o_ptr, j_ptr);
3677         o_ptr->iy = y;
3678         o_ptr->ix = x;
3679         o_ptr->held_m_idx = 0;
3680         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
3681         o_ptr->next_o_idx = g_ptr->o_idx;
3682         g_ptr->o_idx = o_idx;
3683 }
3684
3685
3686 /*!
3687  * todo yminとymaxは本当に使われているのか?
3688  * @brief クエスト用固定ダンジョンをフロアに生成する
3689  * Parse a sub-file of the "extra info"
3690  * @param player_ptr プレーヤーへの参照ポインタ
3691  * @param buf 文字列
3692  * @param ymin 詳細不明
3693  * @param xmin 詳細不明
3694  * @param ymax 詳細不明
3695  * @param xmax 詳細不明
3696  * @param y 詳細不明
3697  * @param x 詳細不明
3698  * @return エラーコード
3699  */
3700 static errr process_dungeon_file_aux(player_type *player_ptr, char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3701 {
3702         int i;
3703         char *zz[33];
3704
3705         /* Skip "empty" lines */
3706         if (!buf[0]) return 0;
3707
3708         /* Skip "blank" lines */
3709         if (iswspace(buf[0])) return 0;
3710
3711         /* Skip comments */
3712         if (buf[0] == '#') return 0;
3713
3714         /* Require "?:*" format */
3715         if (buf[1] != ':') return 1;
3716
3717
3718         /* Process "%:<fname>" */
3719         if (buf[0] == '%')
3720         {
3721                 /* Attempt to Process the given file */
3722                 return process_dungeon_file(player_ptr, buf + 2, ymin, xmin, ymax, xmax);
3723         }
3724
3725         floor_type *floor_ptr = player_ptr->current_floor_ptr;
3726         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3727         if (buf[0] == 'F')
3728         {
3729                 return parse_line_feature(player_ptr->current_floor_ptr, buf);
3730         }
3731
3732         /* Process "D:<dungeon>" -- info for the floor grids */
3733         else if (buf[0] == 'D')
3734         {
3735                 object_type object_type_body;
3736
3737                 /* Acquire the text */
3738                 char *s = buf + 2;
3739
3740                 /* Length of the text */
3741                 int len = strlen(s);
3742
3743                 if (init_flags & INIT_ONLY_BUILDINGS) return 0;
3744
3745                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3746                 {
3747                         grid_type *g_ptr = &floor_ptr->grid_array[*y][*x];
3748
3749                         int idx = s[0];
3750
3751                         OBJECT_IDX object_index = letter[idx].object;
3752                         MONSTER_IDX monster_index = letter[idx].monster;
3753                         int random = letter[idx].random;
3754                         ARTIFACT_IDX artifact_index = letter[idx].artifact;
3755
3756                         /* Lay down a floor */
3757                         g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].feature);
3758
3759                         /* Only the features */
3760                         if (init_flags & INIT_ONLY_FEATURES) continue;
3761
3762                         /* Cave info */
3763                         g_ptr->info = letter[idx].cave_info;
3764
3765                         /* Create a monster */
3766                         if (random & RANDOM_MONSTER)
3767                         {
3768                                 floor_ptr->monster_level = floor_ptr->base_level + monster_index;
3769
3770                                 place_monster(player_ptr, *y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3771
3772                                 floor_ptr->monster_level = floor_ptr->base_level;
3773                         }
3774                         else if (monster_index)
3775                         {
3776                                 int old_cur_num, old_max_num;
3777                                 bool clone = FALSE;
3778
3779                                 if (monster_index < 0)
3780                                 {
3781                                         monster_index = -monster_index;
3782                                         clone = TRUE;
3783                                 }
3784                                 old_cur_num = r_info[monster_index].cur_num;
3785                                 old_max_num = r_info[monster_index].max_num;
3786
3787                                 /* Make alive again */
3788                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3789                                 {
3790                                         r_info[monster_index].cur_num = 0;
3791                                         r_info[monster_index].max_num = 1;
3792                                 }
3793
3794                                 /* Make alive again */
3795                                 /* Hack -- Non-unique Nazguls are semi-unique */
3796                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3797                                 {
3798                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3799                                         {
3800                                                 r_info[monster_index].max_num++;
3801                                         }
3802                                 }
3803
3804                                 /* Place it */
3805                                 place_monster_aux(player_ptr, 0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3806                                 if (clone)
3807                                 {
3808                                         /* clone */
3809                                         floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
3810
3811                                         /* Make alive again for real unique monster */
3812                                         r_info[monster_index].cur_num = old_cur_num;
3813                                         r_info[monster_index].max_num = old_max_num;
3814                                 }
3815                         }
3816
3817                         /* Object (and possible trap) */
3818                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3819                         {
3820                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3821
3822                                 /*
3823                                  * Random trap and random treasure defined
3824                                  * 25% chance for trap and 75% chance for object
3825                                  */
3826                                 if (randint0(100) < 75)
3827                                 {
3828                                         place_object(player_ptr, *y, *x, 0L);
3829                                 }
3830                                 else
3831                                 {
3832                                         place_trap(player_ptr, *y, *x);
3833                                 }
3834
3835                                 floor_ptr->object_level = floor_ptr->base_level;
3836                         }
3837                         else if (random & RANDOM_OBJECT)
3838                         {
3839                                 floor_ptr->object_level = floor_ptr->base_level + object_index;
3840
3841                                 /* Create an out of deep object */
3842                                 if (randint0(100) < 75)
3843                                         place_object(player_ptr, *y, *x, 0L);
3844                                 else if (randint0(100) < 80)
3845                                         place_object(player_ptr, *y, *x, AM_GOOD);
3846                                 else
3847                                         place_object(player_ptr, *y, *x, AM_GOOD | AM_GREAT);
3848
3849                                 floor_ptr->object_level = floor_ptr->base_level;
3850                         }
3851                         /* Random trap */
3852                         else if (random & RANDOM_TRAP)
3853                         {
3854                                 place_trap(player_ptr, *y, *x);
3855                         }
3856                         /* Hidden trap (or door) */
3857                         else if (letter[idx].trap)
3858                         {
3859                                 g_ptr->mimic = g_ptr->feat;
3860                                 g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].trap);
3861                         }
3862                         else if (object_index)
3863                         {
3864                                 object_type *o_ptr = &object_type_body;
3865                                 object_prep(o_ptr, object_index);
3866
3867                                 if (o_ptr->tval == TV_GOLD)
3868                                 {
3869                                         coin_type = object_index - OBJ_GOLD_LIST;
3870                                         make_gold(floor_ptr, o_ptr);
3871                                         coin_type = 0;
3872                                 }
3873
3874                                 /* Apply magic (no messages, no artifacts) */
3875                                 apply_magic(player_ptr, o_ptr, floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
3876
3877                                 drop_here(floor_ptr, o_ptr, *y, *x);
3878                         }
3879
3880                         /* Artifact */
3881                         if (artifact_index)
3882                         {
3883                                 if (a_info[artifact_index].cur_num)
3884                                 {
3885                                         KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
3886                                         object_type forge;
3887                                         object_type *q_ptr = &forge;
3888
3889                                         object_prep(q_ptr, k_idx);
3890                                         drop_here(floor_ptr, q_ptr, *y, *x);
3891                                 }
3892                                 else
3893                                 {
3894                                         if (create_named_art(player_ptr, artifact_index, *y, *x))
3895                                                 a_info[artifact_index].cur_num = 1;
3896                                 }
3897                         }
3898
3899                         /* Terrain special */
3900                         g_ptr->special = letter[idx].special;
3901                 }
3902
3903                 (*y)++;
3904
3905                 return 0;
3906         }
3907
3908         /* Process "Q:<number>:<command>:... -- quest info */
3909         else if (buf[0] == 'Q')
3910         {
3911                 int num;
3912                 quest_type *q_ptr;
3913 #ifdef JP
3914                 if (buf[2] == '$')
3915                         return 0;
3916                 num = tokenize(buf + 2, 33, zz, 0);
3917 #else
3918                 if (buf[2] != '$')
3919                         return 0;
3920                 num = tokenize(buf + 3, 33, zz, 0);
3921 #endif
3922
3923                 /* Have we enough parameters? */
3924                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3925
3926                 /* Get the quest */
3927                 q_ptr = &(quest[atoi(zz[0])]);
3928
3929                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3930                 if (zz[1][0] == 'Q')
3931                 {
3932                         if (init_flags & INIT_ASSIGN)
3933                         {
3934                                 monster_race *r_ptr;
3935                                 artifact_type *a_ptr;
3936
3937                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3938
3939                                 q_ptr->type = (QUEST_TYPE)atoi(zz[2]);
3940                                 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
3941                                 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
3942                                 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
3943                                 q_ptr->level = (DEPTH)atoi(zz[6]);
3944                                 q_ptr->r_idx = (IDX)atoi(zz[7]);
3945                                 q_ptr->k_idx = (IDX)atoi(zz[8]);
3946                                 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
3947
3948                                 if (num > 10) q_ptr->flags = atoi(zz[10]);
3949
3950                                 r_ptr = &r_info[q_ptr->r_idx];
3951                                 if (r_ptr->flags1 & RF1_UNIQUE)
3952                                         r_ptr->flags1 |= RF1_QUESTOR;
3953
3954                                 a_ptr = &a_info[q_ptr->k_idx];
3955                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3956                         }
3957                         return 0;
3958                 }
3959
3960                 else if (zz[1][0] == 'R')
3961                 {
3962                         if (init_flags & INIT_ASSIGN)
3963                         {
3964                                 int count = 0;
3965                                 IDX idx, reward_idx = 0;
3966
3967                                 for (idx = 2; idx < num; idx++)
3968                                 {
3969                                         IDX a_idx = (IDX)atoi(zz[idx]);
3970                                         if (a_idx < 1) continue;
3971                                         if (a_info[a_idx].cur_num > 0) continue;
3972                                         count++;
3973                                         if (one_in_(count)) reward_idx = a_idx;
3974                                 }
3975
3976                                 if (reward_idx)
3977                                 {
3978                                         /* Set quest's rewarding artifact */
3979                                         q_ptr->k_idx = reward_idx;
3980                                         a_info[reward_idx].gen_flags |= TRG_QUESTITEM;
3981                                 }
3982                                 else
3983                                 {
3984                                         /* Change a quest type to KILL_ALL when all artifact of reward list are got */
3985                                         q_ptr->type = QUEST_TYPE_KILL_ALL;
3986                                 }
3987                         }
3988
3989                         return 0;
3990                 }
3991
3992                 /* Process "Q:<q_index>:N:<name>" -- quest name */
3993                 else if (zz[1][0] == 'N')
3994                 {
3995                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY))
3996                         {
3997                                 strcpy(q_ptr->name, zz[2]);
3998                         }
3999
4000                         return 0;
4001                 }
4002
4003                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
4004                 else if (zz[1][0] == 'T')
4005                 {
4006                         if (init_flags & INIT_SHOW_TEXT)
4007                         {
4008                                 strcpy(quest_text[quest_text_line], zz[2]);
4009                                 quest_text_line++;
4010                         }
4011
4012                         return 0;
4013                 }
4014         }
4015
4016         /* Process "W:<command>: ..." -- info for the wilderness */
4017         else if (buf[0] == 'W')
4018         {
4019                 return parse_line_wilderness(player_ptr, buf, xmin, xmax, y, x);
4020         }
4021
4022         /* Process "P:<y>:<x>" -- player position */
4023         else if (buf[0] == 'P')
4024         {
4025                 if (init_flags & INIT_CREATE_DUNGEON)
4026                 {
4027                         if (tokenize(buf + 2, 2, zz, 0) == 2)
4028                         {
4029                                 int panels_x, panels_y;
4030
4031                                 /* Hack - Set the dungeon size */
4032                                 panels_y = (*y / SCREEN_HGT);
4033                                 if (*y % SCREEN_HGT) panels_y++;
4034                                 floor_ptr->height = panels_y * SCREEN_HGT;
4035
4036                                 panels_x = (*x / SCREEN_WID);
4037                                 if (*x % SCREEN_WID) panels_x++;
4038                                 floor_ptr->width = panels_x * SCREEN_WID;
4039
4040                                 /* Assume illegal panel */
4041                                 panel_row_min = floor_ptr->height;
4042                                 panel_col_min = floor_ptr->width;
4043
4044                                 /* Place player in a quest level */
4045                                 if (floor_ptr->inside_quest)
4046                                 {
4047                                         POSITION py, px;
4048
4049                                         /* Delete the monster (if any) */
4050                                         delete_monster(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x);
4051
4052                                         py = atoi(zz[0]);
4053                                         px = atoi(zz[1]);
4054
4055                                         player_ptr->y = py;
4056                                         player_ptr->x = px;
4057                                 }
4058                                 /* Place player in the town */
4059                                 else if (!player_ptr->oldpx && !player_ptr->oldpy)
4060                                 {
4061                                         player_ptr->oldpy = atoi(zz[0]);
4062                                         player_ptr->oldpx = atoi(zz[1]);
4063                                 }
4064                         }
4065                 }
4066
4067                 return 0;
4068         }
4069
4070         /* Process "B:<Index>:<Command>:..." -- Building definition */
4071         else if (buf[0] == 'B')
4072         {
4073                 return parse_line_building(buf);
4074         }
4075
4076         /* Process "M:<type>:<maximum>" -- set maximum values */
4077         else if (buf[0] == 'M')
4078         {
4079                 if (tokenize(buf + 2, 2, zz, 0) == 2)
4080                 {
4081                         /* Maximum towns */
4082                         if (zz[0][0] == 'T')
4083                         {
4084                                 max_towns = (TOWN_IDX)atoi(zz[1]);
4085                         }
4086
4087                         /* Maximum quests */
4088                         else if (zz[0][0] == 'Q')
4089                         {
4090                                 max_q_idx = (QUEST_IDX)atoi(zz[1]);
4091                         }
4092
4093                         /* Maximum r_idx */
4094                         else if (zz[0][0] == 'R')
4095                         {
4096                                 max_r_idx = (RACE_IDX)atoi(zz[1]);
4097                         }
4098
4099                         /* Maximum k_idx */
4100                         else if (zz[0][0] == 'K')
4101                         {
4102                                 max_k_idx = (KIND_OBJECT_IDX)atoi(zz[1]);
4103                         }
4104
4105                         /* Maximum v_idx */
4106                         else if (zz[0][0] == 'V')
4107                         {
4108                                 max_v_idx = (VAULT_IDX)atoi(zz[1]);
4109                         }
4110
4111                         /* Maximum f_idx */
4112                         else if (zz[0][0] == 'F')
4113                         {
4114                                 max_f_idx = (FEAT_IDX)atoi(zz[1]);
4115                         }
4116
4117                         /* Maximum a_idx */
4118                         else if (zz[0][0] == 'A')
4119                         {
4120                                 max_a_idx = (ARTIFACT_IDX)atoi(zz[1]);
4121                         }
4122
4123                         /* Maximum e_idx */
4124                         else if (zz[0][0] == 'E')
4125                         {
4126                                 max_e_idx = (EGO_IDX)atoi(zz[1]);
4127                         }
4128
4129                         /* Maximum d_idx */
4130                         else if (zz[0][0] == 'D')
4131                         {
4132                                 current_world_ptr->max_d_idx = (DUNGEON_IDX)atoi(zz[1]);
4133                         }
4134
4135                         /* Maximum o_idx */
4136                         else if (zz[0][0] == 'O')
4137                         {
4138                                 current_world_ptr->max_o_idx = (OBJECT_IDX)atoi(zz[1]);
4139                         }
4140
4141                         /* Maximum m_idx */
4142                         else if (zz[0][0] == 'M')
4143                         {
4144                                 current_world_ptr->max_m_idx = (MONSTER_IDX)atoi(zz[1]);
4145                         }
4146
4147                         /* Wilderness size */
4148                         else if (zz[0][0] == 'W')
4149                         {
4150                                 /* Maximum wild_x_size */
4151                                 if (zz[0][1] == 'X')
4152                                         current_world_ptr->max_wild_x = (POSITION)atoi(zz[1]);
4153                                 /* Maximum wild_y_size */
4154                                 if (zz[0][1] == 'Y')
4155                                         current_world_ptr->max_wild_y = (POSITION)atoi(zz[1]);
4156                         }
4157
4158                         return 0;
4159                 }
4160         }
4161
4162         return 1;
4163 }
4164
4165 /*
4166 * todo ここから先頭に移すとコンパイル警告が出る……
4167 */
4168 static char tmp[8];
4169 static concptr variant = "ZANGBAND";
4170
4171 /*!
4172  * @brief クエスト用固定ダンジョン生成時の分岐処理
4173  * Helper function for "process_dungeon_file()"
4174  * @param player_ptr プレーヤーへの参照ポインタ
4175  * @param sp
4176  * @param fp
4177  * @return エラーコード
4178  */
4179 static concptr process_dungeon_file_expr(player_type *player_ptr, char **sp, char *fp)
4180 {
4181         char b1 = '[';
4182         char b2 = ']';
4183
4184         char f = ' ';
4185
4186         char *s;
4187         s = (*sp);
4188
4189         /* Skip spaces */
4190         while (iswspace(*s)) s++;
4191
4192         /* Save start */
4193         char *b;
4194         b = s;
4195
4196         /* Default */
4197         concptr v = "?o?o?";
4198
4199         /* Analyze */
4200         if (*s == b1)
4201         {
4202                 concptr p;
4203                 concptr t;
4204
4205                 /* Skip b1 */
4206                 s++;
4207
4208                 /* First */
4209                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4210
4211                 if (!*t)
4212                 {
4213                         /* Nothing */
4214                 }
4215
4216                 /* Function: IOR */
4217                 else if (streq(t, "IOR"))
4218                 {
4219                         v = "0";
4220                         while (*s && (f != b2))
4221                         {
4222                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4223                                 if (*t && !streq(t, "0")) v = "1";
4224                         }
4225                 }
4226
4227                 /* Function: AND */
4228                 else if (streq(t, "AND"))
4229                 {
4230                         v = "1";
4231                         while (*s && (f != b2))
4232                         {
4233                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4234                                 if (*t && streq(t, "0")) v = "0";
4235                         }
4236                 }
4237
4238                 /* Function: NOT */
4239                 else if (streq(t, "NOT"))
4240                 {
4241                         v = "1";
4242                         while (*s && (f != b2))
4243                         {
4244                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4245                                 if (*t && streq(t, "1")) v = "0";
4246                         }
4247                 }
4248
4249                 /* Function: EQU */
4250                 else if (streq(t, "EQU"))
4251                 {
4252                         v = "0";
4253                         if (*s && (f != b2))
4254                         {
4255                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4256                         }
4257                         while (*s && (f != b2))
4258                         {
4259                                 p = process_dungeon_file_expr(player_ptr, &s, &f);
4260                                 if (streq(t, p)) v = "1";
4261                         }
4262                 }
4263
4264                 /* Function: LEQ */
4265                 else if (streq(t, "LEQ"))
4266                 {
4267                         v = "1";
4268                         if (*s && (f != b2))
4269                         {
4270                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4271                         }
4272                         while (*s && (f != b2))
4273                         {
4274                                 p = t;
4275                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4276                                 if (*t && atoi(p) > atoi(t)) v = "0";
4277                         }
4278                 }
4279
4280                 /* Function: GEQ */
4281                 else if (streq(t, "GEQ"))
4282                 {
4283                         v = "1";
4284                         if (*s && (f != b2))
4285                         {
4286                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4287                         }
4288                         while (*s && (f != b2))
4289                         {
4290                                 p = t;
4291                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4292
4293                                 /* Compare two numbers instead of string */
4294                                 if (*t && atoi(p) < atoi(t)) v = "0";
4295                         }
4296                 }
4297
4298                 else
4299                 {
4300                         while (*s && (f != b2))
4301                         {
4302                                 t = process_dungeon_file_expr(player_ptr, &s, &f);
4303                         }
4304                 }
4305
4306                 /* Verify ending */
4307                 if (f != b2) v = "?x?x?";
4308
4309                 /* Extract final and Terminate */
4310                 if ((f = *s) != '\0') *s++ = '\0';
4311
4312                 (*fp) = f;
4313                 (*sp) = s;
4314                 return v;
4315         }
4316
4317         /* Accept all printables except spaces and brackets */
4318 #ifdef JP
4319         while (iskanji(*s) || (isprint(*s) && !my_strchr(" []", *s)))
4320         {
4321                 if (iskanji(*s)) s++;
4322                 s++;
4323         }
4324 #else
4325         while (isprint(*s) && !my_strchr(" []", *s)) ++s;
4326 #endif
4327
4328         /* Extract final and Terminate */
4329         if ((f = *s) != '\0') *s++ = '\0';
4330
4331         /* Variable */
4332         if (*b != '$')
4333         {
4334                 v = b;
4335                 (*fp) = f;
4336                 (*sp) = s;
4337                 return v;
4338         }
4339
4340         /* System */
4341         if (streq(b + 1, "SYS"))
4342         {
4343                 v = ANGBAND_SYS;
4344         }
4345
4346         /* Graphics */
4347         else if (streq(b + 1, "GRAF"))
4348         {
4349                 v = ANGBAND_GRAF;
4350         }
4351
4352         else if (streq(b + 1, "MONOCHROME"))
4353         {
4354                 if (arg_monochrome)
4355                         v = "ON";
4356                 else
4357                         v = "OFF";
4358         }
4359
4360         /* Race */
4361         else if (streq(b + 1, "RACE"))
4362         {
4363                 v = _(rp_ptr->E_title, rp_ptr->title);
4364         }
4365
4366         /* Class */
4367         else if (streq(b + 1, "CLASS"))
4368         {
4369                 v = _(cp_ptr->E_title, cp_ptr->title);
4370         }
4371
4372         /* First realm */
4373         else if (streq(b + 1, "REALM1"))
4374         {
4375                 v = _(E_realm_names[player_ptr->realm1], realm_names[player_ptr->realm1]);
4376         }
4377
4378         /* Second realm */
4379         else if (streq(b + 1, "REALM2"))
4380         {
4381                 v = _(E_realm_names[player_ptr->realm2], realm_names[player_ptr->realm2]);
4382         }
4383
4384         /* Player name */
4385         else if (streq(b + 1, "PLAYER"))
4386         {
4387                 static char tmp_player_name[32];
4388                 char *pn, *tpn;
4389                 for (pn = player_ptr->name, tpn = tmp_player_name; *pn; pn++, tpn++)
4390                 {
4391 #ifdef JP
4392                         if (iskanji(*pn))
4393                         {
4394                                 *(tpn++) = *(pn++);
4395                                 *tpn = *pn;
4396                                 continue;
4397                         }
4398 #endif
4399                         *tpn = my_strchr(" []", *pn) ? '_' : *pn;
4400                 }
4401                 *tpn = '\0';
4402                 v = tmp_player_name;
4403         }
4404
4405         /* Town */
4406         else if (streq(b + 1, "TOWN"))
4407         {
4408                 sprintf(tmp, "%d", player_ptr->town_num);
4409                 v = tmp;
4410         }
4411
4412         /* Level */
4413         else if (streq(b + 1, "LEVEL"))
4414         {
4415                 sprintf(tmp, "%d", player_ptr->lev);
4416                 v = tmp;
4417         }
4418
4419         /* Current quest number */
4420         else if (streq(b + 1, "QUEST_NUMBER"))
4421         {
4422                 sprintf(tmp, "%d", player_ptr->current_floor_ptr->inside_quest);
4423                 v = tmp;
4424         }
4425
4426         /* Number of last quest */
4427         else if (streq(b + 1, "LEAVING_QUEST"))
4428         {
4429                 sprintf(tmp, "%d", leaving_quest);
4430                 v = tmp;
4431         }
4432
4433         /* Quest type */
4434         else if (prefix(b + 1, "QUEST_TYPE"))
4435         {
4436                 /* "QUEST_TYPE" uses a special parameter to determine the type of the quest */
4437                 sprintf(tmp, "%d", quest[atoi(b + 11)].type);
4438                 v = tmp;
4439         }
4440
4441         /* Quest status */
4442         else if (prefix(b + 1, "QUEST"))
4443         {
4444                 /* "QUEST" uses a special parameter to determine the number of the quest */
4445                 sprintf(tmp, "%d", quest[atoi(b + 6)].status);
4446                 v = tmp;
4447         }
4448
4449         /* Random */
4450         else if (prefix(b + 1, "RANDOM"))
4451         {
4452                 /* "RANDOM" uses a special parameter to determine the number of the quest */
4453                 sprintf(tmp, "%d", (int)(current_world_ptr->seed_town%atoi(b + 7)));
4454                 v = tmp;
4455         }
4456
4457         /* Variant name */
4458         else if (streq(b + 1, "VARIANT"))
4459         {
4460                 v = variant;
4461         }
4462
4463         /* Wilderness */
4464         else if (streq(b + 1, "WILDERNESS"))
4465         {
4466                 if (vanilla_town)
4467                         sprintf(tmp, "NONE");
4468                 else if (lite_town)
4469                         sprintf(tmp, "LITE");
4470                 else
4471                         sprintf(tmp, "NORMAL");
4472                 v = tmp;
4473         }
4474
4475         (*fp) = f;
4476         (*sp) = s;
4477         return v;
4478 }
4479
4480
4481 /*!
4482  * @brief クエスト用固定ダンジョン生成時のメインルーチン
4483  * Helper function for "process_dungeon_file()"
4484  * @param player_ptr プレーヤーへの参照ポインタ
4485  * @param name ファイル名
4486  * @param ymin 詳細不明
4487  * @param xmin 詳細不明
4488  * @param ymax 詳細不明
4489  * @param xmax 詳細不明
4490  * @return エラーコード
4491  */
4492 errr process_dungeon_file(player_type *player_ptr, concptr name, int ymin, int xmin, int ymax, int xmax)
4493 {
4494         char buf[1024];
4495         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
4496         FILE *fp;
4497         fp = my_fopen(buf, "r");
4498
4499         /* No such file */
4500         if (!fp) return -1;
4501
4502         /* Process the file */
4503         int num = -1;
4504         errr err = 0;
4505         bool bypass = FALSE;
4506         int x = xmin, y = ymin;
4507         while (my_fgets(fp, buf, sizeof(buf)) == 0)
4508         {
4509                 /* Count lines */
4510                 num++;
4511
4512
4513                 /* Skip "empty" lines */
4514                 if (!buf[0]) continue;
4515
4516                 /* Skip "blank" lines */
4517                 if (iswspace(buf[0])) continue;
4518
4519                 /* Skip comments */
4520                 if (buf[0] == '#') continue;
4521
4522
4523                 /* Process "?:<expr>" */
4524                 if ((buf[0] == '?') && (buf[1] == ':'))
4525                 {
4526                         char f;
4527                         concptr v;
4528                         char *s;
4529
4530                         /* Start */
4531                         s = buf + 2;
4532
4533                         /* Parse the expr */
4534                         v = process_dungeon_file_expr(player_ptr, &s, &f);
4535
4536                         /* Set flag */
4537                         bypass = (streq(v, "0") ? TRUE : FALSE);
4538                         continue;
4539                 }
4540
4541                 /* Apply conditionals */
4542                 if (bypass) continue;
4543
4544                 /* Process the line */
4545                 err = process_dungeon_file_aux(player_ptr, buf, ymin, xmin, ymax, xmax, &y, &x);
4546
4547                 if (err) break;
4548         }
4549
4550         if (err)
4551         {
4552                 concptr oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4553                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4554                 msg_format(_("'%s'を解析中。", "Parsing '%s'."), buf);
4555                 msg_print(NULL);
4556         }
4557
4558         my_fclose(fp);
4559         return err;
4560 }