OSDN Git Service

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