OSDN Git Service

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