OSDN Git Service

b6776743d77fd90a1d679b3f37c7083704ce73e0
[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         "LEVITATION",
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 s_attr;
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                 s_attr = color_char_to_attr(buf[4]);
1545
1546                 /* Paranoia */
1547                 if (s_attr > 127) return (1);
1548
1549                 /* Save the standard values */
1550                 f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
1551                 f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
1552
1553                 /* Is this feature supports lighting? */
1554                 if (buf[5] == ':')
1555                 {
1556                         /* G:c:a:LIT (default) */
1557                         apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
1558
1559                         /* G:c:a:lc:la:dc:da */
1560                         if (!streq(buf + 6, "LIT"))
1561                         {
1562                                 char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
1563
1564                                 if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
1565                                         &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
1566                                         &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
1567                                 if (buf[F_LIT_MAX * 4 + 1]) return 1;
1568
1569                                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1570                                 {
1571                                         switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
1572                                         {
1573                                         case '*':
1574                                                 /* Use default lighting */
1575                                                 break;
1576                                         case '-':
1577                                                 /* No lighting support */
1578                                                 f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
1579                                                 break;
1580                                         default:
1581                                                 /* Extract the color */
1582                                                 f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
1583                                                 if (f_ptr->d_attr[j] > 127) return 1;
1584                                                 break;
1585                                         }
1586                                         f_ptr->d_char[j] = char_tmp[j];
1587                                 }
1588                         }
1589                 }
1590                 else if (!buf[5])
1591                 {
1592                         for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1593                         {
1594                                 f_ptr->d_attr[j] = s_attr;
1595                                 f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
1596                         }
1597                 }
1598                 else return 1;
1599         }
1600
1601         /* Hack -- Process 'F' for flags */
1602         else if (buf[0] == 'F')
1603         {
1604                 /* Parse every entry textually */
1605                 for (s = buf + 2; *s; )
1606                 {
1607                         /* Find the end of this entry */
1608                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1609
1610                         /* Nuke and skip any dividers */
1611                         if (*t)
1612                         {
1613                                 *t++ = '\0';
1614                                 while (*t == ' ' || *t == '|') t++;
1615                         }
1616
1617                         /* XXX XXX XXX Hack -- Read feature power */
1618                         if (1 == sscanf(s, "POWER_%d", &i))
1619                         {
1620                                 /* Extract a "power" */
1621                                 f_ptr->power =  i;
1622
1623                                 /* Start at next entry */
1624                                 s = t;
1625
1626                                 /* Continue */
1627                                 continue;
1628                         }
1629
1630                         /* Parse this entry */
1631                         if (0 != grab_one_feat_flag(f_ptr, s)) return (PARSE_ERROR_INVALID_FLAG);
1632
1633                         /* Start the next entry */
1634                         s = t;
1635                 }
1636         }
1637
1638         /* Process 'W' for "More Info" (one line only) */
1639         else if (buf[0] == 'W')
1640         {
1641                 int priority;
1642
1643                 /* Scan for the value */
1644                 if (1 != sscanf(buf+2, "%d", &priority)) return (PARSE_ERROR_GENERIC);
1645
1646                 /* Save the value */
1647                 f_ptr->priority = priority;
1648         }
1649
1650         /* Process 'K' for "States" (up to four lines + default (which cannot be last)) */
1651         else if (buf[0] == 'K')
1652         {
1653                 s16b offset;
1654
1655                 /* Find the next empty state slot (if any) */
1656                 for (i = 0; i < MAX_FEAT_STATES; i++) if (f_ptr->state[i].action == FF_FLAG_MAX) break;
1657
1658                 /* Oops, no more slots */
1659                 if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
1660
1661                 /* Analyze the first field */
1662                 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
1663
1664                 /* Terminate the field (if necessary) */
1665                 if (*t == ':') *t++ = '\0';
1666
1667                 /* Is this default entry? */
1668                 if (streq(s, "DESTROYED"))
1669                 {
1670                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1671
1672                         /* Record a fake tag index */
1673                         f_ptr->destroyed = -offset;
1674                 }
1675                 else
1676                 {
1677                         /* Reset */
1678                         f_ptr->state[i].action = 0;
1679
1680                         /* Parse this entry */
1681                         if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
1682
1683                         if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
1684
1685                         /* Record a fake tag index */
1686                         f_ptr->state[i].result = -offset;
1687                 }
1688         }
1689
1690         /* Oops */
1691         else    return (6);
1692
1693         /* Success */
1694         return (0);
1695 }
1696
1697
1698 /*
1699  * Convert a fake tag to a real feat index
1700  */
1701 s16b f_tag_to_index(cptr str)
1702 {
1703         u16b i;
1704
1705         /* Search for real index corresponding to this fake tag */
1706         for (i = 0; i < f_head.info_num; i++)
1707         {
1708                 if (streq(f_tag + f_info[i].tag, str))
1709                 {
1710                         /* Return the index */
1711                         return (s16b)i;
1712                 }
1713         }
1714
1715         /* Not found */
1716         return -1;
1717 }
1718
1719
1720 /*
1721  * Search for real index corresponding to this fake tag
1722  */
1723 static void search_real_feat(s16b *feat)
1724 {
1725         int i;
1726
1727         /* Don't convert non-fake tag */
1728         if (*feat >= 0) return;
1729
1730         /* Search for real index corresponding to this fake tag */
1731         for (i = 0; i < f_head.info_num; i++)
1732         {
1733                 if ((-(*feat)) == f_info[i].tag)
1734                 {
1735                         /* Record real index */
1736                         *feat = (s16b)i;
1737                         return;
1738                 }
1739         }
1740
1741         /* Undefined tag */
1742 #ifdef JP
1743         msg_format("̤ÄêµÁ¤Î¥¿¥° '%s'¡£", f_tag + (-(*feat)));
1744 #else
1745         msg_format("%s is undefined.", f_tag + (-(*feat)));
1746 #endif
1747 }
1748
1749
1750 /*
1751  * Retouch fake tags of f_info
1752  */
1753 void retouch_f_info(header *head)
1754 {
1755         int i;
1756
1757         /* Convert fake tags to real feat indices */
1758         for (i = 0; i < head->info_num; i++)
1759         {
1760                 feature_type *f_ptr = &f_info[i];
1761                 int j;
1762
1763                 search_real_feat(&f_ptr->mimic);
1764
1765                 search_real_feat(&f_ptr->destroyed);
1766
1767                 for (j = 0; j < MAX_FEAT_STATES; j++) search_real_feat(&f_ptr->state[j].result);
1768         }
1769 }
1770
1771
1772 /*
1773  * Grab one flag in an object_kind from a textual string
1774  */
1775 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1776 {
1777         int i;
1778
1779         /* Check flags */
1780         for (i = 0; i < TR_FLAG_MAX; i++)
1781         {
1782                 if (streq(what, k_info_flags[i]))
1783                 {
1784                         add_flag(k_ptr->flags, i);
1785                         return (0);
1786                 }
1787         }
1788
1789         if (grab_one_flag(&k_ptr->gen_flags, k_info_gen_flags, what) == 0)
1790                 return 0;
1791
1792         /* Oops */
1793 #ifdef JP
1794         msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1795 #else
1796         msg_format("Unknown object flag '%s'.", what);
1797 #endif
1798
1799
1800         /* Error */
1801         return (1);
1802 }
1803
1804
1805 /*
1806  * Initialize the "k_info" array, by parsing an ascii "template" file
1807  */
1808 errr parse_k_info(char *buf, header *head)
1809 {
1810         int i;
1811
1812         char *s, *t;
1813
1814         /* Current entry */
1815         static object_kind *k_ptr = NULL;
1816
1817
1818         /* Process 'N' for "New/Number/Name" */
1819         if (buf[0] == 'N')
1820         {
1821                 /* Find the colon before the name */
1822                 s = my_strchr(buf+2, ':');
1823
1824                         /* Verify that colon */
1825                 if (!s) return (1);
1826
1827                 /* Nuke the colon, advance to the name */
1828                 *s++ = '\0';
1829
1830 #ifdef JP
1831                 /* Paranoia -- require a name */
1832                 if (!*s) return (1);
1833 #endif
1834                 /* Get the index */
1835                 i = atoi(buf+2);
1836
1837                 /* Verify information */
1838                 if (i <= error_idx) return (4);
1839
1840                 /* Verify information */
1841                 if (i >= head->info_num) return (2);
1842
1843                 /* Save the index */
1844                 error_idx = i;
1845
1846                 /* Point at the "info" */
1847                 k_ptr = &k_info[i];
1848
1849 #ifdef JP
1850                 /* Store the name */
1851                 if (!add_name(&k_ptr->name, head, s)) return (7);
1852 #endif
1853         }
1854
1855         /* There better be a current k_ptr */
1856         else if (!k_ptr) return (3);
1857
1858
1859 #ifdef JP
1860         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
1861         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1862         else if (buf[0] == 'E')
1863         {
1864                 /* nothing to do */
1865         }
1866 #else
1867         else if (buf[0] == 'E')
1868         {
1869                 /* Acquire the Text */
1870                 s = buf+2;
1871
1872                 /* Store the name */
1873                 if (!add_name(&k_ptr->name, head, s)) return (7);
1874         }
1875 #endif
1876
1877         /* Process 'D' for "Description" */
1878         else if (buf[0] == 'D')
1879         {
1880 #ifdef JP
1881                 if (buf[2] == '$')
1882                         return (0);
1883                 /* Acquire the text */
1884                 s = buf+2;
1885 #else
1886                 if (buf[2] != '$')
1887                         return (0);
1888                 /* Acquire the text */
1889                 s = buf+3;
1890 #endif
1891
1892                 /* Store the text */
1893                 if (!add_text(&k_ptr->text, head, s)) return (7);
1894         }
1895
1896         /* Process 'G' for "Graphics" (one line only) */
1897         else if (buf[0] == 'G')
1898         {
1899                 char sym;
1900                 byte tmp;
1901
1902                 /* Paranoia */
1903                 if (buf[1] != ':') return (1);
1904                 if (!buf[2]) return (1);
1905                 if (buf[3] != ':') return (1);
1906                 if (!buf[4]) return (1);
1907
1908                 /* Extract the char */
1909                 sym = buf[2];
1910
1911                 /* Extract the attr */
1912                 tmp = color_char_to_attr(buf[4]);
1913
1914                 /* Paranoia */
1915                 if (tmp > 127) return (1);
1916
1917                 /* Save the values */
1918                 k_ptr->d_attr = tmp;
1919                 k_ptr->d_char = sym;
1920         }
1921
1922         /* Process 'I' for "Info" (one line only) */
1923         else if (buf[0] == 'I')
1924         {
1925                 int tval, sval, pval;
1926
1927                 /* Scan for the values */
1928                 if (3 != sscanf(buf+2, "%d:%d:%d",
1929                                 &tval, &sval, &pval)) return (1);
1930
1931                 /* Save the values */
1932                 k_ptr->tval = tval;
1933                 k_ptr->sval = sval;
1934                 k_ptr->pval = pval;
1935         }
1936
1937         /* Process 'W' for "More Info" (one line only) */
1938         else if (buf[0] == 'W')
1939         {
1940                 int level, extra, wgt;
1941                 long cost;
1942
1943                 /* Scan for the values */
1944                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1945                                 &level, &extra, &wgt, &cost)) return (1);
1946
1947                 /* Save the values */
1948                 k_ptr->level = level;
1949                 k_ptr->extra = extra;
1950                 k_ptr->weight = wgt;
1951                 k_ptr->cost = cost;
1952         }
1953
1954         /* Process 'A' for "Allocation" (one line only) */
1955         else if (buf[0] == 'A')
1956         {
1957                 int i;
1958
1959                 /* XXX XXX XXX Simply read each number following a colon */
1960                 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1961                 {
1962                                 /* Default chance */
1963                         k_ptr->chance[i] = 1;
1964
1965                                 /* Store the attack damage index */
1966                         k_ptr->locale[i] = atoi(s+1);
1967
1968                                 /* Find the slash */
1969                         t = my_strchr(s+1, '/');
1970
1971                                 /* Find the next colon */
1972                         s = my_strchr(s+1, ':');
1973
1974                                 /* If the slash is "nearby", use it */
1975                         if (t && (!s || t < s))
1976                         {
1977                                 int chance = atoi(t+1);
1978                                 if (chance > 0) k_ptr->chance[i] = chance;
1979                         }
1980                 }
1981         }
1982
1983         /* Hack -- Process 'P' for "power" and such */
1984         else if (buf[0] == 'P')
1985         {
1986                 int ac, hd1, hd2, th, td, ta;
1987
1988                 /* Scan for the values */
1989                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1990                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1991
1992                 k_ptr->ac = ac;
1993                 k_ptr->dd = hd1;
1994                 k_ptr->ds = hd2;
1995                 k_ptr->to_h = th;
1996                 k_ptr->to_d = td;
1997                 k_ptr->to_a =  ta;
1998         }
1999
2000         /* Hack -- Process 'F' for flags */
2001         else if (buf[0] == 'F')
2002         {
2003                 /* Parse every entry textually */
2004                 for (s = buf + 2; *s; )
2005                 {
2006                                 /* Find the end of this entry */
2007                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2008
2009                                 /* Nuke and skip any dividers */
2010                         if (*t)
2011                         {
2012                                 *t++ = '\0';
2013                                 while (*t == ' ' || *t == '|') t++;
2014                         }
2015
2016                                 /* Parse this entry */
2017                         if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
2018
2019                                 /* Start the next entry */
2020                         s = t;
2021                 }
2022         }
2023
2024
2025         /* Oops */
2026         else return (6);
2027
2028
2029         /* Success */
2030         return (0);
2031 }
2032
2033
2034 /*
2035  * Grab one flag in an artifact_type from a textual string
2036  */
2037 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
2038 {
2039         int i;
2040
2041         /* Check flags */
2042         for (i = 0; i < TR_FLAG_MAX; i++)
2043         {
2044                 if (streq(what, k_info_flags[i]))
2045                 {
2046                         add_flag(a_ptr->flags, i);
2047                         return (0);
2048                 }
2049         }
2050
2051         if (grab_one_flag(&a_ptr->gen_flags, k_info_gen_flags, what) == 0)
2052                 return 0;
2053
2054         /* Oops */
2055 #ifdef JP
2056         msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
2057 #else
2058         msg_format("Unknown artifact flag '%s'.", what);
2059 #endif
2060
2061
2062         /* Error */
2063         return (1);
2064 }
2065
2066
2067
2068
2069 /*
2070  * Initialize the "a_info" array, by parsing an ascii "template" file
2071  */
2072 errr parse_a_info(char *buf, header *head)
2073 {
2074         int i;
2075
2076         char *s, *t;
2077
2078         /* Current entry */
2079         static artifact_type *a_ptr = NULL;
2080
2081
2082         /* Process 'N' for "New/Number/Name" */
2083         if (buf[0] == 'N')
2084         {
2085                 /* Find the colon before the name */
2086                 s = my_strchr(buf+2, ':');
2087
2088                         /* Verify that colon */
2089                 if (!s) return (1);
2090
2091                 /* Nuke the colon, advance to the name */
2092                 *s++ = '\0';
2093 #ifdef JP
2094                 /* Paranoia -- require a name */
2095                 if (!*s) return (1);
2096 #endif
2097                 /* Get the index */
2098                 i = atoi(buf+2);
2099
2100                 /* Verify information */
2101                 if (i < error_idx) return (4);
2102
2103                 /* Verify information */
2104                 if (i >= head->info_num) return (2);
2105
2106                 /* Save the index */
2107                 error_idx = i;
2108
2109                 /* Point at the "info" */
2110                 a_ptr = &a_info[i];
2111
2112                 /* Ignore everything */
2113                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
2114                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
2115                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
2116                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
2117 #ifdef JP
2118                 /* Store the name */
2119                 if (!add_name(&a_ptr->name, head, s)) return (7);
2120 #endif
2121         }
2122
2123         /* There better be a current a_ptr */
2124         else if (!a_ptr) return (3);
2125
2126
2127 #ifdef JP
2128         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
2129         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
2130         else if (buf[0] == 'E')
2131         {
2132                 /* nothing to do */
2133         }
2134 #else
2135         else if (buf[0] == 'E')
2136         {
2137                 /* Acquire the Text */
2138                 s = buf+2;
2139
2140                 /* Store the name */
2141                 if (!add_name(&a_ptr->name, head, s)) return (7);
2142         }
2143 #endif
2144
2145         /* Process 'D' for "Description" */
2146         else if (buf[0] == 'D')
2147         {
2148 #ifdef JP
2149                 if (buf[2] == '$')
2150                         return (0);
2151                 /* Acquire the text */
2152                 s = buf+2;
2153 #else
2154                 if (buf[2] != '$')
2155                         return (0);
2156                 /* Acquire the text */
2157                 s = buf+3;
2158 #endif
2159
2160                 /* Store the text */
2161                 if (!add_text(&a_ptr->text, head, s)) return (7);
2162         }
2163
2164
2165         /* Process 'I' for "Info" (one line only) */
2166         else if (buf[0] == 'I')
2167         {
2168                 int tval, sval, pval;
2169
2170                 /* Scan for the values */
2171                 if (3 != sscanf(buf+2, "%d:%d:%d",
2172                                 &tval, &sval, &pval)) return (1);
2173
2174                 /* Save the values */
2175                 a_ptr->tval = tval;
2176                 a_ptr->sval = sval;
2177                 a_ptr->pval = pval;
2178         }
2179
2180         /* Process 'W' for "More Info" (one line only) */
2181         else if (buf[0] == 'W')
2182         {
2183                 int level, rarity, wgt;
2184                 long cost;
2185
2186                 /* Scan for the values */
2187                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2188                                 &level, &rarity, &wgt, &cost)) return (1);
2189
2190                 /* Save the values */
2191                 a_ptr->level = level;
2192                 a_ptr->rarity = rarity;
2193                 a_ptr->weight = wgt;
2194                 a_ptr->cost = cost;
2195         }
2196
2197         /* Hack -- Process 'P' for "power" and such */
2198         else if (buf[0] == 'P')
2199         {
2200                 int ac, hd1, hd2, th, td, ta;
2201
2202                 /* Scan for the values */
2203                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2204                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2205
2206                 a_ptr->ac = ac;
2207                 a_ptr->dd = hd1;
2208                 a_ptr->ds = hd2;
2209                 a_ptr->to_h = th;
2210                 a_ptr->to_d = td;
2211                 a_ptr->to_a =  ta;
2212         }
2213
2214         /* Hack -- Process 'F' for flags */
2215         else if (buf[0] == 'F')
2216         {
2217                 /* Parse every entry textually */
2218                 for (s = buf + 2; *s; )
2219                 {
2220                                 /* Find the end of this entry */
2221                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2222
2223                                 /* Nuke and skip any dividers */
2224                         if (*t)
2225                         {
2226                                 *t++ = '\0';
2227                                 while ((*t == ' ') || (*t == '|')) t++;
2228                         }
2229
2230                                 /* Parse this entry */
2231                         if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
2232
2233                                 /* Start the next entry */
2234                         s = t;
2235                 }
2236         }
2237
2238
2239         /* Oops */
2240         else return (6);
2241
2242
2243         /* Success */
2244         return (0);
2245 }
2246
2247
2248 /*
2249  * Grab one flag in a ego-item_type from a textual string
2250  */
2251 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
2252 {
2253         int i;
2254
2255         /* Check flags */
2256         for (i = 0; i < TR_FLAG_MAX; i++)
2257         {
2258                 if (streq(what, k_info_flags[i]))
2259                 {
2260                         add_flag(e_ptr->flags, i);
2261                         return (0);
2262                 }
2263         }
2264
2265         if (grab_one_flag(&e_ptr->gen_flags, k_info_gen_flags, what) == 0)
2266                 return 0;
2267
2268         /* Oops */
2269 #ifdef JP
2270         msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
2271 #else
2272         msg_format("Unknown ego-item flag '%s'.", what);
2273 #endif
2274
2275
2276         /* Error */
2277         return (1);
2278 }
2279
2280
2281
2282
2283 /*
2284  * Initialize the "e_info" array, by parsing an ascii "template" file
2285  */
2286 errr parse_e_info(char *buf, header *head)
2287 {
2288         int i;
2289
2290         char *s, *t;
2291
2292         /* Current entry */
2293         static ego_item_type *e_ptr = NULL;
2294
2295
2296         /* Just before the first record */
2297         error_idx = -1;
2298
2299         /* Just before the first line */
2300         error_line = -1;
2301
2302
2303         /* Process 'N' for "New/Number/Name" */
2304         if (buf[0] == 'N')
2305         {
2306                 /* Find the colon before the name */
2307                 s = my_strchr(buf+2, ':');
2308
2309                         /* Verify that colon */
2310                 if (!s) return (1);
2311
2312                 /* Nuke the colon, advance to the name */
2313                 *s++ = '\0';
2314 #ifdef JP
2315                 /* Paranoia -- require a name */
2316                 if (!*s) return (1);
2317 #endif
2318                 /* Get the index */
2319                 i = atoi(buf+2);
2320
2321                 /* Verify information */
2322                 if (i < error_idx) return (4);
2323
2324                 /* Verify information */
2325                 if (i >= head->info_num) return (2);
2326
2327                 /* Save the index */
2328                 error_idx = i;
2329
2330                 /* Point at the "info" */
2331                 e_ptr = &e_info[i];
2332 #ifdef JP
2333                 /* Store the name */
2334                 if (!add_name(&e_ptr->name, head, s)) return (7);
2335 #endif
2336         }
2337
2338         /* There better be a current e_ptr */
2339         else if (!e_ptr) return (3);
2340
2341
2342 #ifdef JP
2343         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
2344         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2345         else if (buf[0] == 'E')
2346         {
2347                 /* nothing to do */
2348         }
2349 #else
2350         else if (buf[0] == 'E')
2351         {
2352                 /* Acquire the Text */
2353                 s = buf+2;
2354
2355                 /* Store the name */
2356                 if (!add_name(&e_ptr->name, head, s)) return (7);
2357         }
2358 #endif
2359 #if 0
2360
2361         /* Process 'D' for "Description" */
2362         else if (buf[0] == 'D')
2363         {
2364                 /* Acquire the text */
2365                 s = buf+2;
2366
2367                 /* Store the text */
2368                 if (!add_text(&e_ptr->text, head, s)) return (7);
2369         }
2370
2371 #endif
2372
2373         /* Process 'X' for "Xtra" (one line only) */
2374         else if (buf[0] == 'X')
2375         {
2376                 int slot, rating;
2377
2378                 /* Scan for the values */
2379                 if (2 != sscanf(buf+2, "%d:%d",
2380                                 &slot, &rating)) return (1);
2381
2382                 /* Save the values */
2383                 e_ptr->slot = slot;
2384                 e_ptr->rating = rating;
2385         }
2386
2387         /* Process 'W' for "More Info" (one line only) */
2388         else if (buf[0] == 'W')
2389         {
2390                 int level, rarity, pad2;
2391                 long cost;
2392
2393                 /* Scan for the values */
2394                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2395                                 &level, &rarity, &pad2, &cost)) return (1);
2396
2397                 /* Save the values */
2398                 e_ptr->level = level;
2399                 e_ptr->rarity = rarity;
2400                 /* e_ptr->weight = wgt; */
2401                 e_ptr->cost = cost;
2402         }
2403
2404         /* Hack -- Process 'C' for "creation" */
2405         else if (buf[0] == 'C')
2406         {
2407                 int th, td, ta, pv;
2408
2409                 /* Scan for the values */
2410                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
2411                                 &th, &td, &ta, &pv)) return (1);
2412
2413                 e_ptr->max_to_h = th;
2414                 e_ptr->max_to_d = td;
2415                 e_ptr->max_to_a = ta;
2416                 e_ptr->max_pval = pv;
2417         }
2418
2419         /* Hack -- Process 'F' for flags */
2420         else if (buf[0] == 'F')
2421         {
2422                 /* Parse every entry textually */
2423                 for (s = buf + 2; *s; )
2424                 {
2425                                 /* Find the end of this entry */
2426                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2427
2428                                 /* Nuke and skip any dividers */
2429                         if (*t)
2430                         {
2431                                 *t++ = '\0';
2432                                 while ((*t == ' ') || (*t == '|')) t++;
2433                         }
2434
2435                                 /* Parse this entry */
2436                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2437
2438                                 /* Start the next entry */
2439                         s = t;
2440                 }
2441         }
2442
2443         /* Oops */
2444         else return (6);
2445
2446         /* Success */
2447         return (0);
2448 }
2449
2450
2451 /*
2452  * Grab one (basic) flag in a monster_race from a textual string
2453  */
2454 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
2455 {
2456         if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
2457                 return 0;
2458
2459         if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
2460                 return 0;
2461
2462         if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
2463                 return 0;
2464
2465         if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
2466                 return 0;
2467
2468         if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
2469                 return 0;
2470
2471         if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
2472                 return 0;
2473
2474         if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
2475                 return 0;
2476
2477         /* Oops */
2478 #ifdef JP
2479         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2480 #else
2481         msg_format("Unknown monster flag '%s'.", what);
2482 #endif
2483
2484
2485         /* Failure */
2486         return (1);
2487 }
2488
2489
2490 /*
2491  * Grab one (spell) flag in a monster_race from a textual string
2492  */
2493 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2494 {
2495         if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
2496                 return 0;
2497
2498         if (grab_one_flag(&r_ptr->flags5, r_info_flags5, what) == 0)
2499                 return 0;
2500
2501         if (grab_one_flag(&r_ptr->flags6, r_info_flags6, what) == 0)
2502                 return 0;
2503
2504         /* Oops */
2505 #ifdef JP
2506         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2507 #else
2508         msg_format("Unknown monster flag '%s'.", what);
2509 #endif
2510
2511
2512         /* Failure */
2513         return (1);
2514 }
2515
2516
2517
2518
2519 /*
2520  * Initialize the "r_info" array, by parsing an ascii "template" file
2521  */
2522 errr parse_r_info(char *buf, header *head)
2523 {
2524         int i;
2525
2526         char *s, *t;
2527
2528         /* Current entry */
2529         static monster_race *r_ptr = NULL;
2530
2531
2532         /* Process 'N' for "New/Number/Name" */
2533         if (buf[0] == 'N')
2534         {
2535                 /* Find the colon before the name */
2536                 s = my_strchr(buf+2, ':');
2537
2538                         /* Verify that colon */
2539                 if (!s) return (1);
2540
2541                 /* Nuke the colon, advance to the name */
2542                 *s++ = '\0';
2543 #ifdef JP
2544                 /* Paranoia -- require a name */
2545                 if (!*s) return (1);
2546 #endif
2547                 /* Get the index */
2548                 i = atoi(buf+2);
2549
2550                 /* Verify information */
2551                 if (i < error_idx) return (4);
2552
2553                 /* Verify information */
2554                 if (i >= head->info_num) return (2);
2555
2556                 /* Save the index */
2557                 error_idx = i;
2558
2559                 /* Point at the "info" */
2560                 r_ptr = &r_info[i];
2561 #ifdef JP
2562                 /* Store the name */
2563                 if (!add_name(&r_ptr->name, head, s)) return (7);
2564 #endif
2565         }
2566
2567         /* There better be a current r_ptr */
2568         else if (!r_ptr) return (3);
2569
2570
2571 #ifdef JP
2572         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
2573         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2574         else if (buf[0] == 'E')
2575         {
2576                 /* Acquire the Text */
2577                 s = buf+2;
2578
2579                 /* Store the name */
2580                 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2581         }
2582 #else
2583         else if (buf[0] == 'E')
2584         {
2585                 /* Acquire the Text */
2586                 s = buf+2;
2587
2588                 /* Store the name */
2589                 if (!add_name(&r_ptr->name, head, s)) return (7);
2590         }
2591 #endif
2592         /* Process 'D' for "Description" */
2593         else if (buf[0] == 'D')
2594         {
2595 #ifdef JP
2596                 if (buf[2] == '$')
2597                         return (0);
2598                 /* Acquire the text */
2599                 s = buf+2;
2600 #else
2601                 if (buf[2] != '$')
2602                         return (0);
2603                 /* Acquire the text */
2604                 s = buf+3;
2605 #endif
2606
2607                 /* Store the text */
2608                 if (!add_text(&r_ptr->text, head, s)) return (7);
2609         }
2610
2611         /* Process 'G' for "Graphics" (one line only) */
2612         else if (buf[0] == 'G')
2613         {
2614                 char sym;
2615                 byte tmp;
2616
2617                 /* Paranoia */
2618                 if (buf[1] != ':') return (1);
2619                 if (!buf[2]) return (1);
2620                 if (buf[3] != ':') return (1);
2621                 if (!buf[4]) return (1);
2622
2623                 /* Extract the char */
2624                 sym = buf[2];
2625
2626                 /* Extract the attr */
2627                 tmp = color_char_to_attr(buf[4]);
2628
2629                 /* Paranoia */
2630                 if (tmp > 127) return (1);
2631
2632                 /* Save the values */
2633                 r_ptr->d_char = sym;
2634                 r_ptr->d_attr = tmp;
2635         }
2636
2637         /* Process 'I' for "Info" (one line only) */
2638         else if (buf[0] == 'I')
2639         {
2640                 int spd, hp1, hp2, aaf, ac, slp;
2641
2642                 /* Scan for the other values */
2643                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2644                                 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2645
2646                 /* Save the values */
2647                 r_ptr->speed = spd;
2648                 r_ptr->hdice = hp1;
2649                 r_ptr->hside = hp2;
2650                 r_ptr->aaf = aaf;
2651                 r_ptr->ac = ac;
2652                 r_ptr->sleep = slp;
2653         }
2654
2655         /* Process 'W' for "More Info" (one line only) */
2656         else if (buf[0] == 'W')
2657         {
2658                 int lev, rar, pad;
2659                 long exp;
2660                 long nextexp;
2661                 int nextmon;
2662
2663                 /* Scan for the values */
2664                 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2665                                 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2666
2667                 /* Save the values */
2668                 r_ptr->level = lev;
2669                 r_ptr->rarity = rar;
2670                 r_ptr->extra = pad;
2671                 r_ptr->mexp = exp;
2672                 r_ptr->next_exp = nextexp;
2673                 r_ptr->next_r_idx = nextmon;
2674         }
2675
2676         /* Process 'B' for "Blows" (up to four lines) */
2677         else if (buf[0] == 'B')
2678         {
2679                 int n1, n2;
2680
2681                 /* Find the next empty blow slot (if any) */
2682                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2683
2684                 /* Oops, no more slots */
2685                 if (i == 4) return (1);
2686
2687                 /* Analyze the first field */
2688                 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2689
2690                 /* Terminate the field (if necessary) */
2691                 if (*t == ':') *t++ = '\0';
2692
2693                 /* Analyze the method */
2694                 for (n1 = 0; r_info_blow_method[n1]; n1++)
2695                 {
2696                         if (streq(s, r_info_blow_method[n1])) break;
2697                 }
2698
2699                 /* Invalid method */
2700                 if (!r_info_blow_method[n1]) return (1);
2701
2702                 /* Analyze the second field */
2703                 for (s = t; *t && (*t != ':'); t++) /* loop */;
2704
2705                 /* Terminate the field (if necessary) */
2706                 if (*t == ':') *t++ = '\0';
2707
2708                 /* Analyze effect */
2709                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2710                 {
2711                         if (streq(s, r_info_blow_effect[n2])) break;
2712                 }
2713
2714                 /* Invalid effect */
2715                 if (!r_info_blow_effect[n2]) return (1);
2716
2717                 /* Analyze the third field */
2718                 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2719
2720                 /* Terminate the field (if necessary) */
2721                 if (*t == 'd') *t++ = '\0';
2722
2723                 /* Save the method */
2724                 r_ptr->blow[i].method = n1;
2725
2726                 /* Save the effect */
2727                 r_ptr->blow[i].effect = n2;
2728
2729                 /* Extract the damage dice and sides */
2730                 r_ptr->blow[i].d_dice = atoi(s);
2731                 r_ptr->blow[i].d_side = atoi(t);
2732         }
2733
2734         /* Process 'F' for "Basic Flags" (multiple lines) */
2735         else if (buf[0] == 'F')
2736         {
2737                 /* Parse every entry */
2738                 for (s = buf + 2; *s; )
2739                 {
2740                                 /* Find the end of this entry */
2741                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2742
2743                                 /* Nuke and skip any dividers */
2744                         if (*t)
2745                         {
2746                                 *t++ = '\0';
2747                                 while (*t == ' ' || *t == '|') t++;
2748                         }
2749
2750                                 /* Parse this entry */
2751                         if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2752
2753                                 /* Start the next entry */
2754                         s = t;
2755                 }
2756         }
2757
2758         /* Process 'S' for "Spell Flags" (multiple lines) */
2759         else if (buf[0] == 'S')
2760         {
2761                 /* Parse every entry */
2762                 for (s = buf + 2; *s; )
2763                 {
2764                                 /* Find the end of this entry */
2765                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2766
2767                                 /* Nuke and skip any dividers */
2768                         if (*t)
2769                         {
2770                                 *t++ = '\0';
2771                                 while ((*t == ' ') || (*t == '|')) t++;
2772                         }
2773
2774                                 /* XXX XXX XXX Hack -- Read spell frequency */
2775                         if (1 == sscanf(s, "1_IN_%d", &i))
2776                         {
2777                                 /* Extract a "frequency" */
2778                                 r_ptr->freq_spell = 100 / i;
2779
2780                                         /* Start at next entry */
2781                                 s = t;
2782
2783                                 /* Continue */
2784                                 continue;
2785                         }
2786
2787                                 /* Parse this entry */
2788                         if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2789
2790                                 /* Start the next entry */
2791                         s = t;
2792                 }
2793         }
2794
2795         /* Oops */
2796         else return (6);
2797
2798
2799         /* Success */
2800         return (0);
2801 }
2802
2803
2804 /*
2805  * Grab one flag for a dungeon type from a textual string
2806  */
2807 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2808 {
2809         if (grab_one_flag(&d_ptr->flags1, d_info_flags1, what) == 0)
2810                 return 0;
2811
2812         /* Oops */
2813 #ifdef JP
2814         msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2815 #else
2816         msg_format("Unknown dungeon type flag '%s'.", what);
2817 #endif
2818
2819         /* Failure */
2820         return (1);
2821 }
2822
2823 /*
2824  * Grab one (basic) flag in a monster_race from a textual string
2825  */
2826 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2827 {
2828         if (grab_one_flag(&d_ptr->mflags1, r_info_flags1, what) == 0)
2829                 return 0;
2830
2831         if (grab_one_flag(&d_ptr->mflags2, r_info_flags2, what) == 0)
2832                 return 0;
2833
2834         if (grab_one_flag(&d_ptr->mflags3, r_info_flags3, what) == 0)
2835                 return 0;
2836
2837         if (grab_one_flag(&d_ptr->mflags7, r_info_flags7, what) == 0)
2838                 return 0;
2839
2840         if (grab_one_flag(&d_ptr->mflags8, r_info_flags8, what) == 0)
2841                 return 0;
2842
2843         if (grab_one_flag(&d_ptr->mflags9, r_info_flags9, what) == 0)
2844                 return 0;
2845
2846         if (grab_one_flag(&d_ptr->mflagsr, r_info_flagsr, what) == 0)
2847                 return 0;
2848
2849         /* Oops */
2850 #ifdef JP
2851         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2852 #else
2853         msg_format("Unknown monster flag '%s'.", what);
2854 #endif
2855         /* Failure */
2856         return (1);
2857 }
2858
2859
2860 /*
2861  * Grab one (spell) flag in a monster_race from a textual string
2862  */
2863 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2864 {
2865         if (grab_one_flag(&d_ptr->mflags4, r_info_flags4, what) == 0)
2866                 return 0;
2867
2868         if (grab_one_flag(&d_ptr->mflags5, r_info_flags5, what) == 0)
2869                 return 0;
2870
2871         if (grab_one_flag(&d_ptr->mflags6, r_info_flags6, what) == 0)
2872                 return 0;
2873
2874         /* Oops */
2875 #ifdef JP
2876         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2877 #else
2878         msg_format("Unknown monster flag '%s'.", what);
2879 #endif
2880
2881         /* Failure */
2882         return (1);
2883 }
2884
2885 /*
2886  * Initialize the "d_info" array, by parsing an ascii "template" file
2887  */
2888 errr parse_d_info(char *buf, header *head)
2889 {
2890         int i;
2891
2892         char *s, *t;
2893
2894         /* Current entry */
2895         static dungeon_info_type *d_ptr = NULL;
2896
2897
2898         /* Process 'N' for "New/Number/Name" */
2899         if (buf[0] == 'N')
2900         {
2901                 /* Find the colon before the name */
2902                 s = my_strchr(buf+2, ':');
2903
2904                 /* Verify that colon */
2905                 if (!s) return (1);
2906
2907                 /* Nuke the colon, advance to the name */
2908                 *s++ = '\0';
2909 #ifdef JP
2910                 /* Paranoia -- require a name */
2911                 if (!*s) return (1);
2912 #endif
2913                 /* Get the index */
2914                 i = atoi(buf+2);
2915
2916                 /* Verify information */
2917                 if (i < error_idx) return (4);
2918
2919                 /* Verify information */
2920                 if (i >= head->info_num) return (2);
2921
2922                 /* Save the index */
2923                 error_idx = i;
2924
2925                 /* Point at the "info" */
2926                 d_ptr = &d_info[i];
2927 #ifdef JP
2928                 /* Store the name */
2929                 if (!add_name(&d_ptr->name, head, s)) return (7);
2930 #endif
2931         }
2932
2933 #ifdef JP
2934         else if (buf[0] == 'E') return (0);
2935 #else
2936         else if (buf[0] == 'E')
2937         {
2938                 /* Acquire the Text */
2939                 s = buf+2;
2940
2941                 /* Store the name */
2942                 if (!add_name(&d_ptr->name, head, s)) return (7);
2943         }
2944 #endif
2945
2946         /* Process 'D' for "Description */
2947         else if (buf[0] == 'D')
2948         {
2949 #ifdef JP
2950                 if (buf[2] == '$')
2951                         return (0);
2952                 /* Acquire the text */
2953                 s = buf+2;
2954 #else
2955                 if (buf[2] != '$')
2956                         return (0);
2957                 /* Acquire the text */
2958                 s = buf+3;
2959 #endif
2960
2961                 /* Store the text */
2962                 if (!add_text(&d_ptr->text, head, s)) return (7);
2963         }
2964
2965         /* Process 'W' for "More Info" (one line only) */
2966         else if (buf[0] == 'W')
2967         {
2968                 int min_lev, max_lev;
2969                 int min_plev, mode;
2970                 int min_alloc, max_chance;
2971                 int obj_good, obj_great;
2972                 int pit, nest;
2973
2974                 /* Scan for the values */
2975                 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2976                                  &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2977
2978                 /* Save the values */
2979                 d_ptr->mindepth = min_lev;
2980                 d_ptr->maxdepth = max_lev;
2981                 d_ptr->min_plev = min_plev;
2982                 d_ptr->mode = mode;
2983                 d_ptr->min_m_alloc_level = min_alloc;
2984                 d_ptr->max_m_alloc_chance = max_chance;
2985                 d_ptr->obj_good = obj_good;
2986                 d_ptr->obj_great = obj_great;
2987                 d_ptr->pit = pit;
2988                 d_ptr->nest = nest;
2989         }
2990
2991         /* Process 'P' for "Place Info" */
2992         else if (buf[0] == 'P')
2993         {
2994                 int dy, dx;
2995
2996                 /* Scan for the values */
2997                 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2998
2999                 /* Save the values */
3000                 d_ptr->dy = dy;
3001                 d_ptr->dx = dx;
3002         }
3003
3004         /* Process 'L' for "fLoor type" (one line only) */
3005         else if (buf[0] == 'L')
3006         {
3007                 char *zz[16];
3008
3009                 /* Scan for the values */
3010                 if (tokenize(buf+2, DUNGEON_FEAT_PROB_NUM * 2 + 1, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 1)) return (1);
3011
3012                 /* Save the values */
3013                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3014                 {
3015                         d_ptr->floor[i].feat = f_tag_to_index(zz[i * 2]);
3016                         if (d_ptr->floor[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3017
3018                         d_ptr->floor[i].percent = atoi(zz[i * 2 + 1]);
3019                 }
3020                 d_ptr->tunnel_percent = atoi(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3021         }
3022
3023         /* Process 'A' for "wAll type" (one line only) */
3024         else if (buf[0] == 'A')
3025         {
3026                 char *zz[16];
3027
3028                 /* Scan for the values */
3029                 if (tokenize(buf+2, DUNGEON_FEAT_PROB_NUM * 2 + 4, zz, 0) != (DUNGEON_FEAT_PROB_NUM * 2 + 4)) return (1);
3030
3031                 /* Save the values */
3032                 for (i = 0; i < DUNGEON_FEAT_PROB_NUM; i++)
3033                 {
3034                         d_ptr->fill[i].feat = f_tag_to_index(zz[i * 2]);
3035                         if (d_ptr->fill[i].feat < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3036
3037                         d_ptr->fill[i].percent = atoi(zz[i * 2 + 1]);
3038                 }
3039
3040                 d_ptr->outer_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2]);
3041                 if (d_ptr->outer_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3042
3043                 d_ptr->inner_wall = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 1]);
3044                 if (d_ptr->inner_wall < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3045
3046                 d_ptr->stream1 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 2]);
3047                 if (d_ptr->stream1 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3048
3049                 d_ptr->stream2 = f_tag_to_index(zz[DUNGEON_FEAT_PROB_NUM * 2 + 3]);
3050                 if (d_ptr->stream2 < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3051         }
3052
3053         /* Process 'F' for "Dungeon Flags" (multiple lines) */
3054         else if (buf[0] == 'F')
3055         {
3056                 int artif = 0, monst = 0;
3057
3058                 /* Parse every entry */
3059                 for (s = buf + 2; *s; )
3060                 {
3061                         /* Find the end of this entry */
3062                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3063
3064                         /* Nuke and skip any dividers */
3065                         if (*t)
3066                         {
3067                                 *t++ = '\0';
3068                                 while (*t == ' ' || *t == '|') t++;
3069                         }
3070
3071                         /* XXX XXX XXX Hack -- Read Final Artifact */
3072                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3073                         {
3074                                 /* Extract a "Final Artifact" */
3075                                 d_ptr->final_artifact = artif;
3076
3077                                 /* Start at next entry */
3078                                 s = t;
3079
3080                                 /* Continue */
3081                                 continue;
3082                         }
3083
3084                         /* XXX XXX XXX Hack -- Read Final Object */
3085                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3086                         {
3087                                 /* Extract a "Final Artifact" */
3088                                 d_ptr->final_object = artif;
3089
3090                                 /* Start at next entry */
3091                                 s = t;
3092
3093                                 /* Continue */
3094                                 continue;
3095                         }
3096
3097                         /* XXX XXX XXX Hack -- Read Artifact Guardian */
3098                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3099                         {
3100                                 /* Extract a "Artifact Guardian" */
3101                                 d_ptr->final_guardian = monst;
3102
3103                                 /* Start at next entry */
3104                                 s = t;
3105
3106                                 /* Continue */
3107                                 continue;
3108                         }
3109
3110                         /* XXX XXX XXX Hack -- Read Special Percentage */
3111                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3112                         {
3113                                 /* Extract a "Special %" */
3114                                 d_ptr->special_div = monst;
3115
3116                                 /* Start at next entry */
3117                                 s = t;
3118
3119                                 /* Continue */
3120                                 continue;
3121                         }
3122
3123                         /* Parse this entry */
3124                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3125
3126                         /* Start the next entry */
3127                         s = t;
3128                 }
3129         }
3130
3131         /* Process 'M' for "Basic Flags" (multiple lines) */
3132         else if (buf[0] == 'M')
3133         {
3134                 /* Parse every entry */
3135                 for (s = buf + 2; *s; )
3136                 {
3137                         /* Find the end of this entry */
3138                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3139
3140                         /* Nuke and skip any dividers */
3141                         if (*t)
3142                         {
3143                                 *t++ = '\0';
3144                                 while (*t == ' ' || *t == '|') t++;
3145                         }
3146
3147                         /* Hack -- Read monster symbols */
3148                         if (!strncmp(s, "R_CHAR_", 7))
3149                         {
3150                                 /* Skip "R_CHAR_" */
3151                                 s += 7;
3152
3153                                 /* Read a string */
3154                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
3155
3156                                 /* Start at next entry */
3157                                 s = t;
3158
3159                                 /* Continue */
3160                                 continue;
3161                         }
3162
3163                         /* Parse this entry */
3164                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3165
3166                         /* Start the next entry */
3167                         s = t;
3168                 }
3169         }
3170
3171         /* Process 'S' for "Spell Flags" (multiple lines) */
3172         else if (buf[0] == 'S')
3173         {
3174                 /* Parse every entry */
3175                 for (s = buf + 2; *s; )
3176                 {
3177                                 /* Find the end of this entry */
3178                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3179
3180                                 /* Nuke and skip any dividers */
3181                         if (*t)
3182                         {
3183                                 *t++ = '\0';
3184                                 while ((*t == ' ') || (*t == '|')) t++;
3185                         }
3186
3187                                 /* XXX XXX XXX Hack -- Read spell frequency */
3188                         if (1 == sscanf(s, "1_IN_%d", &i))
3189                         {
3190                                 /* Start at next entry */
3191                                 s = t;
3192
3193                                         /* Continue */
3194                                 continue;
3195                         }
3196
3197                                 /* Parse this entry */
3198                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3199
3200                                 /* Start the next entry */
3201                         s = t;
3202                 }
3203         }
3204
3205         /* Oops */
3206         else return (6);
3207
3208         /* Success */
3209         return (0);
3210 }
3211
3212
3213 #else   /* ALLOW_TEMPLATES */
3214
3215 #ifdef MACINTOSH
3216 static int i = 0;
3217 #endif
3218
3219 #endif  /* ALLOW_TEMPLATES */
3220
3221
3222 /* Random dungeon grid effects */
3223 #define RANDOM_NONE         0x00000000
3224 #define RANDOM_FEATURE      0x00000001
3225 #define RANDOM_MONSTER      0x00000002
3226 #define RANDOM_OBJECT       0x00000004
3227 #define RANDOM_EGO          0x00000008
3228 #define RANDOM_ARTIFACT     0x00000010
3229 #define RANDOM_TRAP         0x00000020
3230
3231
3232 typedef struct dungeon_grid dungeon_grid;
3233
3234 struct dungeon_grid
3235 {
3236         int             feature;                /* Terrain feature */
3237         int             monster;                /* Monster */
3238         int             object;                 /* Object */
3239         int             ego;                    /* Ego-Item */
3240         int             artifact;               /* Artifact */
3241         int             trap;                   /* Trap */
3242         int             cave_info;              /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3243         int             special;                /* Reserved for special terrain info */
3244         int             random;                 /* Number of the random effect */
3245 };
3246
3247
3248 static dungeon_grid letter[255];
3249
3250
3251 /*
3252  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3253  */
3254 static errr parse_line_feature(char *buf)
3255 {
3256         int num;
3257         char *zz[9];
3258
3259
3260         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3261
3262         /* Tokenize the line */
3263         if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3264         {
3265                 /* Letter to assign */
3266                 int index = zz[0][0];
3267
3268                 /* Reset the info for the letter */
3269                 letter[index].feature = FEAT_NONE;
3270                 letter[index].monster = 0;
3271                 letter[index].object = 0;
3272                 letter[index].ego = 0;
3273                 letter[index].artifact = 0;
3274                 letter[index].trap = FEAT_NONE;
3275                 letter[index].cave_info = 0;
3276                 letter[index].special = 0;
3277                 letter[index].random = RANDOM_NONE;
3278
3279                 switch (num)
3280                 {
3281                         /* Special */
3282                         case 9:
3283                                 letter[index].special = atoi(zz[8]);
3284                                 /* Fall through */
3285                         /* Trap */
3286                         case 8:
3287                                 if ((zz[7][0] == '*') && !zz[7][1])
3288                                 {
3289                                         letter[index].random |= RANDOM_TRAP;
3290                                 }
3291                                 else
3292                                 {
3293                                         letter[index].trap = f_tag_to_index(zz[7]);
3294                                         if (letter[index].trap < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3295                                 }
3296                                 /* Fall through */
3297                         /* Artifact */
3298                         case 7:
3299                                 if (zz[6][0] == '*')
3300                                 {
3301                                         letter[index].random |= RANDOM_ARTIFACT;
3302                                         if (zz[6][1]) letter[index].artifact = atoi(zz[6] + 1);
3303                                 }
3304                                 else
3305                                 {
3306                                         letter[index].artifact = atoi(zz[6]);
3307                                 }
3308                                 /* Fall through */
3309                         /* Ego-item */
3310                         case 6:
3311                                 if (zz[5][0] == '*')
3312                                 {
3313                                         letter[index].random |= RANDOM_EGO;
3314                                         if (zz[5][1]) letter[index].ego = atoi(zz[5] + 1);
3315                                 }
3316                                 else
3317                                 {
3318                                         letter[index].ego = atoi(zz[5]);
3319                                 }
3320                                 /* Fall through */
3321                         /* Object */
3322                         case 5:
3323                                 if (zz[4][0] == '*')
3324                                 {
3325                                         letter[index].random |= RANDOM_OBJECT;
3326                                         if (zz[4][1]) letter[index].object = atoi(zz[4] + 1);
3327                                 }
3328                                 else
3329                                 {
3330                                         letter[index].object = atoi(zz[4]);
3331                                 }
3332                                 /* Fall through */
3333                         /* Monster */
3334                         case 4:
3335                                 if (zz[3][0] == '*')
3336                                 {
3337                                         letter[index].random |= RANDOM_MONSTER;
3338                                         if (zz[3][1]) letter[index].monster = atoi(zz[3] + 1);
3339                                 }
3340                                 else if (zz[3][0] == 'c')
3341                                 {
3342                                         if (!zz[3][1]) return PARSE_ERROR_GENERIC;
3343                                         letter[index].monster = - atoi(zz[3] + 1);
3344                                 }
3345                                 else
3346                                 {
3347                                         letter[index].monster = atoi(zz[3]);
3348                                 }
3349                                 /* Fall through */
3350                         /* Cave info */
3351                         case 3:
3352                                 letter[index].cave_info = atoi(zz[2]);
3353                                 /* Fall through */
3354                         /* Feature */
3355                         case 2:
3356                                 if ((zz[1][0] == '*') && !zz[1][1])
3357                                 {
3358                                         letter[index].random |= RANDOM_FEATURE;
3359                                 }
3360                                 else
3361                                 {
3362                                         letter[index].feature = f_tag_to_index(zz[1]);
3363                                         if (letter[index].feature < 0) return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
3364                                 }
3365                                 break;
3366                 }
3367
3368                 return (0);
3369         }
3370
3371         return (1);
3372 }
3373
3374
3375 /*
3376  * Process "B:<Index>:<Command>:..." -- Building definition
3377  */
3378 static errr parse_line_building(char *buf)
3379 {
3380         int i;
3381         char *zz[37];
3382         int index;
3383         char *s;
3384
3385 #ifdef JP
3386         if (buf[2] == '$')
3387                 return 0;
3388         s = buf + 2;
3389 #else
3390         if (buf[2] != '$')
3391                 return 0;
3392         s = buf + 3;
3393 #endif
3394         /* Get the building number */
3395         index = atoi(s);
3396
3397         /* Find the colon after the building number */
3398         s = my_strchr(s, ':');
3399
3400         /* Verify that colon */
3401         if (!s) return (1);
3402
3403         /* Nuke the colon, advance to the sub-index */
3404         *s++ = '\0';
3405
3406         /* Paranoia -- require a sub-index */
3407         if (!*s) return (1);
3408
3409         /* Building definition sub-index */
3410         switch (s[0])
3411         {
3412                 /* Building name, owner, race */
3413                 case 'N':
3414                 {
3415                         if (tokenize(s + 2, 3, zz, 0) == 3)
3416                         {
3417                                 /* Name of the building */
3418                                 strcpy(building[index].name, zz[0]);
3419
3420                                 /* Name of the owner */
3421                                 strcpy(building[index].owner_name, zz[1]);
3422
3423                                 /* Race of the owner */
3424                                 strcpy(building[index].owner_race, zz[2]);
3425
3426                                 break;
3427                         }
3428
3429                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3430                 }
3431
3432                 /* Building Action */
3433                 case 'A':
3434                 {
3435                         if (tokenize(s + 2, 8, zz, 0) >= 7)
3436                         {
3437                                 /* Index of the action */
3438                                 int action_index = atoi(zz[0]);
3439
3440                                 /* Name of the action */
3441                                 strcpy(building[index].act_names[action_index], zz[1]);
3442
3443                                 /* Cost of the action for members */
3444                                 building[index].member_costs[action_index] = atoi(zz[2]);
3445
3446                                 /* Cost of the action for non-members */
3447                                 building[index].other_costs[action_index] = atoi(zz[3]);
3448
3449                                 /* Letter assigned to the action */
3450                                 building[index].letters[action_index] = zz[4][0];
3451
3452                                 /* Action code */
3453                                 building[index].actions[action_index] = atoi(zz[5]);
3454
3455                                 /* Action restriction */
3456                                 building[index].action_restr[action_index] = atoi(zz[6]);
3457
3458                                 break;
3459                         }
3460
3461                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3462                 }
3463
3464                 /* Building Classes */
3465                 case 'C':
3466                 {
3467                         if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3468                         {
3469                                 for (i = 0; i < MAX_CLASS; i++)
3470                                 {
3471                                         building[index].member_class[i] = atoi(zz[i]);
3472                                 }
3473
3474                                 break;
3475                         }
3476
3477                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3478                 }
3479
3480                 /* Building Races */
3481                 case 'R':
3482                 {
3483                         if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3484                         {
3485                                 for (i = 0; i < MAX_RACES; i++)
3486                                 {
3487                                         building[index].member_race[i] = atoi(zz[i]);
3488                                 }
3489
3490                                 break;
3491                         }
3492
3493                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3494                 }
3495
3496                 /* Building Realms */
3497                 case 'M':
3498                 {
3499                         if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3500                         {
3501                                 for (i = 0; i < MAX_MAGIC; i++)
3502                                 {
3503                                         building[index].member_realm[i+1] = atoi(zz[i]);
3504                                 }
3505
3506                                 break;
3507                         }
3508
3509                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3510                 }
3511
3512                 case 'Z':
3513                 {
3514                         /* Ignore scripts */
3515                         break;
3516                 }
3517
3518                 default:
3519                 {
3520                         return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3521                 }
3522         }
3523
3524         return (0);
3525 }
3526
3527
3528 /*
3529  * Place the object j_ptr to a grid
3530  */
3531 static void drop_here(object_type *j_ptr, int y, int x)
3532 {
3533         cave_type *c_ptr = &cave[y][x];
3534         object_type *o_ptr;
3535
3536         /* Get new object */
3537         s16b o_idx = o_pop();
3538
3539         /* Access new object */
3540         o_ptr = &o_list[o_idx];
3541
3542         /* Structure copy */
3543         object_copy(o_ptr, j_ptr);
3544
3545
3546         /* Locate */
3547         o_ptr->iy = y;
3548         o_ptr->ix = x;
3549
3550         /* No monster */
3551         o_ptr->held_m_idx = 0;
3552
3553         /* Build a stack */
3554         o_ptr->next_o_idx = c_ptr->o_idx;
3555
3556         /* Place the object */
3557         c_ptr->o_idx = o_idx;
3558 }
3559
3560
3561 /*
3562  * Parse a sub-file of the "extra info"
3563  */
3564 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3565 {
3566         int i;
3567
3568         char *zz[33];
3569
3570
3571         /* Skip "empty" lines */
3572         if (!buf[0]) return (0);
3573
3574         /* Skip "blank" lines */
3575         if (isspace(buf[0])) return (0);
3576
3577         /* Skip comments */
3578         if (buf[0] == '#') return (0);
3579
3580         /* Require "?:*" format */
3581         if (buf[1] != ':') return (1);
3582
3583
3584         /* Process "%:<fname>" */
3585         if (buf[0] == '%')
3586         {
3587                 /* Attempt to Process the given file */
3588                 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3589         }
3590
3591         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3592         if (buf[0] == 'F')
3593         {
3594                 return parse_line_feature(buf);
3595         }
3596
3597         /* Process "D:<dungeon>" -- info for the cave grids */
3598         else if (buf[0] == 'D')
3599         {
3600                 object_type object_type_body;
3601
3602                 /* Acquire the text */
3603                 char *s = buf + 2;
3604
3605                 /* Length of the text */
3606                 int len = strlen(s);
3607
3608                 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3609
3610                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3611                 {
3612                         /* Access the grid */
3613                         cave_type *c_ptr = &cave[*y][*x];
3614
3615                         int idx = s[0];
3616
3617                         int object_index = letter[idx].object;
3618                         int monster_index = letter[idx].monster;
3619                         int random = letter[idx].random;
3620                         int artifact_index = letter[idx].artifact;
3621
3622                         /* Lay down a floor */
3623                         c_ptr->feat = conv_dungeon_feat(letter[idx].feature);
3624
3625                         /* Only the features */
3626                         if (init_flags & INIT_ONLY_FEATURES) continue;
3627
3628                         /* Cave info */
3629                         c_ptr->info = letter[idx].cave_info;
3630
3631                         /* Create a monster */
3632                         if (random & RANDOM_MONSTER)
3633                         {
3634                                 monster_level = base_level + monster_index;
3635
3636                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3637
3638                                 monster_level = base_level;
3639                         }
3640                         else if (monster_index)
3641                         {
3642                                 int old_cur_num, old_max_num;
3643                                 bool clone = FALSE;
3644
3645                                 if (monster_index < 0)
3646                                 {
3647                                         monster_index = -monster_index;
3648                                         clone = TRUE;
3649                                 }
3650                                 old_cur_num = r_info[monster_index].cur_num;
3651                                 old_max_num = r_info[monster_index].max_num;
3652
3653                                 /* Make alive again */
3654                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3655                                 {
3656                                         r_info[monster_index].cur_num = 0;
3657                                         r_info[monster_index].max_num = 1;
3658                                 }
3659
3660                                 /* Make alive again */
3661                                 /* Hack -- Non-unique Nazguls are semi-unique */
3662                                 else if (r_info[monster_index].flags7 & RF7_NAZGUL)
3663                                 {
3664                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3665                                         {
3666                                                 r_info[monster_index].max_num++;
3667                                         }
3668                                 }
3669
3670                                 /* Place it */
3671                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3672                                 if (clone)
3673                                 {
3674                                         /* clone */
3675                                         m_list[hack_m_idx_ii].smart |= SM_CLONED;
3676
3677                                         /* Make alive again for real unique monster */
3678                                         r_info[monster_index].cur_num = old_cur_num;
3679                                         r_info[monster_index].max_num = old_max_num;
3680                                 }
3681                         }
3682
3683                         /* Object (and possible trap) */
3684                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3685                         {
3686                                 object_level = base_level + object_index;
3687
3688                                 /*
3689                                  * Random trap and random treasure defined
3690                                  * 25% chance for trap and 75% chance for object
3691                                  */
3692                                 if (randint0(100) < 75)
3693                                 {
3694                                         place_object(*y, *x, 0L);
3695                                 }
3696                                 else
3697                                 {
3698                                         place_trap(*y, *x);
3699                                 }
3700
3701                                 object_level = base_level;
3702                         }
3703                         else if (random & RANDOM_OBJECT)
3704                         {
3705                                 object_level = base_level + object_index;
3706
3707                                 /* Create an out of deep object */
3708                                 if (randint0(100) < 75)
3709                                         place_object(*y, *x, 0L);
3710                                 else if (randint0(100) < 80)
3711                                         place_object(*y, *x, AM_GOOD);
3712                                 else
3713                                         place_object(*y, *x, AM_GOOD | AM_GREAT);
3714
3715                                 object_level = base_level;
3716                         }
3717                         /* Random trap */
3718                         else if (random & RANDOM_TRAP)
3719                         {
3720                                 place_trap(*y, *x);
3721                         }
3722                         /* Hidden trap (or door) */
3723                         else if (letter[idx].trap)
3724                         {
3725                                 c_ptr->mimic = c_ptr->feat;
3726                                 c_ptr->feat = conv_dungeon_feat(letter[idx].trap);
3727                         }
3728                         else if (object_index)
3729                         {
3730                                 /* Get local object */
3731                                 object_type *o_ptr = &object_type_body;
3732
3733                                 /* Create the item */
3734                                 object_prep(o_ptr, object_index);
3735
3736                                 if (o_ptr->tval == TV_GOLD)
3737                                 {
3738                                         coin_type = object_index - OBJ_GOLD_LIST;
3739                                         make_gold(o_ptr);
3740                                         coin_type = 0;
3741                                 }
3742
3743                                 /* Apply magic (no messages, no artifacts) */
3744                                 apply_magic(o_ptr, base_level, AM_NO_FIXED_ART | AM_GOOD);
3745
3746                                 drop_here(o_ptr, *y, *x);
3747                         }
3748
3749                         /* Artifact */
3750                         if (artifact_index)
3751                         {
3752                                 if (a_info[artifact_index].cur_num)
3753                                 {
3754                                         int k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
3755                                         object_type forge;
3756                                         object_type *q_ptr = &forge;
3757
3758                                         object_prep(q_ptr, k_idx);
3759
3760                                         /* Drop it in the dungeon */
3761                                         drop_here(q_ptr, *y, *x);
3762                                 }
3763                                 else
3764                                 {
3765                                         /* Create the artifact */
3766                                         create_named_art(artifact_index, *y, *x);
3767
3768                                         a_info[artifact_index].cur_num = 1;
3769                                 }
3770                         }
3771
3772                         /* Terrain special */
3773                         c_ptr->special = letter[idx].special;
3774                 }
3775
3776                 (*y)++;
3777
3778                 return (0);
3779         }
3780
3781         /* Process "Q:<number>:<command>:... -- quest info */
3782         else if (buf[0] == 'Q')
3783         {
3784                 int num;
3785                 quest_type *q_ptr;
3786 #ifdef JP
3787                 if (buf[2] == '$')
3788                         return 0;
3789                 num = tokenize(buf + 2, 33, zz, 0);
3790 #else
3791                 if (buf[2] != '$')
3792                         return 0;
3793                 num = tokenize(buf + 3, 33, zz, 0);
3794 #endif
3795
3796                 /* Have we enough parameters? */
3797                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3798
3799                 /* Get the quest */
3800                 q_ptr = &(quest[atoi(zz[0])]);
3801
3802                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3803                 if (zz[1][0] == 'Q')
3804                 {
3805                         if (init_flags & INIT_ASSIGN)
3806                         {
3807                                 monster_race *r_ptr;
3808                                 artifact_type *a_ptr;
3809
3810                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3811
3812                                 q_ptr->type    = atoi(zz[2]);
3813                                 q_ptr->num_mon = atoi(zz[3]);
3814                                 q_ptr->cur_num = atoi(zz[4]);
3815                                 q_ptr->max_num = atoi(zz[5]);
3816                                 q_ptr->level   = atoi(zz[6]);
3817                                 q_ptr->r_idx   = atoi(zz[7]);
3818                                 q_ptr->k_idx   = atoi(zz[8]);
3819                                 q_ptr->dungeon = atoi(zz[9]);
3820
3821                                 if (num > 10)
3822                                         q_ptr->flags  = atoi(zz[10]);
3823
3824                                 r_ptr = &r_info[q_ptr->r_idx];
3825                                 if (r_ptr->flags1 & RF1_UNIQUE)
3826                                         r_ptr->flags1 |= RF1_QUESTOR;
3827
3828                                 a_ptr = &a_info[q_ptr->k_idx];
3829                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3830                         }
3831                         return (0);
3832                 }
3833
3834                 /* Process "Q:<q_index>:N:<name>" -- quest name */
3835                 else if (zz[1][0] == 'N')
3836                 {
3837                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3838                         {
3839                                 strcpy(q_ptr->name, zz[2]);
3840                         }
3841
3842                         return (0);
3843                 }
3844
3845                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3846                 else if (zz[1][0] == 'T')
3847                 {
3848                         if (init_flags & INIT_SHOW_TEXT)
3849                         {
3850                                 strcpy(quest_text[quest_text_line], zz[2]);
3851                                 quest_text_line++;
3852                         }
3853
3854                         return (0);
3855                 }
3856         }
3857
3858         /* Process "W:<command>: ..." -- info for the wilderness */
3859         else if (buf[0] == 'W')
3860         {
3861                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3862         }
3863
3864         /* Process "P:<y>:<x>" -- player position */
3865         else if (buf[0] == 'P')
3866         {
3867                 if (init_flags & INIT_CREATE_DUNGEON)
3868                 {
3869                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3870                         {
3871                                 int panels_x, panels_y;
3872
3873                                 /* Hack - Set the dungeon size */
3874                                 panels_y = (*y / SCREEN_HGT);
3875                                 if (*y % SCREEN_HGT) panels_y++;
3876                                 cur_hgt = panels_y * SCREEN_HGT;
3877
3878                                 panels_x = (*x / SCREEN_WID);
3879                                 if (*x % SCREEN_WID) panels_x++;
3880                                 cur_wid = panels_x * SCREEN_WID;
3881
3882                                 /* Assume illegal panel */
3883                                 panel_row_min = cur_hgt;
3884                                 panel_col_min = cur_wid;
3885
3886                                 /* Place player in a quest level */
3887                                 if (p_ptr->inside_quest)
3888                                 {
3889                                         int y, x;
3890
3891                                         /* Delete the monster (if any) */
3892                                         delete_monster(py, px);
3893
3894                                         y = atoi(zz[0]);
3895                                         x = atoi(zz[1]);
3896
3897                                         py = y;
3898                                         px = x;
3899                                 }
3900                                 /* Place player in the town */
3901                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3902                                 {
3903                                         p_ptr->oldpy = atoi(zz[0]);
3904                                         p_ptr->oldpx = atoi(zz[1]);
3905                                 }
3906                         }
3907                 }
3908
3909                 return (0);
3910         }
3911
3912         /* Process "B:<Index>:<Command>:..." -- Building definition */
3913         else if (buf[0] == 'B')
3914         {
3915                 return parse_line_building(buf);
3916         }
3917
3918         /* Process "M:<type>:<maximum>" -- set maximum values */
3919         else if (buf[0] == 'M')
3920         {
3921                 if (tokenize(buf+2, 2, zz, 0) == 2)
3922                 {
3923                         /* Maximum towns */
3924                         if (zz[0][0] == 'T')
3925                         {
3926                                 max_towns = atoi(zz[1]);
3927                         }
3928
3929                         /* Maximum quests */
3930                         else if (zz[0][0] == 'Q')
3931                         {
3932                                 max_quests = atoi(zz[1]);
3933                         }
3934
3935                         /* Maximum r_idx */
3936                         else if (zz[0][0] == 'R')
3937                         {
3938                                 max_r_idx = atoi(zz[1]);
3939                         }
3940
3941                         /* Maximum k_idx */
3942                         else if (zz[0][0] == 'K')
3943                         {
3944                                 max_k_idx = atoi(zz[1]);
3945                         }
3946
3947                         /* Maximum v_idx */
3948                         else if (zz[0][0] == 'V')
3949                         {
3950                                 max_v_idx = atoi(zz[1]);
3951                         }
3952
3953                         /* Maximum f_idx */
3954                         else if (zz[0][0] == 'F')
3955                         {
3956                                 max_f_idx = atoi(zz[1]);
3957                         }
3958
3959                         /* Maximum a_idx */
3960                         else if (zz[0][0] == 'A')
3961                         {
3962                                 max_a_idx = atoi(zz[1]);
3963                         }
3964
3965                         /* Maximum e_idx */
3966                         else if (zz[0][0] == 'E')
3967                         {
3968                                 max_e_idx = atoi(zz[1]);
3969                         }
3970
3971                         /* Maximum d_idx */
3972                         else if (zz[0][0] == 'D')
3973                         {
3974                                 max_d_idx = atoi(zz[1]); 
3975                         }
3976
3977                         /* Maximum o_idx */
3978                         else if (zz[0][0] == 'O')
3979                         {
3980                                 max_o_idx = atoi(zz[1]);
3981                         }
3982
3983                         /* Maximum m_idx */
3984                         else if (zz[0][0] == 'M')
3985                         {
3986                                 max_m_idx = atoi(zz[1]);
3987                         }
3988
3989                         /* Wilderness size */
3990                         else if (zz[0][0] == 'W')
3991                         {
3992                                 /* Maximum wild_x_size */
3993                                 if (zz[0][1] == 'X')
3994                                         max_wild_x = atoi(zz[1]);
3995                                 /* Maximum wild_y_size */
3996                                 if (zz[0][1] == 'Y')
3997                                         max_wild_y = atoi(zz[1]);
3998                         }
3999
4000                         return (0);
4001                 }
4002         }
4003
4004
4005         /* Failure */
4006         return (1);
4007 }
4008
4009
4010 static char tmp[8];
4011 static cptr variant = "ZANGBAND";
4012
4013
4014 /*
4015  * Helper function for "process_dungeon_file()"
4016  */
4017 static cptr process_dungeon_file_expr(char **sp, char *fp)
4018 {
4019         cptr v;
4020
4021         char *b;
4022         char *s;
4023
4024         char b1 = '[';
4025         char b2 = ']';
4026
4027         char f = ' ';
4028
4029         /* Initial */
4030         s = (*sp);
4031
4032         /* Skip spaces */
4033         while (isspace(*s)) s++;
4034
4035         /* Save start */
4036         b = s;
4037
4038         /* Default */
4039         v = "?o?o?";
4040
4041         /* Analyze */
4042         if (*s == b1)
4043         {
4044                 const char *p;
4045                 const char *t;
4046
4047                 /* Skip b1 */
4048                 s++;
4049
4050                 /* First */
4051                 t = process_dungeon_file_expr(&s, &f);
4052
4053                 /* Oops */
4054                 if (!*t)
4055                 {
4056                         /* Nothing */
4057                 }
4058
4059                 /* Function: IOR */
4060                 else if (streq(t, "IOR"))
4061                 {
4062                         v = "0";
4063                         while (*s && (f != b2))
4064                         {
4065                                 t = process_dungeon_file_expr(&s, &f);
4066                                 if (*t && !streq(t, "0")) v = "1";
4067                         }
4068                 }
4069
4070                 /* Function: AND */
4071                 else if (streq(t, "AND"))
4072                 {
4073                         v = "1";
4074                         while (*s && (f != b2))
4075                         {
4076                                 t = process_dungeon_file_expr(&s, &f);
4077                                 if (*t && streq(t, "0")) v = "0";
4078                         }
4079                 }
4080
4081                 /* Function: NOT */
4082                 else if (streq(t, "NOT"))
4083                 {
4084                         v = "1";
4085                         while (*s && (f != b2))
4086                         {
4087                                 t = process_dungeon_file_expr(&s, &f);
4088                                 if (*t && streq(t, "1")) v = "0";
4089                         }
4090                 }
4091
4092                 /* Function: EQU */
4093                 else if (streq(t, "EQU"))
4094                 {
4095                         v = "0";
4096                         if (*s && (f != b2))
4097                         {
4098                                 t = process_dungeon_file_expr(&s, &f);
4099                         }
4100                         while (*s && (f != b2))
4101                         {
4102                                 p = process_dungeon_file_expr(&s, &f);
4103                                 if (streq(t, p)) v = "1";
4104                         }
4105                 }
4106
4107                 /* Function: LEQ */
4108                 else if (streq(t, "LEQ"))
4109                 {
4110                         v = "1";
4111                         if (*s && (f != b2))
4112                         {
4113                                 t = process_dungeon_file_expr(&s, &f);
4114                         }
4115                         while (*s && (f != b2))
4116                         {
4117                                 p = t;
4118                                 t = process_dungeon_file_expr(&s, &f);
4119                                 if (*t && atoi(p) > atoi(t)) v = "0";
4120                         }
4121                 }
4122
4123                 /* Function: GEQ */
4124                 else if (streq(t, "GEQ"))
4125                 {
4126                         v = "1";
4127                         if (*s && (f != b2))
4128                         {
4129                                 t = process_dungeon_file_expr(&s, &f);
4130                         }
4131                         while (*s && (f != b2))
4132                         {
4133                                 p = t;
4134                                 t = process_dungeon_file_expr(&s, &f);
4135
4136                                 /* Compare two numbers instead of string */
4137                                 if (*t && atoi(p) < atoi(t)) v = "0";
4138                         }
4139                 }
4140
4141                 /* Oops */
4142                 else
4143                 {
4144                         while (*s && (f != b2))
4145                         {
4146                                 t = process_dungeon_file_expr(&s, &f);
4147                         }
4148                 }
4149
4150                 /* Verify ending */
4151                 if (f != b2) v = "?x?x?";
4152
4153                 /* Extract final and Terminate */
4154                 if ((f = *s) != '\0') *s++ = '\0';
4155         }
4156
4157         /* Other */
4158         else
4159         {
4160                 /* Accept all printables except spaces and brackets */
4161                 while (isprint(*s) && !my_strchr(" []", *s)) ++s;
4162
4163                 /* Extract final and Terminate */
4164                 if ((f = *s) != '\0') *s++ = '\0';
4165
4166                 /* Variable */
4167                 if (*b == '$')
4168                 {
4169                         /* System */
4170                         if (streq(b+1, "SYS"))
4171                         {
4172                                 v = ANGBAND_SYS;
4173                         }
4174
4175                         /* Graphics */
4176                         else if (streq(b+1, "GRAF"))
4177                         {
4178                                 v = ANGBAND_GRAF;
4179                         }
4180
4181                         else if (streq(b+1, "MONOCHROME"))
4182                         {
4183                                 if (arg_monochrome)
4184                                         v = "ON";
4185                                 else
4186                                         v = "OFF";
4187                         }
4188
4189                         /* Race */
4190                         else if (streq(b+1, "RACE"))
4191                         {
4192 #ifdef JP
4193                                 v = rp_ptr->E_title;
4194 #else
4195                                 v = rp_ptr->title;
4196 #endif
4197                         }
4198
4199                         /* Class */
4200                         else if (streq(b+1, "CLASS"))
4201                         {
4202 #ifdef JP
4203                                 v = cp_ptr->E_title;
4204 #else
4205                                 v = cp_ptr->title;
4206 #endif
4207                         }
4208
4209                         /* First realm */
4210                         else if (streq(b+1, "REALM1"))
4211                         {
4212 #ifdef JP
4213                                 v = E_realm_names[p_ptr->realm1];
4214 #else
4215                                 v = realm_names[p_ptr->realm1];
4216 #endif
4217                         }
4218
4219                         /* Second realm */
4220                         else if (streq(b+1, "REALM2"))
4221                         {
4222 #ifdef JP
4223                                 v = E_realm_names[p_ptr->realm2];
4224 #else
4225                                 v = realm_names[p_ptr->realm2];
4226 #endif
4227                         }
4228
4229                         /* Player name */
4230                         else if (streq(b+1, "PLAYER"))
4231                         {
4232                                 v = player_base;
4233                         }
4234
4235                         /* Town */
4236                         else if (streq(b+1, "TOWN"))
4237                         {
4238                                 sprintf(tmp, "%d", p_ptr->town_num);
4239                                 v = tmp;
4240                         }
4241
4242                         /* Level */
4243                         else if (streq(b+1, "LEVEL"))
4244                         {
4245                                 sprintf(tmp, "%d", p_ptr->lev);
4246                                 v = tmp;
4247                         }
4248
4249                         /* Current quest number */
4250                         else if (streq(b+1, "QUEST_NUMBER"))
4251                         {
4252                                 sprintf(tmp, "%d", p_ptr->inside_quest);
4253                                 v = tmp;
4254                         }
4255
4256                         /* Number of last quest */
4257                         else if (streq(b+1, "LEAVING_QUEST"))
4258                         {
4259                                 sprintf(tmp, "%d", leaving_quest);
4260                                 v = tmp;
4261                         }
4262
4263                         /* Quest status */
4264                         else if (prefix(b+1, "QUEST"))
4265                         {
4266                                 /* "QUEST" uses a special parameter to determine the number of the quest */
4267                                 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4268                                 v = tmp;
4269                         }
4270
4271                         /* Random */
4272                         else if (prefix(b+1, "RANDOM"))
4273                         {
4274                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
4275                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4276                                 v = tmp;
4277                         }
4278
4279                         /* Variant name */
4280                         else if (streq(b+1, "VARIANT"))
4281                         {
4282                                 v = variant;
4283                         }
4284
4285                         /* Wilderness */
4286                         else if (streq(b+1, "WILDERNESS"))
4287                         {
4288                                 if (vanilla_town)
4289                                         sprintf(tmp, "NONE");
4290                                 else if (lite_town)
4291                                         sprintf(tmp, "LITE");
4292                                 else
4293                                         sprintf(tmp, "NORMAL");
4294                                 v = tmp;
4295                         }
4296                 }
4297
4298                 /* Constant */
4299                 else
4300                 {
4301                         v = b;
4302                 }
4303         }
4304
4305         /* Save */
4306         (*fp) = f;
4307
4308         /* Save */
4309         (*sp) = s;
4310
4311         /* Result */
4312         return (v);
4313 }
4314
4315
4316 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4317 {
4318         FILE *fp;
4319
4320         char buf[1024];
4321
4322         int num = -1;
4323
4324         errr err = 0;
4325
4326         bool bypass = FALSE;
4327
4328         int x = xmin, y = ymin;
4329
4330
4331         /* Build the filename */
4332         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
4333
4334         /* Open the file */
4335         fp = my_fopen(buf, "r");
4336
4337         /* No such file */
4338         if (!fp) return (-1);
4339
4340
4341         /* Process the file */
4342         while (0 == my_fgets(fp, buf, sizeof(buf)))
4343         {
4344                 /* Count lines */
4345                 num++;
4346
4347
4348                 /* Skip "empty" lines */
4349                 if (!buf[0]) continue;
4350
4351                 /* Skip "blank" lines */
4352                 if (isspace(buf[0])) continue;
4353
4354                 /* Skip comments */
4355                 if (buf[0] == '#') continue;
4356
4357
4358                 /* Process "?:<expr>" */
4359                 if ((buf[0] == '?') && (buf[1] == ':'))
4360                 {
4361                         char f;
4362                         cptr v;
4363                         char *s;
4364
4365                         /* Start */
4366                         s = buf + 2;
4367
4368                         /* Parse the expr */
4369                         v = process_dungeon_file_expr(&s, &f);
4370
4371                         /* Set flag */
4372                         bypass = (streq(v, "0") ? TRUE : FALSE);
4373
4374                         /* Continue */
4375                         continue;
4376                 }
4377
4378                 /* Apply conditionals */
4379                 if (bypass) continue;
4380
4381                 /* Process the line */
4382                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4383
4384                 /* Oops */
4385                 if (err) break;
4386         }
4387
4388         /* Errors */
4389         if (err)
4390         {
4391                 cptr oops;
4392
4393                 /* Error string */
4394                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4395
4396                 /* Oops */
4397                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4398 #ifdef JP
4399 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4400 #else
4401                 msg_format("Parsing '%s'.", buf);
4402 #endif
4403
4404                 msg_print(NULL);
4405         }
4406
4407
4408         /* Close the file */
4409         my_fclose(fp);
4410
4411         /* Result */
4412         return (err);
4413 }
4414
4415
4416
4417 #if 0
4418 void write_r_info_txt(void)
4419 {
4420         int i, j, z, fc, bc;
4421         int dlen;
4422
4423         cptr flags[32 * 10];
4424
4425         u32b f_ptr[10];
4426         cptr *n_ptr[10];
4427
4428         monster_race *r_ptr;
4429
4430         monster_blow *b_ptr;
4431
4432         FILE *fff = fopen("output.txt", "wt");
4433
4434         cptr desc;
4435
4436         int mode = -1;
4437
4438         if (!fff) return;
4439
4440         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4441
4442         fprintf(fff, "# Version stamp (required)\n\n");
4443
4444         /* Write Version */
4445         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4446
4447         /* Write a note */
4448         fprintf(fff, "##### The Player #####\n\n");
4449
4450         for (z = -1; z < alloc_race_size; z++)
4451         {
4452                 /* Output the monsters in order */
4453                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4454
4455                 /* Acquire the monster */
4456                 r_ptr = &r_info[i];
4457
4458                 /* Ignore empty monsters */
4459                 if (!strlen(r_name + r_ptr->name)) continue;
4460
4461                 /* Ignore useless monsters */
4462                 if (i && !r_ptr->speed) continue;
4463
4464                 /* Write a note if necessary */
4465                 if (i && (!r_ptr->level != !mode))
4466                 {
4467                         /* Note the town */
4468                         if (!r_ptr->level)
4469                         {
4470                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4471                         }
4472                         /* Note the dungeon */
4473                         else
4474                         {
4475                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4476                         }
4477
4478                         /* Record the change */
4479                         mode = r_ptr->level;
4480                 }
4481
4482                 /* Acquire the flags */
4483                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4484                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4485                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4486                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4487                 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4488                 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4489                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4490                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4491                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4492                 f_ptr[9] = r_ptr->flagsr; n_ptr[9] = r_info_flagsr;
4493
4494                 /* Write New/Number/Name */
4495                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4496
4497                 /* Write Graphic */
4498                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4499
4500                 /* Write Information */
4501                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4502                                                                                                                   r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4503
4504                 /* Write more information */
4505                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4506
4507                 /* Write Blows */
4508                 for(j = 0; j < 4; j++)
4509                 {
4510                         b_ptr = &(r_ptr->blow[j]);
4511
4512                         /* Stop when done */
4513                         if (!b_ptr->method) break;
4514
4515                         /* Write the blows */
4516                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4517                                                                                                           r_info_blow_effect[b_ptr->effect],
4518                                                                                                           b_ptr->d_dice, b_ptr->d_side);
4519                 }
4520
4521                 /* Extract the flags */
4522                 for (fc = 0, j = 0; j < 32 * 3; j++)
4523                 {
4524                         /* Check this flag */
4525                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4526                 }
4527
4528                 /* Extract the extra flags */
4529                 for (j = 32 * 6; j < 32 * 10; j++)
4530                 {
4531                         /* Check this flag */
4532                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4533                 }
4534
4535                 /* Write the flags */
4536                 for (j = 0; j < fc;)
4537                 {
4538                         char buf[160];
4539
4540                         /* Start the line */
4541                         sprintf(buf, "F:");
4542
4543                         for (bc = 0; (bc < 60) && (j < fc); j++)
4544                         {
4545                                 char t[80];
4546
4547                                 /* Format the flag */
4548                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4549
4550                                 /* Add it to the buffer */
4551                                 strcat(buf, t);
4552
4553                                 /* Note the length */
4554                                 bc += strlen(t);
4555                         }
4556
4557                         /* Done with this line; write it */
4558                         fprintf(fff, "%s\n", buf);
4559                 }
4560
4561                 /* Write Spells if applicable */
4562                 if (r_ptr->freq_spell)
4563                 {
4564                         /* Write the frequency */
4565                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4566
4567                         /* Extract the spell flags */
4568                         for (fc = 0, j = 96; j < 192; j++)
4569                         {
4570                                 /* Check this flag */
4571                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4572                         }
4573
4574                         /* Write the flags */
4575                         for (j = 0; j < fc;)
4576                         {
4577                                 char buf[160], *t;
4578
4579                                 /* Start the line */
4580                                 sprintf(buf, "S:");
4581
4582                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4583                                 {
4584                                         int tlen;
4585
4586                                         /* Format the flag */
4587                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4588
4589                                         tlen = strlen(t);
4590
4591                                         /* Note the length */
4592                                         bc += tlen;
4593
4594                                         /* Advance */
4595                                         t += tlen;
4596                                 }
4597
4598                                 /* Done with this line; write it */
4599                                 fprintf(fff, "%s\n", buf);
4600                         }
4601                 }
4602
4603                 /* Acquire the description */
4604                 desc = r_text + r_ptr->text;
4605                 dlen = strlen(desc);
4606
4607                 /* Write Description */
4608                 for (j = 0; j < dlen;)
4609                 {
4610                         char buf[160], *t;
4611
4612                         /* Start the line */
4613                         sprintf(buf, "D:");
4614
4615                         for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4616                         {
4617                                 *t = desc[j];
4618                         }
4619
4620                         /* Terminate it */
4621                         *t = '\0';
4622
4623                         /* Done with this line; write it */
4624                         fprintf(fff, "%s\n", buf);
4625                 }
4626
4627                 /* Space between entries */
4628                 fprintf(fff, "\n");
4629         }
4630
4631         /* Done */
4632         fclose(fff);
4633 }
4634
4635 #endif