OSDN Git Service

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