OSDN Git Service

e0540b8c4995906bc8937bce43d61c1ce6bd20e4
[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 0;
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                         d_ptr->floor[i].percent = atoi(zz[i * 2 + 1]);
3024                 }
3025                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3026         }
3027
3028         /* Process 'A' for "wAll type" (one line only) */
3029         else if (buf[0] == 'A')
3030         {
3031                 char *zz[16];
3032
3033                 /* Scan for the values */
3034                 if (tokenize(buf+2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return (1);
3035
3036                 /* Save the values */
3037                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3038                 {
3039                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
3040                         d_ptr->fill[i].percent = atoi(zz[i * 2 + 1]);
3041                 }
3042                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3043                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
3044                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
3045                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
3046         }
3047
3048         /* Process 'F' for "Dungeon Flags" (multiple lines) */
3049         else if (buf[0] == 'F')
3050         {
3051                 int artif = 0, monst = 0;
3052
3053                 /* Parse every entry */
3054                 for (s = buf + 2; *s; )
3055                 {
3056                         /* Find the end of this entry */
3057                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3058
3059                         /* Nuke and skip any dividers */
3060                         if (*t)
3061                         {
3062                                 *t++ = '\0';
3063                                 while (*t == ' ' || *t == '|') t++;
3064                         }
3065
3066                         /* XXX XXX XXX Hack -- Read Final Artifact */
3067                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3068                         {
3069                                 /* Extract a "Final Artifact" */
3070                                 d_ptr->final_artifact = artif;
3071
3072                                 /* Start at next entry */
3073                                 s = t;
3074
3075                                 /* Continue */
3076                                 continue;
3077                         }
3078
3079                         /* XXX XXX XXX Hack -- Read Final Object */
3080                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3081                         {
3082                                 /* Extract a "Final Artifact" */
3083                                 d_ptr->final_object = artif;
3084
3085                                 /* Start at next entry */
3086                                 s = t;
3087
3088                                 /* Continue */
3089                                 continue;
3090                         }
3091
3092                         /* XXX XXX XXX Hack -- Read Artifact Guardian */
3093                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3094                         {
3095                                 /* Extract a "Artifact Guardian" */
3096                                 d_ptr->final_guardian = monst;
3097
3098                                 /* Start at next entry */
3099                                 s = t;
3100
3101                                 /* Continue */
3102                                 continue;
3103                         }
3104
3105                         /* XXX XXX XXX Hack -- Read Special Percentage */
3106                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3107                         {
3108                                 /* Extract a "Special %" */
3109                                 d_ptr->special_div = monst;
3110
3111                                 /* Start at next entry */
3112                                 s = t;
3113
3114                                 /* Continue */
3115                                 continue;
3116                         }
3117
3118                         /* Parse this entry */
3119                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3120
3121                         /* Start the next entry */
3122                         s = t;
3123                 }
3124         }
3125
3126         /* Process 'M' for "Basic Flags" (multiple lines) */
3127         else if (buf[0] == 'M')
3128         {
3129                 /* Parse every entry */
3130                 for (s = buf + 2; *s; )
3131                 {
3132                         /* Find the end of this entry */
3133                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3134
3135                         /* Nuke and skip any dividers */
3136                         if (*t)
3137                         {
3138                                 *t++ = '\0';
3139                                 while (*t == ' ' || *t == '|') t++;
3140                         }
3141
3142                         /* Hack -- Read monster symbols */
3143                         if (!strncmp(s, "R_CHAR_", 7))
3144                         {
3145                                 /* Skip "R_CHAR_" */
3146                                 s += 7;
3147
3148                                 /* Read a string */
3149                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
3150
3151                                 /* Start at next entry */
3152                                 s = t;
3153
3154                                 /* Continue */
3155                                 continue;
3156                         }
3157
3158                         /* Parse this entry */
3159                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3160
3161                         /* Start the next entry */
3162                         s = t;
3163                 }
3164         }
3165
3166         /* Process 'S' for "Spell Flags" (multiple lines) */
3167         else if (buf[0] == 'S')
3168         {
3169                 /* Parse every entry */
3170                 for (s = buf + 2; *s; )
3171                 {
3172                                 /* Find the end of this entry */
3173                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3174
3175                                 /* Nuke and skip any dividers */
3176                         if (*t)
3177                         {
3178                                 *t++ = '\0';
3179                                 while ((*t == ' ') || (*t == '|')) t++;
3180                         }
3181
3182                                 /* XXX XXX XXX Hack -- Read spell frequency */
3183                         if (1 == sscanf(s, "1_IN_%d", &i))
3184                         {
3185                                 /* Start at next entry */
3186                                 s = t;
3187
3188                                         /* Continue */
3189                                 continue;
3190                         }
3191
3192                                 /* Parse this entry */
3193                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3194
3195                                 /* Start the next entry */
3196                         s = t;
3197                 }
3198         }
3199
3200         /* Oops */
3201         else return (6);
3202
3203         /* Success */
3204         return (0);
3205 }
3206
3207
3208 #else   /* ALLOW_TEMPLATES */
3209
3210 #ifdef MACINTOSH
3211 static int i = 0;
3212 #endif
3213
3214 #endif  /* ALLOW_TEMPLATES */
3215
3216
3217 /* Random dungeon grid effects */
3218 #define RANDOM_NONE         0x00
3219 #define RANDOM_FEATURE      0x01
3220 #define RANDOM_MONSTER      0x02
3221 #define RANDOM_OBJECT       0x04
3222 #define RANDOM_EGO          0x08
3223 #define RANDOM_ARTIFACT     0x10
3224 #define RANDOM_TRAP         0x20
3225
3226
3227 typedef struct dungeon_grid dungeon_grid;
3228
3229 struct dungeon_grid
3230 {
3231         int             feature;                /* Terrain feature */
3232         int             monster;                /* Monster */
3233         int             object;                 /* Object */
3234         int             ego;                    /* Ego-Item */
3235         int             artifact;               /* Artifact */
3236         int             trap;                   /* Trap */
3237         int             cave_info;              /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3238         int             special;                /* Reserved for special terrain info */
3239         int             random;                 /* Number of the random effect */
3240 };
3241
3242
3243 static dungeon_grid letter[255];
3244
3245
3246 /*
3247  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3248  */
3249 static errr parse_line_feature(char *buf)
3250 {
3251         int num;
3252         char *zz[9];
3253
3254
3255         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3256
3257         /* Tokenize the line */
3258         if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3259         {
3260                 /* Letter to assign */
3261                 int index = zz[0][0];
3262
3263                 /* Reset the info for the letter */
3264                 letter[index].feature = 0;
3265                 letter[index].monster = 0;
3266                 letter[index].object = 0;
3267                 letter[index].ego = 0;
3268                 letter[index].artifact = 0;
3269                 letter[index].trap = 0;
3270                 letter[index].cave_info = 0;
3271                 letter[index].special = 0;
3272                 letter[index].random = 0;
3273
3274                 switch (num)
3275                 {
3276                         /* Special */
3277                         case 9:
3278                                 letter[index].special = atoi(zz[8]);
3279                                 /* Fall through */
3280                         /* Trap */
3281                         case 8:
3282                                 if (zz[7][0] == '*')
3283                                 {
3284                                         letter[index].random |= RANDOM_TRAP;
3285
3286                                         if (zz[7][1])
3287                                         {
3288                                                 zz[7]++;
3289                                                 letter[index].trap = atoi(zz[7]);
3290                                         }
3291                                 }
3292                                 else
3293                                 {
3294                                         letter[index].trap = atoi(zz[7]);
3295                                 }
3296                                 /* Fall through */
3297                         /* Artifact */
3298                         case 7:
3299                                 if (zz[6][0] == '*')
3300                                 {
3301                                         letter[index].random |= RANDOM_ARTIFACT;
3302
3303                                         if (zz[6][1])
3304                                         {
3305                                                 zz[6]++;
3306                                                 letter[index].artifact = atoi(zz[6]);
3307                                         }
3308                                 }
3309                                 else
3310                                 {
3311                                         letter[index].artifact = atoi(zz[6]);
3312                                 }
3313                                 /* Fall through */
3314                         /* Ego-item */
3315                         case 6:
3316                                 if (zz[5][0] == '*')
3317                                 {
3318                                         letter[index].random |= RANDOM_EGO;
3319
3320                                         if (zz[5][1])
3321                                         {
3322                                                 zz[5]++;
3323                                                 letter[index].ego = atoi(zz[5]);
3324                                         }
3325                                 }
3326                                 else
3327                                 {
3328                                         letter[index].ego = atoi(zz[5]);
3329                                 }
3330                                 /* Fall through */
3331                         /* Object */
3332                         case 5:
3333                                 if (zz[4][0] == '*')
3334                                 {
3335                                         letter[index].random |= RANDOM_OBJECT;
3336
3337                                         if (zz[4][1])
3338                                         {
3339                                                 zz[4]++;
3340                                                 letter[index].object = atoi(zz[4]);
3341                                         }
3342                                 }
3343                                 else
3344                                 {
3345                                         letter[index].object = atoi(zz[4]);
3346                                 }
3347                                 /* Fall through */
3348                         /* Monster */
3349                         case 4:
3350                                 if (zz[3][0] == '*')
3351                                 {
3352                                         letter[index].random |= RANDOM_MONSTER;
3353                                         if (zz[3][1])
3354                                         {
3355                                                 zz[3]++;
3356                                                 letter[index].monster = atoi(zz[3]);
3357                                         }
3358                                 }
3359                                 else if (zz[3][0] == 'c')
3360                                 {
3361                                         letter[index].monster = - atoi(zz[3]+1);
3362                                 }
3363                                 else
3364                                 {
3365                                         letter[index].monster = atoi(zz[3]);
3366                                 }
3367                                 /* Fall through */
3368                         /* Cave info */
3369                         case 3:
3370                                 letter[index].cave_info = atoi(zz[2]);
3371                                 /* Fall through */
3372                         /* Feature */
3373                         case 2:
3374                                 if (zz[1][0] == '*')
3375                                 {
3376                                         letter[index].random |= RANDOM_FEATURE;
3377                                         if (zz[1][1])
3378                                         {
3379                                                 zz[1]++;
3380                                                 letter[index].feature = atoi(zz[1]);
3381                                         }
3382                                 }
3383                                 else
3384                                 {
3385                                         letter[index].feature = atoi(zz[1]);
3386                                 }
3387                                 break;
3388                 }
3389
3390                 return (0);
3391         }
3392
3393         return (1);
3394 }
3395
3396
3397 /*
3398  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
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 = letter[idx].feature;
3646
3647                         /* Only the features */
3648                         if (init_flags & INIT_ONLY_FEATURES) continue;
3649
3650                         /* Cave info */
3651                         c_ptr->info = letter[idx].cave_info;
3652
3653                         /* Create a monster */
3654                         if (random & RANDOM_MONSTER)
3655                         {
3656                                 monster_level = base_level + monster_index;
3657
3658                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3659
3660                                 monster_level = base_level;
3661                         }
3662                         else if (monster_index)
3663                         {
3664                                 int old_cur_num, old_max_num;
3665                                 bool clone = FALSE;
3666
3667                                 if (monster_index < 0)
3668                                 {
3669                                         monster_index = -monster_index;
3670                                         clone = TRUE;
3671                                 }
3672                                 old_cur_num = r_info[monster_index].cur_num;
3673                                 old_max_num = r_info[monster_index].max_num;
3674
3675                                 /* Make alive again */
3676                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3677                                 {
3678                                         r_info[monster_index].cur_num = 0;
3679                                         r_info[monster_index].max_num = 1;
3680                                 }
3681
3682                                 /* Make alive again */
3683                                 /* Hack -- Non-unique Nazguls are semi-unique */
3684                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3685                                 {
3686                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3687                                         {
3688                                                 r_info[monster_index].max_num++;
3689                                         }
3690                                 }
3691
3692                                 /* Place it */
3693                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3694                                 if (clone)
3695                                 {
3696                                         /* clone */
3697                                         m_list[hack_m_idx_ii].smart |= SM_CLONED;
3698
3699                                         /* Make alive again for real unique monster */
3700                                         r_info[monster_index].cur_num = old_cur_num;
3701                                         r_info[monster_index].max_num = old_max_num;
3702                                 }
3703                         }
3704
3705                         /* Object (and possible trap) */
3706                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3707                         {
3708                                 object_level = base_level + object_index;
3709
3710                                 /*
3711                                  * Random trap and random treasure defined
3712                                  * 25% chance for trap and 75% chance for object
3713                                  */
3714                                 if (randint0(100) < 75)
3715                                 {
3716                                         place_object(*y, *x, 0L);
3717                                 }
3718                                 else
3719                                 {
3720                                         place_trap(*y, *x);
3721                                 }
3722
3723                                 object_level = base_level;
3724                         }
3725                         else if (random & RANDOM_OBJECT)
3726                         {
3727                                 object_level = base_level + object_index;
3728
3729                                 /* Create an out of deep object */
3730                                 if (randint0(100) < 75)
3731                                         place_object(*y, *x, 0L);
3732                                 else if (randint0(100) < 80)
3733                                         place_object(*y, *x, AM_GOOD);
3734                                 else
3735                                         place_object(*y, *x, AM_GOOD | AM_GREAT);
3736
3737                                 object_level = base_level;
3738                         }
3739                         /* Random trap */
3740                         else if (random & RANDOM_TRAP)
3741                         {
3742                                 place_trap(*y, *x);
3743                         }
3744                         /* Hidden trap (or door) */
3745                         else if (letter[idx].trap)
3746                         {
3747                                 c_ptr->mimic = c_ptr->feat;
3748                                 c_ptr->feat = letter[idx].trap;
3749                         }
3750                         else if (object_index)
3751                         {
3752                                 /* Get local object */
3753                                 object_type *o_ptr = &object_type_body;
3754
3755                                 /* Create the item */
3756                                 object_prep(o_ptr, object_index);
3757
3758                                 if (o_ptr->tval == TV_GOLD)
3759                                 {
3760                                         coin_type = object_index - OBJ_GOLD_LIST;
3761                                         make_gold(o_ptr);
3762                                         coin_type = 0;
3763                                 }
3764
3765                                 /* Apply magic (no messages, no artifacts) */
3766                                 apply_magic(o_ptr, base_level, AM_NO_FIXED_ART | AM_GOOD);
3767
3768                                 drop_here(o_ptr, *y, *x);
3769                         }
3770
3771                         /* Artifact */
3772                         if (artifact_index)
3773                         {
3774                                 if (a_info[artifact_index].cur_num)
3775                                 {
3776                                         int k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
3777                                         object_type forge;
3778                                         object_type *q_ptr = &forge;
3779
3780                                         object_prep(q_ptr, k_idx);
3781
3782                                         /* Drop it in the dungeon */
3783                                         drop_here(q_ptr, *y, *x);
3784                                 }
3785                                 else
3786                                 {
3787                                         /* Create the artifact */
3788                                         create_named_art(artifact_index, *y, *x);
3789
3790                                         a_info[artifact_index].cur_num = 1;
3791                                 }
3792                         }
3793
3794                         /* Terrain special */
3795                         c_ptr->special = letter[idx].special;
3796                 }
3797
3798                 (*y)++;
3799
3800                 return (0);
3801         }
3802
3803         /* Process "Q:<number>:<command>:... -- quest info */
3804         else if (buf[0] == 'Q')
3805         {
3806                 int num;
3807                 quest_type *q_ptr;
3808 #ifdef JP
3809                 if (buf[2] == '$')
3810                         return 0;
3811                 num = tokenize(buf + 2, 33, zz, 0);
3812 #else
3813                 if (buf[2] != '$')
3814                         return 0;
3815                 num = tokenize(buf + 3, 33, zz, 0);
3816 #endif
3817
3818                 /* Have we enough parameters? */
3819                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3820
3821                 /* Get the quest */
3822                 q_ptr = &(quest[atoi(zz[0])]);
3823
3824                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3825                 if (zz[1][0] == 'Q')
3826                 {
3827                         if (init_flags & INIT_ASSIGN)
3828                         {
3829                                 monster_race *r_ptr;
3830                                 artifact_type *a_ptr;
3831
3832                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3833
3834                                 q_ptr->type    = atoi(zz[2]);
3835                                 q_ptr->num_mon = atoi(zz[3]);
3836                                 q_ptr->cur_num = atoi(zz[4]);
3837                                 q_ptr->max_num = atoi(zz[5]);
3838                                 q_ptr->level   = atoi(zz[6]);
3839                                 q_ptr->r_idx   = atoi(zz[7]);
3840                                 q_ptr->k_idx   = atoi(zz[8]);
3841                                 q_ptr->dungeon = atoi(zz[9]);
3842
3843                                 if (num > 10)
3844                                         q_ptr->flags  = atoi(zz[10]);
3845
3846                                 r_ptr = &r_info[q_ptr->r_idx];
3847                                 if (r_ptr->flags1 & RF1_UNIQUE)
3848                                         r_ptr->flags1 |= RF1_QUESTOR;
3849
3850                                 a_ptr = &a_info[q_ptr->k_idx];
3851                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3852                         }
3853                         return (0);
3854                 }
3855
3856                 /* Process "Q:<q_index>:N:<name>" -- quest name */
3857                 else if (zz[1][0] == 'N')
3858                 {
3859                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3860                         {
3861                                 strcpy(q_ptr->name, zz[2]);
3862                         }
3863
3864                         return (0);
3865                 }
3866
3867                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3868                 else if (zz[1][0] == 'T')
3869                 {
3870                         if (init_flags & INIT_SHOW_TEXT)
3871                         {
3872                                 strcpy(quest_text[quest_text_line], zz[2]);
3873                                 quest_text_line++;
3874                         }
3875
3876                         return (0);
3877                 }
3878         }
3879
3880         /* Process "W:<command>: ..." -- info for the wilderness */
3881         else if (buf[0] == 'W')
3882         {
3883                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3884         }
3885
3886         /* Process "P:<y>:<x>" -- player position */
3887         else if (buf[0] == 'P')
3888         {
3889                 if (init_flags & INIT_CREATE_DUNGEON)
3890                 {
3891                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3892                         {
3893                                 int panels_x, panels_y;
3894
3895                                 /* Hack - Set the dungeon size */
3896                                 panels_y = (*y / SCREEN_HGT);
3897                                 if (*y % SCREEN_HGT) panels_y++;
3898                                 cur_hgt = panels_y * SCREEN_HGT;
3899
3900                                 panels_x = (*x / SCREEN_WID);
3901                                 if (*x % SCREEN_WID) panels_x++;
3902                                 cur_wid = panels_x * SCREEN_WID;
3903
3904                                 /* Assume illegal panel */
3905                                 panel_row_min = cur_hgt;
3906                                 panel_col_min = cur_wid;
3907
3908                                 /* Place player in a quest level */
3909                                 if (p_ptr->inside_quest)
3910                                 {
3911                                         int y, x;
3912
3913                                         /* Delete the monster (if any) */
3914                                         delete_monster(py, px);
3915
3916                                         y = atoi(zz[0]);
3917                                         x = atoi(zz[1]);
3918
3919                                         py = y;
3920                                         px = x;
3921                                 }
3922                                 /* Place player in the town */
3923                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3924                                 {
3925                                         p_ptr->oldpy = atoi(zz[0]);
3926                                         p_ptr->oldpx = atoi(zz[1]);
3927                                 }
3928                         }
3929                 }
3930
3931                 return (0);
3932         }
3933
3934         /* Process "B:<Index>:<Command>:..." -- Building definition */
3935         else if (buf[0] == 'B')
3936         {
3937                 return parse_line_building(buf);
3938         }
3939
3940         /* Process "M:<type>:<maximum>" -- set maximum values */
3941         else if (buf[0] == 'M')
3942         {
3943                 if (tokenize(buf+2, 2, zz, 0) == 2)
3944                 {
3945                         /* Maximum towns */
3946                         if (zz[0][0] == 'T')
3947                         {
3948                                 max_towns = atoi(zz[1]);
3949                         }
3950
3951                         /* Maximum quests */
3952                         else if (zz[0][0] == 'Q')
3953                         {
3954                                 max_quests = atoi(zz[1]);
3955                         }
3956
3957                         /* Maximum r_idx */
3958                         else if (zz[0][0] == 'R')
3959                         {
3960                                 max_r_idx = atoi(zz[1]);
3961                         }
3962
3963                         /* Maximum k_idx */
3964                         else if (zz[0][0] == 'K')
3965                         {
3966                                 max_k_idx = atoi(zz[1]);
3967                         }
3968
3969                         /* Maximum v_idx */
3970                         else if (zz[0][0] == 'V')
3971                         {
3972                                 max_v_idx = atoi(zz[1]);
3973                         }
3974
3975                         /* Maximum f_idx */
3976                         else if (zz[0][0] == 'F')
3977                         {
3978                                 max_f_idx = atoi(zz[1]);
3979                         }
3980
3981                         /* Maximum a_idx */
3982                         else if (zz[0][0] == 'A')
3983                         {
3984                                 max_a_idx = atoi(zz[1]);
3985                         }
3986
3987                         /* Maximum e_idx */
3988                         else if (zz[0][0] == 'E')
3989                         {
3990                                 max_e_idx = atoi(zz[1]);
3991                         }
3992
3993                         /* Maximum d_idx */
3994                         else if (zz[0][0] == 'D')
3995                         {
3996                                 max_d_idx = atoi(zz[1]); 
3997                         }
3998
3999                         /* Maximum o_idx */
4000                         else if (zz[0][0] == 'O')
4001                         {
4002                                 max_o_idx = atoi(zz[1]);
4003                         }
4004
4005                         /* Maximum m_idx */
4006                         else if (zz[0][0] == 'M')
4007                         {
4008                                 max_m_idx = atoi(zz[1]);
4009                         }
4010
4011                         /* Wilderness size */
4012                         else if (zz[0][0] == 'W')
4013                         {
4014                                 /* Maximum wild_x_size */
4015                                 if (zz[0][1] == 'X')
4016                                         max_wild_x = atoi(zz[1]);
4017                                 /* Maximum wild_y_size */
4018                                 if (zz[0][1] == 'Y')
4019                                         max_wild_y = atoi(zz[1]);
4020                         }
4021
4022                         return (0);
4023                 }
4024         }
4025
4026
4027         /* Failure */
4028         return (1);
4029 }
4030
4031
4032 static char tmp[8];
4033 static cptr variant = "ZANGBAND";
4034
4035
4036 /*
4037  * Helper function for "process_dungeon_file()"
4038  */
4039 static cptr process_dungeon_file_expr(char **sp, char *fp)
4040 {
4041         cptr v;
4042
4043         char *b;
4044         char *s;
4045
4046         char b1 = '[';
4047         char b2 = ']';
4048
4049         char f = ' ';
4050
4051         /* Initial */
4052         s = (*sp);
4053
4054         /* Skip spaces */
4055         while (isspace(*s)) s++;
4056
4057         /* Save start */
4058         b = s;
4059
4060         /* Default */
4061         v = "?o?o?";
4062
4063         /* Analyze */
4064         if (*s == b1)
4065         {
4066                 const char *p;
4067                 const char *t;
4068
4069                 /* Skip b1 */
4070                 s++;
4071
4072                 /* First */
4073                 t = process_dungeon_file_expr(&s, &f);
4074
4075                 /* Oops */
4076                 if (!*t)
4077                 {
4078                         /* Nothing */
4079                 }
4080
4081                 /* Function: IOR */
4082                 else if (streq(t, "IOR"))
4083                 {
4084                         v = "0";
4085                         while (*s && (f != b2))
4086                         {
4087                                 t = process_dungeon_file_expr(&s, &f);
4088                                 if (*t && !streq(t, "0")) v = "1";
4089                         }
4090                 }
4091
4092                 /* Function: AND */
4093                 else if (streq(t, "AND"))
4094                 {
4095                         v = "1";
4096                         while (*s && (f != b2))
4097                         {
4098                                 t = process_dungeon_file_expr(&s, &f);
4099                                 if (*t && streq(t, "0")) v = "0";
4100                         }
4101                 }
4102
4103                 /* Function: NOT */
4104                 else if (streq(t, "NOT"))
4105                 {
4106                         v = "1";
4107                         while (*s && (f != b2))
4108                         {
4109                                 t = process_dungeon_file_expr(&s, &f);
4110                                 if (*t && streq(t, "1")) v = "0";
4111                         }
4112                 }
4113
4114                 /* Function: EQU */
4115                 else if (streq(t, "EQU"))
4116                 {
4117                         v = "0";
4118                         if (*s && (f != b2))
4119                         {
4120                                 t = process_dungeon_file_expr(&s, &f);
4121                         }
4122                         while (*s && (f != b2))
4123                         {
4124                                 p = process_dungeon_file_expr(&s, &f);
4125                                 if (streq(t, p)) v = "1";
4126                         }
4127                 }
4128
4129                 /* Function: LEQ */
4130                 else if (streq(t, "LEQ"))
4131                 {
4132                         v = "1";
4133                         if (*s && (f != b2))
4134                         {
4135                                 t = process_dungeon_file_expr(&s, &f);
4136                         }
4137                         while (*s && (f != b2))
4138                         {
4139                                 p = t;
4140                                 t = process_dungeon_file_expr(&s, &f);
4141                                 if (*t && atoi(p) > atoi(t)) v = "0";
4142                         }
4143                 }
4144
4145                 /* Function: GEQ */
4146                 else if (streq(t, "GEQ"))
4147                 {
4148                         v = "1";
4149                         if (*s && (f != b2))
4150                         {
4151                                 t = process_dungeon_file_expr(&s, &f);
4152                         }
4153                         while (*s && (f != b2))
4154                         {
4155                                 p = t;
4156                                 t = process_dungeon_file_expr(&s, &f);
4157
4158                                 /* Compare two numbers instead of string */
4159                                 if (*t && atoi(p) < atoi(t)) v = "0";
4160                         }
4161                 }
4162
4163                 /* Oops */
4164                 else
4165                 {
4166                         while (*s && (f != b2))
4167                         {
4168                                 t = process_dungeon_file_expr(&s, &f);
4169                         }
4170                 }
4171
4172                 /* Verify ending */
4173                 if (f != b2) v = "?x?x?";
4174
4175                 /* Extract final and Terminate */
4176                 if ((f = *s) != '\0') *s++ = '\0';
4177         }
4178
4179         /* Other */
4180         else
4181         {
4182                 /* Accept all printables except spaces and brackets */
4183                 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
4184
4185                 /* Extract final and Terminate */
4186                 if ((f = *s) != '\0') *s++ = '\0';
4187
4188                 /* Variable */
4189                 if (*b == '$')
4190                 {
4191                         /* System */
4192                         if (streq(b+1, "SYS"))
4193                         {
4194                                 v = ANGBAND_SYS;
4195                         }
4196
4197                         /* Graphics */
4198                         else if (streq(b+1, "GRAF"))
4199                         {
4200                                 v = ANGBAND_GRAF;
4201                         }
4202
4203                         else if (streq(b+1, "MONOCHROME"))
4204                         {
4205                                 if (arg_monochrome)
4206                                         v = "ON";
4207                                 else
4208                                         v = "OFF";
4209                         }
4210
4211                         /* Race */
4212                         else if (streq(b+1, "RACE"))
4213                         {
4214 #ifdef JP
4215                                 v = rp_ptr->E_title;
4216 #else
4217                                 v = rp_ptr->title;
4218 #endif
4219                         }
4220
4221                         /* Class */
4222                         else if (streq(b+1, "CLASS"))
4223                         {
4224 #ifdef JP
4225                                 v = cp_ptr->E_title;
4226 #else
4227                                 v = cp_ptr->title;
4228 #endif
4229                         }
4230
4231                         /* First realm */
4232                         else if (streq(b+1, "REALM1"))
4233                         {
4234 #ifdef JP
4235                                 v = E_realm_names[p_ptr->realm1];
4236 #else
4237                                 v = realm_names[p_ptr->realm1];
4238 #endif
4239                         }
4240
4241                         /* Second realm */
4242                         else if (streq(b+1, "REALM2"))
4243                         {
4244 #ifdef JP
4245                                 v = E_realm_names[p_ptr->realm2];
4246 #else
4247                                 v = realm_names[p_ptr->realm2];
4248 #endif
4249                         }
4250
4251                         /* Player name */
4252                         else if (streq(b+1, "PLAYER"))
4253                         {
4254                                 v = player_base;
4255                         }
4256
4257                         /* Town */
4258                         else if (streq(b+1, "TOWN"))
4259                         {
4260                                 sprintf(tmp, "%d", p_ptr->town_num);
4261                                 v = tmp;
4262                         }
4263
4264                         /* Level */
4265                         else if (streq(b+1, "LEVEL"))
4266                         {
4267                                 sprintf(tmp, "%d", p_ptr->lev);
4268                                 v = tmp;
4269                         }
4270
4271                         /* Current quest number */
4272                         else if (streq(b+1, "QUEST_NUMBER"))
4273                         {
4274                                 sprintf(tmp, "%d", p_ptr->inside_quest);
4275                                 v = tmp;
4276                         }
4277
4278                         /* Number of last quest */
4279                         else if (streq(b+1, "LEAVING_QUEST"))
4280                         {
4281                                 sprintf(tmp, "%d", leaving_quest);
4282                                 v = tmp;
4283                         }
4284
4285                         /* Quest status */
4286                         else if (prefix(b+1, "QUEST"))
4287                         {
4288                                 /* "QUEST" uses a special parameter to determine the number of the quest */
4289                                 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4290                                 v = tmp;
4291                         }
4292
4293                         /* Random */
4294                         else if (prefix(b+1, "RANDOM"))
4295                         {
4296                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
4297                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4298                                 v = tmp;
4299                         }
4300
4301                         /* Variant name */
4302                         else if (streq(b+1, "VARIANT"))
4303                         {
4304                                 v = variant;
4305                         }
4306
4307                         /* Wilderness */
4308                         else if (streq(b+1, "WILDERNESS"))
4309                         {
4310                                 if (vanilla_town)
4311                                         sprintf(tmp, "NONE");
4312                                 else if (lite_town)
4313                                         sprintf(tmp, "LITE");
4314                                 else
4315                                         sprintf(tmp, "NORMAL");
4316                                 v = tmp;
4317                         }
4318                 }
4319
4320                 /* Constant */
4321                 else
4322                 {
4323                         v = b;
4324                 }
4325         }
4326
4327         /* Save */
4328         (*fp) = f;
4329
4330         /* Save */
4331         (*sp) = s;
4332
4333         /* Result */
4334         return (v);
4335 }
4336
4337
4338 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4339 {
4340         FILE *fp;
4341
4342         char buf[1024];
4343
4344         int num = -1;
4345
4346         errr err = 0;
4347
4348         bool bypass = FALSE;
4349
4350         int x = xmin, y = ymin;
4351
4352
4353         /* Build the filename */
4354         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
4355
4356         /* Open the file */
4357         fp = my_fopen(buf, "r");
4358
4359         /* No such file */
4360         if (!fp) return (-1);
4361
4362
4363         /* Process the file */
4364         while (0 == my_fgets(fp, buf, sizeof(buf)))
4365         {
4366                 /* Count lines */
4367                 num++;
4368
4369
4370                 /* Skip "empty" lines */
4371                 if (!buf[0]) continue;
4372
4373                 /* Skip "blank" lines */
4374                 if (isspace(buf[0])) continue;
4375
4376                 /* Skip comments */
4377                 if (buf[0] == '#') continue;
4378
4379
4380                 /* Process "?:<expr>" */
4381                 if ((buf[0] == '?') && (buf[1] == ':'))
4382                 {
4383                         char f;
4384                         cptr v;
4385                         char *s;
4386
4387                         /* Start */
4388                         s = buf + 2;
4389
4390                         /* Parse the expr */
4391                         v = process_dungeon_file_expr(&s, &f);
4392
4393                         /* Set flag */
4394                         bypass = (streq(v, "0") ? TRUE : FALSE);
4395
4396                         /* Continue */
4397                         continue;
4398                 }
4399
4400                 /* Apply conditionals */
4401                 if (bypass) continue;
4402
4403                 /* Process the line */
4404                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4405
4406                 /* Oops */
4407                 if (err) break;
4408         }
4409
4410         /* Errors */
4411         if (err)
4412         {
4413                 cptr oops;
4414
4415                 /* Error string */
4416                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4417
4418                 /* Oops */
4419                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4420 #ifdef JP
4421 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4422 #else
4423                 msg_format("Parsing '%s'.", buf);
4424 #endif
4425
4426                 msg_print(NULL);
4427         }
4428
4429
4430         /* Close the file */
4431         my_fclose(fp);
4432
4433         /* Result */
4434         return (err);
4435 }
4436
4437
4438
4439 #if 0
4440 void write_r_info_txt(void)
4441 {
4442         int i, j, z, fc, bc;
4443         int dlen;
4444
4445         cptr flags[32 * 10];
4446
4447         u32b f_ptr[10];
4448         cptr *n_ptr[10];
4449
4450         monster_race *r_ptr;
4451
4452         monster_blow *b_ptr;
4453
4454         FILE *fff = fopen("output.txt", "wt");
4455
4456         cptr desc;
4457
4458         int mode = -1;
4459
4460         if (!fff) return;
4461
4462         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4463
4464         fprintf(fff, "# Version stamp (required)\n\n");
4465
4466         /* Write Version */
4467         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4468
4469         /* Write a note */
4470         fprintf(fff, "##### The Player #####\n\n");
4471
4472         for (z = -1; z < alloc_race_size; z++)
4473         {
4474                 /* Output the monsters in order */
4475                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4476
4477                 /* Acquire the monster */
4478                 r_ptr = &r_info[i];
4479
4480                 /* Ignore empty monsters */
4481                 if (!strlen(r_name + r_ptr->name)) continue;
4482
4483                 /* Ignore useless monsters */
4484                 if (i && !r_ptr->speed) continue;
4485
4486                 /* Write a note if necessary */
4487                 if (i && (!r_ptr->level != !mode))
4488                 {
4489                         /* Note the town */
4490                         if (!r_ptr->level)
4491                         {
4492                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4493                         }
4494                         /* Note the dungeon */
4495                         else
4496                         {
4497                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4498                         }
4499
4500                         /* Record the change */
4501                         mode = r_ptr->level;
4502                 }
4503
4504                 /* Acquire the flags */
4505                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4506                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4507                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4508                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4509                 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4510                 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4511                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4512                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4513                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4514                 f_ptr[9] = r_ptr->flagsr; n_ptr[9] = r_info_flagsr;
4515
4516                 /* Write New/Number/Name */
4517                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4518
4519                 /* Write Graphic */
4520                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4521
4522                 /* Write Information */
4523                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4524                                                                                                                   r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4525
4526                 /* Write more information */
4527                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4528
4529                 /* Write Blows */
4530                 for(j = 0; j < 4; j++)
4531                 {
4532                         b_ptr = &(r_ptr->blow[j]);
4533
4534                         /* Stop when done */
4535                         if (!b_ptr->method) break;
4536
4537                         /* Write the blows */
4538                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4539                                                                                                           r_info_blow_effect[b_ptr->effect],
4540                                                                                                           b_ptr->d_dice, b_ptr->d_side);
4541                 }
4542
4543                 /* Extract the flags */
4544                 for (fc = 0, j = 0; j < 32 * 3; j++)
4545                 {
4546                         /* Check this flag */
4547                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4548                 }
4549
4550                 /* Extract the extra flags */
4551                 for (j = 32 * 6; j < 32 * 10; j++)
4552                 {
4553                         /* Check this flag */
4554                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4555                 }
4556
4557                 /* Write the flags */
4558                 for (j = 0; j < fc;)
4559                 {
4560                         char buf[160];
4561
4562                         /* Start the line */
4563                         sprintf(buf, "F:");
4564
4565                         for (bc = 0; (bc < 60) && (j < fc); j++)
4566                         {
4567                                 char t[80];
4568
4569                                 /* Format the flag */
4570                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4571
4572                                 /* Add it to the buffer */
4573                                 strcat(buf, t);
4574
4575                                 /* Note the length */
4576                                 bc += strlen(t);
4577                         }
4578
4579                         /* Done with this line; write it */
4580                         fprintf(fff, "%s\n", buf);
4581                 }
4582
4583                 /* Write Spells if applicable */
4584                 if (r_ptr->freq_spell)
4585                 {
4586                         /* Write the frequency */
4587                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4588
4589                         /* Extract the spell flags */
4590                         for (fc = 0, j = 96; j < 192; j++)
4591                         {
4592                                 /* Check this flag */
4593                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4594                         }
4595
4596                         /* Write the flags */
4597                         for (j = 0; j < fc;)
4598                         {
4599                                 char buf[160], *t;
4600
4601                                 /* Start the line */
4602                                 sprintf(buf, "S:");
4603
4604                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4605                                 {
4606                                         int tlen;
4607
4608                                         /* Format the flag */
4609                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4610
4611                                         tlen = strlen(t);
4612
4613                                         /* Note the length */
4614                                         bc += tlen;
4615
4616                                         /* Advance */
4617                                         t += tlen;
4618                                 }
4619
4620                                 /* Done with this line; write it */
4621                                 fprintf(fff, "%s\n", buf);
4622                         }
4623                 }
4624
4625                 /* Acquire the description */
4626                 desc = r_text + r_ptr->text;
4627                 dlen = strlen(desc);
4628
4629                 /* Write Description */
4630                 for (j = 0; j < dlen;)
4631                 {
4632                         char buf[160], *t;
4633
4634                         /* Start the line */
4635                         sprintf(buf, "D:");
4636
4637                         for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4638                         {
4639                                 *t = desc[j];
4640                         }
4641
4642                         /* Terminate it */
4643                         *t = '\0';
4644
4645                         /* Done with this line; write it */
4646                         fprintf(fff, "%s\n", buf);
4647                 }
4648
4649                 /* Space between entries */
4650                 fprintf(fff, "\n");
4651         }
4652
4653         /* Done */
4654         fclose(fff);
4655 }
4656
4657 #endif