OSDN Git Service

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