OSDN Git Service

グローバルにm_nameという変数があり、ローカルのm_nameの宣言を忘れても
[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         "EASY_SPELL",
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
1217         /* Process 'M' for "Mimic" (one line only) */
1218         else if (buf[0] == 'M')
1219         {
1220                 int mimic;
1221
1222                 /* Scan for the values */
1223                 if (1 != sscanf(buf+2, "%d",
1224                                 &mimic)) return (1);
1225
1226                 /* Save the values */
1227                 f_ptr->mimic = mimic;
1228
1229         }
1230
1231
1232         /* Process 'G' for "Graphics" (one line only) */
1233         else if (buf[0] == 'G')
1234         {
1235                 byte tmp;
1236
1237                 /* Paranoia */
1238                 if (!buf[2]) return (1);
1239                 if (!buf[3]) return (1);
1240                 if (!buf[4]) return (1);
1241
1242                 /* Extract the color */
1243                 tmp = color_char_to_attr(buf[4]);
1244
1245                 /* Paranoia */
1246                 if (tmp > 127) return (1);
1247
1248                 /* Save the values */
1249                 f_ptr->d_attr = tmp;
1250                 f_ptr->d_char = buf[2];
1251
1252         }
1253
1254         /* Oops */
1255         else    return (6);
1256
1257         /* Success */
1258         return (0);
1259 }
1260
1261
1262 /*
1263  * Grab one flag in an object_kind from a textual string
1264  */
1265 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1266 {
1267         int i;
1268
1269         /* Check flags */
1270         for (i = 0; i < TR_FLAG_MAX; i++)
1271         {
1272                 if (streq(what, k_info_flags[i]))
1273                 {
1274                         add_flag(k_ptr->flags, i);
1275                         return (0);
1276                 }
1277         }
1278
1279         /* Check gen_flags */
1280         for (i = 0; i < 32; i++)
1281         {
1282                 if (streq(what, k_info_gen_flags[i]))
1283                 {
1284                         k_ptr->gen_flags |= (1L << i);
1285                         return (0);
1286                 }
1287         }
1288
1289         /* Oops */
1290 #ifdef JP
1291         msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1292 #else
1293         msg_format("Unknown object flag '%s'.", what);
1294 #endif
1295
1296
1297         /* Error */
1298         return (1);
1299 }
1300
1301
1302 /*
1303  * Initialize the "k_info" array, by parsing an ascii "template" file
1304  */
1305 errr parse_k_info(char *buf, header *head)
1306 {
1307         int i;
1308
1309         char *s, *t;
1310
1311         /* Current entry */
1312         static object_kind *k_ptr = NULL;
1313
1314
1315         /* Process 'N' for "New/Number/Name" */
1316         if (buf[0] == 'N')
1317         {
1318                 /* Find the colon before the name */
1319                 s = strchr(buf+2, ':');
1320
1321                         /* Verify that colon */
1322                 if (!s) return (1);
1323
1324                 /* Nuke the colon, advance to the name */
1325                 *s++ = '\0';
1326
1327 #ifdef JP
1328                 /* Paranoia -- require a name */
1329                 if (!*s) return (1);
1330 #endif
1331                 /* Get the index */
1332                 i = atoi(buf+2);
1333
1334                 /* Verify information */
1335                 if (i <= error_idx) return (4);
1336
1337                 /* Verify information */
1338                 if (i >= head->info_num) return (2);
1339
1340                 /* Save the index */
1341                 error_idx = i;
1342
1343                 /* Point at the "info" */
1344                 k_ptr = &k_info[i];
1345
1346 #ifdef JP
1347                 /* Store the name */
1348                 if (!add_name(&k_ptr->name, head, s)) return (7);
1349 #endif
1350         }
1351
1352         /* There better be a current k_ptr */
1353         else if (!k_ptr) return (3);
1354
1355
1356 #ifdef JP
1357         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
1358         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1359         else if (buf[0] == 'E')
1360         {
1361                 /* nothing to do */
1362         }
1363 #else
1364         else if (buf[0] == 'E')
1365         {
1366                 /* Acquire the Text */
1367                 s = buf+2;
1368
1369                 /* Store the name */
1370                 if (!add_name(&k_ptr->name, head, s)) return (7);
1371         }
1372 #endif
1373
1374         /* Process 'D' for "Description" */
1375         else if (buf[0] == 'D')
1376         {
1377 #ifdef JP
1378                 if (buf[2] == '$')
1379                         return (0);
1380                 /* Acquire the text */
1381                 s = buf+2;
1382 #else
1383                 if (buf[2] != '$')
1384                         return (0);
1385                 /* Acquire the text */
1386                 s = buf+3;
1387 #endif
1388
1389                 /* Store the text */
1390                 if (!add_text(&k_ptr->text, head, s)) return (7);
1391         }
1392
1393         /* Process 'G' for "Graphics" (one line only) */
1394         else if (buf[0] == 'G')
1395         {
1396                 char sym;
1397                 byte tmp;
1398
1399                 /* Paranoia */
1400                 if (!buf[2]) return (1);
1401                 if (!buf[3]) return (1);
1402                 if (!buf[4]) return (1);
1403
1404                 /* Extract the char */
1405                 sym = buf[2];
1406
1407                 /* Extract the attr */
1408                 tmp = color_char_to_attr(buf[4]);
1409
1410                 /* Paranoia */
1411                 if (tmp > 127) return (1);
1412
1413                 /* Save the values */
1414                 k_ptr->d_attr = tmp;
1415                 k_ptr->d_char = sym;
1416         }
1417
1418         /* Process 'I' for "Info" (one line only) */
1419         else if (buf[0] == 'I')
1420         {
1421                 int tval, sval, pval;
1422
1423                 /* Scan for the values */
1424                 if (3 != sscanf(buf+2, "%d:%d:%d",
1425                                 &tval, &sval, &pval)) return (1);
1426
1427                 /* Save the values */
1428                 k_ptr->tval = tval;
1429                 k_ptr->sval = sval;
1430                 k_ptr->pval = pval;
1431         }
1432
1433         /* Process 'W' for "More Info" (one line only) */
1434         else if (buf[0] == 'W')
1435         {
1436                 int level, extra, wgt;
1437                 long cost;
1438
1439                 /* Scan for the values */
1440                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1441                                 &level, &extra, &wgt, &cost)) return (1);
1442
1443                 /* Save the values */
1444                 k_ptr->level = level;
1445                 k_ptr->extra = extra;
1446                 k_ptr->weight = wgt;
1447                 k_ptr->cost = cost;
1448         }
1449
1450         /* Process 'A' for "Allocation" (one line only) */
1451         else if (buf[0] == 'A')
1452         {
1453                 int i;
1454
1455                 /* XXX XXX XXX Simply read each number following a colon */
1456                 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1457                 {
1458                                 /* Default chance */
1459                         k_ptr->chance[i] = 1;
1460
1461                                 /* Store the attack damage index */
1462                         k_ptr->locale[i] = atoi(s+1);
1463
1464                                 /* Find the slash */
1465                         t = strchr(s+1, '/');
1466
1467                                 /* Find the next colon */
1468                         s = strchr(s+1, ':');
1469
1470                                 /* If the slash is "nearby", use it */
1471                         if (t && (!s || t < s))
1472                         {
1473                                 int chance = atoi(t+1);
1474                                 if (chance > 0) k_ptr->chance[i] = chance;
1475                         }
1476                 }
1477         }
1478
1479         /* Hack -- Process 'P' for "power" and such */
1480         else if (buf[0] == 'P')
1481         {
1482                 int ac, hd1, hd2, th, td, ta;
1483
1484                 /* Scan for the values */
1485                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1486                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1487
1488                 k_ptr->ac = ac;
1489                 k_ptr->dd = hd1;
1490                 k_ptr->ds = hd2;
1491                 k_ptr->to_h = th;
1492                 k_ptr->to_d = td;
1493                 k_ptr->to_a =  ta;
1494         }
1495
1496         /* Hack -- Process 'F' for flags */
1497         else if (buf[0] == 'F')
1498         {
1499                 /* Parse every entry textually */
1500                 for (s = buf + 2; *s; )
1501                 {
1502                                 /* Find the end of this entry */
1503                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1504
1505                                 /* Nuke and skip any dividers */
1506                         if (*t)
1507                         {
1508                                 *t++ = '\0';
1509                                 while (*t == ' ' || *t == '|') t++;
1510                         }
1511
1512                                 /* Parse this entry */
1513                         if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1514
1515                                 /* Start the next entry */
1516                         s = t;
1517                 }
1518         }
1519
1520
1521         /* Oops */
1522         else return (6);
1523
1524
1525         /* Success */
1526         return (0);
1527 }
1528
1529
1530 /*
1531  * Grab one flag in an artifact_type from a textual string
1532  */
1533 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1534 {
1535         int i;
1536
1537         /* Check flags */
1538         for (i = 0; i < TR_FLAG_MAX; i++)
1539         {
1540                 if (streq(what, k_info_flags[i]))
1541                 {
1542                         add_flag(a_ptr->flags, i);
1543                         return (0);
1544                 }
1545         }
1546
1547         /* Check gen_flags */
1548         for (i = 0; i < 32; i++)
1549         {
1550                 if (streq(what, k_info_gen_flags[i]))
1551                 {
1552                         a_ptr->gen_flags |= (1L << i);
1553                         return (0);
1554                 }
1555         }
1556
1557         /* Oops */
1558 #ifdef JP
1559         msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1560 #else
1561         msg_format("Unknown artifact flag '%s'.", what);
1562 #endif
1563
1564
1565         /* Error */
1566         return (1);
1567 }
1568
1569
1570
1571
1572 /*
1573  * Initialize the "a_info" array, by parsing an ascii "template" file
1574  */
1575 errr parse_a_info(char *buf, header *head)
1576 {
1577         int i;
1578
1579         char *s, *t;
1580
1581         /* Current entry */
1582         static artifact_type *a_ptr = NULL;
1583
1584
1585         /* Process 'N' for "New/Number/Name" */
1586         if (buf[0] == 'N')
1587         {
1588                 /* Find the colon before the name */
1589                 s = strchr(buf+2, ':');
1590
1591                         /* Verify that colon */
1592                 if (!s) return (1);
1593
1594                 /* Nuke the colon, advance to the name */
1595                 *s++ = '\0';
1596 #ifdef JP
1597                 /* Paranoia -- require a name */
1598                 if (!*s) return (1);
1599 #endif
1600                 /* Get the index */
1601                 i = atoi(buf+2);
1602
1603                 /* Verify information */
1604                 if (i < error_idx) return (4);
1605
1606                 /* Verify information */
1607                 if (i >= head->info_num) return (2);
1608
1609                 /* Save the index */
1610                 error_idx = i;
1611
1612                 /* Point at the "info" */
1613                 a_ptr = &a_info[i];
1614
1615                 /* Ignore everything */
1616                 add_flag(a_ptr->flags, TR_IGNORE_ACID);
1617                 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
1618                 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
1619                 add_flag(a_ptr->flags, TR_IGNORE_COLD);
1620 #ifdef JP
1621                 /* Store the name */
1622                 if (!add_name(&a_ptr->name, head, s)) return (7);
1623 #endif
1624         }
1625
1626         /* There better be a current a_ptr */
1627         else if (!a_ptr) return (3);
1628
1629
1630 #ifdef JP
1631         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
1632         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1633         else if (buf[0] == 'E')
1634         {
1635                 /* nothing to do */
1636         }
1637 #else
1638         else if (buf[0] == 'E')
1639         {
1640                 /* Acquire the Text */
1641                 s = buf+2;
1642
1643                 /* Store the name */
1644                 if (!add_name(&a_ptr->name, head, s)) return (7);
1645         }
1646 #endif
1647
1648         /* Process 'D' for "Description" */
1649         else if (buf[0] == 'D')
1650         {
1651 #ifdef JP
1652                 if (buf[2] == '$')
1653                         return (0);
1654                 /* Acquire the text */
1655                 s = buf+2;
1656 #else
1657                 if (buf[2] != '$')
1658                         return (0);
1659                 /* Acquire the text */
1660                 s = buf+3;
1661 #endif
1662
1663                 /* Store the text */
1664                 if (!add_text(&a_ptr->text, head, s)) return (7);
1665         }
1666
1667
1668         /* Process 'I' for "Info" (one line only) */
1669         else if (buf[0] == 'I')
1670         {
1671                 int tval, sval, pval;
1672
1673                 /* Scan for the values */
1674                 if (3 != sscanf(buf+2, "%d:%d:%d",
1675                                 &tval, &sval, &pval)) return (1);
1676
1677                 /* Save the values */
1678                 a_ptr->tval = tval;
1679                 a_ptr->sval = sval;
1680                 a_ptr->pval = pval;
1681         }
1682
1683         /* Process 'W' for "More Info" (one line only) */
1684         else if (buf[0] == 'W')
1685         {
1686                 int level, rarity, wgt;
1687                 long cost;
1688
1689                 /* Scan for the values */
1690                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1691                                 &level, &rarity, &wgt, &cost)) return (1);
1692
1693                 /* Save the values */
1694                 a_ptr->level = level;
1695                 a_ptr->rarity = rarity;
1696                 a_ptr->weight = wgt;
1697                 a_ptr->cost = cost;
1698         }
1699
1700         /* Hack -- Process 'P' for "power" and such */
1701         else if (buf[0] == 'P')
1702         {
1703                 int ac, hd1, hd2, th, td, ta;
1704
1705                 /* Scan for the values */
1706                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1707                                 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1708
1709                 a_ptr->ac = ac;
1710                 a_ptr->dd = hd1;
1711                 a_ptr->ds = hd2;
1712                 a_ptr->to_h = th;
1713                 a_ptr->to_d = td;
1714                 a_ptr->to_a =  ta;
1715         }
1716
1717         /* Hack -- Process 'F' for flags */
1718         else if (buf[0] == 'F')
1719         {
1720                 /* Parse every entry textually */
1721                 for (s = buf + 2; *s; )
1722                 {
1723                                 /* Find the end of this entry */
1724                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1725
1726                                 /* Nuke and skip any dividers */
1727                         if (*t)
1728                         {
1729                                 *t++ = '\0';
1730                                 while ((*t == ' ') || (*t == '|')) t++;
1731                         }
1732
1733                                 /* Parse this entry */
1734                         if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1735
1736                                 /* Start the next entry */
1737                         s = t;
1738                 }
1739         }
1740
1741
1742         /* Oops */
1743         else return (6);
1744
1745
1746         /* Success */
1747         return (0);
1748 }
1749
1750
1751 /*
1752  * Grab one flag in a ego-item_type from a textual string
1753  */
1754 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1755 {
1756         int i;
1757
1758         /* Check flags */
1759         for (i = 0; i < TR_FLAG_MAX; i++)
1760         {
1761                 if (streq(what, k_info_flags[i]))
1762                 {
1763                         add_flag(e_ptr->flags, i);
1764                         return (0);
1765                 }
1766         }
1767         
1768         /* Check gen_flags */
1769         for (i = 0; i < 32; i++)
1770         {
1771                 if (streq(what, k_info_gen_flags[i]))
1772                 {
1773                         e_ptr->gen_flags |= (1L << i);
1774                         return (0);
1775                 }
1776         }
1777
1778 /* Oops */
1779 #ifdef JP
1780         msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1781 #else
1782         msg_format("Unknown ego-item flag '%s'.", what);
1783 #endif
1784
1785
1786         /* Error */
1787         return (1);
1788 }
1789
1790
1791
1792
1793 /*
1794  * Initialize the "e_info" array, by parsing an ascii "template" file
1795  */
1796 errr parse_e_info(char *buf, header *head)
1797 {
1798         int i;
1799
1800         char *s, *t;
1801
1802         /* Current entry */
1803         static ego_item_type *e_ptr = NULL;
1804
1805
1806         /* Just before the first record */
1807         error_idx = -1;
1808
1809         /* Just before the first line */
1810         error_line = -1;
1811
1812
1813         /* Process 'N' for "New/Number/Name" */
1814         if (buf[0] == 'N')
1815         {
1816                 /* Find the colon before the name */
1817                 s = strchr(buf+2, ':');
1818
1819                         /* Verify that colon */
1820                 if (!s) return (1);
1821
1822                 /* Nuke the colon, advance to the name */
1823                 *s++ = '\0';
1824 #ifdef JP
1825                 /* Paranoia -- require a name */
1826                 if (!*s) return (1);
1827 #endif
1828                 /* Get the index */
1829                 i = atoi(buf+2);
1830
1831                 /* Verify information */
1832                 if (i < error_idx) return (4);
1833
1834                 /* Verify information */
1835                 if (i >= head->info_num) return (2);
1836
1837                 /* Save the index */
1838                 error_idx = i;
1839
1840                 /* Point at the "info" */
1841                 e_ptr = &e_info[i];
1842 #ifdef JP
1843                 /* Store the name */
1844                 if (!add_name(&e_ptr->name, head, s)) return (7);
1845 #endif
1846         }
1847
1848         /* There better be a current e_ptr */
1849         else if (!e_ptr) return (3);
1850
1851
1852 #ifdef JP
1853         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
1854         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1855         else if (buf[0] == 'E')
1856         {
1857                 /* nothing to do */
1858         }
1859 #else
1860         else if (buf[0] == 'E')
1861         {
1862                 /* Acquire the Text */
1863                 s = buf+2;
1864
1865                 /* Store the name */
1866                 if (!add_name(&e_ptr->name, head, s)) return (7);
1867         }
1868 #endif
1869 #if 0
1870
1871         /* Process 'D' for "Description" */
1872         else if (buf[0] == 'D')
1873         {
1874                 /* Acquire the text */
1875                 s = buf+2;
1876
1877                 /* Store the text */
1878                 if (!add_text(&e_ptr->text, head, s)) return (7);
1879         }
1880
1881 #endif
1882
1883         /* Process 'X' for "Xtra" (one line only) */
1884         else if (buf[0] == 'X')
1885         {
1886                 int slot, rating;
1887
1888                 /* Scan for the values */
1889                 if (2 != sscanf(buf+2, "%d:%d",
1890                                 &slot, &rating)) return (1);
1891
1892                 /* Save the values */
1893                 e_ptr->slot = slot;
1894                 e_ptr->rating = rating;
1895         }
1896
1897         /* Process 'W' for "More Info" (one line only) */
1898         else if (buf[0] == 'W')
1899         {
1900                 int level, rarity, pad2;
1901                 long cost;
1902
1903                 /* Scan for the values */
1904                 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1905                                 &level, &rarity, &pad2, &cost)) return (1);
1906
1907                 /* Save the values */
1908                 e_ptr->level = level;
1909                 e_ptr->rarity = rarity;
1910                 /* e_ptr->weight = wgt; */
1911                 e_ptr->cost = cost;
1912         }
1913
1914         /* Hack -- Process 'C' for "creation" */
1915         else if (buf[0] == 'C')
1916         {
1917                 int th, td, ta, pv;
1918
1919                 /* Scan for the values */
1920                 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1921                                 &th, &td, &ta, &pv)) return (1);
1922
1923                 e_ptr->max_to_h = th;
1924                 e_ptr->max_to_d = td;
1925                 e_ptr->max_to_a = ta;
1926                 e_ptr->max_pval = pv;
1927         }
1928
1929         /* Hack -- Process 'F' for flags */
1930         else if (buf[0] == 'F')
1931         {
1932                 /* Parse every entry textually */
1933                 for (s = buf + 2; *s; )
1934                 {
1935                                 /* Find the end of this entry */
1936                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1937
1938                                 /* Nuke and skip any dividers */
1939                         if (*t)
1940                         {
1941                                 *t++ = '\0';
1942                                 while ((*t == ' ') || (*t == '|')) t++;
1943                         }
1944
1945                                 /* Parse this entry */
1946                         if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
1947
1948                                 /* Start the next entry */
1949                         s = t;
1950                 }
1951         }
1952
1953         /* Oops */
1954         else return (6);
1955
1956         /* Success */
1957         return (0);
1958 }
1959
1960
1961 /*
1962  * Grab one (basic) flag in a monster_race from a textual string
1963  */
1964 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
1965 {
1966         int i;
1967
1968         /* Scan flags1 */
1969         for (i = 0; i < 32; i++)
1970         {
1971                 if (streq(what, r_info_flags1[i]))
1972                 {
1973                         r_ptr->flags1 |= (1L << i);
1974                         return (0);
1975                 }
1976         }
1977
1978         /* Scan flags2 */
1979         for (i = 0; i < 32; i++)
1980         {
1981                 if (streq(what, r_info_flags2[i]))
1982                 {
1983                         r_ptr->flags2 |= (1L << i);
1984                         return (0);
1985                 }
1986         }
1987
1988         /* Scan flags3 */
1989         for (i = 0; i < 32; i++)
1990         {
1991                 if (streq(what, r_info_flags3[i]))
1992                 {
1993                         r_ptr->flags3 |= (1L << i);
1994                         return (0);
1995                 }
1996         }
1997
1998         /* Scan flags7 */
1999         for (i = 0; i < 32; i++)
2000         {
2001                 if (streq(what, r_info_flags7[i]))
2002                 {
2003                         r_ptr->flags7 |= (1L << i);
2004                         return (0);
2005                 }
2006         }
2007
2008         /* Scan flags8 */
2009         for (i = 0; i < 32; i++)
2010         {
2011                 if (streq(what, r_info_flags8[i]))
2012                 {
2013                         r_ptr->flags8 |= (1L << i);
2014                         return (0);
2015                 }
2016         }
2017
2018         /* Scan flags9 */
2019         for (i = 0; i < 32; i++)
2020         {
2021                 if (streq(what, r_info_flags9[i]))
2022                 {
2023                         r_ptr->flags9 |= (1L << i);
2024                         return (0);
2025                 }
2026         }
2027
2028         /* Oops */
2029 #ifdef JP
2030         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2031 #else
2032         msg_format("Unknown monster flag '%s'.", what);
2033 #endif
2034
2035
2036         /* Failure */
2037         return (1);
2038 }
2039
2040
2041 /*
2042  * Grab one (spell) flag in a monster_race from a textual string
2043  */
2044 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2045 {
2046         int i;
2047
2048         /* Scan flags4 */
2049         for (i = 0; i < 32; i++)
2050         {
2051                 if (streq(what, r_info_flags4[i]))
2052                 {
2053                         r_ptr->flags4 |= (1L << i);
2054                         return (0);
2055                 }
2056         }
2057
2058         /* Scan flags5 */
2059         for (i = 0; i < 32; i++)
2060         {
2061                 if (streq(what, r_info_flags5[i]))
2062                 {
2063                         r_ptr->flags5 |= (1L << i);
2064                         return (0);
2065                 }
2066         }
2067
2068         /* Scan flags6 */
2069         for (i = 0; i < 32; i++)
2070         {
2071                 if (streq(what, r_info_flags6[i]))
2072                 {
2073                         r_ptr->flags6 |= (1L << i);
2074                         return (0);
2075                 }
2076         }
2077
2078         /* Oops */
2079 #ifdef JP
2080         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2081 #else
2082         msg_format("Unknown monster flag '%s'.", what);
2083 #endif
2084
2085
2086         /* Failure */
2087         return (1);
2088 }
2089
2090
2091
2092
2093 /*
2094  * Initialize the "r_info" array, by parsing an ascii "template" file
2095  */
2096 errr parse_r_info(char *buf, header *head)
2097 {
2098         int i;
2099
2100         char *s, *t;
2101
2102         /* Current entry */
2103         static monster_race *r_ptr = NULL;
2104
2105
2106         /* Process 'N' for "New/Number/Name" */
2107         if (buf[0] == 'N')
2108         {
2109                 /* Find the colon before the name */
2110                 s = strchr(buf+2, ':');
2111
2112                         /* Verify that colon */
2113                 if (!s) return (1);
2114
2115                 /* Nuke the colon, advance to the name */
2116                 *s++ = '\0';
2117 #ifdef JP
2118                 /* Paranoia -- require a name */
2119                 if (!*s) return (1);
2120 #endif
2121                 /* Get the index */
2122                 i = atoi(buf+2);
2123
2124                 /* Verify information */
2125                 if (i < error_idx) return (4);
2126
2127                 /* Verify information */
2128                 if (i >= head->info_num) return (2);
2129
2130                 /* Save the index */
2131                 error_idx = i;
2132
2133                 /* Point at the "info" */
2134                 r_ptr = &r_info[i];
2135 #ifdef JP
2136                 /* Store the name */
2137                 if (!add_name(&r_ptr->name, head, s)) return (7);
2138 #endif
2139         }
2140
2141         /* There better be a current r_ptr */
2142         else if (!r_ptr) return (3);
2143
2144
2145 #ifdef JP
2146         /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà*/
2147         /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2148         else if (buf[0] == 'E')
2149         {
2150                 /* Acquire the Text */
2151                 s = buf+2;
2152
2153                 /* Store the name */
2154                 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2155         }
2156 #else
2157         else if (buf[0] == 'E')
2158         {
2159                 /* Acquire the Text */
2160                 s = buf+2;
2161
2162                 /* Store the name */
2163                 if (!add_name(&r_ptr->name, head, s)) return (7);
2164         }
2165 #endif
2166         /* Process 'D' for "Description" */
2167         else if (buf[0] == 'D')
2168         {
2169 #ifdef JP
2170                 if (buf[2] == '$')
2171                         return (0);
2172                 /* Acquire the text */
2173                 s = buf+2;
2174 #else
2175                 if (buf[2] != '$')
2176                         return (0);
2177                 /* Acquire the text */
2178                 s = buf+3;
2179 #endif
2180
2181                 /* Store the text */
2182                 if (!add_text(&r_ptr->text, head, s)) return (7);
2183         }
2184
2185         /* Process 'G' for "Graphics" (one line only) */
2186         else if (buf[0] == 'G')
2187         {
2188                 char sym;
2189                 byte tmp;
2190
2191                 /* Paranoia */
2192                 if (!buf[2]) return (1);
2193                 if (!buf[3]) return (1);
2194                 if (!buf[4]) return (1);
2195
2196                 /* Extract the char */
2197                 sym = buf[2];
2198
2199                 /* Extract the attr */
2200                 tmp = color_char_to_attr(buf[4]);
2201
2202                 /* Paranoia */
2203                 if (tmp > 127) return (1);
2204
2205                 /* Save the values */
2206                 r_ptr->d_char = sym;
2207                 r_ptr->d_attr = tmp;
2208         }
2209
2210         /* Process 'I' for "Info" (one line only) */
2211         else if (buf[0] == 'I')
2212         {
2213                 int spd, hp1, hp2, aaf, ac, slp;
2214
2215                 /* Scan for the other values */
2216                 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2217                                 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2218
2219                 /* Save the values */
2220                 r_ptr->speed = spd;
2221                 r_ptr->hdice = hp1;
2222                 r_ptr->hside = hp2;
2223                 r_ptr->aaf = aaf;
2224                 r_ptr->ac = ac;
2225                 r_ptr->sleep = slp;
2226         }
2227
2228         /* Process 'W' for "More Info" (one line only) */
2229         else if (buf[0] == 'W')
2230         {
2231                 int lev, rar, pad;
2232                 long exp;
2233                 long nextexp;
2234                 int nextmon;
2235
2236                 /* Scan for the values */
2237                 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2238                                 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2239
2240                 /* Save the values */
2241                 r_ptr->level = lev;
2242                 r_ptr->rarity = rar;
2243                 r_ptr->extra = pad;
2244                 r_ptr->mexp = exp;
2245                 r_ptr->next_exp = nextexp;
2246                 r_ptr->next_r_idx = nextmon;
2247         }
2248
2249         /* Process 'B' for "Blows" (up to four lines) */
2250         else if (buf[0] == 'B')
2251         {
2252                 int n1, n2;
2253
2254                 /* Find the next empty blow slot (if any) */
2255                 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2256
2257                 /* Oops, no more slots */
2258                 if (i == 4) return (1);
2259
2260                 /* Analyze the first field */
2261                 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2262
2263                 /* Terminate the field (if necessary) */
2264                 if (*t == ':') *t++ = '\0';
2265
2266                 /* Analyze the method */
2267                 for (n1 = 0; r_info_blow_method[n1]; n1++)
2268                 {
2269                         if (streq(s, r_info_blow_method[n1])) break;
2270                 }
2271
2272                 /* Invalid method */
2273                 if (!r_info_blow_method[n1]) return (1);
2274
2275                 /* Analyze the second field */
2276                 for (s = t; *t && (*t != ':'); t++) /* loop */;
2277
2278                 /* Terminate the field (if necessary) */
2279                 if (*t == ':') *t++ = '\0';
2280
2281                 /* Analyze effect */
2282                 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2283                 {
2284                         if (streq(s, r_info_blow_effect[n2])) break;
2285                 }
2286
2287                 /* Invalid effect */
2288                 if (!r_info_blow_effect[n2]) return (1);
2289
2290                 /* Analyze the third field */
2291                 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2292
2293                 /* Terminate the field (if necessary) */
2294                 if (*t == 'd') *t++ = '\0';
2295
2296                 /* Save the method */
2297                 r_ptr->blow[i].method = n1;
2298
2299                 /* Save the effect */
2300                 r_ptr->blow[i].effect = n2;
2301
2302                 /* Extract the damage dice and sides */
2303                 r_ptr->blow[i].d_dice = atoi(s);
2304                 r_ptr->blow[i].d_side = atoi(t);
2305         }
2306
2307         /* Process 'F' for "Basic Flags" (multiple lines) */
2308         else if (buf[0] == 'F')
2309         {
2310                 /* Parse every entry */
2311                 for (s = buf + 2; *s; )
2312                 {
2313                                 /* Find the end of this entry */
2314                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2315
2316                                 /* Nuke and skip any dividers */
2317                         if (*t)
2318                         {
2319                                 *t++ = '\0';
2320                                 while (*t == ' ' || *t == '|') t++;
2321                         }
2322
2323                                 /* Parse this entry */
2324                         if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2325
2326                                 /* Start the next entry */
2327                         s = t;
2328                 }
2329         }
2330
2331         /* Process 'S' for "Spell Flags" (multiple lines) */
2332         else if (buf[0] == 'S')
2333         {
2334                 /* Parse every entry */
2335                 for (s = buf + 2; *s; )
2336                 {
2337                                 /* Find the end of this entry */
2338                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2339
2340                                 /* Nuke and skip any dividers */
2341                         if (*t)
2342                         {
2343                                 *t++ = '\0';
2344                                 while ((*t == ' ') || (*t == '|')) t++;
2345                         }
2346
2347                                 /* XXX XXX XXX Hack -- Read spell frequency */
2348                         if (1 == sscanf(s, "1_IN_%d", &i))
2349                         {
2350                                 /* Extract a "frequency" */
2351                                 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2352
2353                                         /* Start at next entry */
2354                                 s = t;
2355
2356                                 /* Continue */
2357                                 continue;
2358                         }
2359
2360                                 /* Parse this entry */
2361                         if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2362
2363                                 /* Start the next entry */
2364                         s = t;
2365                 }
2366         }
2367
2368         /* Oops */
2369         else return (6);
2370
2371
2372         /* Success */
2373         return (0);
2374 }
2375
2376
2377 /*
2378  * Grab one flag for a dungeon type from a textual string
2379  */
2380 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2381 {
2382         int i;
2383
2384         /* Scan flags1 */
2385         for (i = 0; i < 32; i++)
2386         {
2387                 if (streq(what, d_info_flags1[i]))
2388                 {
2389                         d_ptr->flags1 |= (1L << i);
2390                         return (0);
2391                 }
2392         }
2393
2394         /* Oops */
2395 #ifdef JP
2396         msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2397 #else
2398         msg_format("Unknown dungeon type flag '%s'.", what);
2399 #endif
2400
2401         /* Failure */
2402         return (1);
2403 }
2404
2405 /*
2406  * Grab one (basic) flag in a monster_race from a textual string
2407  */
2408 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2409 {
2410         int i;
2411
2412         /* Scan flags1 */
2413         for (i = 0; i < 32; i++)
2414         {
2415                 if (streq(what, r_info_flags1[i]))
2416                 {
2417                         d_ptr->mflags1 |= (1L << i);
2418                         return (0);
2419                 }
2420         }
2421
2422         /* Scan flags2 */
2423         for (i = 0; i < 32; i++)
2424         {
2425                 if (streq(what, r_info_flags2[i]))
2426                 {
2427                         d_ptr->mflags2 |= (1L << i);
2428                         return (0);
2429                 }
2430         }
2431
2432         /* Scan flags3 */
2433         for (i = 0; i < 32; i++)
2434         {
2435                 if (streq(what, r_info_flags3[i]))
2436                 {
2437                         d_ptr->mflags3 |= (1L << i);
2438                         return (0);
2439                 }
2440         }
2441
2442         /* Scan flags7 */
2443         for (i = 0; i < 32; i++)
2444         {
2445                 if (streq(what, r_info_flags7[i]))
2446                 {
2447                         d_ptr->mflags7 |= (1L << i);
2448                         return (0);
2449                 }
2450         }
2451
2452         /* Scan flags8 */
2453         for (i = 0; i < 32; i++)
2454         {
2455                 if (streq(what, r_info_flags8[i]))
2456                 {
2457                         d_ptr->mflags8 |= (1L << i);
2458                         return (0);
2459                 }
2460         }
2461
2462         /* Scan flags9 */
2463         for (i = 0; i < 32; i++)
2464         {
2465                 if (streq(what, r_info_flags9[i]))
2466                 {
2467                         d_ptr->mflags9 |= (1L << i);
2468                         return (0);
2469                 }
2470         }
2471
2472         /* Oops */
2473 #ifdef JP
2474         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2475 #else
2476         msg_format("Unknown monster flag '%s'.", what);
2477 #endif
2478         /* Failure */
2479         return (1);
2480 }
2481
2482
2483 /*
2484  * Grab one (spell) flag in a monster_race from a textual string
2485  */
2486 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2487 {
2488         int i;
2489
2490         /* Scan flags4 */
2491         for (i = 0; i < 32; i++)
2492         {
2493                 if (streq(what, r_info_flags4[i]))
2494                 {
2495                         d_ptr->mflags4 |= (1L << i);
2496                         return (0);
2497                 }
2498         }
2499
2500         /* Scan flags5 */
2501         for (i = 0; i < 32; i++)
2502         {
2503                 if (streq(what, r_info_flags5[i]))
2504                 {
2505                         d_ptr->mflags5 |= (1L << i);
2506                         return (0);
2507                 }
2508         }
2509
2510         /* Scan flags6 */
2511         for (i = 0; i < 32; i++)
2512         {
2513                 if (streq(what, r_info_flags6[i]))
2514                 {
2515                         d_ptr->mflags6 |= (1L << i);
2516                         return (0);
2517                 }
2518         }
2519
2520         /* Oops */
2521 #ifdef JP
2522         msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2523 #else
2524         msg_format("Unknown monster flag '%s'.", what);
2525 #endif
2526
2527         /* Failure */
2528         return (1);
2529 }
2530
2531 /*
2532  * Initialize the "d_info" array, by parsing an ascii "template" file
2533  */
2534 errr parse_d_info(char *buf, header *head)
2535 {
2536         int i;
2537
2538         char *s, *t;
2539
2540         /* Current entry */
2541         static dungeon_info_type *d_ptr = NULL;
2542
2543
2544         /* Process 'N' for "New/Number/Name" */
2545         if (buf[0] == 'N')
2546         {
2547                 /* Find the colon before the name */
2548                 s = strchr(buf+2, ':');
2549
2550                 /* Verify that colon */
2551                 if (!s) return (1);
2552
2553                 /* Nuke the colon, advance to the name */
2554                 *s++ = '\0';
2555 #ifdef JP
2556                 /* Paranoia -- require a name */
2557                 if (!*s) return (1);
2558 #endif
2559                 /* Get the index */
2560                 i = atoi(buf+2);
2561
2562                 /* Verify information */
2563                 if (i < error_idx) return (4);
2564
2565                 /* Verify information */
2566                 if (i >= head->info_num) return (2);
2567
2568                 /* Save the index */
2569                 error_idx = i;
2570
2571                 /* Point at the "info" */
2572                 d_ptr = &d_info[i];
2573 #ifdef JP
2574                 /* Store the name */
2575                 if (!add_name(&d_ptr->name, head, s)) return (7);
2576 #endif
2577         }
2578
2579 #ifdef JP
2580         else if (buf[0] == 'E') return (0);
2581 #else
2582         else if (buf[0] == 'E')
2583         {
2584                 /* Acquire the Text */
2585                 s = buf+2;
2586
2587                 /* Store the name */
2588                 if (!add_name(&d_ptr->name, head, s)) return (7);
2589         }
2590 #endif
2591
2592         /* Process 'D' for "Description */
2593         else if (buf[0] == 'D')
2594         {
2595 #ifdef JP
2596                 if (buf[2] == '$')
2597                         return (0);
2598                 /* Acquire the text */
2599                 s = buf+2;
2600 #else
2601                 if (buf[2] != '$')
2602                         return (0);
2603                 /* Acquire the text */
2604                 s = buf+3;
2605 #endif
2606
2607                 /* Store the text */
2608                 if (!add_text(&d_ptr->text, head, s)) return (7);
2609         }
2610
2611         /* Process 'W' for "More Info" (one line only) */
2612         else if (buf[0] == 'W')
2613         {
2614                 int min_lev, max_lev;
2615                 int min_plev, mode;
2616                 int min_alloc, max_chance;
2617                 int obj_good, obj_great;
2618                 int pit, nest;
2619
2620                 /* Scan for the values */
2621                 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2622                                  &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2623
2624                 /* Save the values */
2625                 d_ptr->mindepth = min_lev;
2626                 d_ptr->maxdepth = max_lev;
2627                 d_ptr->min_plev = min_plev;
2628                 d_ptr->mode = mode;
2629                 d_ptr->min_m_alloc_level = min_alloc;
2630                 d_ptr->max_m_alloc_chance = max_chance;
2631                 d_ptr->obj_good = obj_good;
2632                 d_ptr->obj_great = obj_great;
2633                 d_ptr->pit = pit;
2634                 d_ptr->nest = nest;
2635         }
2636
2637         /* Process 'P' for "Place Info" */
2638         else if (buf[0] == 'P')
2639         {
2640                 int dy, dx;
2641
2642                 /* Scan for the values */
2643                 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2644
2645                 /* Save the values */
2646                 d_ptr->dy = dy;
2647                 d_ptr->dx = dx;
2648         }
2649
2650         /* Process 'L' for "fLoor type" (one line only) */
2651         else if (buf[0] == 'L')
2652         {
2653                 int f1, f2, f3;
2654                 int p1, p2, p3;
2655                 int tunnel;
2656
2657                 /* Scan for the values */
2658                 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2659                                 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2660
2661                 /* Save the values */
2662                 d_ptr->floor1 = f1;
2663                 d_ptr->floor_percent1 = p1;
2664                 d_ptr->floor2 = f2;
2665                 d_ptr->floor_percent2 = p2;
2666                 d_ptr->floor3 = f3;
2667                 d_ptr->floor_percent3 = p3;
2668                 d_ptr->tunnel_percent = tunnel;
2669         }
2670
2671         /* Process 'A' for "wAll type" (one line only) */
2672         else if (buf[0] == 'A')
2673         {
2674                 int w1, w2, w3, outer, inner, stream1, stream2;
2675                 int p1, p2, p3;
2676
2677                 /* Scan for the values */
2678                 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2679                                  &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2680
2681                 /* Save the values */
2682                 d_ptr->fill_type1 = w1;
2683                 d_ptr->fill_percent1 = p1;
2684                 d_ptr->fill_type2 = w2;
2685                 d_ptr->fill_percent2 = p2;
2686                 d_ptr->fill_type3 = w3;
2687                 d_ptr->fill_percent3 = p3;
2688                 d_ptr->outer_wall = outer;
2689                 d_ptr->inner_wall = inner;
2690                 d_ptr->stream1 = stream1;
2691                 d_ptr->stream2 = stream2;
2692         }
2693
2694         /* Process 'F' for "Dungeon Flags" (multiple lines) */
2695         else if (buf[0] == 'F')
2696         {
2697                 int artif = 0, monst = 0;
2698
2699                 /* Parse every entry */
2700                 for (s = buf + 2; *s; )
2701                 {
2702                                 /* Find the end of this entry */
2703                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2704
2705                                 /* Nuke and skip any dividers */
2706                         if (*t)
2707                         {
2708                                 *t++ = '\0';
2709                                 while (*t == ' ' || *t == '|') t++;
2710                         }
2711
2712                                 /* XXX XXX XXX Hack -- Read Final Artifact */
2713                         if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2714                         {
2715                                 /* Extract a "Final Artifact" */
2716                                 d_ptr->final_artifact = artif;
2717
2718                                 /* Start at next entry */
2719                                 s = t;
2720
2721                                 /* Continue */
2722                                 continue;
2723                         }
2724
2725                                 /* XXX XXX XXX Hack -- Read Final Object */
2726                         if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2727                         {
2728                                 /* Extract a "Final Artifact" */
2729                                 d_ptr->final_object = artif;
2730
2731                                 /* Start at next entry */
2732                                 s = t;
2733
2734                                 /* Continue */
2735                                 continue;
2736                         }
2737
2738                                 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2739                         if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2740                         {
2741                                 /* Extract a "Artifact Guardian" */
2742                                 d_ptr->final_guardian = monst;
2743
2744                                 /* Start at next entry */
2745                                 s = t;
2746
2747                                 /* Continue */
2748                                 continue;
2749                         }
2750
2751                                 /* XXX XXX XXX Hack -- Read Special Percentage */
2752                         if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2753                         {
2754                                 /* Extract a "Special %" */
2755                                 d_ptr->special_div = monst;
2756
2757                                 /* Start at next entry */
2758                                 s = t;
2759
2760                                 /* Continue */
2761                                 continue;
2762                         }
2763
2764                                 /* Parse this entry */
2765                         if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2766
2767                                 /* Start the next entry */
2768                         s = t;
2769                 }
2770         }
2771
2772         /* Process 'M' for "Basic Flags" (multiple lines) */
2773         else if (buf[0] == 'M')
2774         {
2775                 byte r_char_number = 0, r_char;
2776
2777                 /* Parse every entry */
2778                 for (s = buf + 2; *s; )
2779                 {
2780                                 /* Find the end of this entry */
2781                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2782
2783                                 /* Nuke and skip any dividers */
2784                         if (*t)
2785                         {
2786                                 *t++ = '\0';
2787                                 while (*t == ' ' || *t == '|') t++;
2788                         }
2789
2790                                 /* XXX XXX XXX Hack -- Read monster symbols */
2791                         if (1 == sscanf(s, "R_CHAR_%c", &r_char))
2792                         {
2793                                 /* Limited to 5 races */
2794                                 if(r_char_number >= 5) continue;
2795
2796                                 /* Extract a "frequency" */
2797                                 d_ptr->r_char[r_char_number++] = r_char;
2798
2799                                 /* Start at next entry */
2800                                 s = t;
2801
2802                                 /* Continue */
2803                                 continue;
2804                         }
2805
2806                                 /* Parse this entry */
2807                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2808
2809                                 /* Start the next entry */
2810                         s = t;
2811                 }
2812         }
2813
2814         /* Process 'S' for "Spell Flags" (multiple lines) */
2815         else if (buf[0] == 'S')
2816         {
2817                 /* Parse every entry */
2818                 for (s = buf + 2; *s; )
2819                 {
2820                                 /* Find the end of this entry */
2821                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2822
2823                                 /* Nuke and skip any dividers */
2824                         if (*t)
2825                         {
2826                                 *t++ = '\0';
2827                                 while ((*t == ' ') || (*t == '|')) t++;
2828                         }
2829
2830                                 /* XXX XXX XXX Hack -- Read spell frequency */
2831                         if (1 == sscanf(s, "1_IN_%d", &i))
2832                         {
2833                                 /* Start at next entry */
2834                                 s = t;
2835
2836                                         /* Continue */
2837                                 continue;
2838                         }
2839
2840                                 /* Parse this entry */
2841                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2842
2843                                 /* Start the next entry */
2844                         s = t;
2845                 }
2846         }
2847
2848         /* Oops */
2849         else return (6);
2850
2851         /* Success */
2852         return (0);
2853 }
2854
2855
2856 #else   /* ALLOW_TEMPLATES */
2857
2858 #ifdef MACINTOSH
2859 static int i = 0;
2860 #endif
2861
2862 #endif  /* ALLOW_TEMPLATES */
2863
2864
2865 /* Random dungeon grid effects */
2866 #define RANDOM_NONE         0x00
2867 #define RANDOM_FEATURE      0x01
2868 #define RANDOM_MONSTER      0x02
2869 #define RANDOM_OBJECT       0x04
2870 #define RANDOM_EGO          0x08
2871 #define RANDOM_ARTIFACT     0x10
2872 #define RANDOM_TRAP         0x20
2873
2874
2875 typedef struct dungeon_grid dungeon_grid;
2876
2877 struct dungeon_grid
2878 {
2879         int             feature;                /* Terrain feature */
2880         int             monster;                /* Monster */
2881         int             object;                 /* Object */
2882         int             ego;                    /* Ego-Item */
2883         int             artifact;               /* Artifact */
2884         int             trap;                   /* Trap */
2885         int             cave_info;              /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2886         int             special;                /* Reserved for special terrain info */
2887         int             random;                 /* Number of the random effect */
2888 };
2889
2890
2891 static dungeon_grid letter[255];
2892
2893
2894 /*
2895  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2896  */
2897 static errr parse_line_feature(char *buf)
2898 {
2899         int num;
2900         char *zz[9];
2901
2902
2903         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2904
2905         /* Tokenize the line */
2906         if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2907         {
2908                 /* Letter to assign */
2909                 int index = zz[0][0];
2910
2911                 /* Reset the info for the letter */
2912                 letter[index].feature = 0;
2913                 letter[index].monster = 0;
2914                 letter[index].object = 0;
2915                 letter[index].ego = 0;
2916                 letter[index].artifact = 0;
2917                 letter[index].trap = 0;
2918                 letter[index].cave_info = 0;
2919                 letter[index].special = 0;
2920                 letter[index].random = 0;
2921
2922                 switch (num)
2923                 {
2924                         /* Special */
2925                         case 9:
2926                                 letter[index].special = atoi(zz[8]);
2927                                 /* Fall through */
2928                         /* Trap */
2929                         case 8:
2930                                 if (zz[7][0] == '*')
2931                                 {
2932                                         letter[index].random |= RANDOM_TRAP;
2933
2934                                         if (zz[7][1])
2935                                         {
2936                                                 zz[7]++;
2937                                                 letter[index].trap = atoi(zz[7]);
2938                                         }
2939                                 }
2940                                 else
2941                                 {
2942                                         letter[index].trap = atoi(zz[7]);
2943                                 }
2944                                 /* Fall through */
2945                         /* Artifact */
2946                         case 7:
2947                                 if (zz[6][0] == '*')
2948                                 {
2949                                         letter[index].random |= RANDOM_ARTIFACT;
2950
2951                                         if (zz[6][1])
2952                                         {
2953                                                 zz[6]++;
2954                                                 letter[index].artifact = atoi(zz[6]);
2955                                         }
2956                                 }
2957                                 else
2958                                 {
2959                                         letter[index].artifact = atoi(zz[6]);
2960                                 }
2961                                 /* Fall through */
2962                         /* Ego-item */
2963                         case 6:
2964                                 if (zz[5][0] == '*')
2965                                 {
2966                                         letter[index].random |= RANDOM_EGO;
2967
2968                                         if (zz[5][1])
2969                                         {
2970                                                 zz[5]++;
2971                                                 letter[index].ego = atoi(zz[5]);
2972                                         }
2973                                 }
2974                                 else
2975                                 {
2976                                         letter[index].ego = atoi(zz[5]);
2977                                 }
2978                                 /* Fall through */
2979                         /* Object */
2980                         case 5:
2981                                 if (zz[4][0] == '*')
2982                                 {
2983                                         letter[index].random |= RANDOM_OBJECT;
2984
2985                                         if (zz[4][1])
2986                                         {
2987                                                 zz[4]++;
2988                                                 letter[index].object = atoi(zz[4]);
2989                                         }
2990                                 }
2991                                 else
2992                                 {
2993                                         letter[index].object = atoi(zz[4]);
2994                                 }
2995                                 /* Fall through */
2996                         /* Monster */
2997                         case 4:
2998                                 if (zz[3][0] == '*')
2999                                 {
3000                                         letter[index].random |= RANDOM_MONSTER;
3001                                         if (zz[3][1])
3002                                         {
3003                                                 zz[3]++;
3004                                                 letter[index].monster = atoi(zz[3]);
3005                                         }
3006                                 }
3007                                 else if (zz[3][0] == 'c')
3008                                 {
3009                                         letter[index].monster = - atoi(zz[3]+1);
3010                                 }
3011                                 else
3012                                 {
3013                                         letter[index].monster = atoi(zz[3]);
3014                                 }
3015                                 /* Fall through */
3016                         /* Cave info */
3017                         case 3:
3018                                 letter[index].cave_info = atoi(zz[2]);
3019                                 /* Fall through */
3020                         /* Feature */
3021                         case 2:
3022                                 if (zz[1][0] == '*')
3023                                 {
3024                                         letter[index].random |= RANDOM_FEATURE;
3025                                         if (zz[1][1])
3026                                         {
3027                                                 zz[1]++;
3028                                                 letter[index].feature = atoi(zz[1]);
3029                                         }
3030                                 }
3031                                 else
3032                                 {
3033                                         letter[index].feature = atoi(zz[1]);
3034                                 }
3035                                 break;
3036                 }
3037
3038                 return (0);
3039         }
3040
3041         return (1);
3042 }
3043
3044
3045 /*
3046  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3047  */
3048 static errr parse_line_building(char *buf)
3049 {
3050         int i;
3051         char *zz[37];
3052         int index;
3053         char *s;
3054
3055 #ifdef JP
3056         if (buf[2] == '$')
3057                 return 0;
3058         s = buf + 2;
3059 #else
3060         if (buf[2] != '$')
3061                 return 0;
3062         s = buf + 3;
3063 #endif
3064         /* Get the building number */
3065         index = atoi(s);
3066
3067         /* Find the colon after the building number */
3068         s = strchr(s, ':');
3069
3070         /* Verify that colon */
3071         if (!s) return (1);
3072
3073         /* Nuke the colon, advance to the sub-index */
3074         *s++ = '\0';
3075
3076         /* Paranoia -- require a sub-index */
3077         if (!*s) return (1);
3078
3079         /* Building definition sub-index */
3080         switch (s[0])
3081         {
3082                 /* Building name, owner, race */
3083                 case 'N':
3084                 {
3085                         if (tokenize(s + 2, 3, zz, 0) == 3)
3086                         {
3087                                 /* Name of the building */
3088                                 strcpy(building[index].name, zz[0]);
3089
3090                                 /* Name of the owner */
3091                                 strcpy(building[index].owner_name, zz[1]);
3092
3093                                 /* Race of the owner */
3094                                 strcpy(building[index].owner_race, zz[2]);
3095
3096                                 break;
3097                         }
3098
3099                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3100                 }
3101
3102                 /* Building Action */
3103                 case 'A':
3104                 {
3105                         if (tokenize(s + 2, 8, zz, 0) >= 7)
3106                         {
3107                                 /* Index of the action */
3108                                 int action_index = atoi(zz[0]);
3109
3110                                 /* Name of the action */
3111                                 strcpy(building[index].act_names[action_index], zz[1]);
3112
3113                                 /* Cost of the action for members */
3114                                 building[index].member_costs[action_index] = atoi(zz[2]);
3115
3116                                 /* Cost of the action for non-members */
3117                                 building[index].other_costs[action_index] = atoi(zz[3]);
3118
3119                                 /* Letter assigned to the action */
3120                                 building[index].letters[action_index] = zz[4][0];
3121
3122                                 /* Action code */
3123                                 building[index].actions[action_index] = atoi(zz[5]);
3124
3125                                 /* Action restriction */
3126                                 building[index].action_restr[action_index] = atoi(zz[6]);
3127
3128                                 break;
3129                         }
3130
3131                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3132                 }
3133
3134                 /* Building Classes */
3135                 case 'C':
3136                 {
3137                         if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3138                         {
3139                                 for (i = 0; i < MAX_CLASS; i++)
3140                                 {
3141                                         building[index].member_class[i] = atoi(zz[i]);
3142                                 }
3143
3144                                 break;
3145                         }
3146
3147                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3148                 }
3149
3150                 /* Building Races */
3151                 case 'R':
3152                 {
3153                         if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3154                         {
3155                                 for (i = 0; i < MAX_RACES; i++)
3156                                 {
3157                                         building[index].member_race[i] = atoi(zz[i]);
3158                                 }
3159
3160                                 break;
3161                         }
3162
3163                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3164                 }
3165
3166                 /* Building Realms */
3167                 case 'M':
3168                 {
3169                         if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3170                         {
3171                                 for (i = 0; i < MAX_MAGIC; i++)
3172                                 {
3173                                         building[index].member_realm[i+1] = atoi(zz[i]);
3174                                 }
3175
3176                                 break;
3177                         }
3178
3179                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3180                 }
3181
3182                 case 'Z':
3183                 {
3184                         /* Ignore scripts */
3185                         break;
3186                 }
3187
3188                 default:
3189                 {
3190                         return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3191                 }
3192         }
3193
3194         return (0);
3195 }
3196
3197
3198 /*
3199  * Parse a sub-file of the "extra info"
3200  */
3201 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3202 {
3203         int i;
3204
3205         char *zz[33];
3206
3207
3208         /* Skip "empty" lines */
3209         if (!buf[0]) return (0);
3210
3211         /* Skip "blank" lines */
3212         if (isspace(buf[0])) return (0);
3213
3214         /* Skip comments */
3215         if (buf[0] == '#') return (0);
3216
3217         /* Require "?:*" format */
3218         if (buf[1] != ':') return (1);
3219
3220
3221         /* Process "%:<fname>" */
3222         if (buf[0] == '%')
3223         {
3224                 /* Attempt to Process the given file */
3225                 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3226         }
3227
3228         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3229         if (buf[0] == 'F')
3230         {
3231                 return parse_line_feature(buf);
3232         }
3233
3234         /* Process "D:<dungeon>" -- info for the cave grids */
3235         else if (buf[0] == 'D')
3236         {
3237                 object_type object_type_body;
3238
3239                 /* Acquire the text */
3240                 char *s = buf + 2;
3241
3242                 /* Length of the text */
3243                 int len = strlen(s);
3244
3245                 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3246
3247                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3248                 {
3249                         /* Access the grid */
3250                         cave_type *c_ptr = &cave[*y][*x];
3251
3252                         int idx = s[0];
3253
3254                         int object_index = letter[idx].object;
3255                         int monster_index = letter[idx].monster;
3256                         int random = letter[idx].random;
3257                         int artifact_index = letter[idx].artifact;
3258
3259                         /* Lay down a floor */
3260                         c_ptr->feat = letter[idx].feature;
3261
3262                         /* Only the features */
3263                         if (init_flags & INIT_ONLY_FEATURES) continue;
3264
3265                         /* Cave info */
3266                         c_ptr->info = letter[idx].cave_info;
3267
3268                         /* Create a monster */
3269                         if (random & RANDOM_MONSTER)
3270                         {
3271                                 monster_level = base_level + monster_index;
3272
3273                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3274
3275                                 monster_level = base_level;
3276                         }
3277                         else if (monster_index)
3278                         {
3279                                 int old_cur_num, old_max_num;
3280                                 bool clone = FALSE;
3281
3282                                 if (monster_index < 0)
3283                                 {
3284                                         monster_index = -monster_index;
3285                                         clone = TRUE;
3286                                 }
3287                                 old_cur_num = r_info[monster_index].cur_num;
3288                                 old_max_num = r_info[monster_index].max_num;
3289
3290                                 /* Make alive again */
3291                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3292                                 {
3293                                         r_info[monster_index].cur_num = 0;
3294                                         r_info[monster_index].max_num = 1;
3295                                 }
3296
3297                                 /* Make alive again */
3298                                 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3299                                 {
3300                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3301                                         {
3302                                                 r_info[monster_index].max_num++;
3303                                         }
3304                                 }
3305
3306                                 /* Place it */
3307                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3308                                 if (clone)
3309                                 {
3310                                         /* clone */
3311                                         m_list[hack_m_idx_ii].smart |= SM_CLONED;
3312
3313                                         /* Make alive again for real unique monster */
3314                                         r_info[monster_index].cur_num = old_cur_num;
3315                                         r_info[monster_index].max_num = old_max_num;
3316                                 }
3317                         }
3318
3319                         /* Object (and possible trap) */
3320                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3321                         {
3322                                 object_level = base_level + object_index;
3323
3324                                 /*
3325                                  * Random trap and random treasure defined
3326                                  * 25% chance for trap and 75% chance for object
3327                                  */
3328                                 if (randint0(100) < 75)
3329                                 {
3330                                         place_object(*y, *x, FALSE, FALSE);
3331                                 }
3332                                 else
3333                                 {
3334                                         place_trap(*y, *x);
3335                                 }
3336
3337                                 object_level = base_level;
3338                         }
3339                         else if (random & RANDOM_OBJECT)
3340                         {
3341                                 object_level = base_level + object_index;
3342
3343                                 /* Create an out of deep object */
3344                                 if (randint0(100) < 75)
3345                                         place_object(*y, *x, FALSE, FALSE);
3346                                 else if (randint0(100) < 80)
3347                                         place_object(*y, *x, TRUE, FALSE);
3348                                 else
3349                                         place_object(*y, *x, TRUE, TRUE);
3350
3351                                 object_level = base_level;
3352                         }
3353                         /* Random trap */
3354                         else if (random & RANDOM_TRAP)
3355                         {
3356                                 place_trap(*y, *x);
3357                         }
3358                         /* Hidden trap (or door) */
3359                         else if (letter[idx].trap)
3360                         {
3361                                 c_ptr->mimic = c_ptr->feat;
3362                                 c_ptr->feat = letter[idx].trap;
3363                         }
3364                         else if (object_index)
3365                         {
3366                                 /* Get local object */
3367                                 object_type *o_ptr = &object_type_body;
3368
3369                                 /* Create the item */
3370                                 object_prep(o_ptr, object_index);
3371
3372                                 if (o_ptr->tval == TV_GOLD)
3373                                 {
3374                                         coin_type = object_index - OBJ_GOLD_LIST;
3375                                         make_gold(o_ptr);
3376                                         coin_type = 0;
3377                                 }
3378
3379                                 /* Apply magic (no messages, no artifacts) */
3380                                 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3381
3382                                 (void)drop_near(o_ptr, -1, *y, *x);
3383                         }
3384
3385                         /* Artifact */
3386                         if (artifact_index)
3387                         {
3388                                 if (a_info[artifact_index].cur_num)
3389                                 {
3390                                         int k_idx = 198;
3391                                         object_type forge;
3392                                         object_type *q_ptr = &forge;
3393
3394                                         object_prep(q_ptr, k_idx);
3395
3396                                         /* Drop it in the dungeon */
3397                                         (void)drop_near(q_ptr, -1, *y, *x);
3398                                 }
3399                                 else
3400                                 {
3401                                         /* Create the artifact */
3402                                         create_named_art(artifact_index, *y, *x);
3403
3404                                         a_info[artifact_index].cur_num = 1;
3405                                 }
3406                         }
3407
3408                         /* Terrain special */
3409                         c_ptr->special = letter[idx].special;
3410                 }
3411
3412                 (*y)++;
3413
3414                 return (0);
3415         }
3416
3417         /* Process "Q:<number>:<command>:... -- quest info */
3418         else if (buf[0] == 'Q')
3419         {
3420                 int num;
3421                 quest_type *q_ptr;
3422 #ifdef JP
3423                 if (buf[2] == '$')
3424                         return 0;
3425                 num = tokenize(buf + 2, 33, zz, 0);
3426 #else
3427                 if (buf[2] != '$')
3428                         return 0;
3429                 num = tokenize(buf + 3, 33, zz, 0);
3430 #endif
3431
3432                 /* Have we enough parameters? */
3433                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3434
3435                 /* Get the quest */
3436                 q_ptr = &(quest[atoi(zz[0])]);
3437
3438                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3439                 if (zz[1][0] == 'Q')
3440                 {
3441                         if (init_flags & INIT_ASSIGN)
3442                         {
3443                                 monster_race *r_ptr;
3444                                 artifact_type *a_ptr;
3445
3446                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3447
3448                                 q_ptr->type    = atoi(zz[2]);
3449                                 q_ptr->num_mon = atoi(zz[3]);
3450                                 q_ptr->cur_num = atoi(zz[4]);
3451                                 q_ptr->max_num = atoi(zz[5]);
3452                                 q_ptr->level   = atoi(zz[6]);
3453                                 q_ptr->r_idx   = atoi(zz[7]);
3454                                 q_ptr->k_idx   = atoi(zz[8]);
3455                                 q_ptr->dungeon = atoi(zz[9]);
3456
3457                                 if (num > 10)
3458                                         q_ptr->flags  = atoi(zz[10]);
3459
3460                                 r_ptr = &r_info[q_ptr->r_idx];
3461                                 if (r_ptr->flags1 & RF1_UNIQUE)
3462                                         r_ptr->flags1 |= RF1_QUESTOR;
3463
3464                                 a_ptr = &a_info[q_ptr->k_idx];
3465                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3466                         }
3467                         return (0);
3468                 }
3469
3470                 /* Process "Q:<q_index>:N:<name>" -- quest name */
3471                 else if (zz[1][0] == 'N')
3472                 {
3473                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3474                         {
3475                                 strcpy(q_ptr->name, zz[2]);
3476                         }
3477
3478                         return (0);
3479                 }
3480
3481                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3482                 else if (zz[1][0] == 'T')
3483                 {
3484                         if (init_flags & INIT_SHOW_TEXT)
3485                         {
3486                                 strcpy(quest_text[quest_text_line], zz[2]);
3487                                 quest_text_line++;
3488                         }
3489
3490                         return (0);
3491                 }
3492         }
3493
3494         /* Process "W:<command>: ..." -- info for the wilderness */
3495         else if (buf[0] == 'W')
3496         {
3497                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3498         }
3499
3500         /* Process "P:<y>:<x>" -- player position */
3501         else if (buf[0] == 'P')
3502         {
3503                 if (init_flags & INIT_CREATE_DUNGEON)
3504                 {
3505                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3506                         {
3507                                 int panels_x, panels_y;
3508
3509                                 /* Hack - Set the dungeon size */
3510                                 panels_y = (*y / SCREEN_HGT);
3511                                 if (*y % SCREEN_HGT) panels_y++;
3512                                 cur_hgt = panels_y * SCREEN_HGT;
3513
3514                                 panels_x = (*x / SCREEN_WID);
3515                                 if (*x % SCREEN_WID) panels_x++;
3516                                 cur_wid = panels_x * SCREEN_WID;
3517
3518                                 /* Assume illegal panel */
3519                                 panel_row_min = cur_hgt;
3520                                 panel_col_min = cur_wid;
3521
3522                                 /* Place player in a quest level */
3523                                 if (p_ptr->inside_quest)
3524                                 {
3525                                         int y, x;
3526
3527                                         /* Delete the monster (if any) */
3528                                         delete_monster(py, px);
3529
3530                                         y = atoi(zz[0]);
3531                                         x = atoi(zz[1]);
3532
3533                                         py = y;
3534                                         px = x;
3535                                 }
3536                                 /* Place player in the town */
3537                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3538                                 {
3539                                         p_ptr->oldpy = atoi(zz[0]);
3540                                         p_ptr->oldpx = atoi(zz[1]);
3541                                 }
3542                         }
3543                 }
3544
3545                 return (0);
3546         }
3547
3548         /* Process "B:<Index>:<Command>:..." -- Building definition */
3549         else if (buf[0] == 'B')
3550         {
3551                 return parse_line_building(buf);
3552         }
3553
3554         /* Process "M:<type>:<maximum>" -- set maximum values */
3555         else if (buf[0] == 'M')
3556         {
3557                 if (tokenize(buf+2, 2, zz, 0) == 2)
3558                 {
3559                         /* Maximum towns */
3560                         if (zz[0][0] == 'T')
3561                         {
3562                                 max_towns = atoi(zz[1]);
3563                         }
3564
3565                         /* Maximum quests */
3566                         else if (zz[0][0] == 'Q')
3567                         {
3568                                 max_quests = atoi(zz[1]);
3569                         }
3570
3571                         /* Maximum r_idx */
3572                         else if (zz[0][0] == 'R')
3573                         {
3574                                 max_r_idx = atoi(zz[1]);
3575                         }
3576
3577                         /* Maximum k_idx */
3578                         else if (zz[0][0] == 'K')
3579                         {
3580                                 max_k_idx = atoi(zz[1]);
3581                         }
3582
3583                         /* Maximum v_idx */
3584                         else if (zz[0][0] == 'V')
3585                         {
3586                                 max_v_idx = atoi(zz[1]);
3587                         }
3588
3589                         /* Maximum f_idx */
3590                         else if (zz[0][0] == 'F')
3591                         {
3592                                 max_f_idx = atoi(zz[1]);
3593                         }
3594
3595                         /* Maximum a_idx */
3596                         else if (zz[0][0] == 'A')
3597                         {
3598                                 max_a_idx = atoi(zz[1]);
3599                         }
3600
3601                         /* Maximum e_idx */
3602                         else if (zz[0][0] == 'E')
3603                         {
3604                                 max_e_idx = atoi(zz[1]);
3605                         }
3606
3607                         /* Maximum d_idx */
3608                         else if (zz[0][0] == 'D')
3609                         {
3610                                 max_d_idx = atoi(zz[1]); 
3611                         }
3612
3613                         /* Maximum o_idx */
3614                         else if (zz[0][0] == 'O')
3615                         {
3616                                 max_o_idx = atoi(zz[1]);
3617                         }
3618
3619                         /* Maximum m_idx */
3620                         else if (zz[0][0] == 'M')
3621                         {
3622                                 max_m_idx = atoi(zz[1]);
3623                         }
3624
3625                         /* Wilderness size */
3626                         else if (zz[0][0] == 'W')
3627                         {
3628                                 /* Maximum wild_x_size */
3629                                 if (zz[0][1] == 'X')
3630                                         max_wild_x = atoi(zz[1]);
3631                                 /* Maximum wild_y_size */
3632                                 if (zz[0][1] == 'Y')
3633                                         max_wild_y = atoi(zz[1]);
3634                         }
3635
3636                         return (0);
3637                 }
3638         }
3639
3640
3641         /* Failure */
3642         return (1);
3643 }
3644
3645
3646 static char tmp[8];
3647 static cptr variant = "ZANGBAND";
3648
3649
3650 /*
3651  * Helper function for "process_dungeon_file()"
3652  */
3653 static cptr process_dungeon_file_expr(char **sp, char *fp)
3654 {
3655         cptr v;
3656
3657         char *b;
3658         char *s;
3659
3660         char b1 = '[';
3661         char b2 = ']';
3662
3663         char f = ' ';
3664
3665         /* Initial */
3666         s = (*sp);
3667
3668         /* Skip spaces */
3669         while (isspace(*s)) s++;
3670
3671         /* Save start */
3672         b = s;
3673
3674         /* Default */
3675         v = "?o?o?";
3676
3677         /* Analyze */
3678         if (*s == b1)
3679         {
3680                 const char *p;
3681                 const char *t;
3682
3683                 /* Skip b1 */
3684                 s++;
3685
3686                 /* First */
3687                 t = process_dungeon_file_expr(&s, &f);
3688
3689                 /* Oops */
3690                 if (!*t)
3691                 {
3692                         /* Nothing */
3693                 }
3694
3695                 /* Function: IOR */
3696                 else if (streq(t, "IOR"))
3697                 {
3698                         v = "0";
3699                         while (*s && (f != b2))
3700                         {
3701                                 t = process_dungeon_file_expr(&s, &f);
3702                                 if (*t && !streq(t, "0")) v = "1";
3703                         }
3704                 }
3705
3706                 /* Function: AND */
3707                 else if (streq(t, "AND"))
3708                 {
3709                         v = "1";
3710                         while (*s && (f != b2))
3711                         {
3712                                 t = process_dungeon_file_expr(&s, &f);
3713                                 if (*t && streq(t, "0")) v = "0";
3714                         }
3715                 }
3716
3717                 /* Function: NOT */
3718                 else if (streq(t, "NOT"))
3719                 {
3720                         v = "1";
3721                         while (*s && (f != b2))
3722                         {
3723                                 t = process_dungeon_file_expr(&s, &f);
3724                                 if (*t && streq(t, "1")) v = "0";
3725                         }
3726                 }
3727
3728                 /* Function: EQU */
3729                 else if (streq(t, "EQU"))
3730                 {
3731                         v = "1";
3732                         if (*s && (f != b2))
3733                         {
3734                                 t = process_dungeon_file_expr(&s, &f);
3735                         }
3736                         while (*s && (f != b2))
3737                         {
3738                                 p = t;
3739                                 t = process_dungeon_file_expr(&s, &f);
3740                                 if (*t && !streq(p, t)) v = "0";
3741                         }
3742                 }
3743
3744                 /* Function: LEQ */
3745                 else if (streq(t, "LEQ"))
3746                 {
3747                         v = "1";
3748                         if (*s && (f != b2))
3749                         {
3750                                 t = process_dungeon_file_expr(&s, &f);
3751                         }
3752                         while (*s && (f != b2))
3753                         {
3754                                 p = t;
3755                                 t = process_dungeon_file_expr(&s, &f);
3756                                 if (*t && (strcmp(p, t) > 0)) v = "0";
3757                         }
3758                 }
3759
3760                 /* Function: GEQ */
3761                 else if (streq(t, "GEQ"))
3762                 {
3763                         v = "1";
3764                         if (*s && (f != b2))
3765                         {
3766                                 t = process_dungeon_file_expr(&s, &f);
3767                         }
3768                         while (*s && (f != b2))
3769                         {
3770                                 p = t;
3771                                 t = process_dungeon_file_expr(&s, &f);
3772                                 if (*t && (strcmp(p, t) < 0)) v = "0";
3773                         }
3774                 }
3775
3776                 /* Oops */
3777                 else
3778                 {
3779                         while (*s && (f != b2))
3780                         {
3781                                 t = process_dungeon_file_expr(&s, &f);
3782                         }
3783                 }
3784
3785                 /* Verify ending */
3786                 if (f != b2) v = "?x?x?";
3787
3788                 /* Extract final and Terminate */
3789                 if ((f = *s) != '\0') *s++ = '\0';
3790         }
3791
3792         /* Other */
3793         else
3794         {
3795                 /* Accept all printables except spaces and brackets */
3796                 while (isprint(*s) && !strchr(" []", *s)) ++s;
3797
3798                 /* Extract final and Terminate */
3799                 if ((f = *s) != '\0') *s++ = '\0';
3800
3801                 /* Variable */
3802                 if (*b == '$')
3803                 {
3804                         /* System */
3805                         if (streq(b+1, "SYS"))
3806                         {
3807                                 v = ANGBAND_SYS;
3808                         }
3809
3810                         /* Graphics */
3811                         else if (streq(b+1, "GRAF"))
3812                         {
3813                                 v = ANGBAND_GRAF;
3814                         }
3815
3816                         else if (streq(b+1, "MONOCHROME"))
3817                         {
3818                                 if (arg_monochrome)
3819                                         v = "ON";
3820                                 else
3821                                         v = "OFF";
3822                         }
3823
3824                         /* Race */
3825                         else if (streq(b+1, "RACE"))
3826                         {
3827 #ifdef JP
3828                                 v = rp_ptr->E_title;
3829 #else
3830                                 v = rp_ptr->title;
3831 #endif
3832                         }
3833
3834                         /* Class */
3835                         else if (streq(b+1, "CLASS"))
3836                         {
3837 #ifdef JP
3838                                 v = cp_ptr->E_title;
3839 #else
3840                                 v = cp_ptr->title;
3841 #endif
3842                         }
3843
3844                         /* First realm */
3845                         else if (streq(b+1, "REALM1"))
3846                         {
3847 #ifdef JP
3848                                 v = E_realm_names[p_ptr->realm1];
3849 #else
3850                                 v = realm_names[p_ptr->realm1];
3851 #endif
3852                         }
3853
3854                         /* Second realm */
3855                         else if (streq(b+1, "REALM2"))
3856                         {
3857 #ifdef JP
3858                                 v = E_realm_names[p_ptr->realm2];
3859 #else
3860                                 v = realm_names[p_ptr->realm2];
3861 #endif
3862                         }
3863
3864                         /* Player name */
3865                         else if (streq(b+1, "PLAYER"))
3866                         {
3867                                 v = player_base;
3868                         }
3869
3870                         /* Town */
3871                         else if (streq(b+1, "TOWN"))
3872                         {
3873                                 sprintf(tmp, "%d", p_ptr->town_num);
3874                                 v = tmp;
3875                         }
3876
3877                         /* Level */
3878                         else if (streq(b+1, "LEVEL"))
3879                         {
3880                                 sprintf(tmp, "%d", p_ptr->lev);
3881                                 v = tmp;
3882                         }
3883
3884                         /* Current quest number */
3885                         else if (streq(b+1, "QUEST_NUMBER"))
3886                         {
3887                                 sprintf(tmp, "%d", p_ptr->inside_quest);
3888                                 v = tmp;
3889                         }
3890
3891                         /* Number of last quest */
3892                         else if (streq(b+1, "LEAVING_QUEST"))
3893                         {
3894                                 sprintf(tmp, "%d", leaving_quest);
3895                                 v = tmp;
3896                         }
3897
3898                         /* Quest status */
3899                         else if (prefix(b+1, "QUEST"))
3900                         {
3901                                 /* "QUEST" uses a special parameter to determine the number of the quest */
3902                                 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3903                                 v = tmp;
3904                         }
3905
3906                         /* Random */
3907                         else if (prefix(b+1, "RANDOM"))
3908                         {
3909                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
3910                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3911                                 v = tmp;
3912                         }
3913
3914                         /* Variant name */
3915                         else if (streq(b+1, "VARIANT"))
3916                         {
3917                                 v = variant;
3918                         }
3919
3920                         /* Wilderness */
3921                         else if (streq(b+1, "WILDERNESS"))
3922                         {
3923                                 if (vanilla_town)
3924                                         sprintf(tmp, "NONE");
3925                                 else if (lite_town)
3926                                         sprintf(tmp, "LITE");
3927                                 else
3928                                         sprintf(tmp, "NORMAL");
3929                                 v = tmp;
3930                         }
3931                 }
3932
3933                 /* Constant */
3934                 else
3935                 {
3936                         v = b;
3937                 }
3938         }
3939
3940         /* Save */
3941         (*fp) = f;
3942
3943         /* Save */
3944         (*sp) = s;
3945
3946         /* Result */
3947         return (v);
3948 }
3949
3950
3951 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3952 {
3953         FILE *fp;
3954
3955         char buf[1024];
3956
3957         int num = -1;
3958
3959         errr err = 0;
3960
3961         bool bypass = FALSE;
3962
3963         int x = xmin, y = ymin;
3964
3965
3966         /* Build the filename */
3967         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3968
3969         /* Open the file */
3970         fp = my_fopen(buf, "r");
3971
3972         /* No such file */
3973         if (!fp) return (-1);
3974
3975
3976         /* Process the file */
3977         while (0 == my_fgets(fp, buf, sizeof(buf)))
3978         {
3979                 /* Count lines */
3980                 num++;
3981
3982
3983                 /* Skip "empty" lines */
3984                 if (!buf[0]) continue;
3985
3986                 /* Skip "blank" lines */
3987                 if (isspace(buf[0])) continue;
3988
3989                 /* Skip comments */
3990                 if (buf[0] == '#') continue;
3991
3992
3993                 /* Process "?:<expr>" */
3994                 if ((buf[0] == '?') && (buf[1] == ':'))
3995                 {
3996                         char f;
3997                         cptr v;
3998                         char *s;
3999
4000                         /* Start */
4001                         s = buf + 2;
4002
4003                         /* Parse the expr */
4004                         v = process_dungeon_file_expr(&s, &f);
4005
4006                         /* Set flag */
4007                         bypass = (streq(v, "0") ? TRUE : FALSE);
4008
4009                         /* Continue */
4010                         continue;
4011                 }
4012
4013                 /* Apply conditionals */
4014                 if (bypass) continue;
4015
4016                 /* Process the line */
4017                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4018
4019                 /* Oops */
4020                 if (err) break;
4021         }
4022
4023         /* Errors */
4024         if (err)
4025         {
4026                 cptr oops;
4027
4028                 /* Error string */
4029                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4030
4031                 /* Oops */
4032                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4033 #ifdef JP
4034 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4035 #else
4036                 msg_format("Parsing '%s'.", buf);
4037 #endif
4038
4039                 msg_print(NULL);
4040         }
4041
4042
4043         /* Close the file */
4044         my_fclose(fp);
4045
4046         /* Result */
4047         return (err);
4048 }
4049
4050
4051
4052 #if 0
4053 void write_r_info_txt(void)
4054 {
4055         int i, j, z, fc, bc;
4056         int dlen;
4057
4058         cptr flags[288];
4059
4060         u32b f_ptr[9];
4061         cptr *n_ptr[9];
4062
4063         monster_race *r_ptr;
4064
4065         monster_blow *b_ptr;
4066
4067         FILE *fff = fopen("output.txt", "wt");
4068
4069         cptr desc;
4070
4071         int mode = -1;
4072
4073         if (!fff) return;
4074
4075         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4076
4077         fprintf(fff, "# Version stamp (required)\n\n");
4078
4079         /* Write Version */
4080         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4081
4082         /* Write a note */
4083         fprintf(fff, "##### The Player #####\n\n");
4084
4085         for (z = -1; z < alloc_race_size; z++)
4086         {
4087                 /* Output the monsters in order */
4088                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4089
4090                 /* Acquire the monster */
4091                 r_ptr = &r_info[i];
4092
4093                 /* Ignore empty monsters */
4094                 if (!strlen(r_name + r_ptr->name)) continue;
4095
4096                 /* Ignore useless monsters */
4097                 if (i && !r_ptr->speed) continue;
4098
4099                 /* Write a note if necessary */
4100                 if (i && (!r_ptr->level != !mode))
4101                 {
4102                         /* Note the town */
4103                         if (!r_ptr->level)
4104                         {
4105                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4106                         }
4107                         /* Note the dungeon */
4108                         else
4109                         {
4110                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4111                         }
4112
4113                         /* Record the change */
4114                         mode = r_ptr->level;
4115                 }
4116
4117                 /* Acquire the flags */
4118                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4119                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4120                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4121                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4122                 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4123                 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4124                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4125                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4126                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4127
4128                 /* Write New/Number/Name */
4129                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4130
4131                 /* Write Graphic */
4132                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4133
4134                 /* Write Information */
4135                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4136                                                                                                                   r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4137
4138                 /* Write more information */
4139                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4140
4141                 /* Write Blows */
4142                 for(j = 0; j < 4; j++)
4143                 {
4144                         b_ptr = &(r_ptr->blow[j]);
4145
4146                         /* Stop when done */
4147                         if (!b_ptr->method) break;
4148
4149                         /* Write the blows */
4150                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4151                                                                                                           r_info_blow_effect[b_ptr->effect],
4152                                                                                                           b_ptr->d_dice, b_ptr->d_side);
4153                 }
4154
4155                 /* Extract the flags */
4156                 for (fc = 0, j = 0; j < 96; j++)
4157                 {
4158                         /* Check this flag */
4159                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4160                 }
4161
4162                 /* Extract the extra flags */
4163                 for (j = 192; j < 288; j++)
4164                 {
4165                         /* Check this flag */
4166                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4167                 }
4168
4169                 /* Write the flags */
4170                 for (j = 0; j < fc;)
4171                 {
4172                         char buf[160];
4173
4174                         /* Start the line */
4175                         sprintf(buf, "F:");
4176
4177                         for (bc = 0; (bc < 60) && (j < fc); j++)
4178                         {
4179                                 char t[80];
4180
4181                                 /* Format the flag */
4182                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4183
4184                                 /* Add it to the buffer */
4185                                 strcat(buf, t);
4186
4187                                 /* Note the length */
4188                                 bc += strlen(t);
4189                         }
4190
4191                         /* Done with this line; write it */
4192                         fprintf(fff, "%s\n", buf);
4193                 }
4194
4195                 /* Write Spells if applicable */
4196                 if (r_ptr->freq_spell)
4197                 {
4198                         /* Write the frequency */
4199                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4200
4201                         /* Extract the spell flags */
4202                         for (fc = 0, j = 96; j < 192; j++)
4203                         {
4204                                 /* Check this flag */
4205                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4206                         }
4207
4208                         /* Write the flags */
4209                         for (j = 0; j < fc;)
4210                         {
4211                                 char buf[160], *t;
4212
4213                                 /* Start the line */
4214                                 sprintf(buf, "S:");
4215
4216                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4217                                 {
4218                                         int tlen;
4219
4220                                         /* Format the flag */
4221                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4222
4223                                         tlen = strlen(t);
4224
4225                                         /* Note the length */
4226                                         bc += tlen;
4227
4228                                         /* Advance */
4229                                         t += tlen;
4230                                 }
4231
4232                                 /* Done with this line; write it */
4233                                 fprintf(fff, "%s\n", buf);
4234                         }
4235                 }
4236
4237                 /* Acquire the description */
4238                 desc = r_text + r_ptr->text;
4239                 dlen = strlen(desc);
4240
4241                 /* Write Description */
4242                 for (j = 0; j < dlen;)
4243                 {
4244                         char buf[160], *t;
4245
4246                         /* Start the line */
4247                         sprintf(buf, "D:");
4248
4249                         for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4250                         {
4251                                 *t = desc[j];
4252                         }
4253
4254                         /* Terminate it */
4255                         *t = '\0';
4256
4257                         /* Done with this line; write it */
4258                         fprintf(fff, "%s\n", buf);
4259                 }
4260
4261                 /* Space between entries */
4262                 fprintf(fff, "\n");
4263         }
4264
4265         /* Done */
4266         fclose(fff);
4267 }
4268
4269 #endif