OSDN Git Service

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