OSDN Git Service

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