OSDN Git Service

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