OSDN Git Service

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