OSDN Git Service

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