OSDN Git Service

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