OSDN Git Service

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