OSDN Git Service

d21d3a42e8c36cc639579cf632eacd108b2775cc
[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 = 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                 /* Parse every entry */
2776                 for (s = buf + 2; *s; )
2777                 {
2778                         /* Find the end of this entry */
2779                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2780
2781                         /* Nuke and skip any dividers */
2782                         if (*t)
2783                         {
2784                                 *t++ = '\0';
2785                                 while (*t == ' ' || *t == '|') t++;
2786                         }
2787
2788                         /* Hack -- Read monster symbols */
2789                         if (!strncmp(s, "R_CHAR_", 7))
2790                         {
2791                                 /* Skip "R_CHAR_" */
2792                                 s += 7;
2793
2794                                 /* Read a string */
2795                                 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
2796
2797                                 /* Start at next entry */
2798                                 s = t;
2799
2800                                 /* Continue */
2801                                 continue;
2802                         }
2803
2804                         /* Parse this entry */
2805                         if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2806
2807                         /* Start the next entry */
2808                         s = t;
2809                 }
2810         }
2811
2812         /* Process 'S' for "Spell Flags" (multiple lines) */
2813         else if (buf[0] == 'S')
2814         {
2815                 /* Parse every entry */
2816                 for (s = buf + 2; *s; )
2817                 {
2818                                 /* Find the end of this entry */
2819                         for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2820
2821                                 /* Nuke and skip any dividers */
2822                         if (*t)
2823                         {
2824                                 *t++ = '\0';
2825                                 while ((*t == ' ') || (*t == '|')) t++;
2826                         }
2827
2828                                 /* XXX XXX XXX Hack -- Read spell frequency */
2829                         if (1 == sscanf(s, "1_IN_%d", &i))
2830                         {
2831                                 /* Start at next entry */
2832                                 s = t;
2833
2834                                         /* Continue */
2835                                 continue;
2836                         }
2837
2838                                 /* Parse this entry */
2839                         if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2840
2841                                 /* Start the next entry */
2842                         s = t;
2843                 }
2844         }
2845
2846         /* Oops */
2847         else return (6);
2848
2849         /* Success */
2850         return (0);
2851 }
2852
2853
2854 #else   /* ALLOW_TEMPLATES */
2855
2856 #ifdef MACINTOSH
2857 static int i = 0;
2858 #endif
2859
2860 #endif  /* ALLOW_TEMPLATES */
2861
2862
2863 /* Random dungeon grid effects */
2864 #define RANDOM_NONE         0x00
2865 #define RANDOM_FEATURE      0x01
2866 #define RANDOM_MONSTER      0x02
2867 #define RANDOM_OBJECT       0x04
2868 #define RANDOM_EGO          0x08
2869 #define RANDOM_ARTIFACT     0x10
2870 #define RANDOM_TRAP         0x20
2871
2872
2873 typedef struct dungeon_grid dungeon_grid;
2874
2875 struct dungeon_grid
2876 {
2877         int             feature;                /* Terrain feature */
2878         int             monster;                /* Monster */
2879         int             object;                 /* Object */
2880         int             ego;                    /* Ego-Item */
2881         int             artifact;               /* Artifact */
2882         int             trap;                   /* Trap */
2883         int             cave_info;              /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2884         int             special;                /* Reserved for special terrain info */
2885         int             random;                 /* Number of the random effect */
2886 };
2887
2888
2889 static dungeon_grid letter[255];
2890
2891
2892 /*
2893  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2894  */
2895 static errr parse_line_feature(char *buf)
2896 {
2897         int num;
2898         char *zz[9];
2899
2900
2901         if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2902
2903         /* Tokenize the line */
2904         if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2905         {
2906                 /* Letter to assign */
2907                 int index = zz[0][0];
2908
2909                 /* Reset the info for the letter */
2910                 letter[index].feature = 0;
2911                 letter[index].monster = 0;
2912                 letter[index].object = 0;
2913                 letter[index].ego = 0;
2914                 letter[index].artifact = 0;
2915                 letter[index].trap = 0;
2916                 letter[index].cave_info = 0;
2917                 letter[index].special = 0;
2918                 letter[index].random = 0;
2919
2920                 switch (num)
2921                 {
2922                         /* Special */
2923                         case 9:
2924                                 letter[index].special = atoi(zz[8]);
2925                                 /* Fall through */
2926                         /* Trap */
2927                         case 8:
2928                                 if (zz[7][0] == '*')
2929                                 {
2930                                         letter[index].random |= RANDOM_TRAP;
2931
2932                                         if (zz[7][1])
2933                                         {
2934                                                 zz[7]++;
2935                                                 letter[index].trap = atoi(zz[7]);
2936                                         }
2937                                 }
2938                                 else
2939                                 {
2940                                         letter[index].trap = atoi(zz[7]);
2941                                 }
2942                                 /* Fall through */
2943                         /* Artifact */
2944                         case 7:
2945                                 if (zz[6][0] == '*')
2946                                 {
2947                                         letter[index].random |= RANDOM_ARTIFACT;
2948
2949                                         if (zz[6][1])
2950                                         {
2951                                                 zz[6]++;
2952                                                 letter[index].artifact = atoi(zz[6]);
2953                                         }
2954                                 }
2955                                 else
2956                                 {
2957                                         letter[index].artifact = atoi(zz[6]);
2958                                 }
2959                                 /* Fall through */
2960                         /* Ego-item */
2961                         case 6:
2962                                 if (zz[5][0] == '*')
2963                                 {
2964                                         letter[index].random |= RANDOM_EGO;
2965
2966                                         if (zz[5][1])
2967                                         {
2968                                                 zz[5]++;
2969                                                 letter[index].ego = atoi(zz[5]);
2970                                         }
2971                                 }
2972                                 else
2973                                 {
2974                                         letter[index].ego = atoi(zz[5]);
2975                                 }
2976                                 /* Fall through */
2977                         /* Object */
2978                         case 5:
2979                                 if (zz[4][0] == '*')
2980                                 {
2981                                         letter[index].random |= RANDOM_OBJECT;
2982
2983                                         if (zz[4][1])
2984                                         {
2985                                                 zz[4]++;
2986                                                 letter[index].object = atoi(zz[4]);
2987                                         }
2988                                 }
2989                                 else
2990                                 {
2991                                         letter[index].object = atoi(zz[4]);
2992                                 }
2993                                 /* Fall through */
2994                         /* Monster */
2995                         case 4:
2996                                 if (zz[3][0] == '*')
2997                                 {
2998                                         letter[index].random |= RANDOM_MONSTER;
2999                                         if (zz[3][1])
3000                                         {
3001                                                 zz[3]++;
3002                                                 letter[index].monster = atoi(zz[3]);
3003                                         }
3004                                 }
3005                                 else if (zz[3][0] == 'c')
3006                                 {
3007                                         letter[index].monster = - atoi(zz[3]+1);
3008                                 }
3009                                 else
3010                                 {
3011                                         letter[index].monster = atoi(zz[3]);
3012                                 }
3013                                 /* Fall through */
3014                         /* Cave info */
3015                         case 3:
3016                                 letter[index].cave_info = atoi(zz[2]);
3017                                 /* Fall through */
3018                         /* Feature */
3019                         case 2:
3020                                 if (zz[1][0] == '*')
3021                                 {
3022                                         letter[index].random |= RANDOM_FEATURE;
3023                                         if (zz[1][1])
3024                                         {
3025                                                 zz[1]++;
3026                                                 letter[index].feature = atoi(zz[1]);
3027                                         }
3028                                 }
3029                                 else
3030                                 {
3031                                         letter[index].feature = atoi(zz[1]);
3032                                 }
3033                                 break;
3034                 }
3035
3036                 return (0);
3037         }
3038
3039         return (1);
3040 }
3041
3042
3043 /*
3044  * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3045  */
3046 static errr parse_line_building(char *buf)
3047 {
3048         int i;
3049         char *zz[37];
3050         int index;
3051         char *s;
3052
3053 #ifdef JP
3054         if (buf[2] == '$')
3055                 return 0;
3056         s = buf + 2;
3057 #else
3058         if (buf[2] != '$')
3059                 return 0;
3060         s = buf + 3;
3061 #endif
3062         /* Get the building number */
3063         index = atoi(s);
3064
3065         /* Find the colon after the building number */
3066         s = strchr(s, ':');
3067
3068         /* Verify that colon */
3069         if (!s) return (1);
3070
3071         /* Nuke the colon, advance to the sub-index */
3072         *s++ = '\0';
3073
3074         /* Paranoia -- require a sub-index */
3075         if (!*s) return (1);
3076
3077         /* Building definition sub-index */
3078         switch (s[0])
3079         {
3080                 /* Building name, owner, race */
3081                 case 'N':
3082                 {
3083                         if (tokenize(s + 2, 3, zz, 0) == 3)
3084                         {
3085                                 /* Name of the building */
3086                                 strcpy(building[index].name, zz[0]);
3087
3088                                 /* Name of the owner */
3089                                 strcpy(building[index].owner_name, zz[1]);
3090
3091                                 /* Race of the owner */
3092                                 strcpy(building[index].owner_race, zz[2]);
3093
3094                                 break;
3095                         }
3096
3097                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3098                 }
3099
3100                 /* Building Action */
3101                 case 'A':
3102                 {
3103                         if (tokenize(s + 2, 8, zz, 0) >= 7)
3104                         {
3105                                 /* Index of the action */
3106                                 int action_index = atoi(zz[0]);
3107
3108                                 /* Name of the action */
3109                                 strcpy(building[index].act_names[action_index], zz[1]);
3110
3111                                 /* Cost of the action for members */
3112                                 building[index].member_costs[action_index] = atoi(zz[2]);
3113
3114                                 /* Cost of the action for non-members */
3115                                 building[index].other_costs[action_index] = atoi(zz[3]);
3116
3117                                 /* Letter assigned to the action */
3118                                 building[index].letters[action_index] = zz[4][0];
3119
3120                                 /* Action code */
3121                                 building[index].actions[action_index] = atoi(zz[5]);
3122
3123                                 /* Action restriction */
3124                                 building[index].action_restr[action_index] = atoi(zz[6]);
3125
3126                                 break;
3127                         }
3128
3129                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3130                 }
3131
3132                 /* Building Classes */
3133                 case 'C':
3134                 {
3135                         if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3136                         {
3137                                 for (i = 0; i < MAX_CLASS; i++)
3138                                 {
3139                                         building[index].member_class[i] = atoi(zz[i]);
3140                                 }
3141
3142                                 break;
3143                         }
3144
3145                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3146                 }
3147
3148                 /* Building Races */
3149                 case 'R':
3150                 {
3151                         if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3152                         {
3153                                 for (i = 0; i < MAX_RACES; i++)
3154                                 {
3155                                         building[index].member_race[i] = atoi(zz[i]);
3156                                 }
3157
3158                                 break;
3159                         }
3160
3161                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3162                 }
3163
3164                 /* Building Realms */
3165                 case 'M':
3166                 {
3167                         if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3168                         {
3169                                 for (i = 0; i < MAX_MAGIC; i++)
3170                                 {
3171                                         building[index].member_realm[i+1] = atoi(zz[i]);
3172                                 }
3173
3174                                 break;
3175                         }
3176
3177                         return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3178                 }
3179
3180                 case 'Z':
3181                 {
3182                         /* Ignore scripts */
3183                         break;
3184                 }
3185
3186                 default:
3187                 {
3188                         return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3189                 }
3190         }
3191
3192         return (0);
3193 }
3194
3195
3196 /*
3197  * Parse a sub-file of the "extra info"
3198  */
3199 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3200 {
3201         int i;
3202
3203         char *zz[33];
3204
3205
3206         /* Skip "empty" lines */
3207         if (!buf[0]) return (0);
3208
3209         /* Skip "blank" lines */
3210         if (isspace(buf[0])) return (0);
3211
3212         /* Skip comments */
3213         if (buf[0] == '#') return (0);
3214
3215         /* Require "?:*" format */
3216         if (buf[1] != ':') return (1);
3217
3218
3219         /* Process "%:<fname>" */
3220         if (buf[0] == '%')
3221         {
3222                 /* Attempt to Process the given file */
3223                 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3224         }
3225
3226         /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3227         if (buf[0] == 'F')
3228         {
3229                 return parse_line_feature(buf);
3230         }
3231
3232         /* Process "D:<dungeon>" -- info for the cave grids */
3233         else if (buf[0] == 'D')
3234         {
3235                 object_type object_type_body;
3236
3237                 /* Acquire the text */
3238                 char *s = buf + 2;
3239
3240                 /* Length of the text */
3241                 int len = strlen(s);
3242
3243                 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3244
3245                 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3246                 {
3247                         /* Access the grid */
3248                         cave_type *c_ptr = &cave[*y][*x];
3249
3250                         int idx = s[0];
3251
3252                         int object_index = letter[idx].object;
3253                         int monster_index = letter[idx].monster;
3254                         int random = letter[idx].random;
3255                         int artifact_index = letter[idx].artifact;
3256
3257                         /* Lay down a floor */
3258                         c_ptr->feat = letter[idx].feature;
3259
3260                         /* Only the features */
3261                         if (init_flags & INIT_ONLY_FEATURES) continue;
3262
3263                         /* Cave info */
3264                         c_ptr->info = letter[idx].cave_info;
3265
3266                         /* Create a monster */
3267                         if (random & RANDOM_MONSTER)
3268                         {
3269                                 monster_level = base_level + monster_index;
3270
3271                                 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3272
3273                                 monster_level = base_level;
3274                         }
3275                         else if (monster_index)
3276                         {
3277                                 int old_cur_num, old_max_num;
3278                                 bool clone = FALSE;
3279
3280                                 if (monster_index < 0)
3281                                 {
3282                                         monster_index = -monster_index;
3283                                         clone = TRUE;
3284                                 }
3285                                 old_cur_num = r_info[monster_index].cur_num;
3286                                 old_max_num = r_info[monster_index].max_num;
3287
3288                                 /* Make alive again */
3289                                 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3290                                 {
3291                                         r_info[monster_index].cur_num = 0;
3292                                         r_info[monster_index].max_num = 1;
3293                                 }
3294
3295                                 /* Make alive again */
3296                                 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3297                                 {
3298                                         if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3299                                         {
3300                                                 r_info[monster_index].max_num++;
3301                                         }
3302                                 }
3303
3304                                 /* Place it */
3305                                 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3306                                 if (clone)
3307                                 {
3308                                         /* clone */
3309                                         m_list[hack_m_idx_ii].smart |= SM_CLONED;
3310
3311                                         /* Make alive again for real unique monster */
3312                                         r_info[monster_index].cur_num = old_cur_num;
3313                                         r_info[monster_index].max_num = old_max_num;
3314                                 }
3315                         }
3316
3317                         /* Object (and possible trap) */
3318                         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3319                         {
3320                                 object_level = base_level + object_index;
3321
3322                                 /*
3323                                  * Random trap and random treasure defined
3324                                  * 25% chance for trap and 75% chance for object
3325                                  */
3326                                 if (randint0(100) < 75)
3327                                 {
3328                                         place_object(*y, *x, FALSE, FALSE);
3329                                 }
3330                                 else
3331                                 {
3332                                         place_trap(*y, *x);
3333                                 }
3334
3335                                 object_level = base_level;
3336                         }
3337                         else if (random & RANDOM_OBJECT)
3338                         {
3339                                 object_level = base_level + object_index;
3340
3341                                 /* Create an out of deep object */
3342                                 if (randint0(100) < 75)
3343                                         place_object(*y, *x, FALSE, FALSE);
3344                                 else if (randint0(100) < 80)
3345                                         place_object(*y, *x, TRUE, FALSE);
3346                                 else
3347                                         place_object(*y, *x, TRUE, TRUE);
3348
3349                                 object_level = base_level;
3350                         }
3351                         /* Random trap */
3352                         else if (random & RANDOM_TRAP)
3353                         {
3354                                 place_trap(*y, *x);
3355                         }
3356                         /* Hidden trap (or door) */
3357                         else if (letter[idx].trap)
3358                         {
3359                                 c_ptr->mimic = c_ptr->feat;
3360                                 c_ptr->feat = letter[idx].trap;
3361                         }
3362                         else if (object_index)
3363                         {
3364                                 /* Get local object */
3365                                 object_type *o_ptr = &object_type_body;
3366
3367                                 /* Create the item */
3368                                 object_prep(o_ptr, object_index);
3369
3370                                 if (o_ptr->tval == TV_GOLD)
3371                                 {
3372                                         coin_type = object_index - OBJ_GOLD_LIST;
3373                                         make_gold(o_ptr);
3374                                         coin_type = 0;
3375                                 }
3376
3377                                 /* Apply magic (no messages, no artifacts) */
3378                                 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3379
3380                                 (void)drop_near(o_ptr, -1, *y, *x);
3381                         }
3382
3383                         /* Artifact */
3384                         if (artifact_index)
3385                         {
3386                                 if (a_info[artifact_index].cur_num)
3387                                 {
3388                                         int k_idx = 198;
3389                                         object_type forge;
3390                                         object_type *q_ptr = &forge;
3391
3392                                         object_prep(q_ptr, k_idx);
3393
3394                                         /* Drop it in the dungeon */
3395                                         (void)drop_near(q_ptr, -1, *y, *x);
3396                                 }
3397                                 else
3398                                 {
3399                                         /* Create the artifact */
3400                                         create_named_art(artifact_index, *y, *x);
3401
3402                                         a_info[artifact_index].cur_num = 1;
3403                                 }
3404                         }
3405
3406                         /* Terrain special */
3407                         c_ptr->special = letter[idx].special;
3408                 }
3409
3410                 (*y)++;
3411
3412                 return (0);
3413         }
3414
3415         /* Process "Q:<number>:<command>:... -- quest info */
3416         else if (buf[0] == 'Q')
3417         {
3418                 int num;
3419                 quest_type *q_ptr;
3420 #ifdef JP
3421                 if (buf[2] == '$')
3422                         return 0;
3423                 num = tokenize(buf + 2, 33, zz, 0);
3424 #else
3425                 if (buf[2] != '$')
3426                         return 0;
3427                 num = tokenize(buf + 3, 33, zz, 0);
3428 #endif
3429
3430                 /* Have we enough parameters? */
3431                 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3432
3433                 /* Get the quest */
3434                 q_ptr = &(quest[atoi(zz[0])]);
3435
3436                 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3437                 if (zz[1][0] == 'Q')
3438                 {
3439                         if (init_flags & INIT_ASSIGN)
3440                         {
3441                                 monster_race *r_ptr;
3442                                 artifact_type *a_ptr;
3443
3444                                 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3445
3446                                 q_ptr->type    = atoi(zz[2]);
3447                                 q_ptr->num_mon = atoi(zz[3]);
3448                                 q_ptr->cur_num = atoi(zz[4]);
3449                                 q_ptr->max_num = atoi(zz[5]);
3450                                 q_ptr->level   = atoi(zz[6]);
3451                                 q_ptr->r_idx   = atoi(zz[7]);
3452                                 q_ptr->k_idx   = atoi(zz[8]);
3453                                 q_ptr->dungeon = atoi(zz[9]);
3454
3455                                 if (num > 10)
3456                                         q_ptr->flags  = atoi(zz[10]);
3457
3458                                 r_ptr = &r_info[q_ptr->r_idx];
3459                                 if (r_ptr->flags1 & RF1_UNIQUE)
3460                                         r_ptr->flags1 |= RF1_QUESTOR;
3461
3462                                 a_ptr = &a_info[q_ptr->k_idx];
3463                                 a_ptr->gen_flags |= TRG_QUESTITEM;
3464                         }
3465                         return (0);
3466                 }
3467
3468                 /* Process "Q:<q_index>:N:<name>" -- quest name */
3469                 else if (zz[1][0] == 'N')
3470                 {
3471                         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3472                         {
3473                                 strcpy(q_ptr->name, zz[2]);
3474                         }
3475
3476                         return (0);
3477                 }
3478
3479                 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3480                 else if (zz[1][0] == 'T')
3481                 {
3482                         if (init_flags & INIT_SHOW_TEXT)
3483                         {
3484                                 strcpy(quest_text[quest_text_line], zz[2]);
3485                                 quest_text_line++;
3486                         }
3487
3488                         return (0);
3489                 }
3490         }
3491
3492         /* Process "W:<command>: ..." -- info for the wilderness */
3493         else if (buf[0] == 'W')
3494         {
3495                 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3496         }
3497
3498         /* Process "P:<y>:<x>" -- player position */
3499         else if (buf[0] == 'P')
3500         {
3501                 if (init_flags & INIT_CREATE_DUNGEON)
3502                 {
3503                         if (tokenize(buf + 2, 2, zz, 0) == 2)
3504                         {
3505                                 int panels_x, panels_y;
3506
3507                                 /* Hack - Set the dungeon size */
3508                                 panels_y = (*y / SCREEN_HGT);
3509                                 if (*y % SCREEN_HGT) panels_y++;
3510                                 cur_hgt = panels_y * SCREEN_HGT;
3511
3512                                 panels_x = (*x / SCREEN_WID);
3513                                 if (*x % SCREEN_WID) panels_x++;
3514                                 cur_wid = panels_x * SCREEN_WID;
3515
3516                                 /* Assume illegal panel */
3517                                 panel_row_min = cur_hgt;
3518                                 panel_col_min = cur_wid;
3519
3520                                 /* Place player in a quest level */
3521                                 if (p_ptr->inside_quest)
3522                                 {
3523                                         int y, x;
3524
3525                                         /* Delete the monster (if any) */
3526                                         delete_monster(py, px);
3527
3528                                         y = atoi(zz[0]);
3529                                         x = atoi(zz[1]);
3530
3531                                         py = y;
3532                                         px = x;
3533                                 }
3534                                 /* Place player in the town */
3535                                 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3536                                 {
3537                                         p_ptr->oldpy = atoi(zz[0]);
3538                                         p_ptr->oldpx = atoi(zz[1]);
3539                                 }
3540                         }
3541                 }
3542
3543                 return (0);
3544         }
3545
3546         /* Process "B:<Index>:<Command>:..." -- Building definition */
3547         else if (buf[0] == 'B')
3548         {
3549                 return parse_line_building(buf);
3550         }
3551
3552         /* Process "M:<type>:<maximum>" -- set maximum values */
3553         else if (buf[0] == 'M')
3554         {
3555                 if (tokenize(buf+2, 2, zz, 0) == 2)
3556                 {
3557                         /* Maximum towns */
3558                         if (zz[0][0] == 'T')
3559                         {
3560                                 max_towns = atoi(zz[1]);
3561                         }
3562
3563                         /* Maximum quests */
3564                         else if (zz[0][0] == 'Q')
3565                         {
3566                                 max_quests = atoi(zz[1]);
3567                         }
3568
3569                         /* Maximum r_idx */
3570                         else if (zz[0][0] == 'R')
3571                         {
3572                                 max_r_idx = atoi(zz[1]);
3573                         }
3574
3575                         /* Maximum k_idx */
3576                         else if (zz[0][0] == 'K')
3577                         {
3578                                 max_k_idx = atoi(zz[1]);
3579                         }
3580
3581                         /* Maximum v_idx */
3582                         else if (zz[0][0] == 'V')
3583                         {
3584                                 max_v_idx = atoi(zz[1]);
3585                         }
3586
3587                         /* Maximum f_idx */
3588                         else if (zz[0][0] == 'F')
3589                         {
3590                                 max_f_idx = atoi(zz[1]);
3591                         }
3592
3593                         /* Maximum a_idx */
3594                         else if (zz[0][0] == 'A')
3595                         {
3596                                 max_a_idx = atoi(zz[1]);
3597                         }
3598
3599                         /* Maximum e_idx */
3600                         else if (zz[0][0] == 'E')
3601                         {
3602                                 max_e_idx = atoi(zz[1]);
3603                         }
3604
3605                         /* Maximum d_idx */
3606                         else if (zz[0][0] == 'D')
3607                         {
3608                                 max_d_idx = atoi(zz[1]); 
3609                         }
3610
3611                         /* Maximum o_idx */
3612                         else if (zz[0][0] == 'O')
3613                         {
3614                                 max_o_idx = atoi(zz[1]);
3615                         }
3616
3617                         /* Maximum m_idx */
3618                         else if (zz[0][0] == 'M')
3619                         {
3620                                 max_m_idx = atoi(zz[1]);
3621                         }
3622
3623                         /* Wilderness size */
3624                         else if (zz[0][0] == 'W')
3625                         {
3626                                 /* Maximum wild_x_size */
3627                                 if (zz[0][1] == 'X')
3628                                         max_wild_x = atoi(zz[1]);
3629                                 /* Maximum wild_y_size */
3630                                 if (zz[0][1] == 'Y')
3631                                         max_wild_y = atoi(zz[1]);
3632                         }
3633
3634                         return (0);
3635                 }
3636         }
3637
3638
3639         /* Failure */
3640         return (1);
3641 }
3642
3643
3644 static char tmp[8];
3645 static cptr variant = "ZANGBAND";
3646
3647
3648 /*
3649  * Helper function for "process_dungeon_file()"
3650  */
3651 static cptr process_dungeon_file_expr(char **sp, char *fp)
3652 {
3653         cptr v;
3654
3655         char *b;
3656         char *s;
3657
3658         char b1 = '[';
3659         char b2 = ']';
3660
3661         char f = ' ';
3662
3663         /* Initial */
3664         s = (*sp);
3665
3666         /* Skip spaces */
3667         while (isspace(*s)) s++;
3668
3669         /* Save start */
3670         b = s;
3671
3672         /* Default */
3673         v = "?o?o?";
3674
3675         /* Analyze */
3676         if (*s == b1)
3677         {
3678                 const char *p;
3679                 const char *t;
3680
3681                 /* Skip b1 */
3682                 s++;
3683
3684                 /* First */
3685                 t = process_dungeon_file_expr(&s, &f);
3686
3687                 /* Oops */
3688                 if (!*t)
3689                 {
3690                         /* Nothing */
3691                 }
3692
3693                 /* Function: IOR */
3694                 else if (streq(t, "IOR"))
3695                 {
3696                         v = "0";
3697                         while (*s && (f != b2))
3698                         {
3699                                 t = process_dungeon_file_expr(&s, &f);
3700                                 if (*t && !streq(t, "0")) v = "1";
3701                         }
3702                 }
3703
3704                 /* Function: AND */
3705                 else if (streq(t, "AND"))
3706                 {
3707                         v = "1";
3708                         while (*s && (f != b2))
3709                         {
3710                                 t = process_dungeon_file_expr(&s, &f);
3711                                 if (*t && streq(t, "0")) v = "0";
3712                         }
3713                 }
3714
3715                 /* Function: NOT */
3716                 else if (streq(t, "NOT"))
3717                 {
3718                         v = "1";
3719                         while (*s && (f != b2))
3720                         {
3721                                 t = process_dungeon_file_expr(&s, &f);
3722                                 if (*t && streq(t, "1")) v = "0";
3723                         }
3724                 }
3725
3726                 /* Function: EQU */
3727                 else if (streq(t, "EQU"))
3728                 {
3729                         v = "1";
3730                         if (*s && (f != b2))
3731                         {
3732                                 t = process_dungeon_file_expr(&s, &f);
3733                         }
3734                         while (*s && (f != b2))
3735                         {
3736                                 p = t;
3737                                 t = process_dungeon_file_expr(&s, &f);
3738                                 if (*t && !streq(p, t)) v = "0";
3739                         }
3740                 }
3741
3742                 /* Function: LEQ */
3743                 else if (streq(t, "LEQ"))
3744                 {
3745                         v = "1";
3746                         if (*s && (f != b2))
3747                         {
3748                                 t = process_dungeon_file_expr(&s, &f);
3749                         }
3750                         while (*s && (f != b2))
3751                         {
3752                                 p = t;
3753                                 t = process_dungeon_file_expr(&s, &f);
3754                                 if (*t && (strcmp(p, t) > 0)) v = "0";
3755                         }
3756                 }
3757
3758                 /* Function: GEQ */
3759                 else if (streq(t, "GEQ"))
3760                 {
3761                         v = "1";
3762                         if (*s && (f != b2))
3763                         {
3764                                 t = process_dungeon_file_expr(&s, &f);
3765                         }
3766                         while (*s && (f != b2))
3767                         {
3768                                 p = t;
3769                                 t = process_dungeon_file_expr(&s, &f);
3770                                 if (*t && (strcmp(p, t) < 0)) v = "0";
3771                         }
3772                 }
3773
3774                 /* Oops */
3775                 else
3776                 {
3777                         while (*s && (f != b2))
3778                         {
3779                                 t = process_dungeon_file_expr(&s, &f);
3780                         }
3781                 }
3782
3783                 /* Verify ending */
3784                 if (f != b2) v = "?x?x?";
3785
3786                 /* Extract final and Terminate */
3787                 if ((f = *s) != '\0') *s++ = '\0';
3788         }
3789
3790         /* Other */
3791         else
3792         {
3793                 /* Accept all printables except spaces and brackets */
3794                 while (isprint(*s) && !strchr(" []", *s)) ++s;
3795
3796                 /* Extract final and Terminate */
3797                 if ((f = *s) != '\0') *s++ = '\0';
3798
3799                 /* Variable */
3800                 if (*b == '$')
3801                 {
3802                         /* System */
3803                         if (streq(b+1, "SYS"))
3804                         {
3805                                 v = ANGBAND_SYS;
3806                         }
3807
3808                         /* Graphics */
3809                         else if (streq(b+1, "GRAF"))
3810                         {
3811                                 v = ANGBAND_GRAF;
3812                         }
3813
3814                         else if (streq(b+1, "MONOCHROME"))
3815                         {
3816                                 if (arg_monochrome)
3817                                         v = "ON";
3818                                 else
3819                                         v = "OFF";
3820                         }
3821
3822                         /* Race */
3823                         else if (streq(b+1, "RACE"))
3824                         {
3825 #ifdef JP
3826                                 v = rp_ptr->E_title;
3827 #else
3828                                 v = rp_ptr->title;
3829 #endif
3830                         }
3831
3832                         /* Class */
3833                         else if (streq(b+1, "CLASS"))
3834                         {
3835 #ifdef JP
3836                                 v = cp_ptr->E_title;
3837 #else
3838                                 v = cp_ptr->title;
3839 #endif
3840                         }
3841
3842                         /* First realm */
3843                         else if (streq(b+1, "REALM1"))
3844                         {
3845 #ifdef JP
3846                                 v = E_realm_names[p_ptr->realm1];
3847 #else
3848                                 v = realm_names[p_ptr->realm1];
3849 #endif
3850                         }
3851
3852                         /* Second realm */
3853                         else if (streq(b+1, "REALM2"))
3854                         {
3855 #ifdef JP
3856                                 v = E_realm_names[p_ptr->realm2];
3857 #else
3858                                 v = realm_names[p_ptr->realm2];
3859 #endif
3860                         }
3861
3862                         /* Player name */
3863                         else if (streq(b+1, "PLAYER"))
3864                         {
3865                                 v = player_base;
3866                         }
3867
3868                         /* Town */
3869                         else if (streq(b+1, "TOWN"))
3870                         {
3871                                 sprintf(tmp, "%d", p_ptr->town_num);
3872                                 v = tmp;
3873                         }
3874
3875                         /* Level */
3876                         else if (streq(b+1, "LEVEL"))
3877                         {
3878                                 sprintf(tmp, "%d", p_ptr->lev);
3879                                 v = tmp;
3880                         }
3881
3882                         /* Current quest number */
3883                         else if (streq(b+1, "QUEST_NUMBER"))
3884                         {
3885                                 sprintf(tmp, "%d", p_ptr->inside_quest);
3886                                 v = tmp;
3887                         }
3888
3889                         /* Number of last quest */
3890                         else if (streq(b+1, "LEAVING_QUEST"))
3891                         {
3892                                 sprintf(tmp, "%d", leaving_quest);
3893                                 v = tmp;
3894                         }
3895
3896                         /* Quest status */
3897                         else if (prefix(b+1, "QUEST"))
3898                         {
3899                                 /* "QUEST" uses a special parameter to determine the number of the quest */
3900                                 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3901                                 v = tmp;
3902                         }
3903
3904                         /* Random */
3905                         else if (prefix(b+1, "RANDOM"))
3906                         {
3907                                 /* "RANDOM" uses a special parameter to determine the number of the quest */
3908                                 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3909                                 v = tmp;
3910                         }
3911
3912                         /* Variant name */
3913                         else if (streq(b+1, "VARIANT"))
3914                         {
3915                                 v = variant;
3916                         }
3917
3918                         /* Wilderness */
3919                         else if (streq(b+1, "WILDERNESS"))
3920                         {
3921                                 if (vanilla_town)
3922                                         sprintf(tmp, "NONE");
3923                                 else if (lite_town)
3924                                         sprintf(tmp, "LITE");
3925                                 else
3926                                         sprintf(tmp, "NORMAL");
3927                                 v = tmp;
3928                         }
3929                 }
3930
3931                 /* Constant */
3932                 else
3933                 {
3934                         v = b;
3935                 }
3936         }
3937
3938         /* Save */
3939         (*fp) = f;
3940
3941         /* Save */
3942         (*sp) = s;
3943
3944         /* Result */
3945         return (v);
3946 }
3947
3948
3949 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3950 {
3951         FILE *fp;
3952
3953         char buf[1024];
3954
3955         int num = -1;
3956
3957         errr err = 0;
3958
3959         bool bypass = FALSE;
3960
3961         int x = xmin, y = ymin;
3962
3963
3964         /* Build the filename */
3965         path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3966
3967         /* Open the file */
3968         fp = my_fopen(buf, "r");
3969
3970         /* No such file */
3971         if (!fp) return (-1);
3972
3973
3974         /* Process the file */
3975         while (0 == my_fgets(fp, buf, sizeof(buf)))
3976         {
3977                 /* Count lines */
3978                 num++;
3979
3980
3981                 /* Skip "empty" lines */
3982                 if (!buf[0]) continue;
3983
3984                 /* Skip "blank" lines */
3985                 if (isspace(buf[0])) continue;
3986
3987                 /* Skip comments */
3988                 if (buf[0] == '#') continue;
3989
3990
3991                 /* Process "?:<expr>" */
3992                 if ((buf[0] == '?') && (buf[1] == ':'))
3993                 {
3994                         char f;
3995                         cptr v;
3996                         char *s;
3997
3998                         /* Start */
3999                         s = buf + 2;
4000
4001                         /* Parse the expr */
4002                         v = process_dungeon_file_expr(&s, &f);
4003
4004                         /* Set flag */
4005                         bypass = (streq(v, "0") ? TRUE : FALSE);
4006
4007                         /* Continue */
4008                         continue;
4009                 }
4010
4011                 /* Apply conditionals */
4012                 if (bypass) continue;
4013
4014                 /* Process the line */
4015                 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4016
4017                 /* Oops */
4018                 if (err) break;
4019         }
4020
4021         /* Errors */
4022         if (err)
4023         {
4024                 cptr oops;
4025
4026                 /* Error string */
4027                 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4028
4029                 /* Oops */
4030                 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4031 #ifdef JP
4032 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4033 #else
4034                 msg_format("Parsing '%s'.", buf);
4035 #endif
4036
4037                 msg_print(NULL);
4038         }
4039
4040
4041         /* Close the file */
4042         my_fclose(fp);
4043
4044         /* Result */
4045         return (err);
4046 }
4047
4048
4049
4050 #if 0
4051 void write_r_info_txt(void)
4052 {
4053         int i, j, z, fc, bc;
4054         int dlen;
4055
4056         cptr flags[288];
4057
4058         u32b f_ptr[9];
4059         cptr *n_ptr[9];
4060
4061         monster_race *r_ptr;
4062
4063         monster_blow *b_ptr;
4064
4065         FILE *fff = fopen("output.txt", "wt");
4066
4067         cptr desc;
4068
4069         int mode = -1;
4070
4071         if (!fff) return;
4072
4073         fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4074
4075         fprintf(fff, "# Version stamp (required)\n\n");
4076
4077         /* Write Version */
4078         fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4079
4080         /* Write a note */
4081         fprintf(fff, "##### The Player #####\n\n");
4082
4083         for (z = -1; z < alloc_race_size; z++)
4084         {
4085                 /* Output the monsters in order */
4086                 i = (z >= 0) ? alloc_race_table[z].index : 0;
4087
4088                 /* Acquire the monster */
4089                 r_ptr = &r_info[i];
4090
4091                 /* Ignore empty monsters */
4092                 if (!strlen(r_name + r_ptr->name)) continue;
4093
4094                 /* Ignore useless monsters */
4095                 if (i && !r_ptr->speed) continue;
4096
4097                 /* Write a note if necessary */
4098                 if (i && (!r_ptr->level != !mode))
4099                 {
4100                         /* Note the town */
4101                         if (!r_ptr->level)
4102                         {
4103                                 fprintf(fff, "\n##### Town monsters #####\n\n");
4104                         }
4105                         /* Note the dungeon */
4106                         else
4107                         {
4108                                 fprintf(fff, "\n##### Normal monsters #####\n\n");
4109                         }
4110
4111                         /* Record the change */
4112                         mode = r_ptr->level;
4113                 }
4114
4115                 /* Acquire the flags */
4116                 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4117                 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4118                 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4119                 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4120                 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4121                 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4122                 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4123                 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4124                 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4125
4126                 /* Write New/Number/Name */
4127                 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4128
4129                 /* Write Graphic */
4130                 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4131
4132                 /* Write Information */
4133                 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4134                                                                                                                   r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4135
4136                 /* Write more information */
4137                 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4138
4139                 /* Write Blows */
4140                 for(j = 0; j < 4; j++)
4141                 {
4142                         b_ptr = &(r_ptr->blow[j]);
4143
4144                         /* Stop when done */
4145                         if (!b_ptr->method) break;
4146
4147                         /* Write the blows */
4148                         fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4149                                                                                                           r_info_blow_effect[b_ptr->effect],
4150                                                                                                           b_ptr->d_dice, b_ptr->d_side);
4151                 }
4152
4153                 /* Extract the flags */
4154                 for (fc = 0, j = 0; j < 96; j++)
4155                 {
4156                         /* Check this flag */
4157                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4158                 }
4159
4160                 /* Extract the extra flags */
4161                 for (j = 192; j < 288; j++)
4162                 {
4163                         /* Check this flag */
4164                         if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4165                 }
4166
4167                 /* Write the flags */
4168                 for (j = 0; j < fc;)
4169                 {
4170                         char buf[160];
4171
4172                         /* Start the line */
4173                         sprintf(buf, "F:");
4174
4175                         for (bc = 0; (bc < 60) && (j < fc); j++)
4176                         {
4177                                 char t[80];
4178
4179                                 /* Format the flag */
4180                                 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4181
4182                                 /* Add it to the buffer */
4183                                 strcat(buf, t);
4184
4185                                 /* Note the length */
4186                                 bc += strlen(t);
4187                         }
4188
4189                         /* Done with this line; write it */
4190                         fprintf(fff, "%s\n", buf);
4191                 }
4192
4193                 /* Write Spells if applicable */
4194                 if (r_ptr->freq_spell)
4195                 {
4196                         /* Write the frequency */
4197                         fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4198
4199                         /* Extract the spell flags */
4200                         for (fc = 0, j = 96; j < 192; j++)
4201                         {
4202                                 /* Check this flag */
4203                                 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4204                         }
4205
4206                         /* Write the flags */
4207                         for (j = 0; j < fc;)
4208                         {
4209                                 char buf[160], *t;
4210
4211                                 /* Start the line */
4212                                 sprintf(buf, "S:");
4213
4214                                 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4215                                 {
4216                                         int tlen;
4217
4218                                         /* Format the flag */
4219                                         sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4220
4221                                         tlen = strlen(t);
4222
4223                                         /* Note the length */
4224                                         bc += tlen;
4225
4226                                         /* Advance */
4227                                         t += tlen;
4228                                 }
4229
4230                                 /* Done with this line; write it */
4231                                 fprintf(fff, "%s\n", buf);
4232                         }
4233                 }
4234
4235                 /* Acquire the description */
4236                 desc = r_text + r_ptr->text;
4237                 dlen = strlen(desc);
4238
4239                 /* Write Description */
4240                 for (j = 0; j < dlen;)
4241                 {
4242                         char buf[160], *t;
4243
4244                         /* Start the line */
4245                         sprintf(buf, "D:");
4246
4247                         for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4248                         {
4249                                 *t = desc[j];
4250                         }
4251
4252                         /* Terminate it */
4253                         *t = '\0';
4254
4255                         /* Done with this line; write it */
4256                         fprintf(fff, "%s\n", buf);
4257                 }
4258
4259                 /* Space between entries */
4260                 fprintf(fff, "\n");
4261         }
4262
4263         /* Done */
4264         fclose(fff);
4265 }
4266
4267 #endif