OSDN Git Service

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