OSDN Git Service

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