OSDN Git Service

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