OSDN Git Service

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