OSDN Git Service

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