OSDN Git Service

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