OSDN Git Service

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