OSDN Git Service

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