1 /* $Id$ */
2 /* File: init1.c */
3 
4 /* Purpose: Initialization (part 1) -BEN- */
5 
6 #define SERVER
7 
8 #include "angband.h"
9 
10 /*
11  * This file is used to initialize various variables and arrays for the
12  * Angband game.  Note the use of "fd_read()" and "fd_write()" to bypass
13  * the common limitation of "read()" and "write()" to only 32767 bytes
14  * at a time.
15  *
16  * Several of the arrays for Angband are built from "template" files in
17  * the "lib/file" directory, from which quick-load binary "image" files
18  * are constructed whenever they are not present in the "lib/data"
19  * directory, or if those files become obsolete, if we are allowed.
20  *
21  * Warning -- the "ascii" file parsers use a minor hack to collect the
22  * name and text information in a single pass.  Thus, the game will not
23  * be able to load any template file with more than 20K of names or 60K
24  * of text, even though technically, up to 64K should be legal.
25  *
26  * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
27  * in this file is compiled out, and the game will not run unless valid
28  * "binary template files" already exist in "lib/data".  Thus, one can
29  * compile Angband with ALLOW_TEMPLATES defined, run once to create the
30  * "*.raw" files in "lib/data", and then quit, and recompile without
31  * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
32  * from changing the ascii template files in potentially dangerous ways.
33  *
34  * The code could actually be removed and placed into a "stand-alone"
35  * program, but that feels a little silly, especially considering some
36  * of the platforms that we currently support.
37  */
38 
39 
40 #ifdef ALLOW_TEMPLATES
41 
42 
43 /*
44  * Hack -- error tracking
45  */
46 extern s16b error_idx;
47 extern s16b error_line;
48 
49 
50 /*
51  * Hack -- size of the "fake" arrays
52  */
53 extern u32b fake_name_size;
54 extern u32b fake_text_size;
55 
56 
57 
58 /*** Helper arrays for parsing ascii template files ***/
59 
60 /*
61  * Monster Blow Methods
62  */
63 static cptr r_info_blow_method[] =
64 {
65 	"*",
66 	"HIT",
67 	"TOUCH",
68 	"PUNCH",
69 	"KICK",
70 	"CLAW",
71 	"BITE",
72 	"STING",
73 	"XXX1",
74 	"BUTT",
75 	"CRUSH",
76 	"ENGULF",
77 	"CHARGE",	// "XXX2",
78 	"CRAWL",
79 	"DROOL",
80 	"SPIT",
81 	"EXPLODE",	// "XXX3",
82 	"GAZE",
83 	"WAIL",
84 	"SPORE",
85 	"XXX4",
86 	"BEG",
87 	"INSULT",
88 	"MOAN",
89 	"SHOW",		// "XXX5",
90 	"WHISPER",
91 	NULL
92 };
93 
94 
95 /*
96  * Monster Blow Effects
97  */
98 static cptr r_info_blow_effect[] =
99 {
100 	"*",
101 	"HURT",
102 	"POISON",
103 	"UN_BONUS",
104 	"UN_POWER",
105 	"EAT_GOLD",
106 	"EAT_ITEM",
107 	"EAT_FOOD",
108 	"EAT_LITE",
109 	"ACID",
110 	"ELEC",
111 	"FIRE",
112 	"COLD",
113 	"BLIND",
114 	"CONFUSE",
115 	"TERRIFY",
116 	"PARALYZE",
117 	"LOSE_STR",
118 	"LOSE_INT",
119 	"LOSE_WIS",
120 	"LOSE_DEX",
121 	"LOSE_CON",
122 	"LOSE_CHR",
123 	"LOSE_ALL",
124 	"SHATTER",
125 	"EXP_10",
126 	"EXP_20",
127 	"EXP_40",
128 	"EXP_80",
129 	"DISEASE",	// below are PernA additions
130 	"TIME",
131 	"INSANITY",
132 	"HALLU",
133 	"PARASITE",
134 	"DISARM",	// ToME-NET ones
135 	"FAMINE",
136 	"SEDUCE",
137 	"LITE",		/* to replace RBE_BLIND for explosion of "yellow light" */
138 	NULL
139 };
140 
141 /*
142    "DISEASE",
143    "TIME",
144    "INSANITY",
145    "HALLU",
146    "PARASITE",
147 
148    "FAMINE",
149    NULL
150 */
151 
152 /*
153  * Monster race flags
154  */
155 static cptr r_info_flags1[] =
156 {
157 	"UNIQUE",
158 	"QUESTOR",
159 	"MALE",
160 	"FEMALE",
161 	"CHAR_CLEAR",
162 	"CHAR_MULTI",
163 	"ATTR_CLEAR",
164 	"ATTR_MULTI",
165 	"FORCE_DEPTH",
166 	"FORCE_MAXHP",
167 	"FORCE_SLEEP",
168 	"FORCE_EXTRA",
169 	"FRIEND",
170 	"FRIENDS",
171 	"ESCORT",
172 	"ESCORTS",
173 	"NEVER_BLOW",
174 	"NEVER_MOVE",
175 	"RAND_25",
176 	"RAND_50",
177 	"ONLY_GOLD",
178 	"ONLY_ITEM",
179 	"DROP_60",
180 	"DROP_90",
181 	"DROP_1D2",
182 	"DROP_2D2",
183 	"DROP_3D2",
184 	"DROP_4D2",
185 	"DROP_GOOD",
186 	"DROP_GREAT",
187 	"DROP_USEFUL",
188 	"DROP_CHOSEN"
189 };
190 
191 /*
192  * Monster race flags
193  */
194 static cptr r_info_flags2[] =
195 {
196 	"STUPID",
197 	"SMART",
198 	"CAN_SPEAK",	// "XXX1X2",
199 	"REFLECTING",	// "XXX2X2",
200 	"INVISIBLE",
201 	"COLD_BLOOD",
202 	"EMPTY_MIND",
203 	"WEIRD_MIND",
204 	"DEATH_ORB",	// "MULTIPLY",
205 	"REGENERATE",
206 	"SHAPECHANGER",	// "XXX3X2",
207 	"ATTR_ANY",	// "XXX4X2",
208 	"POWERFUL",
209 	"ELDRITCH_HORROR", 		//"XXX5X2",
210 	"AURA_FIRE",	// "XXX7X2",
211 	"AURA_ELEC",	// "XXX6X2",
212 	"OPEN_DOOR",
213 	"BASH_DOOR",
214 	"PASS_WALL",
215 	"KILL_WALL",
216 	"MOVE_BODY",
217 	"KILL_BODY",
218 	"TAKE_ITEM",
219 	"KILL_ITEM",
220 	"BRAIN_1",
221 	"BRAIN_2",
222 	"BRAIN_3",
223 	"BRAIN_4",
224 	"BRAIN_5",
225 	"BRAIN_6",
226 	"BRAIN_7",
227 	"BRAIN_8"
228 };
229 
230 /*
231  * Monster race flags
232  */
233 static cptr r_info_flags3[] =
234 {
235 	"ORC",
236 	"TROLL",
237 	"GIANT",
238 	"DRAGON",
239 	"DEMON",
240 	"UNDEAD",
241 	"EVIL",
242 	"ANIMAL",
243 	"DRAGONRIDER",	// "XXX1X3",
244 	"GOOD",	// "XXX2X3",
245 	"AURA_COLD",	// "XXX3X3",
246 	"NONLIVING",	// "IM_TELE",
247 	"HURT_LITE",
248 	"HURT_ROCK",
249 	"SUSCEP_FIRE",	// "HURT_FIRE",
250 	"SUSCEP_COLD",	// "HURT_COLD",
251 	"IM_ACID",
252 	"IM_ELEC",
253 	"IM_FIRE",
254 	"IM_COLD",
255 	"IM_POIS",
256 	"RES_TELE",	// "IM_PSI",
257 	"RES_NETH",
258 	"RES_WATE",
259 	"RES_PLAS",
260 	"RES_NEXU",
261 	"RES_DISE",
262 	"UNIQUE_4",	// "RES_PSI",
263 	"NO_FEAR",
264 	"NO_STUN",
265 	"NO_CONF",
266 	"NO_SLEEP"
267 };
268 
269 /*
270  * Monster race flags
271  */
272 /* spells 96-127 (innate) */
273 static cptr r_info_flags4[] =
274 {
275 	"SHRIEK",
276 	"UNMAGIC",		//	"CAUSE_4",
277 	"S_ANIMAL",	// "XXX3X4",
278 	"ROCKET",	// "XXX4X4",
279 	"ARROW_1",	// former 1/2 (arrow), now arrow/light
280 	"ARROW_2",	// former 3/4 (missile), now shot/heavy
281 	"ARROW_3",	//	"ARROW_3", now bolt/heavy
282 	"ARROW_4",	//	"ARROW_4", now missile/heavy
283 	"BR_ACID",
284 	"BR_ELEC",
285 	"BR_FIRE",
286 	"BR_COLD",
287 	"BR_POIS",
288 	"BR_NETH",
289 	"BR_LITE",
290 	"BR_DARK",
291 	"BR_CONF",
292 	"BR_SOUN",
293 	"BR_CHAO",
294 	"BR_DISE",
295 	"BR_NEXU",
296 	"BR_TIME",
297 	"BR_INER",
298 	"BR_GRAV",
299 	"BR_SHAR",
300 	"BR_PLAS",
301 	"BR_WALL",
302 	"BR_MANA",
303 	"BR_DISI",	// "XXX8X4"
304 	"BR_NUKE",	// "XXX6X4",
305 	"MOAN",		//"XXX",    <- MOAN is for Halloween event :) -C. Blue
306 	"BOULDER",	// "XXX",
307 };
308 
309 /*
310  * Monster race flags
311  */
312 /* spells 128-159 (normal) */
313 static cptr r_info_flags5[] =
314 {
315 	"BA_ACID",
316 	"BA_ELEC",
317 	"BA_FIRE",
318 	"BA_COLD",
319 	"BA_POIS",
320 	"BA_NETH",
321 	"BA_WATE",
322 	"BA_MANA",
323 	"BA_DARK",
324 	"DRAIN_MANA",
325 	"MIND_BLAST",
326 	"BRAIN_SMASH",
327 	"CURSE",	//	"CAUSE_1",
328 	"RAND_100",		//	"CAUSE_2",
329 	"BA_NUKE",	// "XXX5X4",
330 	"BA_CHAO",	// "XXX7X4",
331 	"BO_ACID",
332 	"BO_ELEC",
333 	"BO_FIRE",
334 	"BO_COLD",
335 	"BO_POIS",
336 	"BO_NETH",
337 	"BO_WATE",
338 	"BO_MANA",
339 	"BO_PLAS",
340 	"BO_ICEE",
341 	"MISSILE",
342 	"SCARE",
343 	"BLIND",
344 	"CONF",
345 	"SLOW",
346 	"HOLD"
347 };
348 
349 /*
350  * Monster race flags
351  */
352 /* spells 160-191 (bizarre) */
353 static cptr r_info_flags6[] =
354 {
355 	"HASTE",
356 	"HAND_DOOM",	// "XXX1X6",
357 	"HEAL",
358 	"S_ANIMALS",	// "XXX2X6",
359 	"BLINK",
360 	"TPORT",
361 	"RAISE_DEAD",	// "XXX3X6",
362 	"S_BUG",	// "XXX4X6",
363 	"TELE_TO",
364 	"TELE_AWAY",
365 	"TELE_LEVEL",
366 	"S_RNG",	// "XXX5",
367 	"DARKNESS",
368 	"TRAPS",
369 	"FORGET",
370 	"S_DRAGONRIDER",	// "XXX6X6",
371 	"S_KIN",	// "XXX7X6",
372 	"S_HI_DEMON",	// "XXX8X6",
373 	"S_MONSTER",
374 	"S_MONSTERS",
375 	"S_ANT",
376 	"S_SPIDER",
377 	"S_HOUND",
378 	"S_HYDRA",
379 	"S_ANGEL",
380 	"S_DEMON",
381 	"S_UNDEAD",
382 	"S_DRAGON",
383 	"S_HI_UNDEAD",
384 	"S_HI_DRAGON",
385 	"S_NAZGUL",
386 	"S_UNIQUE"
387 };
388 
389 #if 0	/* flags6 */
390 	"RAISE_DEAD", /* ToDo: Implement RAISE_DEAD */
391 	"S_BUG",
392 	"S_RNG",
393 	"S_DRAGONRIDER",  /* DG : Summon DragonRider */
394 	"S_KIN",
395 	"S_HI_DEMON",
396 #endif
397 
398 /*
399  * most of r_info_flags7-9 are not implemented;
400  * for now, they're simply to 'deceive' parser.	- Jir -
401  */
402 
403 /*
404  * Monster race flags
405  */
406 static cptr r_info_flags7[] =
407 {
408 	"AQUATIC",
409 	"CAN_SWIM",
410 	"CAN_FLY",
411 	"FRIENDLY",
412 		"PET",
413 		"MORTAL",
414 	"SPIDER",
415 	"NAZGUL",
416 		"DG_CURSE",
417 		"POSSESSOR",
418 	"NO_DEATH",
419 	"NO_TARGET",
420 	"AI_ANNOY",
421 		"AI_SPECIAL",
422 		"NEUTRAL",
423 		"DROP_ART",
424 		"DROP_RANDART",
425 		"AI_PLAYER",
426 		"NO_THEFT",
427 	"NEVER_ACT",
428 	"NO_ESP",
429 	"ATTR_BASE",
430 	"VORTEX",
431 		"OOD_20",
432 		"OOD_15",
433 		"OOD_10",
434 	"ATTR_BNW",
435 		"S_LOWEXP", //"XXX7X27",
436 		"S_NOEXP", //"XXX7X28",
437 	"ATTR_BREATH",	//"XXX7X29",
438 	"MULTIPLY",		//"XXX7X30",
439 	"DISBELIEVE",	//"XXX7X31",
440 };
441 
442 /*
443  * Monster race flags
444  */
445 static cptr r_info_flags8[] =
446 {
447 	"WILD_ONLY",
448 	"WILD_TOWN",
449 	"WILD_EASY",	/* ground without requirements: town/shore/waste/grass/swamp */
450 	"WILD_SHORE",
451 	"WILD_OCEAN",
452 	"WILD_WASTE",
453 	"WILD_WOOD",
454 	"WILD_VOLCANO",
455 	"RAND_5",
456 	"WILD_MOUNTAIN",
457 	"WILD_GRASS",
458 	"NO_CUT",
459 	"CTHANGBAND",
460 	"PERNANGBAND",
461 	"ZANGBAND",
462 	"JOKEANGBAND",
463 	"BASEANGBAND",
464 	"BLUEBAND",
465 	"NO_AUTORET",
466 	"WILD_DESERT",
467 	"WILD_ICE",
468 	"NETHER_REALM",
469 	"PLURAL",
470 	"NO_BLOCK",
471 	"ALLOW_RUNNING",
472 	"AVOID_PERMAWALLS",
473 	"PSEUDO_UNIQUE",
474 	"GENO_PERSIST",
475 	"GENO_NO_THIN",
476 	"CLIMB",
477 	"WILD_SWAMP",	/* ToDo: Implement Swamp */
478 	"WILD_TOO",
479 };
480 
481 
482 /*
483  * Monster race flags - Drops
484  */
485 static cptr r_info_flags9[] =
486 {
487 	"DROP_CORPSE",
488 	"DROP_SKELETON",
489 	"HAS_LITE",
490 	"MIMIC",
491 
492 	"HAS_EGG",
493 	"IMPRESSED",
494 	"SUSCEP_ACID",
495 	"SUSCEP_ELEC",
496 
497 	"SUSCEP_POIS",
498 	"KILL_TREES",
499 	"WYRM_PROTECT",
500 	"DOPPLEGANGER",
501 
502 	"ONLY_DEPTH",
503 	"SPECIAL_GENE",
504 	"NEVER_GENE",
505 	"RES_ACID",
506 
507 	"RES_ELEC",
508 	"RES_FIRE",
509 	"RES_COLD",
510 	"RES_POIS",
511 
512 	"RES_LITE",
513 	"RES_DARK",
514 	"RES_BLIND",
515 	"RES_SOUND",
516 
517 	"RES_SHARDS",
518 	"RES_CHAOS",
519 	"RES_TIME",
520 	"RES_MANA",
521 
522 	"IM_WATER",
523 	"IM_TELE",
524 	"IM_PSI",
525 	"RES_PSI",
526 };
527 
528 /*
529  * Monster race flags - Additional stuff - C. Blue
530  */
531 static cptr r_info_flags0[] =
532 {
533 	"S_HI_MONSTER",
534 	"S_HI_MONSTERS",
535 	"S_HI_UNIQUE",
536 	"ASTAR",//4
537 	"NO_ESCORT",
538 	"NO_NEST",
539 	"FINAL_GUARDIAN", /* should not be used in r_info, since it's set implicitely from d_info */
540 	"BO_DISE",//8
541 	"BA_DISE",
542 	"ROAMING",
543 	"DROP_1",
544 	"X00000800",//12
545 	"X00001000",
546 	"X00002000",
547 	"X00004000",
548 	"X00008000",//16
549 	"X00010000",
550 	"X00020000",
551 	"X00040000",
552 	"X00080000",//20
553 	"X00100000",
554 	"X00200000",
555 	"X00400000",
556 	"X00800000",//24
557 	"X01000000",
558 	"X02000000",
559 	"X04000000",
560 	"X08000000",//28
561 	"X10000000",
562 	"X20000000",
563 	"X40000000",
564 	"X80000000",//32
565 };
566 
567 /*
568  * Trap flags (PernAngband)
569  */
570 static cptr t_info_flags[] =
571 {
572         "CHEST",
573         "DOOR",
574         "FLOOR",
575         "CHANGE",	// "XXX4",
576         "SPECIAL_GENE",
577         "LEVEL_GEN",
578         "XXX7",
579         "XXX8",
580         "XXX9",
581         "XXX10",
582         "XXX11",
583         "XXX12",
584         "XXX13",
585         "XXX14",
586         "XXX15",
587         "XXX16",
588         "LEVEL1",
589         "LEVEL2",
590         "LEVEL3",
591         "LEVEL4",
592         "XXX21",
593         "XXX22",
594         "XXX23",
595         "XXX24",
596         "XXX25",
597         "XXX26",
598         "XXX27",
599         "XXX28",
600         "XXX29",
601         "XXX30",
602         "EASY_ID",
603         "NO_ID"
604 };
605 
606 /*
607  * Object flags
608  */
609 static cptr k_info_flags1[] =
610 {
611 	"STR",
612 	"INT",
613 	"WIS",
614 	"DEX",
615 	"CON",
616 	"CHR",
617 	"MANA",
618 	"SPELL",	// "SPELL_SPEED",
619 	"STEALTH",
620 	"SEARCH",
621 	"INFRA",
622 	"TUNNEL",
623 	"SPEED",
624 	"BLOWS",
625 	"LIFE",	// "LIFE",
626 	"VAMPIRIC",	// "XXX4",
627 	"SLAY_ANIMAL",
628 	"SLAY_EVIL",
629 	"SLAY_UNDEAD",
630 	"SLAY_DEMON",
631 	"SLAY_ORC",
632 	"SLAY_TROLL",
633 	"SLAY_GIANT",
634 	"SLAY_DRAGON",
635 	"KILL_DRAGON",
636         "KILL_DEMON",
637         "KILL_UNDEAD",
638 	"BRAND_POIS",	//"XXX6",
639 	"BRAND_ACID",
640 	"BRAND_ELEC",
641 	"BRAND_FIRE",
642 	"BRAND_COLD"
643 };
644 
645 /*
646  * Object flags
647  */
648 static cptr k_info_flags2[] =
649 {
650 	"SUST_STR",
651 	"SUST_INT",
652 	"SUST_WIS",
653 	"SUST_DEX",
654 	"SUST_CON",
655 	"SUST_CHR",
656         "REDUC_FIRE",	//"INVIS",
657         "REDUC_COLD",	//"LIFE",
658 	"IM_ACID",
659 	"IM_ELEC",
660 	"IM_FIRE",
661 	"IM_COLD",
662         "REDUC_ELEC",	//"SENS_FIRE",
663         "REDUC_ACID",	//"REFLECT",
664 	"FREE_ACT",
665 	"HOLD_LIFE",
666 	"RES_ACID",
667 	"RES_ELEC",
668 	"RES_FIRE",
669 	"RES_COLD",
670 	"RES_POIS",
671 	"RES_FEAR",		// "ANTI_MAGIC",
672 	"RES_LITE",
673 	"RES_DARK",
674 	"RES_BLIND",
675 	"RES_CONF",
676 	"RES_SOUND",
677 	"RES_SHARDS",
678 	"RES_NETHER",
679 	"RES_NEXUS",
680 	"RES_CHAOS",
681 	"RES_DISEN"
682 };
683 
684 /*
685  * Object flags
686  */
687 static cptr k_info_flags3[] =
688 {
689 	"SH_FIRE",
690 	"SH_ELEC",
691         "AUTO_CURSE",
692         "DECAY",
693 	"NO_TELE",
694 	"NO_MAGIC",
695 	"WRAITH",
696 	"TY_CURSE",		// ---
697 	"EASY_KNOW",
698 	"HIDE_TYPE",
699 	"SHOW_MODS",
700 	"INSTA_ART",
701 	"FEATHER",
702         "LITE1",	// "LITE",
703 	"SEE_INVIS",
704 	"NORM_ART",		// "TELEPATHY"
705 	"SLOW_DIGEST",
706 	"REGEN",
707 	"XTRA_MIGHT",
708 	"XTRA_SHOTS",
709 	"IGNORE_ACID",
710 	"IGNORE_ELEC",
711 	"IGNORE_FIRE",
712 	"IGNORE_COLD",
713 	"ACTIVATE",
714 	"DRAIN_EXP",
715 	"TELEPORT",
716 	"AGGRAVATE",
717 	"BLESSED",
718 	"CURSED",
719 	"HEAVY_CURSE",
720 	"PERMA_CURSE"
721 };
722 
723 #if 1	// under construction
724 
725 #if 1	// vs.monst traps flags. implemented.
726 /*
727  * Trap flags
728  */
729 static cptr k_info_flags2_trap[] =
730 {
731         "AUTOMATIC_5",
732         "AUTOMATIC_99",
733         "KILL_GHOST",
734         "TELEPORT_TO",
735         "ONLY_DRAGON",
736         "ONLY_DEMON",
737         "XXX3",
738         "XXX3",
739         "ONLY_ANIMAL",
740         "ONLY_UNDEAD",
741         "ONLY_EVIL",
742         "XXX3",
743 	"XXX3",
744         "XXX3",
745         "XXX3",
746         "XXX3",
747         "XXX3",
748         "XXX3",
749         "XXX3",
750         "XXX3",
751         "XXX3",
752         "XXX3",
753         "XXX3",
754         "XXX3",
755         "XXX3",
756         "XXX3",
757         "XXX3",
758         "XXX3",
759         "XXX3",
760         "XXX3",
761         "XXX3",
762         "XXX3",
763 };
764 #endif	// 0
765 
766 /*
767  * Object flags
768  */
769 static cptr k_info_flags4[] =
770 {
771         "NEVER_BLOW",
772         "PRECOGNITION",
773         "BLACK_BREATH",
774         "RECHARGE",
775         "LEVITATE",
776         "DG_CURSE",
777         "SHOULD2H",
778         "MUST2H",
779         "COULD2H",
780         "CLONE",
781         "SPECIAL_GENE",
782         "CLIMB",
783         "FAST_CAST",
784         "CAPACITY",
785         "CHARGING",
786         "CHEAPNESS",
787         "FOUNTAIN",
788         "ANTIMAGIC_50",
789         "ANTIMAGIC_30",
790         "ANTIMAGIC_20",
791         "ANTIMAGIC_10",
792         "EASY_USE",
793         "IM_NETHER",
794         "RECHARGED",
795         "ULTIMATE",
796         "AUTO_ID",
797         "LITE2",
798         "LITE3",
799         "FUEL_LITE",
800         "ART_EXP",
801         "CURSE_NO_DROP",
802         "NO_RECHARGE"
803 };
804 
805 /*
806  * Object flags
807  */
808 static cptr k_info_flags5[] =
809 {
810         "TEMPORARY",
811         "DRAIN_MANA",
812         "DRAIN_HP",
813 	"VORPAL",	//"XXX5",
814 	"IMPACT",
815         "CRIT",
816         "ATTR_MULTI",
817         "WOUNDING",
818         "FULL_NAME",
819         "LUCK",
820         "IMMOVABLE",
821         "LEVELS",
822 	"FORCE_DEPTH",
823 	"WHITE_LIGHT",
824 	"IGNORE_DISEN",
825 	"RES_TELE",
826 	"SH_COLD",
827 	"IGNORE_MANA",
828 	"IGNORE_WATER",
829 	"RES_TIME",
830 	"RES_MANA",
831 	"IM_POISON",
832 	"IM_WATER",
833 	"RES_WATER",
834 	"REGEN_MANA",	// "XXX8X24",
835 	"DISARM",	// "XXX8X25",
836 	"NO_ENCHANT",	// "XXX8X26",
837 	"CHAOTIC",	//"XXX8X27",
838 	"INVIS",	//"XXX8X28",
839 	"REFLECT",	//"XXX8X29",
840 	"PASS_WATER",	// "NORM_ART" is already in TR3
841 	"WINNERS_ONLY",
842 };
843 
844 static cptr k_info_flags6[] = {
845 	"INSTA_EGO",
846 	"STARTUP",
847 	"XXX00000004",
848 	"XXX00000008",
849 
850 	"XXX00000010",
851 	"XXX00000020",
852 	"XXX00000040",
853 	"XXX00000080",
854 
855 	"XXX00000100",
856 	"XXX00000200",
857 	"XXX00000400",
858 	"XXX00000800",
859 
860 	"XXX00001000",
861 	"XXX00002000",
862 	"XXX00004000",
863 	"XXX00008000",
864 
865 	"XXX00010000",
866 	"XXX00020000",
867 	"XXX00040000",
868 	"XXX00080000",
869 
870 	"XXX00100000",
871 	"XXX00200000",
872 	"XXX00400000",
873 	"XXX00800000",
874 
875 	"XXX01000000",
876 	"XXX02000000",
877 	"XXX04000000",
878 	"XXX08000000",
879 
880 	"XXX10000000",
881 	"XXX20000000",
882 	"XXX40000000",
883 	"XXX80000000",
884 };
885 
886 /*
887  * ESP flags
888  */
889 cptr esp_flags[] =
890 {
891         "ESP_ORC",
892         "ESP_TROLL",
893         "ESP_DRAGON",
894         "ESP_GIANT",
895         "ESP_DEMON",
896         "ESP_UNDEAD",
897         "ESP_EVIL",
898         "ESP_ANIMAL",
899         "ESP_DRAGONRIDER",
900         "ESP_GOOD",
901         "ESP_NONLIVING",
902         "ESP_UNIQUE",
903         "ESP_SPIDER",
904 	"XXX8X02",
905 	"XXX8X02",
906 	"XXX8X02",
907 	"XXX8X02",
908 	"XXX8X17",
909 	"XXX8X18",
910 	"XXX8X19",
911 	"XXX8X20",
912 	"XXX8X21",
913 	"XXX8X22",
914 	"XXX8X23",
915 	"XXX8X24",
916 	"XXX8X25",
917 	"XXX8X26",
918 	"XXX8X27",
919 	"R_ESP_LOW",
920 	"R_ESP_HIGH", /* "XXX8X29", */
921 	"R_ESP_ANY", /* "XXX8X02", */
922         "ESP_ALL",
923 };
924 
925 /* Specially handled properties for ego-items */
926 
927 static cptr ego_flags1[] =
928 {
929         "SUSTAIN",
930         "OLD_RESIST",
931         "ABILITY",
932         "R_ELEM",
933 
934         "R_LOW",
935         "R_HIGH",
936         "R_ANY",
937         "R_DRAGON",
938 
939         "SLAY_WEAP",
940         "DAM_DIE",
941         "DAM_SIZE",
942         "PVAL_M1",
943 
944         "PVAL_M2",
945         "PVAL_M3",
946         "PVAL_M5",
947         "AC_M5",
948 
949         "NO_DOUBLE_EGO",
950         "XXX2",
951         "XXX3",
952         "XXXH1",
953 
954         "XXXH2",
955         "XXXH3",
956         "XXXH5",
957         "XXXD3",
958 
959         "R_ESP",	// "TD_M1",
960         "NO_SEED",	// "TD_M2",
961         "LOW_ABILITY",
962         "R_P_ABILITY",
963 
964         "R_STAT",
965         "R_STAT_SUST",
966         "R_IMMUNITY",
967         "LIMIT_BLOWS"
968 };
969 
970 static cptr ego_flags2[] =
971 {
972         "R_SLAY",
973         "XXX00000002",
974         "XXX00000004",
975         "XXX00000008",
976 
977         "XXX00000010",
978         "XXX00000020",
979         "XXX00000040",
980         "XXX00000080",
981 
982         "XXX00000100",
983         "XXX00000200",
984         "XXX00000400",
985         "XXX00000800",
986 
987         "XXX00001000",
988         "XXX00002000",
989         "XXX00004000",
990         "XXX00008000",
991 
992         "XXX00010000",
993         "XXX00020000",
994         "XXX00040000",
995         "XXX00080000",
996 
997         "XXX00100000",
998         "XXX00200000",
999         "XXX00400000",
1000         "XXX00800000",
1001 
1002         "XXX01000000",
1003         "XXX02000000",
1004         "XXX04000000",
1005         "XXX08000000",
1006 
1007         "XXX10000000",
1008         "XXX20000000",
1009         "XXX40000000",
1010         "XXX80000000"
1011 };
1012 #endif
1013 
1014 /*
1015  * Feature flags
1016  */
1017 static cptr f_info_flags1[] =
1018 {
1019 	"NO_WALK",
1020 	"NO_VISION",
1021 	"CAN_FEATHER",
1022 	"CAN_PASS",
1023 
1024 	"FLOOR",
1025 	"WALL",
1026 	"PERMANENT",
1027 	"CAN_LEVITATE",
1028 
1029 	"REMEMBER",
1030 	"NOTICE",
1031 	"DONT_NOTICE_RUNNING",
1032 	"CAN_RUN",
1033 
1034 	"DOOR",
1035 	"SUPPORT_LIGHT",
1036 	"CAN_CLIMB",
1037 	"TUNNELABLE",
1038 
1039 	"WEB",
1040 	"ATTR_MULTI",
1041 	"SLOW_RUNNING_1",
1042 	"SLOW_RUNNING_2",
1043 
1044 	"SLOW_LEVITATING_1",
1045 	"SLOW_LEVITATING_2",
1046 	"SLOW_CLIMBING_1",
1047 	"SLOW_CLIMBING_2",
1048 
1049 	"SLOW_WALKING_1",
1050 	"SLOW_WALKING_2",
1051 	"SLOW_SWIMMING_1",
1052 	"SLOW_SWIMMING_2",
1053 
1054 	"PROTECTED",	/* monsters cannot spawn on nor teleport to this grid. Addition for monster challenge arena: can't move onto it either! */
1055 	"LOS",	/* cannot target/shoot/cast through this one, but may be able to walk through it ('easy door') */
1056 	"BLOCK_LOS",	/* cannot target/shoot/cast through this one, but may be able to walk through it ('easy door') */
1057 	"BLOCK_CONTACT"	/* like BLOCK_LOS, but allows the player to actually see across it */
1058 };
1059 
1060 static cptr f_info_flags2[] =
1061 {
1062 	"LAMP_LITE",
1063 	"LAMP_LITE_SNOW",
1064 	"SPECIAL_LITE",
1065 	"NIGHT_DARK",
1066 
1067 	"NO_SHADE",
1068 	"NO_LITE_WHITEN",
1069 	"LAMP_LITE_OPTIONAL",
1070 	"NO_ARTICLE",
1071 
1072 	"XXX",
1073 	"XXX",
1074 	"XXX",
1075 	"XXX",
1076 
1077 	"XXX",
1078 	"XXX",
1079 	"XXX",
1080 	"XXX",
1081 
1082 	"XXX",
1083 	"XXX",
1084 	"XXX",
1085 	"XXX",
1086 
1087 	"XXX",
1088 	"XXX",
1089 	"XXX",
1090 	"XXX",
1091 
1092 	"XXX",
1093 	"XXX",
1094 	"XXX",
1095 	"XXX",
1096 
1097 	"XXX",
1098 	"XXX",
1099 	"XXX",
1100 	"BOUNDARY"
1101 };
1102 
1103 #if 1	// flags from ToME, for next expansion
1104 
1105 /*
1106  * Dungeon flags
1107  */
1108 static cptr d_info_flags1[] =
1109 {
1110 	"PRINCIPAL",
1111 	"MAZE",
1112 	"SMALLEST",
1113 	"SMALL",
1114 	"BIG",
1115 	"NO_DOORS",
1116 	"WATER_RIVER",
1117 	"LAVA_RIVER",
1118 	"WATER_RIVERS",
1119 	"LAVA_RIVERS",
1120 	"CAVE",
1121 	"CAVERN",
1122 	"NO_UP",
1123 	"HOT",
1124 	"COLD",
1125 	"FORCE_DOWN",
1126 	"FORGET",
1127 	"NO_DESTROY",
1128 	"SAND_VEIN",
1129 	"CIRCULAR_ROOMS",
1130 	"EMPTY",
1131 	"DAMAGE_FEAT",
1132 	"FLAT",
1133 	"TOWER",
1134 	"RANDOM_TOWNS",
1135 	"DOUBLE",
1136 	"LIFE_LEVEL",
1137 	"EVOLVE",
1138 	"ADJUST_LEVEL_1",
1139 	"ADJUST_LEVEL_2",
1140 	"NO_RECALL",
1141 	"NO_STREAMERS"
1142 };
1143 
1144 static cptr d_info_flags2[] =
1145 {
1146 	"RANDOM",
1147 	"IRON",
1148 	"HELL",
1149 	"NO_RECALL_INTO",
1150 //	"NO_MAP",	/* will be annexed to DF1_FORGET */
1151 	"NO_MAGIC_MAP",
1152 	"MISC_STORES",
1153 	"TOWNS_IRONRECALL",
1154 	"NO_DEATH",	/* 0x00000080L */
1155 	"IRONFIX1",
1156 	"IRONFIX2",
1157 	"IRONFIX3",
1158 	"IRONFIX4",
1159 	"IRONRND1",
1160 	"IRONRND2",
1161 	"IRONRND3",
1162 	"IRONRND4",
1163 	"NO_ENTRY_STAIR",
1164 	"NO_ENTRY_WOR",
1165 	"NO_ENTRY_PROB",
1166 	"NO_ENTRY_FLOAT",
1167 	"NO_EXIT_STAIR",
1168 	"NO_EXIT_WOR",
1169 	"NO_EXIT_PROB",
1170 	"NO_EXIT_FLOAT",
1171 	"NO_STAIRS_UP",
1172 	"NO_STAIRS_DOWN",
1173 	"TOWNS_FIX",
1174 	"TOWNS_RND",
1175 	"ADJUST_LEVEL_1_2",
1176 	"NO_SHAFT",
1177 	"ADJUST_LEVEL_PLAYER",
1178 	"DELETED"	/* not likely */
1179 };
1180 
1181 static cptr d_info_flags3[] =
1182 {
1183 	"JAIL_DUNGEON",		/* not specified directly */
1184 	"HIDDENLIB",
1185 	"NO_SIMPLE_STORES",
1186 	"NO_DUNGEON_BONUS",
1187 	"EXP_5",
1188 	"EXP_10",
1189 	"EXP_20",
1190 	"LUCK_1",
1191 
1192 	"LUCK_5",
1193 	"LUCK_20",
1194 	"LUCK_PROG_IDDC",
1195 	"SHORT_IDDC",
1196 	"DERARE_MONSTERS",
1197 	"MANY_MONSTERS",
1198 	"VMANY_MONSTERS",
1199 	"DEEPSUPPLY",
1200 
1201 	"NO_WALL_STREAMERS",
1202 	"NOT_EMPTY",
1203 	"NOT_WATERY",
1204 	"FEW_ROOMS",
1205 	"NO_VAULTS",
1206 	"NO_MAZE",
1207 	"NO_EMPTY",
1208 	"NO_DESTROYED",
1209 
1210 	"",
1211 	"",
1212 	"",
1213 	"",
1214 	"",
1215 	"",
1216 	"",
1217 	"",
1218 };
1219 
1220 #endif	// 1
1221 
1222 /* Vault flags */
1223 static cptr v_info_flags1[] =
1224 {
1225 	"FORCE_FLAGS",
1226 	"NO_TELE",
1227 	"NO_GENO",
1228 	"NO_MAP",
1229 	"NO_MAGIC_MAP",
1230 	"NO_DESTROY",
1231 	"NO_MAGIC",
1232 	"XXX1",		// ASK_LEAVE
1233 	"XXX1",
1234 	"XXX1",
1235 	"XXX1",
1236 	"XXX1",		// DESC
1237 	"XXX1",
1238 	"XXX1",
1239 	"XXX1",
1240 	"XXX1",
1241 	"XXX1",
1242 	"XXX1",
1243 	"XXX1",
1244 	"XXX1",
1245 	"NO_EASY_TRUEARTS",
1246 	"NO_EASY_RANDARTS",
1247 	"RARE_TRUEARTS",
1248 	"RARE_RANDARTS",
1249 	"NO_TRUEARTS",
1250 	"NO_RANDARTS",
1251 	"XXX1",
1252 	"XXX1",
1253 	"NO_PENETR",
1254 	"HIVES",
1255 	"NO_MIRROR",
1256 	"NO_ROTATE"
1257 };
1258 
1259 /* Skill flags */
1260 static cptr s_info_flags1[] =
1261 {
1262         "HIDDEN",
1263         "AUTO_HIDE",
1264 	"DUMMY",
1265 	"MAX_1",
1266 
1267 	"MAX_10",
1268 	"MAX_20",
1269 	"MAX_25",
1270 	"AUTO_MAX",
1271 
1272 	"XXX1",
1273 	"XXX1",
1274 	"XXX1",
1275 	"XXX1",
1276 
1277 	"XXX1",
1278 	"XXX1",
1279 	"XXX1",
1280 	"XXX1",
1281 
1282 	"XXX1",
1283 	"XXX1",
1284 	"XXX1",
1285 	"XXX1",
1286 
1287 	"XXX1",
1288 	"XXX1",
1289 	"XXX1",
1290 	"XXX1",
1291 
1292 	"XXX1",
1293 	"XXX1",
1294 	"MKEY_SCHOOL",		/* Below are Client flags */
1295 	"MKEY_HARDCODE",
1296 
1297 	"MKEY_SPELL",		/* Realm spells */
1298 	"MKEY_TVAL",
1299 	"MKEY_ITEM",
1300 	"MKEY_DIRECTION"
1301 };
1302 
1303 
1304 /*
1305  * Dungeon effect types (used in E:damage:frequency:type entry in d_info.txt)
1306  */
1307 static struct
1308 {
1309 	cptr name;
1310 	int feat;
1311 } d_info_dtypes[] =
1312 {
1313 	{"ELEC", GF_ELEC},
1314 	{"POISON", GF_POIS},
1315 	{"ACID", GF_ACID},
1316 	{"COLD", GF_COLD},
1317 	{"FIRE", GF_FIRE},
1318 	{"MISSILE", GF_MISSILE},
1319 	{"ARROW", GF_ARROW},
1320 	{"PLASMA", GF_PLASMA},
1321 	{"WATER", GF_WATER},
1322 	{"LITE", GF_LITE},
1323 	{"DARK", GF_DARK},
1324 	{"LITE_WEAK", GF_LITE_WEAK},
1325 	{"LITE_DARK", GF_DARK_WEAK},
1326 	{"SHARDS", GF_SHARDS},
1327 	{"SOUND", GF_SOUND},
1328 	{"CONFUSION", GF_CONFUSION},
1329 	{"FORCE", GF_FORCE},
1330 	{"INERTIA", GF_INERTIA},
1331 	{"MANA", GF_MANA},
1332 	{"METEOR", GF_METEOR},
1333 	{"ICE", GF_ICE},
1334 	{"CHAOS", GF_CHAOS},
1335 	{"NETHER", GF_NETHER},
1336 	{"DISENCHANT", GF_DISENCHANT},
1337 	{"NEXUS", GF_NEXUS},
1338 	{"TIME", GF_TIME},
1339 	{"GRAVITY", GF_GRAVITY},
1340 	{"INFERNO", GF_INFERNO},
1341 	{"DETONATION", GF_DETONATION},
1342 	{"ROCKET", GF_ROCKET},
1343 	{"NUKE", GF_NUKE},
1344 	{"HOLY_FIRE", GF_HOLY_FIRE},
1345 	{"HELL_FIRE", GF_HELL_FIRE},
1346 	{"DISINTEGRATE", GF_DISINTEGRATE},
1347 #if 0	// implement them first
1348 	{"DESTRUCTION", GF_DESTRUCTION},
1349 	{"RAISE", GF_RAISE},
1350 #else	// 0
1351 	{"DESTRUCTION", 0},
1352 	{"RAISE", 0},
1353 #endif	// 0
1354 	{NULL, 0}
1355 };
1356 
1357 /*
1358  * Stores flags
1359  */
1360 static cptr st_info_flags1[] =
1361 {
1362 	"DEPEND_LEVEL",
1363 	"SHALLOW_LEVEL",
1364 	"MEDIUM_LEVEL",
1365 	"DEEP_LEVEL",
1366 	"RARE",
1367 	"VERY_RARE",
1368 //	"COMMON",
1369 	"FLAT_BASE",
1370 	"ALL_ITEM",
1371 	"RANDOM",
1372 	"FORCE_LEVEL",
1373 	"MUSEUM",
1374 	"NO_DISCOUNT",
1375 	"NO_DISCOUNT2",
1376 	"EGO",
1377 	"RARE_EGO",
1378 	"PRICE1",
1379 	"PRICE2",
1380 	"PRICE4",
1381 	"PRICE16",
1382 	"GOOD",
1383 	"GREAT",
1384 	"PRICY_ITEMS1",
1385 	"PRICY_ITEMS2",
1386 	"PRICY_ITEMS3",
1387 	"PRICY_ITEMS4",
1388 	"HARD_STEAL",
1389 	"VHARD_STEAL",
1390 	"SPECIAL",
1391 	"BUY67",
1392 	"NO_DISCOUNT1",
1393 	"XXX",
1394 	"ZEROLEVEL"
1395 };
1396 
1397 /*** Initialize from ascii template files ***/
1398 
1399 
1400 
1401 /* New: Parse for conditioned comments depending on compilation definitions - C. Blue
1402    Example: $RPG_SERVER$N:158:The Secret Weapon
1403    Usage: '$'/'%' <condition> '$'/'!'
1404 	a leading '$' prepares a condition test
1405 	a leading '%' ignores <condition> ("commented out")
1406 	a final '$' tests for <condition>,
1407 	a final '!' tests for NOT<condition> */
invalid_server_conditions(char * buf)1408 static bool invalid_server_conditions(char *buf)
1409 {
1410 	char cc[1024 + 1], m[20];
1411 	int ccn = 1;
1412 	bool invalid = FALSE;
1413 
1414 	/* while loop to allow multiple macros appended to each other in the same line! */
1415 	while (buf[0] == '$' || buf[0] == '%') {
1416 		bool negation = FALSE, ignore = (buf[0] == '%');
1417 
1418 		/* read the tag between $...$ symbols */
1419 		while (buf[ccn] != '$' && buf[ccn] != '!' && buf[ccn] != '\0')
1420 			{ cc[ccn - 1] = buf[ccn]; ccn++; }
1421 
1422 		if (buf[ccn] == '\0') return TRUE; /* end of line reached, completely invalid */
1423 
1424 		/* inverted rule? means that tag is between $...! symbols */
1425 		if (buf[ccn] == '!') negation = TRUE;
1426 		cc[ccn - 1] = '\0';
1427 		/* remember the macro we found */
1428 		strcpy(m, cc);
1429 
1430 		/* In case the line passes and we will actually process it,
1431 		   already prepare it by cutting away the leading $...$ tag. */
1432 		strcpy(cc, buf + ccn + 1);
1433 		strcpy(buf, cc);
1434 
1435 		/* Test for leading '%' meaning this condition is currently commented out */
1436 		if (ignore) continue;
1437 
1438 		/* info:
1439 		   'MAIN_SERVER' isn't defined in the actual program.
1440 		   It's just a switch that means
1441 		   "don't parse this line if any special macro is defined".
1442 		   (negation: "parse this line if any special macro is defined".)
1443 
1444 		   Any other rule means
1445 		   "only parse this line if that particular macro is defined".
1446 
1447 		   And any negation of a rule means
1448 		   "don't parse this line if that particular macro is defined".
1449 		*/
1450 #ifndef RPG_SERVER
1451 		if (streq(m, "RPG_SERVER") && !negation) invalid = TRUE;
1452 #else
1453 		if (streq(m, "MAIN_SERVER") && !negation) invalid = TRUE;
1454 		if (streq(m, "RPG_SERVER") && negation) invalid = TRUE;
1455 #endif
1456 #ifndef ARCADE_SERVER
1457 		if (streq(m, "ARCADE_SERVER") && !negation) invalid = TRUE;
1458 #else
1459 		if (streq(m, "MAIN_SERVER") && !negation) invalid = TRUE;
1460 		if (streq(m, "ARCADE_SERVER") && negation) invalid = TRUE;
1461 #endif
1462 
1463 #ifndef TEST_SERVER
1464 		if (streq(m, "TEST_SERVER") && !negation) invalid = TRUE;
1465 #else
1466 		if (streq(m, "TEST_SERVER") && negation) invalid = TRUE;
1467 #endif
1468 
1469 		/* special flags that can occur additionally to server types */
1470 //#ifndef HALLOWEEN
1471 if (!season_halloween) {
1472 		if (streq(m, "HALLOWEEN") && !negation) invalid = TRUE;
1473 //#else
1474 } else {
1475 		if (streq(m, "HALLOWEEN") && negation) invalid = TRUE;
1476 //#endif
1477 }
1478 //#ifndef WINTER_SEASON
1479 if (season != SEASON_WINTER) {
1480 		if (streq(m, "WINTER_SEASON") && !negation) invalid = TRUE;
1481 //#else
1482 } else {
1483 		if (streq(m, "WINTER_SEASON") && negation) invalid = TRUE;
1484 //#endif
1485 }
1486 if (!season_xmas) {
1487 		if (streq(m, "XMAS") && !negation) invalid = TRUE;
1488 } else {
1489 		if (streq(m, "XMAS") && negation) invalid = TRUE;
1490 }
1491 //#ifndef NEW_YEARS_EVE
1492 if (!season_newyearseve) {
1493 		if (streq(m, "NEW_YEARS_EVE") && !negation) invalid = TRUE;
1494 //#else
1495 } else {
1496 		if (streq(m, "NEW_YEARS_EVE") && negation) invalid = TRUE;
1497 //#endif
1498 }
1499 #ifndef ENABLE_MAIA
1500 		if (streq(m, "ENABLE_MAIA") && !negation) invalid = TRUE;
1501 #else
1502 		if (streq(m, "ENABLE_MAIA") && negation) invalid = TRUE;
1503 #endif
1504 #ifndef USE_NEW_SHIELDS
1505 		if (streq(m, "USE_NEW_SHIELDS") && !negation) invalid = TRUE;
1506 #else
1507 		if (streq(m, "USE_NEW_SHIELDS") && negation) invalid = TRUE;
1508 #endif
1509 #ifndef NEW_SHIELDS_NO_AC
1510 		if (streq(m, "NEW_SHIELDS_NO_AC") && !negation) invalid = TRUE;
1511 #else
1512 		if (streq(m, "NEW_SHIELDS_NO_AC") && negation) invalid = TRUE;
1513 #endif
1514 #ifndef DUAL_WIELD
1515 		if (streq(m, "DUAL_WIELD") && !negation) invalid = TRUE;
1516 #else
1517 		if (streq(m, "DUAL_WIELD") && negation) invalid = TRUE;
1518 #endif
1519 #ifndef ENABLE_STANCES
1520 		if (streq(m, "ENABLE_STANCES") && !negation) invalid = TRUE;
1521 #else
1522 		if (streq(m, "ENABLE_STANCES") && negation) invalid = TRUE;
1523 #endif
1524 #ifndef ENABLE_MCRAFT
1525 		if (streq(m, "ENABLE_MCRAFT") && !negation) invalid = TRUE;
1526 #else
1527 		if (streq(m, "ENABLE_MCRAFT") && negation) invalid = TRUE;
1528 #endif
1529 #ifndef NEW_TOMES
1530 		if (streq(m, "NEW_TOMES") && !negation) invalid = TRUE;
1531 #else
1532 		if (streq(m, "NEW_TOMES") && negation) invalid = TRUE;
1533 #endif
1534 //#ifndef PRECIOUS_STONES
1535 //		if (streq(m, "PRECIOUS_STONES") && !negation) invalid = TRUE;
1536 //#else
1537 //		if (streq(m, "PRECIOUS_STONES") && negation) invalid = TRUE;
1538 //#endif
1539 #ifndef EXPAND_TV_POTION
1540 		if (streq(m, "EXPAND_TV_POTION") && !negation) invalid = TRUE;
1541 #else
1542 		if (streq(m, "EXPAND_TV_POTION") && negation) invalid = TRUE;
1543 #endif
1544 #ifndef TO_AC_CAP_30
1545 		if (streq(m, "AC30") && !negation) invalid = TRUE;
1546 #else
1547 		if (streq(m, "AC30") && negation) invalid = TRUE;
1548 #endif
1549 
1550 		/* List all known flags. If we hit an unknown flag, ignore the line by default! */
1551 		if (strcmp(m, "MAIN_SERVER") &&
1552 		    strcmp(m, "RPG_SERVER") &&
1553 		    strcmp(m, "ARCADE_SERVER") &&
1554 		    strcmp(m, "TEST_SERVER") &&
1555 		    strcmp(m, "HALLOWEEN") &&
1556 		    strcmp(m, "WINTER_SEASON") &&
1557 		    strcmp(m, "NEW_YEARS_EVE") &&
1558 		    strcmp(m, "ENABLE_MAIA") &&
1559 		    strcmp(m, "USE_NEW_SHIELDS") &&
1560 		    strcmp(m, "NEW_SHIELDS_NO_AC") &&
1561 		    strcmp(m, "DUAL_WIELD") &&
1562 		    strcmp(m, "ENABLE_STANCES") &&
1563 		    strcmp(m, "ENABLE_MCRAFT") &&
1564 		    strcmp(m, "NEW_TOMES") &&
1565 //		    strcmp(m, "PRECIOUS_STONES") &&
1566 		    strcmp(m, "EXPAND_TV_POTION") &&
1567 		    strcmp(m, "AC30") &&
1568 			TRUE)
1569 			invalid = TRUE;
1570 	}
1571 
1572 	return invalid; /* only pass if none of our tests proves to be invalid */
1573 }
1574 
1575 /*
1576  * Grab one race flag from a textual string
1577  */
1578 static bool unknown_shut_up = FALSE;
grab_one_class_flag(s32b * choice,cptr what)1579 static errr grab_one_class_flag(s32b *choice, cptr what)
1580 {
1581 	int i;
1582 	cptr s;
1583 
1584 	/* Scan classes flags */
1585 //	for (i = 0; i < max_c_idx && (s = class_info[i].title + c_name); i++)
1586 	for (i = 0; i < MAX_CLASS && (s = class_info[i].title); i++)
1587 	{
1588 		if (streq(what, s))
1589 		{
1590 			(choice[i / 32]) |= (1L << i);
1591 			return (0);
1592 		}
1593 	}
1594 
1595 	/* Oops */
1596 	if (!unknown_shut_up) s_printf("Unknown class flag '%s'.\n", what);
1597 
1598 	/* Failure */
1599 	return (1);
1600 }
grab_one_race_allow_flag(s32b * choice,cptr what)1601 static errr grab_one_race_allow_flag(s32b *choice, cptr what)
1602 {
1603 	int i;
1604 	cptr s;
1605 
1606 #ifndef ENABLE_MAIA
1607 	/* Hack, so ow_info.txt works */
1608 	if (streq(what, "Maia")) return 0;
1609 #endif
1610 
1611 	/* Scan classes flags */
1612 //	for (i = 0; i < max_rp_idx && (s = race_info[i].title + rp_name); i++)
1613 	for (i = 0; i < MAX_RACE && (s = race_info[i].title); i++) {
1614 		if (streq(what, s)) {
1615 			(choice[i / 32]) |= (1L << i);
1616 			return (0);
1617 		}
1618 	}
1619 
1620 	/* Oops */
1621 	if (!unknown_shut_up) s_printf("(1)Unknown race flag '%s'.\n", what);
1622 
1623 	/* Failure */
1624 	return (1);
1625 }
1626 
1627 /*
1628  * Grab one realm from a textual string
1629  */
grab_one_player_realm_flag(s32b * realms,cptr what)1630 static errr grab_one_player_realm_flag(s32b *realms, cptr what)
1631 {
1632 #if 0	// basically, always fail
1633 	int i;
1634 
1635 	/* Check flags1 */
1636 	for (i = 1; i < MAX_REALM; i++)
1637 	{
1638 		if (streq(what, realm_names[i][0]))
1639 		{
1640 			(realms[(i - 1) / 32]) |= (1L << (i - 1));
1641 			return (0);
1642 		}
1643 	}
1644 #endif	// 0
1645 
1646 	/* Oops */
1647 	if (!unknown_shut_up) s_printf("Unknown realm name '%s'.\n", what);
1648 
1649 	/* Error */
1650 	return (1);
1651 }
1652 
1653 /*
1654  * Grab one flag in a vault_type from a textual string
1655  */
grab_one_vault_flag(vault_type * v_ptr,cptr what)1656 static errr grab_one_vault_flag(vault_type *v_ptr, cptr what)
1657 {
1658 	int i;
1659 
1660 	/* Check flags1 */
1661 	for (i = 0; i < 32; i++)
1662 	{
1663                 if (streq(what, v_info_flags1[i]))
1664 		{
1665                         v_ptr->flags1 |= (1L << i);
1666 			return (0);
1667 		}
1668 	}
1669 
1670 	/* Oops */
1671 	s_printf("Unknown vault flag '%s'.\n", what);
1672 
1673 	/* Error */
1674 	return (1);
1675 }
1676 
1677 
1678 /*
1679  * Initialize the "v_info" array, by parsing an ascii "template" file
1680  */
init_v_info_txt(FILE * fp,char * buf)1681 errr init_v_info_txt(FILE *fp, char *buf)
1682 {
1683 	int i;
1684 
1685 	char *s, *t;
1686 
1687 	/* Not ready yet */
1688 	bool okay = FALSE;
1689 
1690 	/* Current entry */
1691 	vault_type *v_ptr = NULL;
1692 
1693 
1694 	/* Just before the first record */
1695 	error_idx = -1;
1696 
1697 	/* Just before the first line */
1698 	error_line = -1;
1699 
1700 
1701 	/* Prepare the "fake" stuff */
1702 	v_head->name_size = 0;
1703 	v_head->text_size = 0;
1704 
1705 	/* Parse */
1706 	while (0 == my_fgets(fp, buf, 1024, FALSE))
1707 	{
1708 		/* Advance the line number */
1709 		error_line++;
1710 
1711 		/* parse server conditions */
1712 		if (invalid_server_conditions(buf)) continue;
1713 
1714 		/* Skip comments and blank lines */
1715 		if (!buf[0] || (buf[0] == '#')) continue;
1716 
1717 		/* Verify correct "colon" format */
1718 		if (buf[1] != ':') return (1);
1719 
1720 
1721 		/* Hack -- Process 'V' for "Version" */
1722 		if (buf[0] == 'V')
1723 		{
1724 			int v1, v2, v3;
1725 
1726 			/* Scan for the values */
1727 			if ((3 != sscanf(buf, "V:%d.%d.%d", &v1, &v2, &v3)) ||
1728 			    (v1 != v_head->v_major) ||
1729 			    (v2 != v_head->v_minor) ||
1730 			    (v3 != v_head->v_patch))
1731 			{
1732 				/* It only annoying -- DG */
1733 //				return (2);
1734 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
1735 			}
1736 
1737 			/* Okay to proceed */
1738 			okay = TRUE;
1739 
1740 			/* Continue */
1741 			continue;
1742 		}
1743 
1744 		/* No version yet */
1745 		if (!okay) return (2);
1746 
1747 
1748 		/* Process 'N' for "New/Number/Name" */
1749 		if (buf[0] == 'N')
1750 		{
1751 			/* Find the colon before the name */
1752 			s = strchr(buf + 2, ':');
1753 
1754 			/* Verify that colon */
1755 			if (!s) return (1);
1756 
1757 			/* Nuke the colon, advance to the name */
1758 			*s++ = '\0';
1759 
1760 			/* Paranoia -- require a name */
1761 			if (!*s) return (1);
1762 
1763 			/* Get the index */
1764 			i = atoi(buf + 2);
1765 
1766 			/* Verify information */
1767 			if (i <= error_idx) return (4);
1768 
1769 			/* Verify information */
1770 			if (i >= (int) v_head->info_num) return (2);
1771 
1772 			/* Save the index */
1773 			error_idx = i;
1774 
1775 			/* Point at the "info" */
1776 			v_ptr = &v_info[i];
1777 
1778 			/* Hack -- Verify space */
1779 			if (v_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1780 
1781 			/* Advance and Save the name index */
1782 			if (!v_ptr->name) v_ptr->name = ++v_head->name_size;
1783 
1784 			/* Append chars to the name */
1785 			strcpy(v_name + v_head->name_size, s);
1786 
1787 			/* Advance the index */
1788 			v_head->name_size += strlen(s);
1789 
1790 			/* Next... */
1791 			continue;
1792 		}
1793 
1794 		/* There better be a current v_ptr */
1795 		if (!v_ptr) return (3);
1796 
1797 
1798 		/* Process 'D' for "Description" */
1799 		if (buf[0] == 'D')
1800 		{
1801 			/* Acquire the text */
1802 			s = buf + 2;
1803 
1804 			/* Hack -- Verify space */
1805 			if (v_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1806 
1807 			/* Advance and Save the text index */
1808 			if (!v_ptr->text) v_ptr->text = ++v_head->text_size;
1809 
1810 			/* Append chars to the name */
1811 			strcpy(v_text + v_head->text_size, s);
1812 
1813 			/* Advance the index */
1814 			v_head->text_size += strlen(s);
1815 
1816 			/* Next... */
1817 			continue;
1818 		}
1819 
1820 
1821 		/* Process 'X' for "Extra info" (one line only) */
1822 		if (buf[0] == 'X')
1823 		{
1824 			int typ, rat, hgt, wid;
1825 
1826 			/* Scan for the values */
1827 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
1828 			                &typ, &rat, &hgt, &wid)) return (1);
1829 
1830 			/* Save the values */
1831 			v_ptr->typ = typ;
1832 			v_ptr->rat = rat;
1833 			v_ptr->hgt = hgt;
1834 			v_ptr->wid = wid;
1835 
1836 			/* Next... */
1837 			continue;
1838 		}
1839 
1840 		/* Hack -- Process 'F' for flags */
1841 		if (buf[0] == 'F')
1842 		{
1843 			/* Parse every entry textually */
1844 			for (s = buf + 2; *s; )
1845 			{
1846 				/* Find the end of this entry */
1847 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1848 
1849 				/* Nuke and skip any dividers */
1850 				if (*t)
1851 				{
1852 					*t++ = '\0';
1853 					while (*t == ' ' || *t == '|') t++;
1854 				}
1855 
1856 				/* Parse this entry */
1857 				if (0 != grab_one_vault_flag(v_ptr, s)) return (5);
1858 
1859 				/* Start the next entry */
1860 				s = t;
1861 			}
1862 
1863 			/* Next... */
1864 			continue;
1865 		}
1866 
1867 		/* Oops */
1868 		return (6);
1869 	}
1870 
1871 
1872 	/* Complete the "name" and "text" sizes */
1873 	++v_head->name_size;
1874 	++v_head->text_size;
1875 
1876 
1877 	/* No version yet */
1878 	if (!okay) return (2);
1879 
1880 	max_v_idx = ++error_idx;
1881 
1882 	/* Success */
1883 	return (0);
1884 }
1885 
1886 
1887 #if 0
1888 /*
1889  * Initialize the "f_info" array, by parsing an ascii "template" file
1890  */
1891 errr init_f_info_txt(FILE *fp, char *buf)
1892 {
1893 	int i;
1894 
1895 	char *s;
1896 
1897 	/* Not ready yet */
1898 	bool okay = FALSE;
1899 
1900 	/* Current entry */
1901 	feature_type *f_ptr = NULL;
1902 
1903 
1904 	/* Just before the first record */
1905 	error_idx = -1;
1906 
1907 	/* Just before the first line */
1908 	error_line = -1;
1909 
1910 
1911 	/* Prepare the "fake" stuff */
1912 	f_head->name_size = 0;
1913 	f_head->text_size = 0;
1914 
1915 	/* Parse */
1916 	while (0 == my_fgets(fp, buf, 1024, FALSE))
1917 	{
1918 		/* Advance the line number */
1919 		error_line++;
1920 
1921 		/* parse server conditions */
1922 		if (invalid_server_conditions(buf)) continue;
1923 
1924 		/* Skip comments and blank lines */
1925 		if (!buf[0] || (buf[0] == '#')) continue;
1926 
1927 		/* Verify correct "colon" format */
1928 		if (buf[1] != ':') return (1);
1929 
1930 
1931 		/* Hack -- Process 'V' for "Version" */
1932 		if (buf[0] == 'V')
1933 		{
1934 			int v1, v2, v3;
1935 
1936 			/* Scan for the values */
1937 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
1938 			    (v1 != f_head->v_major) ||
1939 			    (v2 != f_head->v_minor) ||
1940 			    (v3 != f_head->v_patch))
1941 			{
1942 				/* It only annoying -- DG */
1943 //				return (2);
1944 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
1945 			}
1946 
1947 			/* Okay to proceed */
1948 			okay = TRUE;
1949 
1950 			/* Continue */
1951 			continue;
1952 		}
1953 
1954 		/* No version yet */
1955 		if (!okay) return (2);
1956 
1957 
1958 		/* Process 'N' for "New/Number/Name" */
1959 		if (buf[0] == 'N')
1960 		{
1961 			/* Find the colon before the name */
1962 			s = strchr(buf + 2, ':');
1963 
1964 			/* Verify that colon */
1965 			if (!s) return (1);
1966 
1967 			/* Nuke the colon, advance to the name */
1968 			*s++ = '\0';
1969 
1970 			/* Paranoia -- require a name */
1971 			if (!*s) return (1);
1972 
1973 			/* Get the index */
1974 			i = atoi(buf + 2);
1975 
1976 			/* Verify information */
1977 			if (i <= error_idx) return (4);
1978 
1979 			/* Verify information */
1980 			if (i >= (int) f_head->info_num) return (2);
1981 
1982 			/* Save the index */
1983 			error_idx = i;
1984 
1985 			/* Point at the "info" */
1986 			f_ptr = &f_info[i];
1987 
1988 			/* Hack -- Verify space */
1989 			if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1990 
1991 			/* Advance and Save the name index */
1992 			if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
1993 
1994 			/* Append chars to the name */
1995 			strcpy(f_name + f_head->name_size, s);
1996 
1997 			/* Advance the index */
1998 			f_head->name_size += strlen(s);
1999 
2000 			/* Default "mimic" */
2001 			f_ptr->mimic = i;
2002 
2003 			/* Next... */
2004 			continue;
2005 		}
2006 
2007 		/* There better be a current f_ptr */
2008 		if (!f_ptr) return (3);
2009 
2010 
2011 #if 0
2012 
2013 		/* Process 'D' for "Description" */
2014 		if (buf[0] == 'D')
2015 		{
2016 			/* Acquire the text */
2017 			s = buf + 2;
2018 
2019 			/* Hack -- Verify space */
2020 			if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2021 
2022 			/* Advance and Save the text index */
2023 			if (!f_ptr->text) f_ptr->text = ++f_head->text_size;
2024 
2025 			/* Append chars to the name */
2026 			strcpy(f_text + f_head->text_size, s);
2027 
2028 			/* Advance the index */
2029 			f_head->text_size += strlen(s);
2030 
2031 			/* Next... */
2032 			continue;
2033 		}
2034 
2035 #endif
2036 
2037 
2038 		/* Process 'M' for "Mimic" (one line only) */
2039 		if (buf[0] == 'M')
2040 		{
2041 			int mimic;
2042 
2043 			/* Scan for the values */
2044 			if (1 != sscanf(buf + 2, "%d",
2045 			                &mimic)) return (1);
2046 
2047 			/* Save the values */
2048 			f_ptr->mimic = mimic;
2049 
2050 			/* Next... */
2051 			continue;
2052 		}
2053 
2054 
2055 		/* Process 'G' for "Graphics" (one line only) */
2056 		if (buf[0] == 'G')
2057 		{
2058 			int tmp;
2059 
2060 			/* Paranoia */
2061 			if (!buf[2]) return (1);
2062 			if (!buf[3]) return (1);
2063 			if (!buf[4]) return (1);
2064 
2065 			/* Extract the color */
2066 			tmp = color_char_to_attr(buf[4]);
2067 			if (tmp < 0) return (1);
2068 
2069 			/* Save the values */
2070 			f_ptr->f_char = buf[2];
2071 			f_ptr->f_attr = tmp;
2072 
2073 			/* Next... */
2074 			continue;
2075 		}
2076 
2077 
2078 		/* Oops */
2079 		return (6);
2080 	}
2081 
2082 
2083 	/* Complete the "name" and "text" sizes */
2084 	++f_head->name_size;
2085 	++f_head->text_size;
2086 
2087 
2088 	/* No version yet */
2089 	if (!okay) return (2);
2090 
2091 
2092 	/* Success */
2093 	return (0);
2094 }
2095 #else // 0
2096 
2097 /*
2098  * Grab one flag in an feature_type from a textual string
2099  */
grab_one_feature_flag(feature_type * f_ptr,cptr what)2100 static errr grab_one_feature_flag(feature_type *f_ptr, cptr what)
2101 {
2102 	int i;
2103 
2104 	/* Check flags1 */
2105 	for (i = 0; i < 32; i++) {
2106                 if (streq(what, f_info_flags1[i])) {
2107                         f_ptr->flags1 |= (1L << i);
2108 			return (0);
2109 		}
2110                 if (streq(what, f_info_flags2[i])) {
2111                         f_ptr->flags2 |= (1L << i);
2112 			return (0);
2113 		}
2114 	}
2115 
2116 	/* Oops */
2117 	s_printf("Unknown object flag '%s'.\n", what);
2118 
2119 	/* Error */
2120 	return (1);
2121 }
2122 
2123 
2124 /*
2125  * Initialize the "f_info" array, by parsing an ascii "template" file
2126  */
init_f_info_txt(FILE * fp,char * buf)2127 errr init_f_info_txt(FILE *fp, char *buf)
2128 {
2129 	int i;
2130 
2131 	char *s, *t;
2132 
2133 	/* Not ready yet */
2134 	bool okay = FALSE;
2135 	u32b default_desc = 0, default_tunnel = 0, default_block = 0;
2136 
2137 	/* Current entry */
2138 	feature_type *f_ptr = NULL;
2139 
2140 
2141 	/* Just before the first record */
2142 	error_idx = -1;
2143 
2144 	/* Just before the first line */
2145 	error_line = -1;
2146 
2147 
2148 	/* Prepare the "fake" stuff */
2149 	f_head->name_size = 0;
2150 	f_head->text_size = 0;
2151 
2152 	/* Add some fake descs */
2153 	default_desc = ++f_head->text_size;
2154 	strcpy(f_text + f_head->text_size, "a wall blocking your way");
2155 	f_head->text_size += strlen("a wall blocking your way");
2156 
2157 	default_tunnel = ++f_head->text_size;
2158 	strcpy(f_text + f_head->text_size, "You cannot tunnel through that.");
2159 	f_head->text_size += strlen("You cannot tunnel through that.");
2160 
2161 	default_block = ++f_head->text_size;
2162 	strcpy(f_text + f_head->text_size, "a wall blocking your way");
2163 	f_head->text_size += strlen("a wall blocking your way");
2164 
2165 	/* Parse */
2166 	while (0 == my_fgets(fp, buf, 1024, FALSE))
2167 	{
2168 		/* Advance the line number */
2169 		error_line++;
2170 
2171 		/* parse server conditions */
2172 		if (invalid_server_conditions(buf)) continue;
2173 
2174 		/* Skip comments and blank lines */
2175 		if (!buf[0] || (buf[0] == '#')) continue;
2176 
2177 		/* Verify correct "colon" format */
2178 		if (buf[1] != ':') return (1);
2179 
2180 
2181 		/* Hack -- Process 'V' for "Version" */
2182 		if (buf[0] == 'V')
2183 		{
2184 			int v1, v2, v3;
2185 
2186 			/* Scan for the values */
2187 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
2188 					(v1 != f_head->v_major) ||
2189 					(v2 != f_head->v_minor) ||
2190 					(v3 != f_head->v_patch))
2191 			{
2192 				/* It only annoying -- DG */
2193 				//				return (2);
2194 				//				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
2195 			}
2196 
2197 			/* Okay to proceed */
2198 			okay = TRUE;
2199 
2200 			/* Continue */
2201 			continue;
2202 		}
2203 
2204 		/* No version yet */
2205 		if (!okay) return (2);
2206 
2207 
2208 		/* Process 'N' for "New/Number/Name" */
2209 		if (buf[0] == 'N')
2210 		{
2211 			/* Find the colon before the name */
2212 			s = strchr(buf + 2, ':');
2213 
2214 			/* Verify that colon */
2215 			if (!s) return (1);
2216 
2217 			/* Nuke the colon, advance to the name */
2218 			*s++ = '\0';
2219 
2220 			/* Paranoia -- require a name */
2221 			if (!*s) return (1);
2222 
2223 			/* Get the index */
2224 			i = atoi(buf + 2);
2225 
2226 			/* Verify information */
2227 			if (i <= error_idx) return (4);
2228 
2229 			/* Verify information */
2230 			if (i >= (int) f_head->info_num) return (2);
2231 
2232 			/* Save the index */
2233 			error_idx = i;
2234 
2235 			/* Point at the "info" */
2236 			f_ptr = &f_info[i];
2237 
2238 			/* Hack -- Verify space */
2239 			if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2240 
2241 			/* Advance and Save the name index */
2242 			if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
2243 
2244 			/* Append chars to the name */
2245 			strcpy(f_name + f_head->name_size, s);
2246 
2247 			/* Advance the index */
2248 			f_head->name_size += strlen(s);
2249 
2250 			/* Default "mimic" */
2251 			f_ptr->mimic = i;
2252 			f_ptr->text = default_desc;
2253 			f_ptr->block = default_desc;
2254 			f_ptr->tunnel = default_tunnel;
2255 			f_ptr->block = default_block;
2256 
2257 			/* Next... */
2258 			continue;
2259 		}
2260 
2261 		/* There better be a current f_ptr */
2262 		if (!f_ptr) return (3);
2263 
2264 
2265 		/* Process 'D' for "Descriptions" */
2266 		if (buf[0] == 'D')
2267 		{
2268 			/* Acquire the text */
2269 			s = buf+4;
2270 
2271 			/* Hack -- Verify space */
2272 			if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2273 
2274 			switch (buf[2])
2275 			{
2276 				case '0':
2277 					/* Advance and Save the text index */
2278 					f_ptr->text = ++f_head->text_size;
2279 					break;
2280 				case '1':
2281 					/* Advance and Save the text index */
2282 					f_ptr->tunnel = ++f_head->text_size;
2283 					break;
2284 				case '2':
2285 					/* Advance and Save the text index */
2286 					f_ptr->block = ++f_head->text_size;
2287 					break;
2288 				default:
2289 					return (6);
2290 					break;
2291 			}
2292 
2293 			/* Append chars to the name */
2294 			strcpy(f_text + f_head->text_size, s);
2295 
2296 			/* Advance the index */
2297 			f_head->text_size += strlen(s);
2298 
2299 			/* Next... */
2300 			continue;
2301 		}
2302 
2303 
2304 		/* Process 'M' for "Mimic" (one line only) */
2305 		if (buf[0] == 'M')
2306 		{
2307 			int mimic;
2308 
2309 			/* Scan for the values */
2310 			if (1 != sscanf(buf + 2, "%d",
2311 						&mimic)) return (1);
2312 
2313 						/* Save the values */
2314 						f_ptr->mimic = mimic;
2315 
2316 						/* Next... */
2317 						continue;
2318 		}
2319 
2320 		/* Process 'S' for "Shimmer" (one line only) */
2321 		if (buf[0] == 'S')
2322 		{
2323 			char s0, s1, s2, s3, s4, s5, s6;
2324 
2325 			/* Scan for the values */
2326 			if (7 != sscanf(buf + 2, "%c:%c:%c:%c:%c:%c:%c",
2327 						&s0, &s1, &s2, &s3, &s4, &s5, &s6)) return (1);
2328 
2329 						/* Save the values */
2330 						f_ptr->shimmer[0] = color_char_to_attr(s0);
2331 						f_ptr->shimmer[1] = color_char_to_attr(s1);
2332 						f_ptr->shimmer[2] = color_char_to_attr(s2);
2333 						f_ptr->shimmer[3] = color_char_to_attr(s3);
2334 						f_ptr->shimmer[4] = color_char_to_attr(s4);
2335 						f_ptr->shimmer[5] = color_char_to_attr(s5);
2336 						f_ptr->shimmer[6] = color_char_to_attr(s6);
2337 
2338 						/* Next... */
2339 						continue;
2340 		}
2341 
2342 
2343 		/* Process 'G' for "Graphics" (one line only) */
2344 		if (buf[0] == 'G')
2345 		{
2346 			int tmp;
2347 
2348 			/* Paranoia */
2349 			if (!buf[2]) return (1);
2350 			if (!buf[3]) return (1);
2351 			if (!buf[4]) return (1);
2352 
2353 			/* Extract the color */
2354 			tmp = color_char_to_attr(buf[4]);
2355 
2356 			/* Paranoia */
2357 			if (tmp < 0) return (1);
2358 
2359 			/* Save the values */
2360 #if 0
2361 			f_ptr->d_attr = tmp;
2362 			f_ptr->d_char = buf[2];
2363 #else	// 0
2364 			f_ptr->f_attr = tmp;
2365 			f_ptr->f_char = buf[2];
2366 #endif	// 0
2367 
2368 			/* Next... */
2369 			continue;
2370 		}
2371 
2372 		/* Process 'E' for "Effects" (up to four lines) -SC- */
2373 		if (buf[0] == 'E')
2374 		{
2375 			int side, dice, freq, type;
2376 			cptr tmp;
2377 
2378 			/* Find the next empty blow slot (if any) */
2379 			for (i = 0; i < 4; i++) if ((!f_ptr->d_side[i]) &&
2380 					(!f_ptr->d_dice[i])) break;
2381 
2382 			/* Oops, no more slots */
2383 			if (i == 4) return (1);
2384 
2385 			/* Scan for the values */
2386 			if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
2387 						&dice, &side, &freq, &type))
2388 			{
2389 				int j;
2390 
2391 				if (3 != sscanf(buf + 2, "%dd%d:%d",
2392 							&dice, &side, &freq)) return (1);
2393 
2394 							tmp = buf + 2;
2395 							for (j = 0; j < 2; j++)
2396 							{
2397 								tmp = strchr(tmp, ':');
2398 								if (tmp == NULL) return(1);
2399 								tmp++;
2400 							}
2401 
2402 							j = 0;
2403 
2404 							while (d_info_dtypes[j].name != NULL)
2405 								if (strcmp(d_info_dtypes[j].name, tmp) == 0)
2406 								{
2407 									f_ptr->d_type[i] = d_info_dtypes[j].feat;
2408 									break;
2409 								}
2410 								else j++;
2411 
2412 								if (d_info_dtypes[j].name == NULL) return(1);
2413 			}
2414 			else
2415 				f_ptr->d_type[i] = type;
2416 
2417 			freq *= 1;//was 10
2418 			/* Save the values */
2419 			f_ptr->d_side[i] = side;
2420 			f_ptr->d_dice[i] = dice;
2421 			f_ptr->d_frequency[i] = freq;
2422 
2423 			/* Next... */
2424 			continue;
2425 		}
2426 
2427 		/* Hack -- Process 'F' for flags */
2428 		if (buf[0] == 'F')
2429 		{
2430 			/* Parse every entry textually */
2431 			for (s = buf + 2; *s; )
2432 			{
2433 				/* Find the end of this entry */
2434 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2435 
2436 				/* Nuke and skip any dividers */
2437 				if (*t)
2438 				{
2439 					*t++ = '\0';
2440 					while (*t == ' ' || *t == '|') t++;
2441 				}
2442 
2443 				/* Parse this entry */
2444 				if (0 != grab_one_feature_flag(f_ptr, s)) return (5);
2445 
2446 				/* Start the next entry */
2447 				s = t;
2448 			}
2449 
2450 			/* Next... */
2451 			continue;
2452 		}
2453 
2454 
2455 
2456 		/* Oops */
2457 		return (6);
2458 	}
2459 
2460 
2461 	/* Complete the "name" and "text" sizes */
2462 	++f_head->name_size;
2463 	++f_head->text_size;
2464 
2465 
2466 	/* No version yet */
2467 	if (!okay) return (2);
2468 
2469 	max_f_idx = ++error_idx;
2470 
2471 	/* implied flags */
2472 	for (i = 0; i < max_f_idx; i++) {
2473 		if ((f_info[i].flags2 & FF2_BOUNDARY)) f_info[i].flags1 |= FF1_PERMANENT;
2474 	}
2475 
2476 	/* Success */
2477 	return (0);
2478 }
2479 #endif	// 0
2480 
2481 
2482 /*
2483  * Grab one flag in an object_kind from a textual string
2484  */
grab_one_kind_flag(object_kind * k_ptr,cptr what)2485 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what) {
2486 	int i;
2487 
2488 	for (i = 0; i < 32; i++) {
2489 		/* Check flags1 */
2490 		if (streq(what, k_info_flags1[i])) {
2491 			k_ptr->flags1 |= (1L << i);
2492 			return (0);
2493 		}
2494 		/* Check flags2 */
2495 		if (streq(what, k_info_flags2[i])) {
2496 			k_ptr->flags2 |= (1L << i);
2497 			return (0);
2498 		}
2499 #if 1
2500 		/* Check flags2 -- traps*/
2501 		if (streq(what, k_info_flags2_trap[i])) {
2502 			k_ptr->flags2 |= (1L << i);
2503 			return (0);
2504 		}
2505 #endif	// 0
2506 		/* Check flags3 */
2507 		if (streq(what, k_info_flags3[i])) {
2508 			k_ptr->flags3 |= (1L << i);
2509 			return (0);
2510 		}
2511 		/* Check flags4 */
2512                 if (streq(what, k_info_flags4[i])) {
2513                         k_ptr->flags4 |= (1L << i);
2514 			return (0);
2515 		}
2516 	        /* Check flags5 */
2517                 if (streq(what, k_info_flags5[i])) {
2518                         k_ptr->flags5 |= (1L << i);
2519 			return (0);
2520 		}
2521 	        /* Check flags6 */
2522                 if (streq(what, k_info_flags6[i])) {
2523                         k_ptr->flags6 |= (1L << i);
2524 			return (0);
2525 		}
2526 
2527 	        /* Check esp_flags */
2528                 if (streq(what, esp_flags[i])) {
2529                         k_ptr->esp |= (1L << i);
2530 			return (0);
2531 		}
2532 	}
2533 
2534 	/* Oops */
2535 	s_printf("Unknown object flag '%s'.\n", what);
2536 
2537 	/* Error */
2538 	return (1);
2539 }
2540 
2541 
2542 
2543 /*
2544  * Initialize the "k_info" array, by parsing an ascii "template" file
2545  */
init_k_info_txt(FILE * fp,char * buf)2546 errr init_k_info_txt(FILE *fp, char *buf)
2547 {
2548 	int i, idx = 0;
2549 
2550 	char *s, *t;
2551 #ifdef KIND_DIZ
2552 	char tmp[MSG_LEN];
2553 #endif
2554 
2555 	/* Not ready yet */
2556 	bool okay = FALSE;
2557 
2558 	/* Current entry */
2559 	object_kind *k_ptr = NULL;
2560 
2561 
2562 	/* Just before the first record */
2563 	error_idx = -1;
2564 
2565 	/* Just before the first line */
2566 	error_line = -1;
2567 
2568 
2569 	/* Prepare the "fake" stuff */
2570 	k_head->name_size = 0;
2571 	k_head->text_size = 0;
2572 
2573 	/* Parse */
2574 	while (0 == my_fgets(fp, buf, 1024, FALSE))
2575 	{
2576 		/* Advance the line number */
2577 		error_line++;
2578 
2579 		/* parse server conditions */
2580 		if (invalid_server_conditions(buf)) continue;
2581 
2582 		/* Skip comments and blank lines */
2583 		if (!buf[0] || (buf[0] == '#')) continue;
2584 
2585 		/* Verify correct "colon" format */
2586 		if (buf[1] != ':') return (1);
2587 
2588 
2589 		/* Hack -- Process 'V' for "Version" */
2590 		if (buf[0] == 'V')
2591 		{
2592 			int v1, v2, v3;
2593 
2594 			/* Scan for the values */
2595 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
2596 			    (v1 != k_head->v_major) ||
2597 			    (v2 != k_head->v_minor) ||
2598 			    (v3 != k_head->v_patch))
2599 			{
2600 				/* It only annoying -- DG */
2601 //				return (2);
2602 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
2603 			}
2604 
2605 			/* Okay to proceed */
2606 			okay = TRUE;
2607 
2608 			/* Continue */
2609 			continue;
2610 		}
2611 
2612 		/* No version yet */
2613 		if (!okay) return (2);
2614 
2615 
2616 		/* Process 'N' for "New/Number/Name" */
2617 		if (buf[0] == 'N')
2618 		{
2619 			/* Find the colon before the name */
2620 			s = strchr(buf + 2, ':');
2621 
2622 			/* Verify that colon */
2623 			if (!s) return (1);
2624 
2625 			/* Nuke the colon, advance to the name */
2626 			*s++ = '\0';
2627 
2628 			/* Paranoia -- require a name */
2629 			if (!*s) return (1);
2630 
2631 			/* Get the index */
2632 			//i = atoi(buf + 2);
2633 
2634 			/* Count it up */
2635 			i = ++idx;
2636 
2637 			/* Verify information */
2638 			if (i <= error_idx) return (4);
2639 
2640 			/* Verify information */
2641 			if (i >= (int) k_head->info_num) return (2);
2642 
2643 			/* Save the index */
2644 			error_idx = i;
2645 
2646 			/* Point at the "info" */
2647 			k_ptr = &k_info[i];
2648 
2649 			/* For quest_statuseffect() */
2650 			k_info_num[atoi(buf + 2)] = i;
2651 
2652 			/* Hack -- Verify space */
2653 			if (k_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2654 
2655 			/* Advance and Save the name index */
2656 			if (!k_ptr->name) k_ptr->name = ++k_head->name_size;
2657 
2658 			/* Append chars to the name */
2659 			strcpy(k_name + k_head->name_size, s);
2660 
2661 			/* Advance the index */
2662 			k_head->name_size += strlen(s);
2663 
2664 			/* Next... */
2665 			continue;
2666 		}
2667 
2668 		/* There better be a current k_ptr */
2669 		if (!k_ptr) return (3);
2670 
2671 
2672 
2673 		/* Process 'D' for "Description" */
2674 		if (buf[0] == 'D')
2675 		{
2676 #ifdef KIND_DIZ
2677 			/* Acquire the text */
2678 			s = buf + 2;
2679 
2680 			strcpy(tmp, " \377w");
2681 			strcat(tmp, s);
2682 			strcat(tmp, "\n");
2683 
2684 			/* Hack -- Verify space */
2685 			if (k_head->text_size + strlen(tmp) + 8 > fake_text_size) return (7);
2686 
2687 			/* Advance and Save the text index */
2688 			if (!k_ptr->text) k_ptr->text = ++k_head->text_size;
2689 
2690 			/* Append chars to the name */
2691 			strcpy(k_text + k_head->text_size, tmp);
2692 
2693 			/* Advance the index */
2694 			k_head->text_size += strlen(tmp);
2695 #endif
2696 			/* Next... */
2697 			continue;
2698 		}
2699 
2700 
2701 
2702 		/* Process 'G' for "Graphics" (one line only) */
2703 		if (buf[0] == 'G')
2704 		{
2705 			char sym;
2706 			int tmp;
2707 
2708 			/* Paranoia */
2709 			if (!buf[2]) return (1);
2710 			if (!buf[3]) return (1);
2711 			if (!buf[4]) return (1);
2712 
2713 			/* Extract the char */
2714 			sym = buf[2];
2715 
2716 			/* Extract the attr */
2717 			tmp = color_char_to_attr(buf[4]);
2718 
2719 			/* Paranoia */
2720 			if (tmp < 0) return (1);
2721 
2722 			/* Save the values */
2723 			k_ptr->k_char = sym;
2724 			k_ptr->k_attr = tmp;
2725 
2726 			/* Next... */
2727 			continue;
2728 		}
2729 
2730 		/* Process 'I' for "Info" (one line only) */
2731 		if (buf[0] == 'I')
2732 		{
2733 			int tval, sval, pval;
2734 
2735 			/* Scan for the values */
2736 			if (3 != sscanf(buf + 2, "%d:%d:%d",
2737 			                &tval, &sval, &pval)) return (1);
2738 
2739 			/* Save the values */
2740 			k_ptr->tval = tval;
2741 			k_ptr->sval = sval;
2742 			k_ptr->pval = pval;
2743 
2744 			/* Next... */
2745 			continue;
2746 		}
2747 
2748 		/* Process 'W' for "More Info" (one line only) */
2749 		if (buf[0] == 'W')
2750 		{
2751 			int level, extra, wgt;
2752 			int cost;
2753 
2754 			/* Scan for the values */
2755 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
2756 			                &level, &extra, &wgt, &cost)) return (1);
2757 
2758 			/* Save the values */
2759 			k_ptr->level = level;
2760 			k_ptr->extra = extra;
2761 			k_ptr->weight = wgt;
2762 			k_ptr->cost = cost;
2763 
2764 			/* Next... */
2765 			continue;
2766 		}
2767 
2768 		/* Process 'A' for "Allocation" (one line only) */
2769 		if (buf[0] == 'A')
2770 		{
2771 			int i;
2772 
2773 			/* XXX XXX XXX Simply read each number following a colon */
2774 			for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
2775 			{
2776 				/* Default chance */
2777 				k_ptr->chance[i] = 1;
2778 
2779 				/* Store the attack damage index */
2780 				k_ptr->locale[i] = atoi(s+1);
2781 
2782 				/* Find the slash */
2783 				t = strchr(s+1, '/');
2784 
2785 				/* Find the next colon */
2786 				s = strchr(s+1, ':');
2787 
2788 				/* If the slash is "nearby", use it */
2789 				if (t && (!s || t < s))
2790 				{
2791 					int chance = atoi(t+1);
2792 					if (chance > 0) k_ptr->chance[i] = chance;
2793 				}
2794 			}
2795 
2796 			/* Next... */
2797 			continue;
2798 		}
2799 
2800 		/* Hack -- Process 'P' for "power" and such */
2801 		if (buf[0] == 'P')
2802 		{
2803 			int ac, hd1, hd2, th, td, ta;
2804 
2805 			/* Scan for the values */
2806 			if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
2807 			                &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2808 
2809 			k_ptr->ac = ac;
2810 			k_ptr->dd = hd1;
2811 			k_ptr->ds = hd2;
2812 			k_ptr->to_h = th;
2813 			k_ptr->to_d = td;
2814 			k_ptr->to_a =  ta;
2815 
2816 			/* Next... */
2817 			continue;
2818 		}
2819 
2820 		/* Hack -- Process 'F' for flags */
2821 		if (buf[0] == 'F')
2822 		{
2823 			/* Parse every entry textually */
2824 			for (s = buf + 2; *s; )
2825 			{
2826 				/* Find the end of this entry */
2827 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2828 
2829 				/* Nuke and skip any dividers */
2830 				if (*t)
2831 				{
2832 					*t++ = '\0';
2833 					while (*t == ' ' || *t == '|') t++;
2834 				}
2835 
2836 				/* Parse this entry */
2837 				if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
2838 
2839 				/* Start the next entry */
2840 				s = t;
2841 			}
2842 
2843 			/* Next... */
2844 			continue;
2845 		}
2846 
2847 
2848 		/* Oops */
2849 		return (6);
2850 	}
2851 
2852 
2853 	/* Complete the "name" and "text" sizes */
2854 	++k_head->name_size;
2855 	++k_head->text_size;
2856 
2857 
2858 	/* No version yet */
2859 	if (!okay) return (2);
2860 
2861 #if DEBUG_LEVEL > 2
2862 	/* Debug -- print total no. */
2863 	s_printf("k_info total: %d\n", idx);
2864 #endif	// DEBUG_LEVEL
2865 
2866 	max_k_idx = ++idx;
2867 
2868 	/* Success */
2869 	return (0);
2870 }
2871 
2872 
2873 /*
2874  * Grab one flag in an artifact_type from a textual string
2875  */
grab_one_artifact_flag(artifact_type * a_ptr,cptr what)2876 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what) {
2877 	int i;
2878 
2879 	/* Check flags1 */
2880 	for (i = 0; i < 32; i++) {
2881 		if (streq(what, k_info_flags1[i])) {
2882 			a_ptr->flags1 |= (1L << i);
2883 			return (0);
2884 		}
2885 		/* Check flags2 */
2886 		if (streq(what, k_info_flags2[i])) {
2887 			a_ptr->flags2 |= (1L << i);
2888 			return (0);
2889 		}
2890 		/* Check flags3 */
2891 		if (streq(what, k_info_flags3[i])) {
2892 			a_ptr->flags3 |= (1L << i);
2893 			return (0);
2894 		}
2895 #if 1
2896 	        /* Check flags2 -- traps (huh? - Jir -) */
2897                 if (streq(what, k_info_flags2_trap[i])) {
2898                         a_ptr->flags2 |= (1L << i);
2899 			return (0);
2900 		}
2901 #endif	// 0
2902 	        /* Check flags4 */
2903                 if (streq(what, k_info_flags4[i])) {
2904                         a_ptr->flags4 |= (1L << i);
2905 			return (0);
2906 		}
2907 	        /* Check flags5 */
2908                 if (streq(what, k_info_flags5[i])) {
2909                         a_ptr->flags5 |= (1L << i);
2910 			return (0);
2911 		}
2912 	        /* Check flags6 */
2913                 if (streq(what, k_info_flags6[i])) {
2914                         a_ptr->flags6 |= (1L << i);
2915 			return (0);
2916 		}
2917 
2918 	        /* Check esp_flags */
2919                 if (streq(what, esp_flags[i])) {
2920                         a_ptr->esp |= (1L << i);
2921 			return (0);
2922 		}
2923 	}
2924 
2925 	/* Oops */
2926 	s_printf("Unknown artifact flag '%s'.\n", what);
2927 
2928 	/* Error */
2929 	return (1);
2930 }
2931 
2932 
2933 
2934 
2935 /*
2936  * Initialize the "a_info" array, by parsing an ascii "template" file
2937  */
init_a_info_txt(FILE * fp,char * buf)2938 errr init_a_info_txt(FILE *fp, char *buf)
2939 {
2940 	int i;
2941 
2942 	char *s, *t;
2943 #ifdef ART_DIZ
2944 	char tmp[MSG_LEN];
2945 #endif
2946 
2947 	/* Not ready yet */
2948 	bool okay = FALSE;
2949 
2950 	/* Current entry */
2951 	artifact_type *a_ptr = NULL;
2952 
2953 
2954 	/* Just before the first record */
2955 	error_idx = -1;
2956 
2957 	/* Just before the first line */
2958 	error_line = -1;
2959 
2960 
2961 	/* Parse */
2962 	while (0 == my_fgets(fp, buf, 1024, FALSE))
2963 	{
2964 		/* Advance the line number */
2965 		error_line++;
2966 
2967 		/* parse server conditions */
2968 		if (invalid_server_conditions(buf)) continue;
2969 
2970 		/* Skip comments and blank lines */
2971 		if (!buf[0] || (buf[0] == '#')) continue;
2972 
2973 		/* Verify correct "colon" format */
2974 		if (buf[1] != ':') return (1);
2975 
2976 
2977 		/* Hack -- Process 'V' for "Version" */
2978 		if (buf[0] == 'V')
2979 		{
2980 			int v1, v2, v3;
2981 
2982 			/* Scan for the values */
2983 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
2984 			    (v1 != a_head->v_major) ||
2985 			    (v2 != a_head->v_minor) ||
2986 			    (v3 != a_head->v_patch))
2987 			{
2988 				/* It only annoying -- DG */
2989 //				return (2);
2990 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
2991 			}
2992 
2993 			/* Okay to proceed */
2994 			okay = TRUE;
2995 
2996 			/* Continue */
2997 			continue;
2998 		}
2999 
3000 		/* No version yet */
3001 		if (!okay) return (2);
3002 
3003 
3004 		/* Process 'N' for "New/Number/Name" */
3005 		if (buf[0] == 'N')
3006 		{
3007 			/* Find the colon before the name */
3008 			s = strchr(buf + 2, ':');
3009 
3010 			/* Verify that colon */
3011 			if (!s) return (1);
3012 
3013 			/* Nuke the colon, advance to the name */
3014 			*s++ = '\0';
3015 
3016 			/* Paranoia -- require a name */
3017 			if (!*s) return (1);
3018 
3019 			/* Get the index */
3020 			i = atoi(buf + 2);
3021 
3022 			/* Verify information */
3023 			if (i < error_idx) return (4);
3024 
3025 			/* Verify information */
3026 			if (i >= (int) a_head->info_num) return (2);
3027 
3028 			/* Save the index */
3029 			error_idx = i;
3030 
3031 			/* Point at the "info" */
3032 			a_ptr = &a_info[i];
3033 
3034 			/* Hack -- Verify space */
3035 			if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
3036 
3037 			/* Advance and Save the name index */
3038 			if (!a_ptr->name) a_ptr->name = ++a_head->name_size;
3039 
3040 			/* Append chars to the name */
3041 			strcpy(a_name + a_head->name_size, s);
3042 
3043 			/* Advance the index */
3044 			a_head->name_size += strlen(s);
3045 
3046 			/* Ignore everything */
3047 			a_ptr->flags3 |= (TR3_IGNORE_ACID);
3048 			a_ptr->flags3 |= (TR3_IGNORE_ELEC);
3049 			a_ptr->flags3 |= (TR3_IGNORE_FIRE);
3050 			a_ptr->flags3 |= (TR3_IGNORE_COLD);
3051 			a_ptr->flags5 |= (TR5_IGNORE_WATER);
3052 
3053 			/* Next... */
3054 			continue;
3055 		}
3056 
3057 		/* There better be a current a_ptr */
3058 		if (!a_ptr) return (3);
3059 
3060 
3061 		/* Process 'D' for "Description" */
3062 		if (buf[0] == 'D') {
3063 #ifdef ART_DIZ
3064 			/* Acquire the text */
3065 			s = buf + 2;
3066 
3067 			strcpy(tmp, " \377u");
3068 			strcat(tmp, s);
3069 			strcat(tmp, "\n");
3070 
3071 			/* Hack -- Verify space */
3072 			if (a_head->text_size + strlen(tmp) + 8 > fake_text_size) return (7);
3073 
3074 			/* Advance and Save the text index */
3075 			if (!a_ptr->text) a_ptr->text = ++a_head->text_size;
3076 
3077 			/* Append chars to the text */
3078 			strcpy(a_text + a_head->text_size, tmp);
3079 
3080 			/* Advance the index */
3081 			a_head->text_size += strlen(tmp);
3082 #endif
3083 			/* Next... */
3084 			continue;
3085 		}
3086 
3087 
3088 		/* Process 'I' for "Info" (one line only) */
3089 		if (buf[0] == 'I')
3090 		{
3091 			int tval, sval, pval;
3092 
3093 			/* Scan for the values */
3094 			if (3 != sscanf(buf + 2, "%d:%d:%d",
3095 			                &tval, &sval, &pval)) return (1);
3096 
3097 			/* Save the values */
3098 			a_ptr->tval = tval;
3099 			a_ptr->sval = sval;
3100 			a_ptr->pval = pval;
3101 
3102 			/* Next... */
3103 			continue;
3104 		}
3105 
3106 		/* Process 'W' for "More Info" (one line only) */
3107 		if (buf[0] == 'W')
3108 		{
3109 			int level, rarity, wgt;
3110 			int cost;
3111 
3112 			/* Scan for the values */
3113 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
3114 			                &level, &rarity, &wgt, &cost)) return (1);
3115 
3116 			/* Save the values */
3117 			a_ptr->level = level;
3118 			a_ptr->rarity = rarity;
3119 			a_ptr->weight = wgt;
3120 			a_ptr->cost = cost;
3121 
3122 			/* Next... */
3123 			continue;
3124 		}
3125 
3126 		/* Hack -- Process 'P' for "power" and such */
3127 		if (buf[0] == 'P')
3128 		{
3129 			int ac, hd1, hd2, th, td, ta;
3130 
3131 			/* Scan for the values */
3132 			if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
3133 			                &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
3134 
3135 			a_ptr->ac = ac;
3136 			a_ptr->dd = hd1;
3137 			a_ptr->ds = hd2;
3138 			a_ptr->to_h = th;
3139 			a_ptr->to_d = td;
3140 			a_ptr->to_a =  ta;
3141 
3142 			/* Next... */
3143 			continue;
3144 		}
3145 
3146                 /* Process 'Z' for "Granted power" */
3147                 if (buf[0] == 'Z')
3148 		{
3149 #if 0
3150                         int i;
3151 
3152 			/* Acquire the text */
3153 			s = buf + 2;
3154 
3155                         /* Find it in the list */
3156                         for (i = 0; i < power_max; i++)
3157                         {
3158                                 if (!stricmp(s, powers_type[i].name)) break;
3159                         }
3160 
3161                         if (i == power_max) return (6);
3162 
3163                         a_ptr->power = i;
3164 
3165 #endif	// 0
3166 			/* Next... */
3167 			continue;
3168 		}
3169 
3170 		/* Hack -- Process 'F' for flags */
3171 		if (buf[0] == 'F')
3172 		{
3173 			/* Parse every entry textually */
3174 			for (s = buf + 2; *s; )
3175 			{
3176 				/* Find the end of this entry */
3177 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3178 
3179 				/* Nuke and skip any dividers */
3180 				if (*t)
3181 				{
3182 					*t++ = '\0';
3183 					while ((*t == ' ') || (*t == '|')) t++;
3184 				}
3185 
3186 				/* Parse this entry */
3187 				if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
3188 
3189 				/* Start the next entry */
3190 				s = t;
3191 			}
3192 
3193 			/* Next... */
3194 			continue;
3195 		}
3196 
3197 
3198 		/* Oops */
3199 		return (6);
3200 	}
3201 
3202 
3203 	/* Complete the "name" and "text" sizes */
3204 	++a_head->name_size;
3205 	++a_head->text_size;
3206 
3207 
3208 	/* No version yet */
3209 	if (!okay) return (2);
3210 
3211 	max_a_idx = ++error_idx;
3212 
3213 	/* Success */
3214 	return (0);
3215 }
3216 
3217 /*
3218  * Grab one flag from a textual string
3219  */
grab_one_skill_flag(u32b * f1,cptr what)3220 static errr grab_one_skill_flag(u32b *f1, cptr what)
3221 {
3222 	int i;
3223 
3224 	/* Check flags1 */
3225 	for (i = 0; i < 32; i++)
3226 	{
3227                 if (streq(what, s_info_flags1[i]))
3228 		{
3229 			(*f1) |= (1L << i);
3230 			return (0);
3231 		}
3232 	}
3233 
3234 	/* Oops */
3235 	s_printf("(2)Unknown skill flag '%s'.\n", what);
3236 
3237 	/* Error */
3238 	return (1);
3239 }
3240 
3241 
3242 /*
3243  * Initialize the "s_info" array, by parsing an ascii "template" file
3244  */
init_s_info_txt(FILE * fp,char * buf)3245 errr init_s_info_txt(FILE *fp, char *buf)
3246 {
3247 	int i, z, order = 1;
3248 
3249 	char *s;
3250 
3251 	/* Not ready yet */
3252 	bool okay = FALSE;
3253 
3254 	/* Current entry */
3255 	skill_type *s_ptr = NULL;
3256 
3257 
3258 	/* Just before the first record */
3259 	error_idx = -1;
3260 
3261 	/* Just before the first line */
3262 	error_line = -1;
3263 
3264 
3265 	/* Parse */
3266 	while (0 == my_fgets(fp, buf, 1024, FALSE))
3267 	{
3268 		/* Advance the line number */
3269 		error_line++;
3270 
3271 		/* parse server conditions */
3272 		if (invalid_server_conditions(buf)) continue;
3273 
3274 		/* Skip comments and blank lines */
3275 		if (!buf[0] || (buf[0] == '#')) continue;
3276 
3277 		/* Verify correct "colon" format */
3278 		if (buf[1] != ':') return (1);
3279 
3280 
3281 		/* Hack -- Process 'V' for "Version" */
3282 		if (buf[0] == 'V')
3283 		{
3284 			int v1, v2, v3;
3285 
3286 #ifdef VERIFY_VERSION_STAMP
3287 
3288 			/* Scan for the values */
3289 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
3290 			    (v1 != s_head->v_major) ||
3291 			    (v2 != s_head->v_minor) ||
3292 			    (v3 != s_head->v_patch))
3293 			{
3294 				return (2);
3295 			}
3296 
3297 #else /* VERIFY_VERSION_STAMP */
3298 
3299 			/* Scan for the values */
3300 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
3301 
3302 #endif /* VERIFY_VERSION_STAMP */
3303 
3304 			/* Okay to proceed */
3305 			okay = TRUE;
3306 
3307 			/* Continue */
3308 			continue;
3309 		}
3310 
3311 		/* No version yet */
3312 		if (!okay) return (2);
3313 
3314 
3315 		/* Process 'T' for "skill Tree" */
3316 		if (buf[0] == 'T')
3317 		{
3318 			char *sec;
3319 			s16b s1, s2;
3320 
3321 			/* Scan for the values */
3322 			if (NULL == (sec = strchr(buf + 2, ':')))
3323 			{
3324 				return (1);
3325 			}
3326 			*sec = '\0';
3327 			sec++;
3328 			if (!*sec) return (1);
3329 
3330 			s1 = find_skill(buf + 2);
3331 			s2 = find_skill(sec);
3332 			if (s2 == -1) return (1);
3333 
3334 			s_info[s2].father = s1;
3335 			s_info[s2].order = order++;
3336 
3337 			/* Next... */
3338 			continue;
3339 		}
3340 
3341 		/* Process 'E' for "Exclusive" */
3342 		if (buf[0] == 'E')
3343 		{
3344 			char *sec;
3345 			s16b s1, s2;
3346 
3347 			/* Scan for the values */
3348 			if (NULL == (sec = strchr(buf + 2, ':')))
3349 			{
3350 				return (1);
3351 			}
3352 			*sec = '\0';
3353 			sec++;
3354 			if (!*sec) return (1);
3355 
3356 			s1 = find_skill(buf + 2);
3357 			s2 = find_skill(sec);
3358 			if ((s1 == -1) || (s2 == -1)) return (1);
3359 
3360 			s_info[s1].action[s2] = SKILL_EXCLUSIVE;
3361 			s_info[s2].action[s1] = SKILL_EXCLUSIVE;
3362 
3363 			/* Next... */
3364 			continue;
3365 		}
3366 
3367 
3368 		/* Process 'O' for "Opposite" */
3369 		if (buf[0] == 'O')
3370 		{
3371 			char *sec, *cval;
3372 			s16b s1, s2;
3373 
3374 			/* Scan for the values */
3375 			if (NULL == (sec = strchr(buf + 2, ':')))
3376 			{
3377 				return (1);
3378 			}
3379 			*sec = '\0';
3380 			sec++;
3381 			if (!*sec) return (1);
3382 			if (NULL == (cval = strchr(sec, '%')))
3383 			{
3384 				return (1);
3385 			}
3386 			*cval = '\0';
3387 			cval++;
3388 			if (!*cval) return (1);
3389 
3390 			s1 = find_skill(buf + 2);
3391 			s2 = find_skill(sec);
3392 			if ((s1 == -1) || (s2 == -1)) return (1);
3393 
3394 			s_info[s1].action[s2] = -atoi(cval);
3395 
3396 			/* Next... */
3397 			continue;
3398 		}
3399 
3400                 /* Process 'A' for "Amical/friendly" */
3401                 if (buf[0] == 'f')
3402 		{
3403 			char *sec, *cval;
3404 			s16b s1, s2;
3405 
3406 			/* Scan for the values */
3407 			if (NULL == (sec = strchr(buf + 2, ':')))
3408 			{
3409 				return (1);
3410 			}
3411 			*sec = '\0';
3412 			sec++;
3413 			if (!*sec) return (1);
3414 			if (NULL == (cval = strchr(sec, '%')))
3415 			{
3416 				return (1);
3417 			}
3418 			*cval = '\0';
3419 			cval++;
3420 			if (!*cval) return (1);
3421 
3422 			s1 = find_skill(buf + 2);
3423 			s2 = find_skill(sec);
3424 			if ((s1 == -1) || (s2 == -1)) return (1);
3425 
3426 			s_info[s1].action[s2] = atoi(cval);
3427 
3428 			/* Next... */
3429 			continue;
3430 		}
3431 
3432 		/* Process 'N' for "New/Number/Name" */
3433 		if (buf[0] == 'N')
3434 		{
3435 			/* Find the colon before the name */
3436 			s = strchr(buf + 2, ':');
3437 
3438 			/* Verify that colon */
3439 			if (!s) return (1);
3440 
3441 			/* Nuke the colon, advance to the name */
3442 			*s++ = '\0';
3443 
3444 			/* Paranoia -- require a name */
3445 			if (!*s) return (1);
3446 
3447 			/* Get the index */
3448 			i = atoi(buf + 2);
3449 
3450 			/* Verify information */
3451 			if (i >= (int) s_head->info_num) return (2);
3452 
3453 			/* Save the index */
3454 			error_idx = i;
3455 
3456 			/* Point at the "info" */
3457 			s_ptr = &s_info[i];
3458 
3459 			/* Hack -- Verify space */
3460 			if (s_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
3461 
3462 			/* Advance and Save the name index */
3463 			if (!s_ptr->name) s_ptr->name = ++s_head->name_size;
3464 
3465 			/* Append chars to the name */
3466 			strcpy(s_name + s_head->name_size, s);
3467 
3468 			/* Advance the index */
3469 			s_head->name_size += strlen(s);
3470 
3471 			/* Init */
3472 			s_ptr->action_mkey = 0;
3473 //			s_ptr->dev = FALSE;
3474 			for (z = 0; z < MAX_SKILLS; z++)
3475 //			for (z = 0; z < max_s_idx; z++)
3476 			{
3477 				s_ptr->action[z] = 0;
3478 			}
3479 
3480 			/* Next... */
3481 			continue;
3482 		}
3483 
3484 		/* There better be a current s_ptr */
3485 		if (!s_ptr) return (3);
3486 
3487 		/* Process 'D' for "Description" */
3488 		if (buf[0] == 'D')
3489 		{
3490 			/* Acquire the text */
3491 			s = buf + 2;
3492 
3493 			/* Hack -- Verify space */
3494 			if (s_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
3495 
3496 			/* Advance and Save the text index */
3497 			if (!s_ptr->desc)
3498 			{
3499 				s_ptr->desc = ++s_head->text_size;
3500 
3501 				/* Append chars to the name */
3502 				strcpy(s_text + s_head->text_size, s);
3503 
3504 				/* Advance the index */
3505 				s_head->text_size += strlen(s);
3506 			}
3507 			else
3508 			{
3509 				/* Append chars to the name */
3510 				strcpy(s_text + s_head->text_size, format("\n%s", s));
3511 
3512 				/* Advance the index */
3513 				s_head->text_size += strlen(s) + 1;
3514 			}
3515 
3516 			/* Next... */
3517 			continue;
3518 		}
3519 
3520 		/* Process 'A' for "Activation Description" */
3521 		if (buf[0] == 'A')
3522 		{
3523 			char *txt;
3524 
3525 			/* Acquire the text */
3526 			s = buf + 2;
3527 
3528 			if (NULL == (txt = strchr(s, ':'))) return (1);
3529 			*txt = '\0';
3530 			txt++;
3531 
3532 			/* Hack -- Verify space */
3533 			if (s_head->text_size + strlen(txt) + 8 > fake_text_size) return (7);
3534 
3535 			/* Advance and Save the text index */
3536 			if (!s_ptr->action_desc) s_ptr->action_desc = ++s_head->text_size;
3537 
3538 			/* Append chars to the name */
3539 			strcpy(s_text + s_head->text_size, txt);
3540 			s_ptr->action_mkey = atoi(s);
3541 
3542 			/* Advance the index */
3543 			s_head->text_size += strlen(txt);
3544 
3545 			/* Next... */
3546 			continue;
3547 		}
3548 
3549 		/* Process 'I' for "Info" (one line only) */
3550 		if (buf[0] == 'I')
3551 		{
3552 			int rate, tval;
3553 
3554 			/* Scan for the values */
3555 			if (2 != sscanf(buf + 2, "%d:%d", &rate, &tval))
3556 			{
3557 				return (1);
3558 			}
3559 
3560 			/* Save the values */
3561 			s_ptr->rate = rate;
3562 			s_ptr->tval = tval;
3563 
3564 			/* Next... */
3565 			continue;
3566 		}
3567 
3568                 /* Process 'F' for flags */
3569 		if (buf[0] == 'F')
3570 		{
3571                         char *t;
3572 
3573 			/* Parse every entry textually */
3574 			for (s = buf + 2; *s; )
3575 			{
3576 				/* Find the end of this entry */
3577 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3578 
3579 				/* Nuke and skip any dividers */
3580 				if (*t)
3581 				{
3582 					*t++ = '\0';
3583 					while ((*t == ' ') || (*t == '|')) t++;
3584 				}
3585 
3586 				/* Parse this entry */
3587                                 if (0 != grab_one_skill_flag(&(s_ptr->flags1), s)) return (5);
3588 
3589 				/* Start the next entry */
3590 				s = t;
3591 			}
3592 
3593 			/* Next... */
3594 			continue;
3595 		}
3596 
3597 		/* Oops */
3598 		return (6);
3599 	}
3600 
3601 
3602 	/* Complete the "name" and "text" sizes */
3603 	++s_head->name_size;
3604 	++s_head->text_size;
3605 
3606 
3607 	/* No version yet */
3608 	if (!okay) return (2);
3609 
3610 	max_s_idx = ++error_idx;
3611 
3612 	/* Success */
3613 	return (0);
3614 }
3615 
3616 
3617 /*
3618  * Grab one flag in a ego-item_type from a textual string
3619  */
grab_one_ego_item_flag(ego_item_type * e_ptr,cptr what,int n)3620 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what, int n)
3621 {
3622 	int i;
3623 
3624 	for (i = 0; i < 32; i++) {
3625 		/* Check flags1 */
3626 		if (streq(what, k_info_flags1[i])) {
3627                         e_ptr->flags1[n] |= (1L << i);
3628 			return (0);
3629 		}
3630 		/* Check flags2 */
3631 		if (streq(what, k_info_flags2[i])) {
3632                         e_ptr->flags2[n] |= (1L << i);
3633 			return (0);
3634 		}
3635 #if 1
3636 	        /* Check flags2 -- traps */
3637                 if (streq(what, k_info_flags2_trap[i])) {
3638                         e_ptr->flags2[n] |= (1L << i);
3639 			return (0);
3640 		}
3641 #endif	// 0
3642 		/* Check flags3 */
3643 		if (streq(what, k_info_flags3[i])) {
3644                         e_ptr->flags3[n] |= (1L << i);
3645 			return (0);
3646 		}
3647 #if 1
3648 	        /* Check flags4 */
3649                 if (streq(what, k_info_flags4[i])) {
3650                         e_ptr->flags4[n] |= (1L << i);
3651 			return (0);
3652 		}
3653 	        /* Check flags5 */
3654                 if (streq(what, k_info_flags5[i])) {
3655                         e_ptr->flags5[n] |= (1L << i);
3656 			return (0);
3657 		}
3658 
3659 	        /* Check esp_flags */
3660                 if (streq(what, esp_flags[i])) {
3661                         e_ptr->esp[n] |= (1L << i);
3662 			return (0);
3663 		}
3664 
3665     		/* Check ego_flags */
3666                 if (streq(what, ego_flags1[i])) {
3667                         e_ptr->fego1[n] |= (1L << i);
3668 			return (0);
3669 		}
3670                 if (streq(what, ego_flags2[i])) {
3671                         e_ptr->fego2[n] |= (1L << i);
3672 			return (0);
3673 		}
3674 #endif
3675 	}
3676 	/* Oops */
3677 	s_printf("Unknown ego-item flag '%s'.\n", what);
3678 
3679 	/* Error */
3680 	return (1);
3681 }
3682 
3683 
3684 
3685 
3686 /*
3687  * Initialize the "e_info" array, by parsing an ascii "template" file
3688  */
init_e_info_txt(FILE * fp,char * buf)3689 errr init_e_info_txt(FILE *fp, char *buf)
3690 {
3691 //	int i;
3692         int i, cur_r = -1, cur_t = 0, j;
3693 
3694 	char *s, *t;
3695 
3696 	/* Not ready yet */
3697 	bool okay = FALSE;
3698 
3699 	/* Current entry */
3700 	ego_item_type *e_ptr = NULL;
3701 
3702 
3703 	/* Just before the first record */
3704 	error_idx = -1;
3705 
3706 	/* Just before the first line */
3707 	error_line = -1;
3708 
3709 
3710 	/* Parse */
3711 	while (0 == my_fgets(fp, buf, 1024, FALSE))
3712 	{
3713 		/* Advance the line number */
3714 		error_line++;
3715 
3716 		/* parse server conditions */
3717 		if (invalid_server_conditions(buf)) continue;
3718 
3719 		/* Skip comments and blank lines */
3720 		if (!buf[0] || (buf[0] == '#')) continue;
3721 
3722 		/* Verify correct "colon" format */
3723 		if (buf[1] != ':') return (1);
3724 
3725 
3726 		/* Hack -- Process 'V' for "Version" */
3727 		if (buf[0] == 'V')
3728 		{
3729 			int v1, v2, v3;
3730 
3731 			/* Scan for the values */
3732 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
3733 			    (v1 != e_head->v_major) ||
3734 			    (v2 != e_head->v_minor) ||
3735 			    (v3 != e_head->v_patch))
3736 			{
3737 				/* It only annoying -- DG */
3738 //				return (2);
3739 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
3740 			}
3741 
3742 			/* Okay to proceed */
3743 			okay = TRUE;
3744 
3745 			/* Continue */
3746 			continue;
3747 		}
3748 
3749 		/* No version yet */
3750 		if (!okay) return (2);
3751 
3752 
3753 		/* Process 'N' for "New/Number/Name" */
3754 		if (buf[0] == 'N')
3755 		{
3756 			/* Find the colon before the name */
3757 			s = strchr(buf + 2, ':');
3758 
3759 			/* Verify that colon */
3760 			if (!s) return (1);
3761 
3762 			/* Nuke the colon, advance to the name */
3763 			*s++ = '\0';
3764 
3765 			/* Paranoia -- require a name */
3766 			if (!*s) return (1);
3767 
3768 			/* Hack for Amulet of Telepathic Awareness: '-' becomes an empty name */
3769 			if (*s == '-') *s = 0;
3770 
3771 			/* Get the index */
3772 			i = atoi(buf + 2);
3773 
3774 			/* Verify information */
3775 			if (i < error_idx) return (4);
3776 
3777 			/* Verify information */
3778 			if (i >= (int) e_head->info_num) return (2);
3779 
3780 			/* Save the index */
3781 			error_idx = i;
3782 
3783 			/* Point at the "info" */
3784 			e_ptr = &e_info[i];
3785 
3786 			/* Hack -- Verify space */
3787 			if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
3788 
3789 			/* Advance and Save the name index */
3790 			if (!e_ptr->name) e_ptr->name = ++e_head->name_size;
3791 
3792 			/* Append chars to the name */
3793 			strcpy(e_name + e_head->name_size, s);
3794 
3795 			/* Advance the index */
3796 			e_head->name_size += strlen(s);
3797 
3798                         /* Needed hack ported */
3799 //                        e_ptr->power = -1;
3800                         cur_r = -1;
3801                         cur_t = 0;
3802 
3803                         for (j = 0; j < MAX_EGO_BASETYPES; j++)
3804                         {
3805                                 e_ptr->tval[j] = 255;
3806                         }
3807                         for (j = 0; j < 5; j++)
3808                         {
3809                                 e_ptr->rar[j] = 0;
3810                                 e_ptr->flags1[j] = 0;
3811                                 e_ptr->flags2[j] = 0;
3812                                 e_ptr->flags3[j] = 0;
3813                                 e_ptr->flags4[j] = 0;
3814                                 e_ptr->flags5[j] = 0;
3815                                 e_ptr->flags6[j] = 0;
3816                                 e_ptr->esp[j] = 0;
3817                         }
3818 
3819 			/* Next... */
3820 			continue;
3821 		}
3822 
3823 		/* There better be a current e_ptr */
3824 		if (!e_ptr) return (3);
3825 
3826 
3827 
3828 		/* Process 'D' for "Description" */
3829 		if (buf[0] == 'D')
3830 		{
3831 #if 0
3832 			/* Acquire the text */
3833 			s = buf + 2;
3834 
3835 			/* Hack -- Verify space */
3836 			if (e_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
3837 
3838 			/* Advance and Save the text index */
3839 			if (!e_ptr->text) e_ptr->text = ++e_head->text_size;
3840 
3841 			/* Append chars to the name */
3842 			strcpy(e_text + e_head->text_size, s);
3843 
3844 			/* Advance the index */
3845 			e_head->text_size += strlen(s);
3846 
3847 #endif
3848 			/* Next... */
3849 			continue;
3850 		}
3851 
3852 
3853 		/* PernA flags	- Jir - */
3854                 /* Process 'T' for "Tval/Sval" (up to 5 lines) */
3855                 if (buf[0] == 'T')
3856 		{
3857                         int tv, minsv, maxsv;
3858                         if (cur_t == MAX_EGO_BASETYPES) {
3859 				s_printf("ERROR: Exceeded MAX_EGO_BASETYPES in ego index %d.\n", error_idx);
3860                         	return (1);
3861                         }
3862 
3863 			/* Scan for the values */
3864                         if (3 != sscanf(buf + 2, "%d:%d:%d",
3865                                 &tv, &minsv, &maxsv)) return (1);
3866 
3867 			/* Save the values */
3868                         e_ptr->tval[cur_t] = tv;
3869                         e_ptr->min_sval[cur_t] = minsv;
3870                         e_ptr->max_sval[cur_t] = maxsv;
3871 
3872                         cur_t++;
3873 
3874 			/* Next... */
3875 			continue;
3876 		}
3877 
3878                 /* Process 'R' for "flags rarity" (up to 5 lines) */
3879                 if (buf[0] == 'R')
3880 		{
3881                         int rar;
3882 
3883 			/* Scan for the values */
3884                         if (1 != sscanf(buf + 2, "%d",
3885                                 &rar)) return (1);
3886 
3887                         cur_r++;
3888 
3889 			/* Save the values */
3890                         e_ptr->rar[cur_r] = rar;
3891 
3892 			/* Next... */
3893 			continue;
3894 		}
3895 
3896 #if 0
3897 		/* Process 'X' for "Xtra" (one line only) */
3898 		if (buf[0] == 'X')
3899 		{
3900 			int slot, rating;
3901                         char pos;	// actually it's boolean
3902 
3903 			/* Scan for the values */
3904 			if (2 != sscanf(buf + 2, "%d:%d",
3905 			                &slot, &rating)) return (1);
3906 
3907 			/* Save the values */
3908 			e_ptr->slot = slot;
3909 			e_ptr->rating = rating;
3910 
3911 			/* Next... */
3912 			continue;
3913 		}
3914 #endif	// 0
3915 
3916 		/* Process 'X' for "Xtra" (one line only) */
3917 		if (buf[0] == 'X')
3918 		{
3919 			int slot, rating;
3920                         char pos;
3921 
3922 			/* Scan for the values */
3923                         if (3 != sscanf(buf + 2, "%c:%d:%d",
3924                                 &pos, &slot, &rating)) return (1);
3925 
3926 			/* Save the values */
3927                         /* e_ptr->slot = slot; */
3928 			e_ptr->rating = rating;
3929                         e_ptr->before = (pos == 'B')?TRUE:FALSE;
3930 
3931 			/* Next... */
3932 			continue;
3933 		}
3934 
3935 		/* Process 'W' for "More Info" (one line only) */
3936 		if (buf[0] == 'W')
3937 		{
3938 			int level, rarity, pad2;	// rarity2
3939 			int cost;
3940 
3941 			/* Scan for the values */
3942 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
3943 			                &level, &rarity, &pad2, &cost)) return (1);
3944 
3945 			/* Save the values */
3946 			e_ptr->level = level;
3947 			e_ptr->rarity = rarity;
3948 			/* e_ptr->weight = wgt; */
3949 			e_ptr->mrarity = pad2;
3950 			e_ptr->cost = cost;
3951 
3952 			/* Next... */
3953 			continue;
3954 		}
3955 
3956 		/* Hack -- Process 'C' for "creation" */
3957 		if (buf[0] == 'C')
3958 		{
3959 			int th, td, ta, pv;
3960 
3961 			/* Scan for the values */
3962 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
3963 			                &th, &td, &ta, &pv)) return (1);
3964 
3965 			e_ptr->max_to_h = th;
3966 			e_ptr->max_to_d = td;
3967 			e_ptr->max_to_a = ta;
3968 			e_ptr->max_pval = pv;
3969 
3970 			/* Next... */
3971 			continue;
3972 		}
3973                 /* Process 'Z' for "Granted power" */
3974                 if (buf[0] == 'Z')
3975 		{
3976 #if 0
3977                         int i;
3978 
3979 			/* Acquire the text */
3980 			s = buf + 2;
3981 
3982                         /* Find it in the list */
3983                         for (i = 0; i < power_max; i++)
3984                         {
3985                                 if (!stricmp(s, powers_type[i].name)) break;
3986                         }
3987 
3988                         if (i == power_max) return (6);
3989 
3990                         e_ptr->power = i;
3991 
3992 #endif	// 0
3993 			/* Next... */
3994 			continue;
3995 		}
3996 
3997 		/* Hack -- Process 'F' for flags */
3998 		if (buf[0] == 'F')
3999 		{
4000                         if (cur_r == -1) return (6);
4001 
4002 			/* Parse every entry textually */
4003 			for (s = buf + 2; *s; )
4004 			{
4005 				/* Find the end of this entry */
4006 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
4007 
4008 				/* Nuke and skip any dividers */
4009 				if (*t)
4010 				{
4011 					*t++ = '\0';
4012 					while ((*t == ' ') || (*t == '|')) t++;
4013 				}
4014 
4015 				/* Parse this entry */
4016 				if (0 != grab_one_ego_item_flag(e_ptr, s, cur_r)) return (5);
4017 
4018 				/* Start the next entry */
4019 				s = t;
4020 			}
4021 
4022 			/* Next... */
4023 			continue;
4024 		}
4025 
4026 		/* Oops */
4027 		return (6);
4028 	}
4029 
4030 
4031 	/* Complete the "name" and "text" sizes */
4032 	++e_head->name_size;
4033 	++e_head->text_size;
4034 
4035 
4036 	/* No version yet */
4037 	if (!okay) return (2);
4038 
4039 	max_e_idx = ++error_idx;
4040 
4041 	/* Success */
4042 	return (0);
4043 }
4044 
4045 
4046 /*
4047  * Grab one (basic) flag in a monster_race from a textual string
4048  */
grab_one_basic_flag(monster_race * r_ptr,cptr what)4049 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
4050 {
4051 	int i;
4052 
4053 	/* Most common flags first - mikaelh */
4054 
4055 	/* Scan flags3 */
4056 	for (i = 0; i < 32; i++)
4057 	{
4058 		if (streq(what, r_info_flags3[i]))
4059 		{
4060 			r_ptr->flags3 |= (1L << i);
4061 			return (0);
4062 		}
4063 	}
4064 
4065 	/* Scan flags1 */
4066 	for (i = 0; i < 32; i++)
4067 	{
4068 		if (streq(what, r_info_flags1[i]))
4069 		{
4070 			r_ptr->flags1 |= (1L << i);
4071 			return (0);
4072 		}
4073 	}
4074 
4075 	/* Scan flags2 */
4076 	for (i = 0; i < 32; i++)
4077 	{
4078 		if (streq(what, r_info_flags2[i]))
4079 		{
4080 			r_ptr->flags2 |= (1L << i);
4081 			return (0);
4082 		}
4083 	}
4084 
4085 	/* Scan flags8 */
4086 	for (i = 0; i < 32; i++)
4087 	{
4088 		if (streq(what, r_info_flags8[i]))
4089 		{
4090 			r_ptr->flags8 |= (1L << i);
4091 			return (0);
4092 		}
4093 	}
4094 
4095 	/* Scan flags7 */
4096 	for (i = 0; i < 32; i++)
4097 	{
4098 		if (streq(what, r_info_flags7[i]))
4099 		{
4100 			r_ptr->flags7 |= (1L << i);
4101 			return (0);
4102 		}
4103 	}
4104 
4105 	/* Scan flags9 */
4106 	for (i = 0; i < 32; i++)
4107 	{
4108 		if (streq(what, r_info_flags9[i]))
4109 		{
4110 			r_ptr->flags9 |= (1L << i);
4111 			return (0);
4112 		}
4113 	}
4114 
4115 	/* Scan flags0 */
4116 	for (i = 0; i < 32; i++)
4117 	{
4118 		if (streq(what, r_info_flags0[i]))
4119 		{
4120 			r_ptr->flags0 |= (1L << i);
4121 			return (0);
4122 		}
4123 	}
4124 
4125 	/* Oops */
4126 	s_printf("Unknown monster flag '%s'.\n", what);
4127 
4128 	/* Failure */
4129 	return (1);
4130 }
4131 
4132 
4133 /*
4134  * Grab one (spell) flag in a monster_race from a textual string
4135  */
grab_one_spell_flag(monster_race * r_ptr,cptr what)4136 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
4137 {
4138 	int i;
4139 
4140 	/* Scan flags5 */
4141 	for (i = 0; i < 32; i++)
4142 	{
4143 		if (streq(what, r_info_flags5[i]))
4144 		{
4145 			r_ptr->flags5 |= (1L << i);
4146 			return (0);
4147 		}
4148 	}
4149 
4150 	/* Scan flags6 */
4151 	for (i = 0; i < 32; i++)
4152 	{
4153 		if (streq(what, r_info_flags6[i]))
4154 		{
4155 			r_ptr->flags6 |= (1L << i);
4156 			return (0);
4157 		}
4158 	}
4159 
4160 	/* Scan flags4 */
4161 	for (i = 0; i < 32; i++)
4162 	{
4163 		if (streq(what, r_info_flags4[i]))
4164 		{
4165 			r_ptr->flags4 |= (1L << i);
4166 			return (0);
4167 		}
4168 	}
4169 
4170 	/* Scan flags0 */
4171 	for (i = 0; i < 32; i++)
4172 	{
4173 		if (streq(what, r_info_flags0[i]))
4174 		{
4175 			r_ptr->flags0 |= (1L << i);
4176 			return (0);
4177 		}
4178 	}
4179 
4180 	/* For Halloween Event we need new MOAN in RF8 -C. Blue */
4181 	/* Scan flags8 */
4182 if (season_halloween) {
4183 	for (i = 0; i < 32; i++)
4184 	{
4185 		if (streq(what, r_info_flags8[i]))
4186 		{
4187 			r_ptr->flags8 |= (1L << i);
4188 			return (0);
4189 		}
4190 	}
4191 }
4192 
4193 	/* Oops */
4194 	s_printf("Unknown monster flag '%s'.\n", what);
4195 
4196 	/* Failure */
4197 	return (1);
4198 }
4199 
4200 
4201 
4202 
4203 /*
4204  * Initialize the "r_info" array, by parsing an ascii "template" file
4205  */
init_r_info_txt(FILE * fp,char * buf)4206 errr init_r_info_txt(FILE *fp, char *buf)
4207 {
4208 	int i, j;
4209 	char *s, *t;
4210 	/* Not ready yet */
4211 	bool okay = FALSE;
4212 	/* Current entry */
4213 	monster_race *r_ptr = NULL;
4214 
4215 
4216 	/* Just before the first record */
4217 	error_idx = -1;
4218 
4219 	/* Just before the first line */
4220 	error_line = -1;
4221 
4222 
4223 	/* Start the "fake" stuff */
4224 	r_head->name_size = 0;
4225 	r_head->text_size = 0;
4226 
4227 	/* Parse */
4228 	while (0 == my_fgets(fp, buf, 1024, FALSE)) {
4229 		/* Advance the line number */
4230 		error_line++;
4231 
4232 		/* parse server conditions */
4233 		if (invalid_server_conditions(buf)) continue;
4234 
4235 		/* Skip comments and blank lines */
4236 		if (!buf[0] || (buf[0] == '#')) continue;
4237 
4238 		/* Verify correct "colon" format */
4239 		if (buf[1] != ':') return (1);
4240 
4241 
4242 		/* Hack -- Process 'V' for "Version" */
4243 		if (buf[0] == 'V') {
4244 			int v1, v2, v3;
4245 
4246 			/* Scan for the values */
4247 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
4248 			    (v1 != r_head->v_major) ||
4249 			    (v2 != r_head->v_minor) ||
4250 			    (v3 != r_head->v_patch)) {
4251 				/* It only annoying -- DG */
4252 //				return (2);
4253 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
4254 			}
4255 
4256 			/* Okay to proceed */
4257 			okay = TRUE;
4258 
4259 			/* Continue */
4260 			continue;
4261 		}
4262 
4263 		/* No version yet */
4264 		if (!okay) return (2);
4265 
4266 
4267 		/* Process 'N' for "New/Number/Name" */
4268 		if (buf[0] == 'N') {
4269 			/* Find the colon before the name */
4270 			s = strchr(buf + 2, ':');
4271 
4272 			/* Verify that colon */
4273 			if (!s) return (1);
4274 
4275 			/* Nuke the colon, advance to the name */
4276 			*s++ = '\0';
4277 
4278 			/* Paranoia -- require a name */
4279 			if (!*s) return (1);
4280 
4281 			/* Get the index */
4282 			i = atoi(buf + 2);
4283 
4284 			/* Verify information */
4285 			if (i < error_idx) return (4);
4286 
4287 			/* Verify information */
4288 			if (i >= (int) r_head->info_num) return (2);
4289 
4290 			/* Save the index */
4291 			error_idx = i;
4292 
4293 			/* Point at the "info" */
4294 			r_ptr = &r_info[i];
4295 
4296 			/* Hack -- Verify space */
4297 			if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
4298 
4299 			/* Advance and Save the name index */
4300 			if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
4301 
4302 			/* Append chars to the name */
4303 			strcpy(r_name + r_head->name_size, s);
4304 
4305 			/* Advance the index */
4306 			r_head->name_size += strlen(s);
4307 
4308 			/* Check for duplicate version of this monster that just
4309 			   differs by FRIENDS flag, to make mimicry more consistent. - C. Blue */
4310 			for (j = 1; j < i; j++) {
4311 				if (strcmp(r_info[j].name + r_name, s)) continue;
4312 				r_ptr->dup_idx = j;
4313 				break;
4314 			}
4315 
4316 #if 1	// pernA hack -- someday.
4317 			/* HACK -- Those ones HAVE to have a set default value */
4318 			r_ptr->drops.treasure = OBJ_GENE_TREASURE;
4319 			r_ptr->drops.combat = OBJ_GENE_COMBAT;
4320 			r_ptr->drops.magic = OBJ_GENE_MAGIC;
4321 			r_ptr->drops.tools = OBJ_GENE_TOOL;
4322 			r_ptr->freq_innate = r_ptr->freq_spell = 0;
4323 #endif	// 0
4324 
4325 			/* Next... */
4326 			continue;
4327 		}
4328 
4329 		/* There better be a current r_ptr */
4330 		if (!r_ptr) return (3);
4331 
4332 
4333 		/* Process 'D' for "Description" */
4334 		if (buf[0] == 'D') {
4335 #if 0	// I've never seen this used :)		- Jir -
4336 			/* Acquire the text */
4337 			s = buf + 2;
4338 
4339 			/* Hack -- Verify space */
4340 			if (r_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
4341 
4342 			/* Advance and Save the text index */
4343 			if (!r_ptr->text) r_ptr->text = ++r_head->text_size;
4344 
4345 			/* Append chars to the name */
4346 			strcpy(r_text + r_head->text_size, s);
4347 
4348 			/* Advance the index */
4349 			r_head->text_size += strlen(s);
4350 #endif
4351 
4352 			/* Next... */
4353 			continue;
4354 		}
4355 
4356 		/* Process 'G' for "Graphics" (one line only) */
4357 		if (buf[0] == 'G') {
4358 			char sym;
4359 			int tmp;
4360 
4361 			/* Paranoia */
4362 			if (!buf[2]) return (1);
4363 			if (!buf[3]) return (1);
4364 			if (!buf[4]) return (1);
4365 
4366 			/* Extract the char */
4367 			sym = buf[2];
4368 
4369 			/* Extract the attr */
4370 			tmp = color_char_to_attr(buf[4]);
4371 
4372 			/* Paranoia */
4373 			if (tmp < 0) return (1);
4374 
4375 			/* Save the values */
4376 			r_ptr->d_char = sym;
4377 			r_ptr->d_attr = tmp;
4378 
4379 			/* Next... */
4380 			continue;
4381 		}
4382 
4383 		/* Process 'I' for "Info" (one line only) */
4384 		if (buf[0] == 'I') {
4385 			int spd, hp1, hp2, aaf, ac, slp;
4386 
4387 			/* Scan for the other values */
4388 			if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
4389 			                &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
4390 
4391 			/* Save the values */
4392 			r_ptr->speed = spd;
4393 			r_ptr->hdice = hp1;
4394 			r_ptr->hside = hp2;
4395 			r_ptr->aaf = aaf;
4396 			r_ptr->ac = ac;
4397 			r_ptr->sleep = slp;
4398 
4399 			/* Next... */
4400 			continue;
4401 		}
4402 
4403 		/* Process 'E' for "Body Parts" (one line only) */
4404 		if (buf[0] == 'E') {
4405 #if 1
4406                         int weap, tors, fing, head, arms, legs;
4407 
4408 			/* Scan for the other values */
4409                         if (BODY_MAX != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
4410                                 &weap, &tors, &arms, &fing, &head, &legs)) return (1);
4411 
4412 			/* Save the values */
4413                         r_ptr->body_parts[BODY_WEAPON] = weap;
4414                         r_ptr->body_parts[BODY_TORSO] = tors;
4415                         r_ptr->body_parts[BODY_ARMS] = arms;
4416                         r_ptr->body_parts[BODY_FINGER] = fing;
4417                         r_ptr->body_parts[BODY_HEAD] = head;
4418                         r_ptr->body_parts[BODY_LEGS] = legs;
4419 
4420                         /* Mega debugging hack */
4421                         if (weap > arms) quit(format("monster %d, %d weapon(s), %d arm(s) !", error_idx, weap, arms));
4422 
4423 #endif	// 0
4424 			/* Next... */
4425 			continue;
4426 		}
4427 
4428 		/* Process 'O' for "Object type" (one line only) */
4429 		if (buf[0] == 'O') {
4430 #if 1
4431                         int treasure, combat, magic, tools;
4432 
4433 			/* Scan for the values */
4434                         if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
4435                                 &treasure, &combat, &magic, &tools)) return (1);
4436 
4437 			/* Save the values */
4438                         r_ptr->drops.treasure = treasure;
4439                         r_ptr->drops.combat = combat;
4440                         r_ptr->drops.magic = magic;
4441                         r_ptr->drops.tools = tools;
4442 
4443 #endif	// 0
4444 			/* Next... */
4445 			continue;
4446 		}
4447 
4448 		/* Process 'W' for "More Info" (one line only) */
4449 		if (buf[0] == 'W') {
4450 			int lev, rar, pad;
4451 			int exp;
4452 
4453 			/* Scan for the values */
4454 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
4455 			                &lev, &rar, &pad, &exp)) return (1);
4456 
4457 			/* Save the values */
4458 			r_ptr->level = lev;
4459 			r_ptr->rarity = rar;
4460 //			r_ptr->extra = pad;
4461 #if 1	//
4462 			r_ptr->extra = 0;
4463                         /* MEGA HACK */
4464                         if(!pad) pad = 100;
4465                         r_ptr->weight = pad;
4466 #endif
4467 			r_ptr->mexp = exp;
4468 
4469 			/* Next... */
4470 			continue;
4471 		}
4472 
4473 		/* Process 'B' for "Blows" (up to four lines) */
4474 		if (buf[0] == 'B') {
4475 			int n1, n2;
4476 
4477 			/* Find the next empty blow slot (if any) */
4478 			for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
4479 
4480 			/* Oops, no more slots */
4481 			if (i == 4) return (1);
4482 
4483 			/* Analyze the first field */
4484 			for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
4485 
4486 			/* Terminate the field (if necessary) */
4487 			if (*t == ':') *t++ = '\0';
4488 
4489 			/* Analyze the method */
4490 			for (n1 = 0; r_info_blow_method[n1]; n1++)
4491 				if (streq(s, r_info_blow_method[n1])) break;
4492 
4493 			/* Invalid method */
4494 			if (!r_info_blow_method[n1]) return (1);
4495 
4496 			/* Analyze the second field */
4497 			for (s = t; *t && (*t != ':'); t++) /* loop */;
4498 
4499 			/* Terminate the field (if necessary) */
4500 			if (*t == ':') *t++ = '\0';
4501 
4502 			/* Analyze effect */
4503 			for (n2 = 0; r_info_blow_effect[n2]; n2++)
4504 				if (streq(s, r_info_blow_effect[n2])) break;
4505 
4506 			/* Invalid effect */
4507 			if (!r_info_blow_effect[n2]) return (1);
4508 
4509 			/* Analyze the third field */
4510 			for (s = t; *t && (*t != 'd'); t++) /* loop */;
4511 
4512 			/* Terminate the field (if necessary) */
4513 			if (*t == 'd') *t++ = '\0';
4514 
4515 			/* Save the method */
4516 			r_ptr->blow[i].method = n1;
4517 
4518 			/* Save the effect */
4519 			r_ptr->blow[i].effect = n2;
4520 
4521 			/* Extract the damage dice and sides */
4522 			r_ptr->blow[i].d_dice = atoi(s);
4523 			r_ptr->blow[i].d_side = atoi(t);
4524 
4525 			/* Next... */
4526 			continue;
4527 		}
4528 
4529 		/* Process 'F' for "Basic Flags" (multiple lines) */
4530 		if (buf[0] == 'F') {
4531 			/* Parse every entry */
4532 			for (s = buf + 2; *s; ) {
4533 				/* Find the end of this entry */
4534 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
4535 
4536 				/* Nuke and skip any dividers */
4537 				if (*t) {
4538 					*t++ = '\0';
4539 					while (*t == ' ' || *t == '|') t++;
4540 				}
4541 
4542 				/* Hack: Flag 'DUN_xx' dungeon restriction 'flag', for Ufthak - C. Blue ;) */
4543 				if (1 == sscanf(s, "DUN_%d", &i)) {
4544 					/* Extract the dungeon it is restricted to */
4545                                         r_ptr->restrict_dun = i;
4546 
4547 					/* Start at next entry */
4548 					s = t;
4549 
4550 					/* Continue */
4551 					continue;
4552 				}
4553 
4554 				/* Parse this entry */
4555 				if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
4556 
4557 				/* Start the next entry */
4558 				s = t;
4559 			}
4560 
4561 			/* Next... */
4562 			continue;
4563 		}
4564 
4565 		/* Process 'S' for "Spell Flags" (multiple lines) */
4566 		if (buf[0] == 'S') {
4567 			/* Parse every entry */
4568 			for (s = buf + 2; *s; ) {
4569 				/* Find the end of this entry */
4570 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
4571 
4572 				/* Nuke and skip any dividers */
4573 				if (*t) {
4574 					*t++ = '\0';
4575 					while ((*t == ' ') || (*t == '|')) t++;
4576 				}
4577 
4578 				/* XXX XXX XXX Hack -- Read spell frequency */
4579 				if (1 == sscanf(s, "1_IN_%d", &i)) {
4580 					/* Extract a "frequency" */
4581 					r_ptr->freq_spell = r_ptr->freq_innate = 100 / i;
4582 
4583 					/* Start at next entry */
4584 					s = t;
4585 
4586 					/* Continue */
4587 					continue;
4588 				}
4589 
4590 				/* Parse this entry */
4591 				if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
4592 
4593 				/* Start the next entry */
4594 				s = t;
4595 			}
4596 
4597 			/* Next... */
4598 			continue;
4599 		}
4600 
4601 		/* Oops */
4602 		return (6);
4603 	}
4604 
4605 
4606 	/* Complete the "name" and "text" sizes */
4607 	++r_head->name_size;
4608 	++r_head->text_size;
4609 
4610 
4611 	/* XXX XXX XXX XXX The ghost is unused */
4612 
4613 	/* Mega-Hack -- acquire "ghost" */
4614 	r_ptr = &r_info[MAX_R_IDX-1];
4615 
4616 	/* Acquire the next index */
4617 	r_ptr->name = r_head->name_size;
4618 	r_ptr->text = r_head->text_size;
4619 
4620 	/* Save some space for the ghost info */
4621 	r_head->name_size += 64;
4622 	r_head->text_size += 64;
4623 
4624 	/* Hack -- Default name/text for the ghost */
4625 	strcpy(r_name + r_ptr->name, "Nobody, the Undefined Ghost");
4626 	strcpy(r_text + r_ptr->text, "It seems strangely familiar...");
4627 
4628 	/* Hack -- set the char/attr info */
4629 	r_ptr->d_attr = r_ptr->x_attr = TERM_WHITE;
4630 	r_ptr->d_char = r_ptr->x_char = 'G';
4631 
4632 	/* Hack -- Try to prevent a few "potential" bugs */
4633 	r_ptr->flags1 |= (RF1_UNIQUE);
4634 
4635 	/* Hack -- Try to prevent a few "potential" bugs */
4636 	r_ptr->flags1 |= (RF1_NEVER_MOVE | RF1_NEVER_BLOW);
4637 
4638 	/* Hack -- Try to prevent a few "potential" bugs */
4639 	r_ptr->hdice = r_ptr->hside = 1;
4640 
4641 	/* Hack -- Try to prevent a few "potential" bugs */
4642 	r_ptr->mexp = 1L;
4643 
4644 	for (i = 1; i < MAX_R_IDX; i++) {
4645 		/* Invert flag WILD_ONLY <-> RF8_DUNGEON */
4646 		r_info[i].flags8 ^= 1L;
4647 
4648 		/* WILD_TOO without any other wilderness flags enables all flags */
4649 #if 0
4650 		if ((r_info[i].flags8 & RF8_WILD_TOO) && !(r_info[i].flags8 & 0x7FFFFFFE))
4651 			r_info[i].flags8 = 0x0463;
4652 #else	// 0
4653 		if ((r_info[i].flags8 & RF8_WILD_TOO) &&
4654 				!(r_info[i].flags8 & RF8_WILD_TOO_MASK))
4655 			r_info[i].flags8 |= RF8_WILD_TOO_MASK;
4656 #endif	// 0
4657 
4658 		/* WILD_EASY without any other wilderness flags enables all flags */
4659 		if ((r_info[i].flags8 & RF8_WILD_EASY) &&
4660 				!(r_info[i].flags8 & RF8_WILD_EASY_MASK))
4661 			r_info[i].flags8 |= RF8_WILD_EASY_MASK;
4662 
4663 		/* Implied flags */
4664 
4665 		/* Uniques can never occure more than 20 levels ood */
4666 		if (r_info[i].flags1 & RF1_UNIQUE) r_info[i].flags7 |= RF7_OOD_20;
4667 
4668 		/* Certain NON-UNIQUE monsters don't use shields, so they don't block */
4669 		else if (r_info[i].d_char == 'p') {
4670 			if (r_info[i].d_attr == 'b' || r_info[i].d_attr == 'o' ||
4671 			    r_info[i].d_attr == 'G' || r_info[i].d_attr == 'r' ||
4672 			    r_info[i].d_attr == 'R')
4673 				r_info[i].flags8 |= RF8_NO_BLOCK;
4674 		} else if (r_info[i].d_char == 'h') {
4675 			if (r_info[i].d_attr == 'r' || r_info[i].d_attr == 'v' ||
4676 			    r_info[i].d_attr == 'R')
4677 				r_info[i].flags8 |= RF8_NO_BLOCK;
4678 		}
4679 
4680 		/* As we know, chaos resistance implies confusion resistance.. */
4681 		if ((r_info[i].flags9 & RF9_RES_CHAOS)) r_info[i].flags3 |= RF3_NO_CONF;
4682 
4683 		/* For d_info rules: Formally an immunity implies the according resistance. */
4684 		if ((r_info[i].flags9 & RF9_IM_PSI)) r_info[i].flags9 |= RF9_RES_PSI;
4685 		if ((r_info[i].flags9 & RF9_IM_WATER)) r_info[i].flags3 |= RF3_RES_WATE;
4686 		if ((r_info[i].flags3 & RF3_IM_POIS)) r_info[i].flags9 |= RF9_RES_POIS;
4687 		if ((r_info[i].flags3 & RF3_IM_ELEC)) r_info[i].flags9 |= RF9_RES_ELEC;
4688 		if ((r_info[i].flags3 & RF3_IM_COLD)) r_info[i].flags9 |= RF9_RES_COLD;
4689 		if ((r_info[i].flags3 & RF3_IM_FIRE)) r_info[i].flags9 |= RF9_RES_FIRE;
4690 		if ((r_info[i].flags3 & RF3_IM_ACID)) r_info[i].flags9 |= RF9_RES_ACID;
4691 
4692 		/* clear flags that we want to be 'disabled' in defines.h for the time being,
4693 		   for example RF6_RAISE_DEAD isn't implemented fully! - C. Blue */
4694 		r_info[i].flags1 &= ~RF1_DISABLE_MASK;
4695 		r_info[i].flags2 &= ~RF2_DISABLE_MASK;
4696 		r_info[i].flags3 &= ~RF3_DISABLE_MASK;
4697 		r_info[i].flags4 &= ~RF4_DISABLE_MASK;
4698 		r_info[i].flags5 &= ~RF5_DISABLE_MASK;
4699 		r_info[i].flags6 &= ~RF6_DISABLE_MASK;
4700 		r_info[i].flags7 &= ~RF7_DISABLE_MASK;
4701 		r_info[i].flags8 &= ~RF8_DISABLE_MASK;
4702 		r_info[i].flags9 &= ~RF9_DISABLE_MASK;
4703 		r_info[i].flags0 &= ~RF0_DISABLE_MASK;
4704 	}
4705 
4706 
4707 	/* No version yet */
4708 	if (!okay) return (2);
4709 
4710 	max_r_idx = ++error_idx;
4711 
4712 	/* Success */
4713 	return (0);
4714 }
4715 
4716 #ifdef RANDUNIS
4717 /*
4718  * Grab one (basic) flag in a monster_race from a textual string
4719  */
grab_one_basic_ego_flag(monster_ego * re_ptr,cptr what,bool add)4720 static errr grab_one_basic_ego_flag(monster_ego *re_ptr, cptr what, bool add)
4721 {
4722 	int i;
4723 
4724 	/* Scan flags1 */
4725 	for (i = 0; i < 32; i++)
4726 	{
4727 		if (streq(what, r_info_flags1[i]))
4728 		{
4729                         if (add)
4730                                 re_ptr->mflags1 |= (1L << i);
4731                         else
4732                                 re_ptr->nflags1 |= (1L << i);
4733 			return (0);
4734 		}
4735 	}
4736 
4737 	/* Scan flags2 */
4738 	for (i = 0; i < 32; i++)
4739 	{
4740 		if (streq(what, r_info_flags2[i]))
4741 		{
4742                         if (add)
4743                                 re_ptr->mflags2 |= (1L << i);
4744                         else
4745                                 re_ptr->nflags2 |= (1L << i);
4746 			return (0);
4747 		}
4748 	}
4749 
4750 	/* Scan flags3 */
4751 	for (i = 0; i < 32; i++)
4752 	{
4753 		if (streq(what, r_info_flags3[i]))
4754 		{
4755                         if (add)
4756                                 re_ptr->mflags3 |= (1L << i);
4757                         else
4758                                 re_ptr->nflags3 |= (1L << i);
4759 			return (0);
4760 		}
4761 	}
4762 	/* Scan flags7 */
4763 	for (i = 0; i < 32; i++)
4764 	{
4765 		if (streq(what, r_info_flags7[i]))
4766 		{
4767                         if (add)
4768                                 re_ptr->mflags7 |= (1L << i);
4769                         else
4770                                 re_ptr->nflags7 |= (1L << i);
4771 			return (0);
4772 		}
4773 	}
4774 
4775 	/* Scan flags8 */
4776 	for (i = 0; i < 32; i++)
4777 	{
4778 		if (streq(what, r_info_flags8[i]))
4779 		{
4780                         if (add)
4781                                 re_ptr->mflags8 |= (1L << i);
4782                         else
4783                                 re_ptr->nflags8 |= (1L << i);
4784 			return (0);
4785 		}
4786 	}
4787 
4788 	/* Scan flags9 */
4789 	for (i = 0; i < 32; i++)
4790 	{
4791 		if (streq(what, r_info_flags9[i]))
4792 		{
4793                         if (add)
4794                                 re_ptr->mflags9 |= (1L << i);
4795                         else
4796                                 re_ptr->nflags9 |= (1L << i);
4797 			return (0);
4798 		}
4799 	}
4800 
4801 	/* Oops */
4802 	s_printf("Unknown monster flag '%s'.\n", what);
4803 
4804 	/* Failure */
4805 	return (1);
4806 }
4807 
4808 
4809 /*
4810  * Grab one (spell) flag in a monster_race from a textual string
4811  */
grab_one_spell_ego_flag(monster_ego * re_ptr,cptr what,bool add)4812 static errr grab_one_spell_ego_flag(monster_ego *re_ptr, cptr what, bool add)
4813 {
4814 	int i;
4815 
4816 	/* Scan flags4 */
4817 	for (i = 0; i < 32; i++)
4818 	{
4819 		if (streq(what, r_info_flags4[i]))
4820 		{
4821                         if (add)
4822                                 re_ptr->mflags4 |= (1L << i);
4823                         else
4824                                 re_ptr->nflags4 |= (1L << i);
4825 			return (0);
4826 		}
4827 	}
4828 
4829 	/* Scan flags5 */
4830 	for (i = 0; i < 32; i++)
4831 	{
4832 		if (streq(what, r_info_flags5[i]))
4833 		{
4834                         if (add)
4835                                 re_ptr->mflags5 |= (1L << i);
4836                         else
4837                                 re_ptr->nflags5 |= (1L << i);
4838 			return (0);
4839 		}
4840 	}
4841 
4842 	/* Scan flags6 */
4843 	for (i = 0; i < 32; i++)
4844 	{
4845 		if (streq(what, r_info_flags6[i]))
4846 		{
4847                         if (add)
4848                                 re_ptr->mflags6 |= (1L << i);
4849                         else
4850                                 re_ptr->nflags6 |= (1L << i);
4851 			return (0);
4852 		}
4853 	}
4854 
4855 	/* Scan flags0 */
4856 	for (i = 0; i < 32; i++)
4857 	{
4858 		if (streq(what, r_info_flags0[i]))
4859 		{
4860                         if (add)
4861                                 re_ptr->mflags0 |= (1L << i);
4862                         else
4863                                 re_ptr->nflags0 |= (1L << i);
4864 			return (0);
4865 		}
4866 	}
4867 
4868 	/* Oops */
4869 	s_printf("Unknown monster flag '%s'.\n", what);
4870 
4871 	/* Failure */
4872 	return (1);
4873 }
4874 
4875 
4876 /* Values in re_info can be fixed, added, substracted or percented */
monster_ego_modify(char c)4877 static byte monster_ego_modify(char c)
4878 {
4879         switch (c)
4880         {
4881                 case '+': return MEGO_ADD;
4882                 case '-': return MEGO_SUB;
4883                 case '=': return MEGO_FIX;
4884                 case '%': return MEGO_PRC;
4885                 default:
4886                 {
4887                         s_printf("Unknown monster ego value modifier %c.\n", c);
4888                         return MEGO_ADD;
4889                 }
4890         }
4891 }
4892 
4893 /*
4894  * Grab one (basic) flag in a monster_race from a textual string
4895  */
grab_one_ego_flag(monster_ego * re_ptr,cptr what,bool must)4896 static errr grab_one_ego_flag(monster_ego *re_ptr, cptr what, bool must)
4897 {
4898 	int i;
4899 
4900 	/* Scan flags1 */
4901 	for (i = 0; i < 32; i++)
4902 	{
4903 		if (streq(what, r_info_flags1[i]))
4904 		{
4905                         if (must) re_ptr->flags1 |= (1L << i);
4906                         else re_ptr->hflags1 |= (1L << i);
4907 			return (0);
4908 		}
4909 	}
4910 
4911 	/* Scan flags2 */
4912 	for (i = 0; i < 32; i++)
4913 	{
4914 		if (streq(what, r_info_flags2[i]))
4915 		{
4916                         if (must) re_ptr->flags2 |= (1L << i);
4917                         else re_ptr->hflags2 |= (1L << i);
4918 			return (0);
4919 		}
4920 	}
4921 
4922 	/* Scan flags3 */
4923 	for (i = 0; i < 32; i++)
4924 	{
4925 		if (streq(what, r_info_flags3[i]))
4926 		{
4927                         if (must) re_ptr->flags3 |= (1L << i);
4928                         else re_ptr->hflags3 |= (1L << i);
4929 			return (0);
4930 		}
4931 	}
4932 	/* Scan flags7 */
4933 	for (i = 0; i < 32; i++)
4934 	{
4935 		if (streq(what, r_info_flags7[i]))
4936 		{
4937                         if (must) re_ptr->flags7 |= (1L << i);
4938                         else re_ptr->hflags7 |= (1L << i);
4939 			return (0);
4940 		}
4941 	}
4942 
4943 	/* Scan flags8 */
4944 	for (i = 0; i < 32; i++)
4945 	{
4946 		if (streq(what, r_info_flags8[i]))
4947 		{
4948                         if (must) re_ptr->flags8 |= (1L << i);
4949                         else re_ptr->hflags8 |= (1L << i);
4950 			return (0);
4951 		}
4952 	}
4953 
4954 	/* Scan flags9 */
4955 	for (i = 0; i < 32; i++)
4956 	{
4957 		if (streq(what, r_info_flags9[i]))
4958 		{
4959                         if (must) re_ptr->flags9 |= (1L << i);
4960 			else re_ptr->hflags9 |= (1L << i);
4961 			return (0);
4962 		}
4963 	}
4964 
4965 	/* Oops */
4966 	s_printf("Unknown monster flag '%s'.\n", what);
4967 
4968 	/* Failure */
4969 	return (1);
4970 }
4971 
4972 /*
4973  * Initialize the "re_info" array, by parsing an ascii "template" file
4974  */
init_re_info_txt(FILE * fp,char * buf)4975 errr init_re_info_txt(FILE *fp, char *buf)
4976 {
4977         int i, j;
4978 
4979         byte blow_num = 0;
4980         int r_char_number = 0, nr_char_number = 0;
4981 
4982 	char *s, *t;
4983 
4984 	/* Not ready yet */
4985 	bool okay = FALSE;
4986 
4987 	/* Current entry */
4988         monster_ego *re_ptr = NULL;
4989 
4990 
4991 	/* Just before the first record */
4992 	error_idx = -1;
4993 
4994 	/* Just before the first line */
4995 	error_line = -1;
4996 
4997 
4998 	/* Start the "fake" stuff */
4999         re_head->name_size = 0;
5000         re_head->text_size = 0;
5001 
5002 	/* Parse */
5003 	while (0 == my_fgets(fp, buf, 1024, FALSE))
5004 	{
5005 		/* Advance the line number */
5006 		error_line++;
5007 
5008 		/* Skip comments and blank lines */
5009 		if (!buf[0] || (buf[0] == '#')) continue;
5010 
5011 		/* Verify correct "colon" format */
5012 		if (buf[1] != ':') return (1);
5013 
5014 
5015 		/* Hack -- Process 'V' for "Version" */
5016 		if (buf[0] == 'V')
5017 		{
5018 			int v1, v2, v3;
5019 
5020 			/* Scan for the values */
5021 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
5022                             (v1 != re_head->v_major) ||
5023                             (v2 != re_head->v_minor) ||
5024                             (v3 != re_head->v_patch))
5025 			{
5026 //				return (2);
5027 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
5028 			}
5029 
5030 			/* Okay to proceed */
5031 			okay = TRUE;
5032 
5033 			/* Continue */
5034 			continue;
5035 		}
5036 
5037 		/* No version yet */
5038 		if (!okay) return (2);
5039 
5040 
5041 		/* Process 'N' for "New/Number/Name" */
5042 		if (buf[0] == 'N')
5043 		{
5044 			/* Find the colon before the name */
5045 			s = strchr(buf + 2, ':');
5046 
5047 			/* Verify that colon */
5048 			if (!s) return (1);
5049 
5050 			/* Nuke the colon, advance to the name */
5051 			*s++ = '\0';
5052 
5053 			/* Paranoia -- require a name */
5054 			if (!*s) return (1);
5055 
5056 			/* Get the index */
5057 			i = atoi(buf + 2);
5058 
5059 			/* Verify information */
5060 			if (i < error_idx) return (4);
5061 
5062 			/* Verify information */
5063                         if (i >= (int) re_head->info_num) return (2);
5064 
5065 			/* Save the index */
5066 			error_idx = i;
5067 
5068 			/* Point at the "info" */
5069                         re_ptr = &re_info[i];
5070 
5071 			/* Hack -- Verify space */
5072                         if (re_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
5073 
5074 			/* Advance and Save the name index */
5075                         if (!re_ptr->name) re_ptr->name = ++re_head->name_size;
5076 
5077 			/* Append chars to the name */
5078                         strcpy(re_name + re_head->name_size, s);
5079 
5080 			/* Advance the index */
5081                         re_head->name_size += strlen(s);
5082 
5083                         /* Some inits */
5084                         blow_num = 0;
5085                         r_char_number = 0;
5086                         nr_char_number = 0;
5087                         for (j = 0; j < 10; j++) re_ptr->r_char[j] = 0;
5088                         for (j = 0; j < 10; j++) re_ptr->nr_char[j] = 0;
5089                         for (j = 0; j < 4; j++)
5090                         {
5091                                 re_ptr->blow[j].method = 0;
5092                                 re_ptr->blow[j].effect = 0;
5093                                 re_ptr->blow[j].d_dice = 0;
5094                                 re_ptr->blow[j].d_side = 0;
5095                                 re_ptr->blowm[j][0] = MEGO_ADD;
5096                                 re_ptr->blowm[j][1] = MEGO_ADD;
5097                         }
5098 
5099 			/* Next... */
5100 			continue;
5101 		}
5102 
5103                 /* There better be a current re_ptr */
5104                 if (!re_ptr) return (3);
5105 
5106 		/* Process 'G' for "Graphics" (one line only) */
5107 		if (buf[0] == 'G')
5108 		{
5109 			char sym;
5110 			int tmp;
5111 
5112 			/* Paranoia */
5113 			if (!buf[2]) return (1);
5114 			if (!buf[3]) return (1);
5115 			if (!buf[4]) return (1);
5116 
5117 			/* Extract the char */
5118                         if (buf[2] != '*') sym = buf[2];
5119                         else sym = MEGO_CHAR_ANY;
5120 
5121 			/* Extract the attr */
5122                         if (buf[4] != '*') tmp = color_char_to_attr(buf[4]);
5123                         else tmp = MEGO_CHAR_ANY;
5124 
5125 			/* Paranoia */
5126 			if (tmp < 0) return (1);
5127 
5128 			/* Save the values */
5129                         re_ptr->d_char = sym;
5130                         re_ptr->d_attr = tmp;
5131 
5132 			/* Next... */
5133 			continue;
5134 		}
5135 
5136 		/* Process 'I' for "Info" (one line only) */
5137 		if (buf[0] == 'I')
5138 		{
5139 			int spd, hp1, hp2, aaf, ac, slp;
5140                         char mspd, mhp1, mhp2, maaf, mac, mslp;
5141 
5142 			/* Scan for the other values */
5143                         if (12 != sscanf(buf + 2, "%c%d:%c%dd%c%d:%c%d:%c%d:%c%d",
5144                                 &mspd, &spd, &mhp1, &hp1, &mhp2, &hp2, &maaf, &aaf, &mac, &ac, &mslp, &slp)) return (1);
5145 
5146 			/* Save the values */
5147                         re_ptr->speed = (spd << 2) + monster_ego_modify(mspd);
5148                         re_ptr->hdice = (hp1 << 2) + monster_ego_modify(mhp1);
5149                         re_ptr->hside = (hp2 << 2) + monster_ego_modify(mhp2);
5150                         re_ptr->aaf = (aaf << 2) + monster_ego_modify(maaf);
5151                         re_ptr->ac = (ac << 2) + monster_ego_modify(mac);
5152                         re_ptr->sleep = (slp << 2) + monster_ego_modify(mslp);
5153 
5154 			/* Next... */
5155 			continue;
5156 		}
5157 
5158 		/* Process 'W' for "More Info" (one line only) */
5159 		if (buf[0] == 'W')
5160 		{
5161                         int lev, rar, wt;
5162                         char mlev, mwt, mexp, pos;
5163 			int exp;
5164 
5165 			/* Scan for the values */
5166                         if (8 != sscanf(buf + 2, "%c%d:%d:%c%d:%c%d:%c",
5167                                 &mlev, &lev, &rar, &mwt, &wt, &mexp, &exp, &pos)) return (1);
5168 
5169 			/* Save the values */
5170                         re_ptr->level = (lev << 2) + monster_ego_modify(mlev);
5171                         re_ptr->rarity = rar;
5172                         re_ptr->weight = (wt << 2) + monster_ego_modify(mwt);
5173                         re_ptr->mexp = (exp << 2) + monster_ego_modify(mexp);
5174                         re_ptr->before = (pos == 'B')?TRUE:FALSE;
5175 
5176 			/* Next... */
5177 			continue;
5178 		}
5179 
5180 		/* Process 'B' for "Blows" (up to four lines) */
5181 		if (buf[0] == 'B')
5182 		{
5183                         int n1, n2, dice, side;
5184                         char mdice, mside;
5185 
5186 			/* Oops, no more slots */
5187                         if (blow_num == 4)
5188 						{
5189 							s_printf("no more slots!\n");
5190 							return (1);
5191 						}
5192 
5193 			/* Analyze the first field */
5194 			for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
5195 
5196 			/* Terminate the field (if necessary) */
5197 			if (*t == ':') *t++ = '\0';
5198 
5199 			/* Analyze the method */
5200 			for (n1 = 0; r_info_blow_method[n1]; n1++)
5201 			{
5202 				if (streq(s, r_info_blow_method[n1])) break;
5203 			}
5204 
5205 			/* Invalid method */
5206 			if (!r_info_blow_method[n1])
5207 			{
5208 				s_printf("invalid method!\n");
5209 				return (1);
5210 			}
5211 
5212 			/* Analyze the second field */
5213 			for (s = t; *t && (*t != ':'); t++) /* loop */;
5214 
5215 			/* Terminate the field (if necessary) */
5216 			if (*t == ':') *t++ = '\0';
5217 
5218 			/* Analyze effect */
5219 			for (n2 = 0; r_info_blow_effect[n2]; n2++)
5220 			{
5221 				if (streq(s, r_info_blow_effect[n2])) break;
5222 			}
5223 
5224 			/* Invalid effect */
5225 			if (!r_info_blow_effect[n2])
5226 			{
5227 				s_printf("invalid effect!\n");
5228 				return (1);
5229 			}
5230 
5231 			/* Save the method */
5232                         re_ptr->blow[blow_num].method = n1;
5233 
5234 			/* Save the effect */
5235                         re_ptr->blow[blow_num].effect = n2;
5236 
5237 			/* Extract the damage dice and sides */
5238                         if (4 != sscanf(t, "%c%dd%c%d",
5239                                 &mdice, &dice, &mside, &side))
5240 						{
5241 							s_printf("strange dice!\n");
5242 							return (1);
5243 						}
5244 
5245                         re_ptr->blow[blow_num].d_dice = dice;
5246                         re_ptr->blow[blow_num].d_side = side;
5247                         re_ptr->blowm[blow_num][0] = monster_ego_modify(mdice);
5248                         re_ptr->blowm[blow_num][1] = monster_ego_modify(mside);
5249                         blow_num++;
5250 
5251 			/* Next... */
5252 			continue;
5253 		}
5254 
5255                 /* Process 'F' for "Flags monster must have" (multiple lines) */
5256                 if (buf[0] == 'F')
5257 		{
5258                         char r_char;
5259 
5260 			/* Parse every entry */
5261 			for (s = buf + 2; *s; )
5262 			{
5263 				/* Find the end of this entry */
5264 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5265 
5266 				/* Nuke and skip any dividers */
5267 				if (*t)
5268 				{
5269 					*t++ = '\0';
5270 					while (*t == ' ' || *t == '|') t++;
5271 				}
5272 
5273                                 /* XXX XXX XXX Hack -- Read monster symbols */
5274                                 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
5275                                 {
5276                                         /* Limited to 5+5 races */
5277                                         if(r_char_number >= 10) continue;
5278 
5279 					/* Extract a "frequency" */
5280                                         re_ptr->r_char[r_char_number++] = r_char;
5281 
5282 					/* Start at next entry */
5283 					s = t;
5284 
5285 					/* Continue */
5286 					continue;
5287 				}
5288 
5289 				/* Parse this entry */
5290                                 if (0 != grab_one_ego_flag(re_ptr, s, TRUE)) return (5);
5291 
5292 				/* Start the next entry */
5293 				s = t;
5294 			}
5295 
5296 			/* Next... */
5297 			continue;
5298 		}
5299 
5300                 /* Process 'H' for "Flags monster must not have" (multiple lines) */
5301                 if (buf[0] == 'H')
5302 		{
5303                         char r_char;
5304 
5305 			/* Parse every entry */
5306 			for (s = buf + 2; *s; )
5307 			{
5308 				/* Find the end of this entry */
5309 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5310 
5311 				/* Nuke and skip any dividers */
5312 				if (*t)
5313 				{
5314 					*t++ = '\0';
5315 					while (*t == ' ' || *t == '|') t++;
5316 				}
5317 
5318                                 /* XXX XXX XXX Hack -- Read monster symbols */
5319                                 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
5320                                 {
5321                                         /* Limited to 5 races */
5322                                         if(nr_char_number >= 10) continue;
5323 
5324 					/* Extract a "frequency" */
5325                                         re_ptr->nr_char[nr_char_number++] = r_char;
5326 
5327 					/* Start at next entry */
5328 					s = t;
5329 
5330 					/* Continue */
5331 					continue;
5332 				}
5333 
5334 				/* Parse this entry */
5335                                 if (0 != grab_one_ego_flag(re_ptr, s, FALSE)) return (5);
5336 
5337 				/* Start the next entry */
5338 				s = t;
5339 			}
5340 
5341 			/* Next... */
5342 			continue;
5343 		}
5344 
5345                 /* Process 'M' for "Basic Monster Flags" (multiple lines) */
5346                 if (buf[0] == 'M')
5347 		{
5348 			/* Parse every entry */
5349 			for (s = buf + 2; *s; )
5350 			{
5351 				/* Find the end of this entry */
5352 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5353 
5354 				/* Nuke and skip any dividers */
5355 				if (*t)
5356 				{
5357 					*t++ = '\0';
5358 					while (*t == ' ' || *t == '|') t++;
5359 				}
5360 
5361 				/* Parse this entry */
5362                                 if (0 != grab_one_basic_ego_flag(re_ptr, s, TRUE)) return (5);
5363 
5364 				/* Start the next entry */
5365 				s = t;
5366 			}
5367 
5368 			/* Next... */
5369 			continue;
5370 		}
5371 
5372                 /* Process 'O' for "Basic Monster -Flags" (multiple lines) */
5373                 if (buf[0] == 'O')
5374 		{
5375 			/* Parse every entry */
5376 			for (s = buf + 2; *s; )
5377 			{
5378 				/* Find the end of this entry */
5379 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5380 
5381 				/* Nuke and skip any dividers */
5382 				if (*t)
5383 				{
5384 					*t++ = '\0';
5385 					while (*t == ' ' || *t == '|') t++;
5386 				}
5387 
5388                                 /* XXX XXX XXX Hack -- Read no flags */
5389                                 if (!strcmp(s, "MF_ALL"))
5390 				{
5391                                         /* No flags */
5392                                         re_ptr->nflags1 = re_ptr->nflags2 = re_ptr->nflags3 = re_ptr->nflags7 = re_ptr->nflags8 = re_ptr->nflags9 = 0xFFFFFFFF;
5393 
5394 					/* Start at next entry */
5395 					s = t;
5396 
5397 					/* Continue */
5398 					continue;
5399 				}
5400 
5401 				/* Parse this entry */
5402                                 if (0 != grab_one_basic_ego_flag(re_ptr, s, FALSE)) return (5);
5403 
5404 				/* Start the next entry */
5405 				s = t;
5406 			}
5407 
5408 			/* Next... */
5409 			continue;
5410 		}
5411 
5412                 /* Process 'S' for "Spell Flags" (multiple lines) */
5413                 if (buf[0] == 'S')
5414 		{
5415 			/* Parse every entry */
5416 			for (s = buf + 2; *s; )
5417 			{
5418 				/* Find the end of this entry */
5419 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5420 
5421 				/* Nuke and skip any dividers */
5422 				if (*t)
5423 				{
5424 					*t++ = '\0';
5425 					while ((*t == ' ') || (*t == '|')) t++;
5426 				}
5427 
5428 				/* XXX XXX XXX Hack -- Read spell frequency */
5429 				if (1 == sscanf(s, "1_IN_%d", &i))
5430 				{
5431 					/* Extract a "frequency" */
5432                                         re_ptr->freq_spell = re_ptr->freq_innate = 100 / i;
5433 
5434 					/* Start at next entry */
5435 					s = t;
5436 
5437 					/* Continue */
5438 					continue;
5439 				}
5440 
5441 				/* Parse this entry */
5442                                 if (0 != grab_one_spell_ego_flag(re_ptr, s, TRUE)) return (5);
5443 
5444 				/* Start the next entry */
5445 				s = t;
5446 			}
5447 
5448 			/* Next... */
5449 			continue;
5450                 }
5451 
5452                 /* Process 'T' for "Spell -Flags" (multiple lines) */
5453                 if (buf[0] == 'T')
5454 		{
5455 			/* Parse every entry */
5456 			for (s = buf + 2; *s; )
5457 			{
5458 				/* Find the end of this entry */
5459 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5460 
5461 				/* Nuke and skip any dividers */
5462 				if (*t)
5463 				{
5464 					*t++ = '\0';
5465 					while ((*t == ' ') || (*t == '|')) t++;
5466 				}
5467 
5468                                 /* XXX XXX XXX Hack -- Read no flags */
5469                                 if (!strcmp(s, "MF_ALL"))
5470 				{
5471                                         /* No flags */
5472                                         re_ptr->nflags4 = re_ptr->nflags5 = re_ptr->nflags6 = 0xFFFFFFFF;
5473 
5474 					/* Start at next entry */
5475 					s = t;
5476 
5477 					/* Continue */
5478 					continue;
5479 				}
5480 
5481 				/* Parse this entry */
5482                                 if (0 != grab_one_spell_ego_flag(re_ptr, s, FALSE)) return (5);
5483 
5484 				/* Start the next entry */
5485 				s = t;
5486 			}
5487 
5488 			/* Next... */
5489 			continue;
5490 		}
5491 
5492 		/* Oops */
5493 		return (6);
5494 	}
5495 
5496 
5497 	/* Complete the "name" and "text" sizes */
5498         ++re_head->name_size;
5499 
5500 	/* No version yet */
5501 	if (!okay) return (2);
5502 
5503 	max_re_idx = ++error_idx;
5504 
5505 	/* Success */
5506 	return (0);
5507 }
5508 
5509 #endif	//	RANDUNIS
5510 
5511 /*
5512  * Yummie traps borrowed from PernAngband	- Jir -
5513  */
5514 
5515 /*
5516  * Grab one flag in an trap_kind from a textual string
5517  */
grab_one_trap_type_flag(trap_kind * t_ptr,cptr what)5518 static errr grab_one_trap_type_flag(trap_kind *t_ptr, cptr what)
5519 {
5520 	s16b i;
5521 
5522 	/* Check flags1 */
5523 	for (i = 0; i < 32; i++)
5524 	{
5525 		if (streq(what, t_info_flags[i]))
5526 		{
5527 			t_ptr->flags |= (1L << i);
5528 			return (0);
5529 		}
5530 	}
5531 	/* Oops */
5532 	s_printf("Unknown trap_type flag '%s'.\n", what);
5533 
5534 	/* Error */
5535 	return (1);
5536 }
5537 
5538 
5539 /*
5540  * Initialize the "tr_info" array, by parsing an ascii "template" file
5541  */
init_t_info_txt(FILE * fp,char * buf)5542 errr init_t_info_txt(FILE *fp, char *buf)
5543 {
5544 	int i;
5545 
5546 	char *s, *t;
5547 
5548 	/* Not ready yet */
5549 	bool okay = FALSE;
5550 
5551 	/* Current entry */
5552 	trap_kind *t_ptr = NULL;
5553 
5554 
5555 	/* Just before the first record */
5556 	error_idx = -1;
5557 
5558 	/* Just before the first line */
5559 	error_line = -1;
5560 
5561 
5562 	/* Prepare the "fake" stuff */
5563 	t_head->name_size = 0;
5564 	t_head->text_size = 0;
5565 
5566 	/* Parse */
5567 	while (0 == my_fgets(fp, buf, 1024, FALSE))
5568 	{
5569 		/* Advance the line number */
5570 		error_line++;
5571 
5572 		/* parse server conditions */
5573 		if (invalid_server_conditions(buf)) continue;
5574 
5575 		/* Skip comments and blank lines */
5576 		if (!buf[0] || (buf[0] == '#')) continue;
5577 
5578 		/* Verify correct "colon" format */
5579 		if (buf[1] != ':') return (1);
5580 
5581 
5582 		/* Hack -- Process 'V' for "Version" */
5583 		if (buf[0] == 'V')
5584 		{
5585 			int v1, v2, v3;
5586 
5587 			/* Scan for the values */
5588 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
5589 			    (v1 != t_head->v_major) ||
5590 			    (v2 != t_head->v_minor) ||
5591 			    (v3 != t_head->v_patch))
5592 			{
5593 //				return (2);
5594 //				s_printf("Warning: different version file(%d.%d.%d)\n", v1, v2, v3);
5595 			}
5596 
5597 			/* Okay to proceed */
5598 			okay = TRUE;
5599 
5600 			/* Continue */
5601 			continue;
5602 		}
5603 
5604 		/* No version yet */
5605 		if (!okay) return (2);
5606 
5607 
5608 		/* Process 'N' for "New/Number/Name" */
5609 		if (buf[0] == 'N')
5610 		{
5611 			/* Find the colon before the name */
5612 			s = strchr(buf + 2, ':');
5613 
5614 			/* Verify that colon */
5615 			if (!s) return (1);
5616 
5617 			/* Nuke the colon, advance to the name */
5618 			*s++ = '\0';
5619 
5620 			/* Paranoia -- require a name */
5621 			if (!*s) return (1);
5622 
5623 			/* Get the index */
5624 			i = atoi(buf + 2);
5625 
5626 			/* Verify information */
5627 			if (i <= error_idx) return (4);
5628 
5629 			/* Verify information */
5630 			if (i >= (int) t_head->info_num) return (2);
5631 
5632 			/* Save the index */
5633 			error_idx = i;
5634 
5635 			/* Point at the "info" */
5636 			t_ptr = &t_info[i];
5637 
5638 			/* Hack -- Verify space */
5639 			if (t_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
5640 
5641 			/* Advance and Save the name index */
5642 			if (!t_ptr->name) t_ptr->name = ++t_head->name_size;
5643 
5644 			/* Append chars to the name */
5645 			strcpy(t_name + t_head->name_size, s);
5646 
5647 			/* Advance the index */
5648 			t_head->name_size += strlen(s);
5649 
5650 			/* Next... */
5651 			continue;
5652 		}
5653 
5654 		/* There better be a current t_ptr */
5655 		if (!t_ptr) return (3);
5656 
5657 
5658 		/* Process 'I' for "Information" */
5659 		if (buf[0] == 'I')
5660 		{
5661 			int probability, another, p1valinc, difficulty;
5662 			int minlevel;
5663 			int dd, ds, vanish;
5664 			char color;
5665 
5666 			/* Scan for the values */
5667 			if (9 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%dd%d:%c:%d",
5668 					&difficulty, &probability, &another,
5669 					&p1valinc, &minlevel, &dd, &ds,
5670 					&color, &vanish)) return (1);
5671 
5672 			t_ptr->difficulty  = (byte)difficulty;
5673 			t_ptr->probability = (s16b)probability;
5674 			t_ptr->another     = (s16b)another;
5675 			t_ptr->p1valinc     = (s16b)p1valinc;
5676 			t_ptr->minlevel    = (byte)minlevel;
5677 			t_ptr->dd          = (s16b)dd;
5678 			t_ptr->ds          = (s16b)ds;
5679 			t_ptr->color       = color_char_to_attr(color);
5680 			t_ptr->vanish      = (byte)vanish;
5681 
5682 			/* Megahack -- move pernA-oriented instakill traps deeper */
5683 			if (19 < error_idx && error_idx < 134)
5684 				t_ptr->minlevel += 5;
5685 
5686 			/* Next... */
5687 			continue;
5688 		}
5689 
5690 
5691 		/* Process 'D' for "Description" */
5692 		if (buf[0] == 'D')
5693 		{
5694 			/* Acquire the text */
5695 			s = buf + 2;
5696 
5697 			/* Hack -- Verify space */
5698 			if (t_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
5699 
5700 			/* Advance and Save the text index */
5701 			if (!t_ptr->text) t_ptr->text = ++t_head->text_size;
5702 
5703 			/* Append chars to the name */
5704 			strcpy(t_text + t_head->text_size, s);
5705 
5706 			/* Advance the index */
5707 			t_head->text_size += strlen(s);
5708 
5709 			/* Next... */
5710 			continue;
5711 		}
5712 
5713 
5714 		/* Hack -- Process 'F' for flags */
5715 		if (buf[0] == 'F')
5716 		{
5717 
5718                         t_ptr->flags = 0;
5719 
5720 			/* Parse every entry textually */
5721 			for (s = buf + 2; *s; )
5722 			{
5723 				/* Find the end of this entry */
5724 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
5725 
5726 				/* Nuke and skip any dividers */
5727 				if (*t)
5728 				{
5729 					*t++ = '\0';
5730 					while (*t == ' ' || *t == '|') t++;
5731 				}
5732 
5733 				/* Parse this entry */
5734                                 if (0 != grab_one_trap_type_flag(t_ptr, s)) return (5);
5735 
5736 				/* Start the next entry */
5737 				s = t;
5738 			}
5739 
5740 			/* Next... */
5741 			continue;
5742 		}
5743 
5744 
5745 		/* Oops */
5746 		return (6);
5747 	}
5748 
5749 
5750 	/* Complete the "name" and "text" sizes */
5751 	++t_head->name_size;
5752 	++t_head->text_size;
5753 
5754 
5755 	/* No version yet */
5756 	if (!okay) return (2);
5757 
5758 	max_t_idx = ++error_idx;
5759 
5760 	/* Success */
5761 	return (0);
5762 }
5763 
5764 
5765 /*
5766  * Grab one flag for a dungeon type from a textual string
5767  */
grab_one_dungeon_flag(dungeon_info_type * d_ptr,cptr what)5768 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
5769 {
5770 	int i;
5771 
5772 	/* Scan flags1 */
5773 	for (i = 0; i < 32; i++)
5774 	{
5775 		if (streq(what, d_info_flags1[i]))
5776 		{
5777 			d_ptr->flags1 |= (1L << i);
5778 			return (0);
5779 		}
5780 	}
5781 
5782 	/* Scan flags2 */
5783 	for (i = 0; i < 32; i++)
5784 	{
5785 		if (streq(what, d_info_flags2[i]))
5786 		{
5787 			d_ptr->flags2 |= (1L << i);
5788 			return (0);
5789 		}
5790 	}
5791 
5792 	/* Scan flags3 */
5793 	for (i = 0; i < 32; i++)
5794 	{
5795 		if (streq(what, d_info_flags3[i]))
5796 		{
5797 			d_ptr->flags3 |= (1L << i);
5798 			return (0);
5799 		}
5800 	}
5801 
5802 	/* Oops */
5803 	s_printf("Unknown dungeon type flag '%s'.\n", what);
5804 
5805 	/* Failure */
5806 	return (1);
5807 }
5808 
5809 /*
5810  * Grab one (basic) flag in a monster_race from a textual string
5811  */
grab_one_basic_monster_flag(dungeon_info_type * d_ptr,cptr what,byte rule)5812 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what, byte rule)
5813 {
5814 	int i;
5815 
5816 	/* Scan flags1 */
5817 	for (i = 0; i < 32; i++)
5818 	{
5819 		if (streq(what, r_info_flags1[i]))
5820 		{
5821 			d_ptr->rules[rule].mflags1 |= (1L << i);
5822 			return (0);
5823 		}
5824 	}
5825 
5826 	/* Scan flags2 */
5827 	for (i = 0; i < 32; i++)
5828 	{
5829 		if (streq(what, r_info_flags2[i]))
5830 		{
5831 			d_ptr->rules[rule].mflags2 |= (1L << i);
5832 			return (0);
5833 		}
5834 	}
5835 
5836 	/* Scan flags3 */
5837 	for (i = 0; i < 32; i++)
5838 	{
5839 		if (streq(what, r_info_flags3[i]))
5840 		{
5841 			d_ptr->rules[rule].mflags3 |= (1L << i);
5842 			return (0);
5843 		}
5844 	}
5845 
5846 	/* Scan flags7 */
5847 	for (i = 0; i < 32; i++)
5848 	{
5849 		if (streq(what, r_info_flags7[i]))
5850 		{
5851 			d_ptr->rules[rule].mflags7 |= (1L << i);
5852 			return (0);
5853 		}
5854 	}
5855 
5856 	/* Scan flags8 */
5857 	for (i = 0; i < 32; i++)
5858 	{
5859 		if (streq(what, r_info_flags8[i]))
5860 		{
5861 			d_ptr->rules[rule].mflags8 |= (1L << i);
5862 			return (0);
5863 		}
5864 	}
5865 
5866 	/* Scan flags9 */
5867 	for (i = 0; i < 32; i++)
5868 	{
5869 		if (streq(what, r_info_flags9[i]))
5870 		{
5871 			d_ptr->rules[rule].mflags9 |= (1L << i);
5872 			return (0);
5873 		}
5874 	}
5875 
5876 	/* Oops */
5877 	s_printf("Unknown monster flag '%s'.\n", what);
5878 
5879 	/* Failure */
5880 	return (1);
5881 }
5882 
5883 
5884 /*
5885  * Grab one (spell) flag in a monster_race from a textual string
5886  */
grab_one_spell_monster_flag(dungeon_info_type * d_ptr,cptr what,byte rule)5887 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what, byte rule)
5888 {
5889 	int i;
5890 
5891 	/* Scan flags4 */
5892 	for (i = 0; i < 32; i++)
5893 	{
5894 		if (streq(what, r_info_flags4[i]))
5895 		{
5896 			d_ptr->rules[rule].mflags4 |= (1L << i);
5897 			return (0);
5898 		}
5899 	}
5900 
5901 	/* Scan flags5 */
5902 	for (i = 0; i < 32; i++)
5903 	{
5904 		if (streq(what, r_info_flags5[i]))
5905 		{
5906 			d_ptr->rules[rule].mflags5 |= (1L << i);
5907 			return (0);
5908 		}
5909 	}
5910 
5911 	/* Scan flags6 */
5912 	for (i = 0; i < 32; i++)
5913 	{
5914 		if (streq(what, r_info_flags6[i]))
5915 		{
5916 			d_ptr->rules[rule].mflags6 |= (1L << i);
5917 			return (0);
5918 		}
5919 	}
5920 
5921 	/* Scan flags0 */
5922 	for (i = 0; i < 32; i++)
5923 	{
5924 		if (streq(what, r_info_flags0[i]))
5925 		{
5926 			d_ptr->rules[rule].mflags0 |= (1L << i);
5927 			return (0);
5928 		}
5929 	}
5930 
5931 	/* Oops */
5932 	s_printf("Unknown monster flag '%s'.\n", what);
5933 
5934 	/* Failure */
5935 	return (1);
5936 }
5937 
5938 /*
5939  * Initialize the "d_info" array, by parsing an ascii "template" file
5940  */
init_d_info_txt(FILE * fp,char * buf)5941 errr init_d_info_txt(FILE *fp, char *buf)
5942 {
5943 	int i, j;
5944 
5945 	byte rule_num = 0;
5946 
5947 	byte r_char_number = 0;
5948 
5949 	char *s, *t;
5950 
5951 	/* Not ready yet */
5952 	bool okay = FALSE;
5953 
5954 	/* Current entry */
5955 	dungeon_info_type *d_ptr = NULL;
5956 
5957 	/* Just before the first record */
5958 	error_idx = -1;
5959 
5960 	/* Just before the first line */
5961 	error_line = -1;
5962 
5963 
5964 	/* Start the "fake" stuff */
5965 	d_head->name_size = 0;
5966 	d_head->text_size = 0;
5967 
5968 	/* Parse */
5969 	while (0 == my_fgets(fp, buf, 1024, FALSE))
5970 	{
5971 		/* Advance the line number */
5972 		error_line++;
5973 
5974 		/* parse server conditions */
5975 		if (invalid_server_conditions(buf)) continue;
5976 
5977 		/* Skip comments and blank lines */
5978 		if (!buf[0] || (buf[0] == '#')) continue;
5979 
5980 		/* Verify correct "colon" format */
5981 		if (buf[1] != ':') return (1);
5982 
5983 
5984 		/* Hack -- Process 'V' for "Version" */
5985 		if (buf[0] == 'V')
5986 		{
5987 			int v1, v2, v3;
5988 
5989 #ifdef VERIFY_VERSION_STAMP
5990 
5991 			/* Scan for the values */
5992 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
5993 			    (v1 != d_head->v_major) ||
5994 			    (v2 != d_head->v_minor) ||
5995 			    (v3 != d_head->v_patch))
5996 			{
5997 				return (2);
5998 			}
5999 
6000 #else /* VERIFY_VERSION_STAMP */
6001 
6002 			/* Scan for the values */
6003 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
6004 
6005 #endif /* VERIFY_VERSION_STAMP */
6006 
6007 			/* Okay to proceed */
6008 			okay = TRUE;
6009 
6010 			/* Continue */
6011 			continue;
6012 		}
6013 
6014 		/* No version yet */
6015 		if (!okay) return (2);
6016 
6017 
6018 		/* Process 'N' for "New/Number/Name" */
6019 		if (buf[0] == 'N')
6020 		{
6021 			/* Find the colon before the name */
6022 			s = strchr(buf + 2, ':');
6023 
6024 			/* Verify that colon */
6025 			if (!s) return (1);
6026 
6027 			/* Nuke the colon, advance to the name */
6028 			*s++ = '\0';
6029 
6030 			/* Paranoia -- require a name */
6031 			if (!*s) return (1);
6032 
6033 			/* Get the index */
6034 			i = atoi(buf + 2);
6035 
6036 			/* Verify information */
6037 			if (i < error_idx) return (4);
6038 
6039 			/* Verify information */
6040 			if (i >= (int) d_head->info_num) return (2);
6041 
6042 			/* Save the index */
6043 			error_idx = i;
6044 
6045 			/* Point at the "info" */
6046 			d_ptr = &d_info[i];
6047 
6048 			/* Default for dungeon level borders: Solid permanent granite wall. */
6049 			d_ptr->feat_boundary = FEAT_PERM_SOLID;
6050 
6051 			/* New (for fountains of blood) - remember own index */
6052 //			d_ptr->idx = error_idx;
6053 
6054 			/* Hack -- Verify space */
6055 			if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
6056 
6057 			/* Advance and Save the name index */
6058 			if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
6059 
6060 			/* Append chars to the name */
6061 			strcpy(d_name + d_head->name_size, s);
6062 
6063 			/* Advance the index */
6064 			d_head->name_size += strlen(s);
6065 
6066 			/* HACK -- Those ones HAVE to have a set default value */
6067 			d_ptr->ix = -1;
6068 			d_ptr->iy = -1;
6069 			d_ptr->ox = -1;
6070 			d_ptr->oy = -1;
6071 			d_ptr->fill_method = 1;
6072 			rule_num = -1;
6073 			r_char_number = 0;
6074 			for (j = 0; j < 5; j++) {
6075 				int k;
6076 
6077 				d_ptr->rules[j].mode = DUNGEON_MODE_NONE;
6078 				d_ptr->rules[j].percent = 0;
6079 
6080 				for (k = 0; k < 5; k++) d_ptr->rules[j].r_char[k] = 0;
6081 			}
6082 
6083 			/* HACK -- Those ones HAVE to have a set default value */
6084 			d_ptr->objs.treasure = OBJ_GENE_TREASURE;
6085 			d_ptr->objs.combat = OBJ_GENE_COMBAT;
6086 			d_ptr->objs.magic = OBJ_GENE_MAGIC;
6087 			d_ptr->objs.tools = OBJ_GENE_TOOL;
6088 
6089 			/* Next... */
6090 			continue;
6091 		}
6092 
6093 		/* There better be a current d_ptr */
6094 		if (!d_ptr) return (3);
6095 
6096 		/* Process 'D' for "Description */
6097 		if (buf[0] == 'D')
6098 		{
6099 			/* Acquire short name */
6100 			d_ptr->short_name[0] = buf[2];
6101 			d_ptr->short_name[1] = buf[3];
6102 			d_ptr->short_name[2] = buf[4];
6103 
6104 			/* Acquire the text */
6105 			s = buf + 6;
6106 
6107 			/* Hack -- Verify space */
6108 			if (d_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
6109 
6110 			/* Advance and Save the text index */
6111 			if (!d_ptr->text) d_ptr->text = ++d_head->text_size;
6112 
6113 			/* Append chars to the name */
6114 			strcpy(d_text + d_head->text_size, s);
6115 
6116 			/* Advance the index */
6117 			d_head->text_size += strlen(s);
6118 
6119 			/* Next... */
6120 			continue;
6121 		}
6122 
6123 		/* Process 'R' for "monster generation Rule" (up to 5 lines) */
6124 		if (buf[0] == 'B') {
6125 			int feat_boundary;
6126 
6127 			/* Scan for the values */
6128 			if (1 != sscanf(buf + 2, "%d",
6129 				&feat_boundary)) return (1);
6130 
6131 			d_ptr->feat_boundary = feat_boundary;
6132 			/* Next... */
6133 			continue;
6134 		}
6135 
6136 		/* Process 'W' for "More Info" (one line only) */
6137 		if (buf[0] == 'W')
6138 		{
6139 			int min_lev, max_lev;
6140 			int min_plev, next;
6141 			int min_alloc, max_chance;
6142 
6143 			/* Scan for the values */
6144 			if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
6145 				&min_lev, &max_lev, &min_plev, &next, &min_alloc, &max_chance)) return (1);
6146 
6147 			/* Save the values */
6148 			d_ptr->mindepth = min_lev;
6149 			d_ptr->maxdepth = max_lev;
6150 			d_ptr->min_plev = min_plev;
6151 			d_ptr->next = next;
6152 			d_ptr->min_m_alloc_level = min_alloc;
6153 			d_ptr->max_m_alloc_chance = max_chance;
6154 
6155 			/* Next... */
6156 			continue;
6157 		}
6158 
6159 		/* Process 'L' for "fLoor type" (one line only) */
6160 		if (buf[0] == 'L')
6161 		{
6162 			int f[5], p[5];
6163 			int i, j;
6164 
6165 			/* Scan for the values */
6166 			if (10 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
6167 				&f[0], &p[0], &f[1], &p[1], &f[2], &p[2], &f[3], &p[3], &f[4], &p[4])) {
6168 				/* Scan for the values - part ii*/
6169 				if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d", &p[0], &p[1],
6170 						&p[2], &p[3], &p[4])) return (1);
6171 
6172 				/* Save the values */
6173 				for (i = 0; i < 5; i++) d_ptr->floor_percent[i][1] = p[i];
6174 
6175 				continue;
6176 			}
6177 
6178 			/* Save the values */
6179 			for (i = 0; i < 5; i++) {
6180 				d_ptr->floor[i] = f[i];
6181 				for (j = 0; j <= 1; j++) d_ptr->floor_percent[i][j] = p[i];
6182 			}
6183 
6184 			/* Next... */
6185 			continue;
6186 		}
6187 
6188 		/* Process 'O' for "Object type" (one line only) */
6189 		if (buf[0] == 'O')
6190 		{
6191 			int treasure, combat, magic, tools;
6192 
6193 			/* Scan for the values */
6194 			if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
6195 				&treasure, &combat, &magic, &tools)) return (1);
6196 
6197 			/* Save the values */
6198 			d_ptr->objs.treasure = treasure;
6199 			d_ptr->objs.combat = combat;
6200 			d_ptr->objs.magic = magic;
6201 			d_ptr->objs.tools = tools;
6202 
6203 			/* Next... */
6204 			continue;
6205 		}
6206 
6207 		/* Process 'A' for "wAll type" (one line only) */
6208 		if (buf[0] == 'A')
6209 		{
6210 			int outer, inner;
6211 			int w[5], p[5];
6212 			int i, j;
6213 
6214 			/* Scan for the values */
6215 			if (12 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
6216 				&w[0], &p[0], &w[1], &p[1], &w[2], &p[2], &w[3], &p[3], &w[4], &p[4], &outer, &inner))
6217 			{
6218 				/* Scan for the values - part ii*/
6219 				if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d", &p[0], &p[1],
6220 				    &p[2], &p[3], &p[4])) return (1);
6221 
6222 				/* Save the values */
6223 				for (i = 0; i < 5; i++) d_ptr->fill_percent[i][1] = p[i];
6224 
6225 				continue;
6226 			}
6227 
6228 			/* Save the values */
6229 			for (i = 0; i < 5; i++) {
6230 				d_ptr->fill_type[i] = w[i];
6231 				for (j = 0; j <= 1; j++) d_ptr->fill_percent[i][j] = p[i];
6232 			}
6233 
6234 			d_ptr->outer_wall = outer;
6235 			d_ptr->inner_wall = inner;
6236 
6237 			/* Next... */
6238 			continue;
6239 		}
6240 
6241 		/* Process 'E' for "Effects" (up to four lines) -SC- */
6242 		if (buf[0] == 'E')
6243 		{
6244 			int side, dice, freq, type;
6245 			cptr tmp;
6246 
6247 			/* Find the next empty blow slot (if any) */
6248 			for (i = 0; i < 4; i++) if ((!d_ptr->d_side[i]) &&
6249 						    (!d_ptr->d_dice[i])) break;
6250 
6251 			/* Oops, no more slots */
6252 			if (i == 4) return (1);
6253 
6254 			/* Scan for the values */
6255 			  if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
6256 				  &dice, &side, &freq, &type))
6257 			{
6258 				int j;
6259 
6260 				if (3 != sscanf(buf + 2, "%dd%d:%d",
6261 						&dice, &side, &freq)) return (1);
6262 
6263 				tmp = buf + 2;
6264 				for (j = 0; j < 2; j++)
6265 				{
6266 					tmp = strchr(tmp, ':');
6267 					if (tmp == NULL) return(1);
6268 					tmp++;
6269 				}
6270 
6271 				j = 0;
6272 
6273 				while (d_info_dtypes[j].name != NULL)
6274 					if (strcmp(d_info_dtypes[j].name, tmp) == 0)
6275 					{
6276 						d_ptr->d_type[i] = d_info_dtypes[j].feat;
6277 						break;
6278 					}
6279 					else j++;
6280 
6281 				if (d_info_dtypes[j].name == NULL) return(1);
6282 			}
6283 			else
6284 				d_ptr->d_type[i] = type;
6285 
6286 			freq *= 10;
6287 			/* Save the values */
6288 			d_ptr->d_side[i] = side;
6289 			d_ptr->d_dice[i] = dice;
6290 			d_ptr->d_frequency[i] = freq;
6291 
6292 			/* Next... */
6293 			continue;
6294 		}
6295 
6296 		/* Process 'F' for "Dungeon Flags" (multiple lines) */
6297 		if (buf[0] == 'F')
6298 		{
6299 			int artif = 0, monst = 0, obj = 0;
6300 			int ix = -1, iy = -1, ox = -1, oy = -1;
6301 			int fill_method;
6302 
6303 			/* Parse every entry */
6304 			for (s = buf + 2; *s; )
6305 			{
6306 				/* Find the end of this entry */
6307 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
6308 
6309 				/* Nuke and skip any dividers */
6310 				if (*t)
6311 				{
6312 					*t++ = '\0';
6313 					while (*t == ' ' || *t == '|') t++;
6314 				}
6315 
6316 				/* XXX XXX XXX Hack -- Read dungeon in/out coords */
6317 				if (4 == sscanf(s, "WILD_%d_%d__%d_%d", &ix, &iy, &ox, &oy))
6318 				{
6319 					d_ptr->ix = ix;
6320 					d_ptr->iy = iy;
6321 					d_ptr->ox = ox;
6322 					d_ptr->oy = oy;
6323 
6324 					/* Start at next entry */
6325 					s = t;
6326 
6327 					/* Continue */
6328 					continue;
6329 				}
6330 
6331 				/* XXX XXX XXX Hack -- Read dungeon fill method */
6332 				if (1 == sscanf(s, "FILL_METHOD_%d", &fill_method))
6333 				{
6334 					d_ptr->fill_method = fill_method;
6335 
6336 					/* Start at next entry */
6337 					s = t;
6338 
6339 					/* Continue */
6340 					continue;
6341 				}
6342 
6343 				/* XXX XXX XXX Hack -- Read Final Object */
6344 				if (1 == sscanf(s, "FINAL_OBJECT_%d", &obj))
6345 				{
6346 					/* Extract a "Final Artifact" */
6347 					d_ptr->final_object = obj;
6348 
6349 					/* Start at next entry */
6350 					s = t;
6351 
6352 					/* Continue */
6353 					continue;
6354 				}
6355 
6356 				/* XXX XXX XXX Hack -- Read Final Artifact */
6357 				if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
6358 				{
6359 					/* Extract a "Final Artifact" */
6360 					d_ptr->final_artifact = artif;
6361 
6362 					/* Start at next entry */
6363 					s = t;
6364 
6365 					/* Continue */
6366 					continue;
6367 				}
6368 
6369 				/* XXX XXX XXX Hack -- Read Artifact Guardian */
6370 				if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
6371 				{
6372 					/* Extract a "Artifact Guardian" */
6373 					d_ptr->final_guardian = monst;
6374 
6375 					/* automatically mark it as such, no need for doing that in r_info.txt */
6376 					r_info[monst].flags0 |= RF0_FINAL_GUARDIAN;
6377 
6378 					/* Start at next entry */
6379 					s = t;
6380 
6381 					/* Continue */
6382 					continue;
6383 				}
6384 
6385 				/* Parse this entry */
6386 				if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
6387 
6388 				/* Start the next entry */
6389 				s = t;
6390 			}
6391 
6392 			/* Next... */
6393 			continue;
6394 		}
6395 
6396 		/* Process 'R' for "monster generation Rule" (up to 5 lines) */
6397 		if (buf[0] == 'R')
6398 		{
6399 			int percent, mode;
6400 			int z, y, lims[5];
6401 
6402 			/* Scan for the values */
6403 			if (2 != sscanf(buf + 2, "%d:%d",
6404 				&percent, &mode)) return (1);
6405 
6406 			/* Save the values */
6407 			r_char_number = 0;
6408 			rule_num++;
6409 
6410 			d_ptr->rules[rule_num].percent = percent;
6411 			d_ptr->rules[rule_num].mode = mode;
6412 
6413 			/* Lets remap the flat percents */
6414 			lims[0] = d_ptr->rules[0].percent;
6415 			for (y = 1; y <= rule_num; y++)
6416 			{
6417 				lims[y] = lims[y - 1] + d_ptr->rules[y].percent;
6418 			}
6419 			for (z = 0; z < 100; z++)
6420 			{
6421 				for (y = rule_num; y >= 0; y--)
6422 				{
6423 					if (z < lims[y]) d_ptr->rule_percents[z] = y;
6424 				}
6425 			}
6426 
6427 			/* Next... */
6428 			continue;
6429 		}
6430 
6431 		/* Process 'M' for "Basic Flags" (multiple lines) */
6432 		if (buf[0] == 'M')
6433 		{
6434 			byte r_char;
6435 
6436 			/* Parse every entry */
6437 			for (s = buf + 2; *s; )
6438 			{
6439 				/* Find the end of this entry */
6440 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
6441 
6442 				/* Nuke and skip any dividers */
6443 				if (*t)
6444 				{
6445 					*t++ = '\0';
6446 					while (*t == ' ' || *t == '|') t++;
6447 				}
6448 
6449 				/* XXX XXX XXX Hack -- Read monster symbols */
6450 				if (1 == sscanf(s, "R_CHAR_%c", &r_char))
6451 				{
6452 					/* Limited to 5 races */
6453 					if(r_char_number >= 5) continue;
6454 
6455 					/* Extract a "frequency" */
6456 					d_ptr->rules[rule_num].r_char[r_char_number++] = r_char;
6457 
6458 					/* Start at next entry */
6459 					s = t;
6460 
6461 					/* Continue */
6462 					continue;
6463 				}
6464 
6465 				/* Parse this entry */
6466 				if (0 != grab_one_basic_monster_flag(d_ptr, s, rule_num)) return (5);
6467 
6468 				/* Start the next entry */
6469 				s = t;
6470 			}
6471 
6472 			/* Next... */
6473 			continue;
6474 		}
6475 
6476 		/* Process 'S' for "Spell Flags" (multiple lines) */
6477 		if (buf[0] == 'S')
6478 		{
6479 			/* Parse every entry */
6480 			for (s = buf + 2; *s; )
6481 			{
6482 				/* Find the end of this entry */
6483 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
6484 
6485 				/* Nuke and skip any dividers */
6486 				if (*t)
6487 				{
6488 					*t++ = '\0';
6489 					while ((*t == ' ') || (*t == '|')) t++;
6490 				}
6491 
6492 				/* Parse this entry */
6493 				if (0 != grab_one_spell_monster_flag(d_ptr, s, rule_num)) return (5);
6494 
6495 				/* Start the next entry */
6496 				s = t;
6497 			}
6498 
6499 			/* Next... */
6500 			continue;
6501 		}
6502 
6503 		/* Oops */
6504 		return (6);
6505 	}
6506 
6507 
6508 	/* Complete the "name" and "text" sizes */
6509 	++d_head->name_size;
6510 	++d_head->text_size;
6511 
6512 	/* No version yet */
6513 	if (!okay) return (2);
6514 
6515 	/* Hack -- acquire total number */
6516 	max_d_idx = ++error_idx;
6517 
6518 #if DEBUG_LEVEL > 2
6519 	/* Debug -- print total no. */
6520 	s_printf("d_info total: %d\n", max_d_idx);
6521 #endif	// DEBUG_LEVEL
6522 
6523 	/* Success */
6524 	return (0);
6525 }
6526 
6527 
6528 
6529 /*
6530  * Grab one race flag from a textual string
6531  */
grab_one_race_flag(owner_type * ow_ptr,int state,cptr what)6532 static errr grab_one_race_flag(owner_type *ow_ptr, int state, cptr what)
6533 {
6534 	/* int i;
6535 	cptr s; */
6536 
6537 	/* Scan race flags */
6538 	unknown_shut_up = TRUE;
6539 	if (!grab_one_race_allow_flag(ow_ptr->races[state], what))
6540 	{
6541 		unknown_shut_up = FALSE;
6542 		return (0);
6543 	}
6544 
6545 	/* Scan classes flags */
6546 	if (!grab_one_class_flag(ow_ptr->classes[state], what))
6547 	{
6548 		unknown_shut_up = FALSE;
6549 		return (0);
6550 	}
6551 
6552 	/* Scan realms flags */
6553 	if (!grab_one_player_realm_flag(ow_ptr->realms[state], what))
6554 	{
6555 		unknown_shut_up = FALSE;
6556 		return (0);
6557 	}
6558 
6559 	/* Oops */
6560 	unknown_shut_up = FALSE;
6561 	s_printf("Unknown race/class/realm flag '%s'.\n", what);
6562 
6563 	/* Failure */
6564 	return (1);
6565 }
6566 
6567 /*
6568  * Grab one store flag from a textual string
6569  */
grab_one_store_flag(store_info_type * st_ptr,cptr what)6570 static errr grab_one_store_flag(store_info_type *st_ptr, cptr what)
6571 {
6572 	int i;
6573 
6574 	/* Scan store flags */
6575 	for (i = 0; i < 32; i++)
6576 	{
6577 		if (streq(what, st_info_flags1[i]))
6578 		{
6579 			st_ptr->flags1 |= (1L << i);
6580 			return (0);
6581 		}
6582 	}
6583 
6584 	/* Oops */
6585 	s_printf("Unknown store flag '%s'.\n", what);
6586 
6587 	/* Failure */
6588 	return (1);
6589 }
6590 
6591 /*
6592  * Initialize the "st_info" array, by parsing an ascii "template" file
6593  */
init_st_info_txt(FILE * fp,char * buf)6594 errr init_st_info_txt(FILE *fp, char *buf)
6595 {
6596 	int i = 0, item_idx = 0/*, cnt = 0*/;
6597 
6598 	char *s, *t;
6599 
6600 	/* Not ready yet */
6601 	bool okay = FALSE;
6602 
6603 	/* Current entry */
6604 	store_info_type *st_ptr = NULL;
6605 
6606 
6607 	/* Just before the first record */
6608 	error_idx = -1;
6609 
6610 	/* Just before the first line */
6611 	error_line = -1;
6612 
6613 
6614 	/* Start the "fake" stuff */
6615 	st_head->name_size = 0;
6616 	st_head->text_size = 0;
6617 
6618 	/* Parse */
6619 	while (0 == my_fgets(fp, buf, 1024, FALSE))
6620 	{
6621 		/* Advance the line number */
6622 		error_line++;
6623 
6624 		/* parse server conditions */
6625 		if (invalid_server_conditions(buf)) continue;
6626 
6627 		/* Skip comments and blank lines */
6628 		if (!buf[0] || (buf[0] == '#')) continue;
6629 
6630 		/* Verify correct "colon" format */
6631 		if (buf[1] != ':') return (1);
6632 
6633 
6634 		/* Hack -- Process 'V' for "Version" */
6635 		if (buf[0] == 'V')
6636 		{
6637 			int v1, v2, v3;
6638 
6639 #ifdef VERIFY_VERSION_STAMP
6640 
6641 			/* Scan for the values */
6642 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
6643 			    (v1 != st_head->v_major) ||
6644 			    (v2 != st_head->v_minor) ||
6645 			    (v3 != st_head->v_patch))
6646 			{
6647 				return (2);
6648 			}
6649 
6650 #else /* VERIFY_VERSION_STAMP */
6651 
6652 			/* Scan for the values */
6653 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
6654 
6655 #endif /* VERIFY_VERSION_STAMP */
6656 
6657 			/* Okay to proceed */
6658 			okay = TRUE;
6659 
6660 			/* Continue */
6661 			continue;
6662 		}
6663 
6664 		/* No version yet */
6665 		if (!okay) return (2);
6666 
6667 
6668 		/* Process 'N' for "New/Number/Name" */
6669 		if (buf[0] == 'N')
6670 		{
6671 			/* Find the colon before the name */
6672 			s = strchr(buf + 2, ':');
6673 
6674 			/* Verify that colon */
6675 			if (!s) return (1);
6676 
6677 			/* Nuke the colon, advance to the name */
6678 			*s++ = '\0';
6679 
6680 			/* Paranoia -- require a name */
6681 			if (!*s) return (1);
6682 
6683 			/* Get the index */
6684 			i = atoi(buf + 2);
6685 
6686 //			++cnt;
6687 
6688 			/* Verify information */
6689 			if (i < error_idx) return (4);
6690 
6691 			/* Verify information */
6692 			if (i >= (int) st_head->info_num) return (2);
6693 
6694 			/* Save the index */
6695 			error_idx = i;
6696 
6697 			/* Point at the "info" */
6698 			st_ptr = &st_info[i];
6699 
6700 			/* Hack -- Verify space */
6701 			if (st_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
6702 
6703 			/* Advance and Save the name index */
6704 			if (!st_ptr->name) st_ptr->name = ++st_head->name_size;
6705 
6706 			/* Append chars to the name */
6707 			strcpy(st_name + st_head->name_size, s);
6708 
6709 			/* Advance the index */
6710 			st_head->name_size += strlen(s);
6711 
6712 			/* We are ready for a new set of objects */
6713 			item_idx = 0;
6714 
6715 			/* Next... */
6716 			continue;
6717 		}
6718 
6719 		/* There better be a current st_ptr */
6720 		if (!st_ptr) return (3);
6721 
6722 		/* Process 'I' for "Items" (multiple lines) */
6723 		if (buf[0] == 'I')
6724 		{
6725 			/* Find the colon before the name */
6726 			s = strchr(buf + 2, ':');
6727 
6728 			/* Verify that colon */
6729 			if (!s) return (1);
6730 
6731 			/* Nuke the colon, advance to the name */
6732 			*s++ = '\0';
6733 
6734 			/* Paranoia -- require a name */
6735 			if (!*s) return (1);
6736 
6737 			/* Get the index */
6738 			st_ptr->table[item_idx][1] = atoi(buf + 2);
6739 
6740 			/* Append chars to the name */
6741 			st_ptr->table[item_idx++][0] = test_item_name(s);
6742 
6743 			st_ptr->table_num = item_idx;
6744 
6745 			/* Next... */
6746 			continue;
6747 		}
6748 
6749 		/* Process 'T' for "Tval/sval" */
6750 		if (buf[0] == 'T')
6751 		{
6752 			int tv1, sv1, rar1;
6753 
6754 			/* Scan for the values */
6755 			if (3 != sscanf(buf + 2, "%d:%d:%d",
6756 				&rar1, &tv1, &sv1)) return (1);
6757 
6758 			/* Get the index */
6759 			st_ptr->table[item_idx][1] = rar1;
6760 			/* Hack -- 256 as a sval means all possible items */
6761 			st_ptr->table[item_idx++][0] = (sv1 < 256)?lookup_kind(tv1, sv1):tv1 + 10000;
6762 
6763 			st_ptr->table_num = item_idx;
6764 
6765 			/* Next... */
6766 			continue;
6767 		}
6768 
6769 		/* Process 'G' for "Graphics" one line only) */
6770 		if (buf[0] == 'G')
6771 		{
6772 			char c, a;
6773 			int attr;
6774 
6775 			/* Scan for the values */
6776 			if (2 != sscanf(buf + 2, "%c:%c",
6777 				&c, &a)) return (1);
6778 
6779 			/* Extract the color */
6780 			attr = color_char_to_attr(a);
6781 
6782 			/* Paranoia */
6783 			if (attr < 0) return (1);
6784 
6785 			/* Save the values */
6786 			st_ptr->d_char = c;
6787 			st_ptr->d_attr = attr;
6788 
6789 			/* Next... */
6790 			continue;
6791 		}
6792 
6793 		/* Process 'A' for "Actions" (one line only) */
6794 		if (buf[0] == 'A')
6795 		{
6796 			int a1, a2, a3, a4, a5, a6;
6797 
6798 			/* Scan for the values */
6799 			if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
6800 				&a1, &a2, &a3, &a4, &a5, &a6)) return (1);
6801 
6802 			/* Save the values */
6803 			st_ptr->actions[0] = a1;
6804 			st_ptr->actions[1] = a2;
6805 			st_ptr->actions[2] = a3;
6806 			st_ptr->actions[3] = a4;
6807 			st_ptr->actions[4] = a5;
6808 			st_ptr->actions[5] = a6;
6809 
6810 			/* Next... */
6811 			continue;
6812 		}
6813 
6814 		/* Process 'F' for "store Flags" (multiple lines) */
6815 		if (buf[0] == 'F')
6816 		{
6817 			/* Parse every entry */
6818 			for (s = buf + 2; *s; )
6819 			{
6820 				/* Find the end of this entry */
6821 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
6822 
6823 				/* Nuke and skip any dividers */
6824 				if (*t)
6825 				{
6826 					*t++ = '\0';
6827 					while (*t == ' ' || *t == '|') t++;
6828 				}
6829 
6830 				/* Parse this entry */
6831 				if (0 != grab_one_store_flag(st_ptr, s)) return (5);
6832 
6833 				/* Start the next entry */
6834 				s = t;
6835 			}
6836 
6837 			/* Next... */
6838 			continue;
6839 		}
6840 
6841 		/* Process 'O' for "Owners" (one line only) */
6842 		if (buf[0] == 'O')
6843 		{
6844 			int a1, a2, a3, a4, a5, a6;
6845 
6846 			/* Scan for the values */
6847 			if (MAX_STORE_OWNERS != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
6848 				&a1, &a2, &a3, &a4, &a5, &a6)) return (1);
6849 
6850 			/* Save the values */
6851 			st_ptr->owners[0] = a1;
6852 			st_ptr->owners[1] = a2;
6853 			st_ptr->owners[2] = a3;
6854 			st_ptr->owners[3] = a4;
6855 			st_ptr->owners[4] = a5;
6856 			st_ptr->owners[5] = a6; /* MAX_STORE_OWNERS */
6857 
6858 			/* Next... */
6859 			continue;
6860 		}
6861 
6862 		/* Process 'W' for "Extra info" (one line only) */
6863 		if (buf[0] == 'W')
6864 		{
6865 			int max_obj;
6866 
6867 			/* Scan for the values */
6868 			if (1 != sscanf(buf + 2, "%d",
6869 				&max_obj)) return (1);
6870 
6871 			/* Save the values */
6872 			if (max_obj > STORE_INVEN_MAX) max_obj = STORE_INVEN_MAX;
6873 			st_ptr->max_obj = max_obj;
6874 
6875 			/* Next... */
6876 			continue;
6877 		}
6878 
6879 		/* Oops */
6880 		return (6);
6881 	}
6882 
6883 
6884 	/* Complete the "name" and "text" sizes */
6885 	++st_head->name_size;
6886 	++st_head->text_size;
6887 
6888 	/* No version yet */
6889 	if (!okay) return (2);
6890 
6891 	/* Hack -- acquire total number */
6892 	max_st_idx = ++error_idx;
6893 
6894 #if DEBUG_LEVEL > 2
6895 	/* Debug -- print total no. */
6896 	s_printf("st_info total: %d\n", max_st_idx);
6897 #endif	// DEBUG_LEVEL
6898 
6899 	/* Success */
6900 	return (0);
6901 }
6902 
6903 /*
6904  * Initialize the "ba_info" array, by parsing an ascii "template" file
6905  */
init_ba_info_txt(FILE * fp,char * buf)6906 errr init_ba_info_txt(FILE *fp, char *buf)
6907 {
6908 	int i = 0;
6909 
6910 	char *s;
6911 
6912 	/* Not ready yet */
6913 	bool okay = FALSE;
6914 
6915 	/* Current entry */
6916 	store_action_type *ba_ptr = NULL;
6917 
6918 
6919 	/* Just before the first record */
6920 	error_idx = -1;
6921 
6922 	/* Just before the first line */
6923 	error_line = -1;
6924 
6925 
6926 	/* Start the "fake" stuff */
6927 	ba_head->name_size = 0;
6928 	ba_head->text_size = 0;
6929 
6930 	/* Parse */
6931 	while (0 == my_fgets(fp, buf, 1024, FALSE))
6932 	{
6933 		/* Advance the line number */
6934 		error_line++;
6935 
6936 		/* Skip comments and blank lines */
6937 		if (!buf[0] || (buf[0] == '#')) continue;
6938 
6939 		/* Verify correct "colon" format */
6940 		if (buf[1] != ':') return (1);
6941 
6942 
6943 		/* Hack -- Process 'V' for "Version" */
6944 		if (buf[0] == 'V')
6945 		{
6946 			int v1, v2, v3;
6947 
6948 #ifdef VERIFY_VERSION_STAMP
6949 
6950 			/* Scan for the values */
6951 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
6952 			    (v1 != ba_head->v_major) ||
6953 			    (v2 != ba_head->v_minor) ||
6954 			    (v3 != ba_head->v_patch))
6955 			{
6956 				return (2);
6957 			}
6958 
6959 #else /* VERIFY_VERSION_STAMP */
6960 
6961 			/* Scan for the values */
6962 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
6963 
6964 #endif /* VERIFY_VERSION_STAMP */
6965 
6966 			/* Okay to proceed */
6967 			okay = TRUE;
6968 
6969 			/* Continue */
6970 			continue;
6971 		}
6972 
6973 		/* No version yet */
6974 		if (!okay) return (2);
6975 
6976 
6977 		/* Process 'N' for "New/Number/Name" */
6978 		if (buf[0] == 'N')
6979 		{
6980 			/* Find the colon before the name */
6981 			s = strchr(buf + 2, ':');
6982 
6983 			/* Verify that colon */
6984 			if (!s) return (1);
6985 
6986 			/* Nuke the colon, advance to the name */
6987 			*s++ = '\0';
6988 
6989 			/* Paranoia -- require a name */
6990 			if (!*s) return (1);
6991 
6992 			/* Get the index */
6993 			i = atoi(buf + 2);
6994 
6995 			/* Verify information */
6996 			if (i < error_idx) return (4);
6997 
6998 			/* Verify information */
6999 			if (i >= (int) ba_head->info_num) return (2);
7000 
7001 			/* Save the index */
7002 			error_idx = i;
7003 
7004 			/* Point at the "info" */
7005 			ba_ptr = &ba_info[i];
7006 
7007 			/* Hack -- Verify space */
7008 			if (ba_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
7009 
7010 			/* Advance and Save the name index */
7011 			if (!ba_ptr->name) ba_ptr->name = ++ba_head->name_size;
7012 
7013 			/* Append chars to the name */
7014 			strcpy(ba_name + ba_head->name_size, s);
7015 
7016 			/* Advance the index */
7017 			ba_head->name_size += strlen(s);
7018 
7019 			/* Next... */
7020 			continue;
7021 		}
7022 
7023 		/* There better be a current ba_ptr */
7024 		if (!ba_ptr) return (3);
7025 
7026 		/* Process 'C' for "Costs" (one line only) */
7027 		if (buf[0] == 'C')
7028 		{
7029 			int ch, cn, cl;
7030 
7031 			/* Scan for the values */
7032 			if (3 != sscanf(buf + 2, "%d:%d:%d",
7033 				&ch, &cn, &cl)) return (1);
7034 
7035 			/* Save the values */
7036 			ba_ptr->costs[STORE_HATED] = ch;
7037 			ba_ptr->costs[STORE_NORMAL] = cn;
7038 			ba_ptr->costs[STORE_LIKED] = cl;
7039 
7040 			/* Next... */
7041 			continue;
7042 		}
7043 
7044 		/* Process 'I' for "Infos" (one line only) */
7045 		if (buf[0] == 'I')
7046 		{
7047 			int act, act_res;
7048 			char letter;
7049 			unsigned int flags;
7050 
7051 			/* Scan for the values */
7052 			if (4 != sscanf(buf + 2, "%d:%d:%c:%u",
7053 				&act, &act_res, &letter, &flags)) return (1);
7054 
7055 			/* Save the values */
7056 			ba_ptr->action = act;
7057 			ba_ptr->action_restr = act_res;
7058 			ba_ptr->letter = letter;
7059 			ba_ptr->flags = (byte)flags;
7060 
7061 			/* Next... */
7062 			continue;
7063 		}
7064 
7065 		/* Oops */
7066 		return (6);
7067 	}
7068 
7069 
7070 	/* Complete the "name" and "text" sizes */
7071 	++ba_head->name_size;
7072 	++ba_head->text_size;
7073 
7074 	/* No version yet */
7075 	if (!okay) return (2);
7076 
7077 	max_ba_idx = ++error_idx;
7078 
7079 	/* Success */
7080 	return (0);
7081 }
7082 
7083 /*
7084  * Initialize the "ow_info" array, by parsing an ascii "template" file
7085  */
init_ow_info_txt(FILE * fp,char * buf)7086 errr init_ow_info_txt(FILE *fp, char *buf)
7087 {
7088 	int i;
7089 
7090 	char *s, *t;
7091 
7092 	/* Not ready yet */
7093 	bool okay = FALSE;
7094 
7095 	/* Current entry */
7096 	owner_type *ow_ptr = NULL;
7097 
7098 
7099 	/* Just before the first record */
7100 	error_idx = -1;
7101 
7102 	/* Just before the first line */
7103 	error_line = -1;
7104 
7105 
7106 	/* Start the "fake" stuff */
7107 	ow_head->name_size = 0;
7108 	ow_head->text_size = 0;
7109 
7110 	/* Parse */
7111 	while (0 == my_fgets(fp, buf, 1024, FALSE))
7112 	{
7113 		/* Advance the line number */
7114 		error_line++;
7115 
7116 		/* Skip comments and blank lines */
7117 		if (!buf[0] || (buf[0] == '#')) continue;
7118 
7119 		/* Verify correct "colon" format */
7120 		if (buf[1] != ':') return (1);
7121 
7122 
7123 		/* Hack -- Process 'V' for "Version" */
7124 		if (buf[0] == 'V')
7125 		{
7126 			int v1, v2, v3;
7127 
7128 #ifdef VERIFY_VERSION_STAMP
7129 
7130 			/* Scan for the values */
7131 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
7132 			    (v1 != ow_head->v_major) ||
7133 			    (v2 != ow_head->v_minor) ||
7134 			    (v3 != ow_head->v_patch))
7135 			{
7136 				return (2);
7137 			}
7138 
7139 #else /* VERIFY_VERSION_STAMP */
7140 
7141 			/* Scan for the values */
7142 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
7143 
7144 #endif /* VERIFY_VERSION_STAMP */
7145 
7146 			/* Okay to proceed */
7147 			okay = TRUE;
7148 
7149 			/* Continue */
7150 			continue;
7151 		}
7152 
7153 		/* No version yet */
7154 		if (!okay) return (2);
7155 
7156 
7157 		/* Process 'N' for "New/Number/Name" */
7158 		if (buf[0] == 'N')
7159 		{
7160 			/* Find the colon before the name */
7161 			s = strchr(buf + 2, ':');
7162 
7163 			/* Verify that colon */
7164 			if (!s) return (1);
7165 
7166 			/* Nuke the colon, advance to the name */
7167 			*s++ = '\0';
7168 
7169 			/* Paranoia -- require a name */
7170 			if (!*s) return (1);
7171 
7172 			/* Get the index */
7173 			i = atoi(buf + 2);
7174 
7175 			/* Verify information */
7176 			if (i < error_idx) return (4);
7177 
7178 			/* Verify information */
7179 			if (i >= (int) ow_head->info_num) return (2);
7180 
7181 			/* Save the index */
7182 			error_idx = i;
7183 
7184 			/* Point at the "info" */
7185 			ow_ptr = &ow_info[i];
7186 
7187 			/* Hack -- Verify space */
7188 			if (ow_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
7189 
7190 			/* Advance and Save the name index */
7191 			if (!ow_ptr->name) ow_ptr->name = ++ow_head->name_size;
7192 
7193 			/* Append chars to the name */
7194 			strcpy(ow_name + ow_head->name_size, s);
7195 
7196 			/* Advance the index */
7197 			ow_head->name_size += strlen(s);
7198 
7199 			/* Next... */
7200 			continue;
7201 		}
7202 
7203 		/* There better be a current ow_ptr */
7204 		if (!ow_ptr) return (3);
7205 
7206 
7207 		/* Process 'C' for "Costs" (one line only) */
7208 		if (buf[0] == 'C')
7209 		{
7210 			int ch, cn, cl;
7211 
7212 			/* Scan for the values */
7213 			if (3 != sscanf(buf + 2, "%d:%d:%d",
7214 				&ch, &cn, &cl)) return (1);
7215 
7216 			/* Save the values */
7217 			ow_ptr->costs[STORE_HATED] = ch;
7218 			ow_ptr->costs[STORE_NORMAL] = cn;
7219 			ow_ptr->costs[STORE_LIKED] = cl;
7220 
7221 			/* Next... */
7222 			continue;
7223 		}
7224 
7225 		/* Process 'I' for "Info" (multiple lines line only) */
7226 		if (buf[0] == 'I')
7227 		{
7228 			int cost, max_inf, min_inf, haggle, insult;
7229 
7230 			/* Scan for the values */
7231 			if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d",
7232 				&cost, &max_inf, &min_inf, &haggle, &insult)) return (1);
7233 
7234 			/* Save the values */
7235 //			ow_ptr->max_cost = cost;
7236 			ow_ptr->max_cost = cost * STORE_PURSE_BOOST;
7237 			ow_ptr->max_inflate = max_inf;
7238 			ow_ptr->min_inflate = min_inf;
7239 			ow_ptr->haggle_per = haggle;
7240 			ow_ptr->insult_max = insult;
7241 
7242 			/* Next... */
7243 			continue;
7244 		}
7245 
7246 		/* Process 'L' for "Liked races/classes/realms" (multiple lines) */
7247 		if (buf[0] == 'L')
7248 		{
7249 			/* Parse every entry */
7250 			for (s = buf + 2; *s; )
7251 			{
7252 				/* Find the end of this entry */
7253 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
7254 
7255 				/* Nuke and skip any dividers */
7256 				if (*t)
7257 				{
7258 					*t++ = '\0';
7259 					while (*t == ' ' || *t == '|') t++;
7260 				}
7261 
7262 				/* Parse this entry */
7263 				if (0 != grab_one_race_flag(ow_ptr, STORE_LIKED, s)) return (5);
7264 
7265 				/* Start the next entry */
7266 				s = t;
7267 			}
7268 
7269 			/* Next... */
7270 			continue;
7271 		}
7272 		/* Process 'H' for "Hated races/classes/realms" (multiple lines) */
7273 		if (buf[0] == 'H')
7274 		{
7275 			/* Parse every entry */
7276 			for (s = buf + 2; *s; )
7277 			{
7278 				/* Find the end of this entry */
7279 				for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
7280 
7281 				/* Nuke and skip any dividers */
7282 				if (*t)
7283 				{
7284 					*t++ = '\0';
7285 					while (*t == ' ' || *t == '|') t++;
7286 				}
7287 
7288 				/* Parse this entry */
7289 				if (0 != grab_one_race_flag(ow_ptr, STORE_HATED, s)) return (5);
7290 
7291 				/* Start the next entry */
7292 				s = t;
7293 			}
7294 
7295 			/* Next... */
7296 			continue;
7297 		}
7298 
7299 		/* Oops */
7300 		return (6);
7301 	}
7302 
7303 
7304 	/* Complete the "name" and "text" sizes */
7305 	++ow_head->name_size;
7306 	++ow_head->text_size;
7307 
7308 	/* No version yet */
7309 	if (!okay) return (2);
7310 
7311 	max_ow_idx = ++error_idx;
7312 
7313 	/* Success */
7314 	return (0);
7315 }
7316 
7317 
7318 /*
7319  * Initialize the "q_info" array, by parsing an ascii "template" file
7320  */
init_q_info_txt(FILE * fp,char * buf)7321 errr init_q_info_txt(FILE *fp, char *buf) {
7322 	int i, j, k, l, stage, goal, nextstage, questor;
7323 	char *s;
7324 	char codename[QI_CODENAME_LEN + 1], creator[NAME_LEN], questname[MAX_CHARS];
7325 	char tmpbuf[MAX_CHARS], *c, *cc, flagbuf[QI_FLAGS + 1], flagbuf2[QI_FLAGS + 1], tmpbuf2[MAX_CHARS];
7326 	int lc;
7327 
7328 	/* for initialising questor information with default values when reading
7329 	   a Q line without an F-line following it up (since those are optional) */
7330 	bool init_F[QI_QUESTORS];
7331 	int lc_flagsacc = 0;//compiler warning
7332 
7333 	qi_questor *q_questor;
7334 	qi_kill *q_kill;
7335 	qi_retrieve *q_ret;
7336 	qi_deliver *q_del;
7337 	qi_goal *q_goal;
7338 	qi_reward *q_rew;
7339 	qi_stage *q_stage;
7340 	qi_keyword *q_key;
7341 	qi_kwreply *q_kwr;
7342 	qi_questitem *q_qitem;
7343 	qi_feature *q_feat;
7344 	qi_questor_morph *q_qmorph;
7345 	qi_questor_hostility *q_qhost;
7346 	qi_questor_act *q_qact;
7347 	qi_monsterspawn *q_mspawn;
7348 
7349 	bool disabled;
7350 	u16b flags;
7351 
7352 	/* Not ready yet */
7353 	bool okay = FALSE;
7354 	/* Current entry */
7355 	quest_info *q_ptr = NULL;
7356 	/* Just before the first record */
7357 	error_idx = -1;
7358 	/* Just before the first line */
7359 	error_line = -1;
7360 
7361 	/* Start the "fake" stuff */
7362 	q_head->name_size = 0;
7363 	q_head->text_size = 0;
7364 
7365 	/* pre-init, to set all non-loaded quests explicitely to a 'unavailable' state,
7366 	   paranoia, since bool's init value is FALSE (aka zero) anyway. */
7367 	for (i = 0; i < MAX_Q_IDX; i++) q_info[i].defined = FALSE;
7368 
7369 	/* Parse */
7370 	while (0 == my_fgets(fp, buf, 1024, FALSE)) {
7371 		/* Advance the line number */
7372 		error_line++;
7373 
7374 		/* parse server conditions */
7375 		if (invalid_server_conditions(buf)) continue;
7376 		/* Skip comments and blank lines */
7377 		if (!buf[0] || (buf[0] == '#') || !buf[1]) continue;
7378 		/* Verify correct "colon" format */
7379 		if (buf[1] != ':' && buf[2] != ':') return (1);
7380 
7381 		/* Hack -- Process 'V' for "Version" */
7382 		if (buf[0] == 'V') {
7383 			int v1, v2, v3;
7384 
7385 #ifdef VERIFY_VERSION_STAMP
7386 			/* Scan for the values */
7387 			if ((3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) ||
7388 			    (v1 != q_head->v_major) ||
7389 			    (v2 != q_head->v_minor) ||
7390 			    (v3 != q_head->v_patch))
7391 				return (2);
7392 #else /* VERIFY_VERSION_STAMP */
7393 			/* Scan for the values */
7394 			if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
7395 #endif /* VERIFY_VERSION_STAMP */
7396 			/* Okay to proceed */
7397 			okay = TRUE;
7398 			/* Continue */
7399 			continue;
7400 		}
7401 		/* No version yet */
7402 		if (!okay) return (2);
7403 
7404 		/* Process 'N' for "New/Number/Name" */
7405 		if (buf[0] == 'N') {
7406 			/* Find the colon before the name */
7407 			s = strchr(buf + 2, ':');
7408 			/* Verify that colon */
7409 			if (!s) return (1);
7410 
7411 			/* Nuke the colon, advance to the name */
7412 			*s++ = '\0';
7413 			/* Paranoia -- require a name */
7414 			if (!*s) return (1);
7415 
7416 			/* Get the index */
7417 			i = atoi(buf + 2);
7418 			/* Verify information */
7419 			if (i < error_idx) return (4);
7420 			/* Verify information */
7421 			if (i >= (int) q_head->info_num) return (2);
7422 
7423 			/* Save the index */
7424 			error_idx = i;
7425 			/* Point at the "info" */
7426 			q_ptr = &q_info[i];
7427 			q_ptr->defined = TRUE;
7428 
7429 
7430 			/* ---------- we got a new quest entry ---------- */
7431 
7432 			/* initialise sub-structures */
7433 			q_ptr->questors = 0;
7434 			q_ptr->questor = NULL;
7435 			q_ptr->stages = 0;
7436 			q_ptr->stage = NULL;
7437 			for (j = 0; j < QI_STAGES; j++) q_ptr->stage_idx[j] = -1;
7438 			q_ptr->keywords = 0;
7439 			q_ptr->keyword = NULL;
7440 			q_ptr->kwreplies = 0;
7441 			q_ptr->kwreply = NULL;
7442 
7443 
7444 			/* Scan for the values -- careful: lenghts are hard-coded, QI_CODENAME_LEN, NAME_LEN - 1, MAX_CHARS - 1 */
7445 			if (3 > (j = sscanf(s, "%10[^:]:%19[^:]:%79[^:]:%8[^:]",
7446 			    codename, creator, questname, tmpbuf))) return (1);
7447 
7448 			if (j == 4 && tolower(tmpbuf[strlen(tmpbuf) - 1]) == 'x') disabled = TRUE;
7449 			else disabled = FALSE;
7450 
7451 			/* initialise prequest codenames */
7452 			for (k = 0; k < QI_PREREQUISITES; k++) q_ptr->prerequisites[k][0] = 0;
7453 
7454 			/* Hack -- Verify space */
7455 			if (q_head->name_size + strlen(questname) + 8 > fake_name_size) return (7);
7456 			/* Advance and Save the name index */
7457 			if (!q_ptr->name) q_ptr->name = ++q_head->name_size;
7458 			/* Append chars to the name */
7459 			strcpy(q_name + q_head->name_size, questname);
7460 			/* Advance the index */
7461 			q_head->name_size += strlen(questname);
7462 
7463 			strcpy(q_ptr->codename, codename);
7464 			strcpy(q_ptr->creator, creator);
7465 
7466 
7467 			/* ---------- initialise default values, because some flag lines/values are optional) ---------- */
7468 
7469 			/* 'I' */
7470 			q_ptr->privilege = 0;
7471 			q_ptr->individual = 1;
7472 			q_ptr->minlev = 0;
7473 			q_ptr->maxlev = 100;
7474 			/* optional parm: is quest repeatable? */
7475 			if (j == 4) {
7476 				/* hack: disable quest? */
7477 				if (disabled) {
7478 					q_ptr->active = FALSE;
7479 					q_ptr->disabled = TRUE;
7480 					s_printf("QUEST: Disabling '%s' (%d, %s)\n", q_name + q_ptr->name, error_idx, q_ptr->codename);
7481 				}
7482 				q_ptr->repeatable = atoi(tmpbuf); /* this defaults to 0 if just 'x' is specified without a number */
7483 			}
7484 			else q_ptr->repeatable = 0; /* could also default to infinitely repeatable maybe, -1 */
7485 			q_ptr->quest_done_credit_stage = 1; /* after first stage change, quest "cannot" be cancelled anymore */
7486 			q_ptr->races = 0xFFFFF;
7487 			q_ptr->classes = 0xFFFF;
7488 			q_ptr->mode_norm = TRUE;
7489 			q_ptr->mode_el = TRUE;
7490 			q_ptr->mode_pvp = FALSE; /* by default, pvp chars cannot do quests */
7491 			q_ptr->must_be_fruitbat = 0;
7492 			q_ptr->must_be_monster = 0;
7493 
7494 			/* 'U' */
7495 			q_ptr->ending_stage = 0;
7496 			q_ptr->cooldown = 0;
7497 
7498 			/* 'T' */
7499 			q_ptr->night = q_ptr->day = TRUE;
7500 			q_ptr->morning = q_ptr->forenoon = q_ptr->noon = q_ptr->afternoon = TRUE;
7501 			q_ptr->evening = q_ptr->midnight = q_ptr->deepnight = TRUE;
7502 			q_ptr->time_start = q_ptr->time_stop = -1;
7503 
7504 			q_ptr->flags = 0x0000; //no reason
7505 
7506 			/* init 'F' check */
7507 			for (j = 0; j < QI_QUESTORS; j++) init_F[j] = FALSE;
7508 			lc_flagsacc = 0;
7509 
7510 			continue;
7511 		}
7512 
7513 		/* There better be a current q_ptr */
7514 		if (!q_ptr) return (3);
7515 
7516 		/* Process 'C' for list of stages (usually stage 0) that allow players to acquire the quest */
7517 		if (buf[0] == 'C') {
7518 			s = buf + 2;
7519 			/* read list of numbers, separated by colons */
7520 			while (*s >= '0' && *s <= '9') {
7521 				j = atoi(s);
7522 				if (j < 0 || j >= QI_STAGES) return 1;
7523 
7524 				q_stage = init_quest_stage(error_idx, j);
7525 				q_stage->accepts = TRUE;
7526 
7527 				if (!(s = strchr(s, ':'))) break;
7528 				s++;
7529 				while (*s == ' ') s++; /* paranoia for comfort ^^ */
7530 			}
7531 			continue;
7532 		}
7533 
7534 		/* Process 'I' for player restrictions */
7535 		if (buf[0] == 'I') {
7536 			char races[6], classes[5];
7537 			int priv, indiv, minlev, maxlev, qdcs;
7538 			int mode_norm, mode_el, mode_pvp, must_bat, must_form;
7539 
7540 			s = buf + 2;
7541 			if (12 != sscanf(s, "%d:%d:%d:%d:%5[^:]:%4[^:]:%d:%d:%d:%d:%d:%d",
7542 			    &priv, &indiv, &minlev, &maxlev, races, classes,
7543 			    &mode_norm, &mode_el, &mode_pvp, &must_bat, &must_form,
7544 			    &qdcs))
7545 				return (1);
7546 
7547 			q_ptr->privilege = priv;
7548 			q_ptr->individual = indiv;
7549 			q_ptr->minlev = minlev;
7550 			q_ptr->maxlev = maxlev;
7551 			q_ptr->quest_done_credit_stage = qdcs;
7552 			q_ptr->races = strtol(races, NULL, 16);
7553 			q_ptr->classes = strtol(classes, NULL, 16);
7554 			/* modes/body */
7555 			q_ptr->mode_norm = (mode_norm != 0);
7556 			q_ptr->mode_el = (mode_el != 0);
7557 			q_ptr->mode_pvp = (mode_pvp != 0);
7558 			q_ptr->must_be_fruitbat = must_bat;
7559 			q_ptr->must_be_monster = must_form;
7560 			continue;
7561 		}
7562 
7563 		/* Process 'E' for list of prequests required to begin this quest */
7564 		if (buf[0] == 'E') {
7565 			s = buf + 2;
7566 			sscanf(s, "%10[^:]:%10[^:]:%10[^:]:%10[^:]:%10[^:]", //QI_CODENAME_LEN hard-coded!
7567 			    q_ptr->prerequisites[0], q_ptr->prerequisites[1], q_ptr->prerequisites[2], q_ptr->prerequisites[3], q_ptr->prerequisites[4]);
7568 			continue;
7569 		}
7570 
7571 		/* Process 'T' for quest starting times */
7572 		if (buf[0] == 'T') {
7573 			int night, day, mor, fnoo, noo, aft, eve, mid, dee, tstart, tstop;
7574 
7575 			s = buf + 2;
7576 			if (11 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
7577 			    &night, &day, &mor, &fnoo, &noo, &aft, &eve, &mid, &dee, &tstart, &tstop)) return (1);
7578 
7579 			q_ptr->night = (night != 0);
7580 			q_ptr->day = (day != 0);
7581 			q_ptr->morning = (mor != 0);
7582 			q_ptr->forenoon = (fnoo != 0);
7583 			q_ptr->noon = (noo != 0);
7584 			q_ptr->afternoon = (aft != 0);
7585 			q_ptr->evening = (eve != 0);
7586 			q_ptr->midnight = (mid != 0);
7587 			q_ptr->deepnight = (dee != 0);
7588 			q_ptr->time_start = tstart;
7589 			q_ptr->time_stop = tstop;
7590 			continue;
7591 		}
7592 
7593 		/* Process 'U' for quest duration */
7594 		if (buf[0] == 'U') {
7595 			int es, cd;
7596 
7597 			s = buf + 2;
7598 			if (3 != sscanf(s, "%d:%d:%d",
7599 			    &es, &q_ptr->max_duration, &cd)) return (1);
7600 
7601 			q_ptr->ending_stage = es;
7602 			q_ptr->cooldown = (s16b) cd;
7603 			continue;
7604 		}
7605 
7606 		//--------------------------------------------------------------------------------------------
7607 		/* Process 'Q' for questor (creature) type */
7608 		if (buf[0] == 'Q') {
7609 			int q, ridx, minlv, maxlv, tval, sval;
7610 			char ch, attr;
7611 			int good, great, vgreat;
7612 			int pval, bpval, name1, name2, name2b;
7613 
7614 			/* find out questor type first */
7615 			s = buf + 2;
7616 			q = atoi(s);
7617 
7618 			lc = q_ptr->questors;
7619 			if (lc >= QI_QUESTORS) return 1;
7620 			q_questor = init_quest_questor(error_idx, lc);
7621 
7622 			switch (q) {
7623 			case QI_QUESTOR_NPC:
7624 				if (7 != sscanf(s, "%d:%d:%c:%c:%d:%d:%[^:]",
7625 				    &q, &ridx, &ch, &attr, &minlv, &maxlv,
7626 				    tmpbuf)) return (1);
7627 				q_questor->type = q;
7628 				q_questor->ridx = ridx;
7629 				q_questor->rchar = ch;
7630 				q_questor->rattr = color_char_to_attr(attr);
7631 				q_questor->rlevmin = minlv;
7632 				q_questor->rlevmax = maxlv;
7633 				strcpy(q_questor->name, tmpbuf);
7634 				break;
7635 			case QI_QUESTOR_PARCHMENT:
7636 				if (5 != sscanf(s, "%d:%d:%c:%d:%[^:]",
7637 				    &q, &sval, &attr,
7638 				    &minlv, tmpbuf)) return (1);
7639 				q_questor->type = q;
7640 				q_questor->psval = sval;
7641 				q_questor->rattr = color_char_to_attr(attr);
7642 				q_questor->plev = minlv;
7643 				strcpy(q_questor->name, tmpbuf);
7644 				break;
7645 			case QI_QUESTOR_ITEM_PICKUP:
7646 				if (14 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%c:%d:%[^:]",
7647 				    &q, &tval, &sval, &pval, &bpval, &name1, &name2, &name2b,
7648 				    &good, &great, &vgreat, &attr, &minlv, tmpbuf)) return (1);
7649 				q_questor->type = q;
7650 				q_questor->otval = tval;
7651 				q_questor->osval = sval;
7652 				q_questor->opval = pval;
7653 				q_questor->obpval = bpval;
7654 				q_questor->oname1 = name1;
7655 				q_questor->oname2 = name2;
7656 				q_questor->oname2b = name2b;
7657 				q_questor->ogood = good;
7658 				q_questor->ogreat = great;
7659 				q_questor->overygreat = vgreat;
7660 				q_questor->oattr = color_char_to_attr(attr);
7661 				q_questor->olev = minlv;
7662 				strcpy(q_questor->name, tmpbuf);
7663 				break;
7664 			default:
7665 				return 1;
7666 			}
7667 
7668 			/* init defaults for optional line 'F' */
7669 			if (!init_F[lc]) {
7670 				q_questor->accept_los = FALSE;
7671 				q_questor->accept_interact = TRUE;
7672 				q_questor->talkable = TRUE;
7673 				q_questor->despawned = FALSE;
7674 				q_questor->invincible = TRUE;
7675 			}
7676 			continue;
7677 		}
7678 
7679 		/* Process 'K' for questor drops/exp if it is killable and player manages to kill it */
7680 		if (buf[0] == 'K') {
7681 			int d, dtv, dsv, dpv, dbpv, dn1, dn2, dn2b, dg, dgr, dvgr, dcr, au, exp;
7682 			s = buf + 2;
7683 			if (14 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
7684 			    &d, &dtv, &dsv, &dpv, &dbpv, &dn1, &dn2, &dn2b, &dg, &dgr, &dvgr, &dcr, &au, &exp)) return (1);
7685 
7686 			lc = q_ptr->questors;
7687 			if (!lc) return 1; /* so a K-line must always follow somewhere after its Q line */
7688 			q_questor = init_quest_questor(error_idx, lc - 1); /* pick the newest, already existing one */
7689 
7690 			q_questor->drops = d;
7691 			q_questor->drops_tval = dtv;
7692 			q_questor->drops_sval = dsv;
7693 			q_questor->drops_pval = dpv;
7694 			q_questor->drops_bpval = dbpv;
7695 			q_questor->drops_name1 = dn1;
7696 			q_questor->drops_name2 = dn2;
7697 			q_questor->drops_name2b = dn2b;
7698 			q_questor->drops_good = (dg != 0);
7699 			q_questor->drops_great = (dgr != 0);
7700 			q_questor->drops_vgreat = (dvgr != 0);
7701 			q_questor->drops_reward = dcr;
7702 			q_questor->drops_gold = au;
7703 			q_questor->exp = exp;
7704 			continue;
7705 		}
7706 
7707 		/* Process 'L' for questor starting location type */
7708 		if (buf[0] == 'L') {
7709 			/* we have 2 sub-types of 'D' lines */
7710 			if (buf[1] == ':') { /* init */
7711 				int loc, wx, wy, wz, terr, sx, sy, rad, tpx, tpy;
7712 				u16b towns;
7713 				u32b terrtype;
7714 
7715 				s = buf + 2;
7716 				if (13 != sscanf(s, "%d:%u:%hu:%d:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d", //byte, u16b, u32b
7717 				    &loc, &terrtype, &towns, &wx, &wy, &wz, &terr, &sx, &sy, &rad, tmpbuf, &tpx, &tpy)) return (1);
7718 
7719 				lc = q_ptr->questors;
7720 				if (!lc) return 1; /* so an L-line must always follow somewhere after its Q line */
7721 				q_questor = init_quest_questor(error_idx, lc - 1); /* pick the newest, already existing one */
7722 
7723 				q_questor->q_loc.s_location_type = (byte)loc;
7724 				q_questor->q_loc.s_terrains = terrtype;
7725 				q_questor->q_loc.s_towns_array = towns;
7726 				q_questor->q_loc.start_wpos.wx = (char)wx;
7727 				q_questor->q_loc.start_wpos.wy = (char)wy;
7728 				q_questor->q_loc.start_wpos.wz = (char)wz;
7729 				q_questor->q_loc.terrain_patch = (terr != 0);
7730 				q_questor->q_loc.start_x = sx;
7731 				q_questor->q_loc.start_y = sy;
7732 				q_questor->q_loc.radius = rad;
7733 
7734 				q_questor->q_loc.tpref = NULL;
7735 				if (tmpbuf[0] != '-') {
7736 					c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
7737 					strcpy(c, tmpbuf);
7738 					q_questor->q_loc.tpref = c;
7739 					q_questor->q_loc.tpref_x = tpx;
7740 					q_questor->q_loc.tpref_y = tpy;
7741 				}
7742 				continue;
7743 			} else if (buf[1] == 'd') { /* dungeons */
7744 				int lmin, lmax;
7745 				s = buf + 3;
7746 
7747 				if (2 > sscanf(s, "%d:%d", &lmin, &lmax)) return (1);
7748 
7749 				lc = q_ptr->questors;
7750 				if (!lc) return 1; /* so an L-line must always follow somewhere after its Q line */
7751 				q_questor = init_quest_questor(error_idx, lc - 1); /* pick the newest, already existing one */
7752 
7753 				q_questor->q_loc.dlevmin = lmin;
7754 				q_questor->q_loc.dlevmax = lmax;
7755 
7756 				/* advance to 3rd parm, which is where the list of dungeon indices starts */
7757 				s = strchr(s, ':') + 1;
7758 				s = strchr(s, ':');
7759 				if (!s) return 1;
7760 				s++;
7761 
7762 				q_questor->q_loc.s_dungeons = 0;
7763 				/* read list of numbers, separated by colons */
7764 				while (*s >= '0' && *s <= '9') {
7765 					if (q_questor->q_loc.s_dungeons == MAX_D_IDX) return 1;
7766 
7767 					j = atoi(s);
7768 					if (j < 0 || j > 255) return 1;
7769 
7770 					q_questor->q_loc.s_dungeon[q_questor->q_loc.s_dungeons] = j;
7771 					q_questor->q_loc.s_dungeons++;
7772 
7773 					if (!(s = strchr(s, ':'))) break;
7774 					s++;
7775 					while (*s == ' ') s++; /* paranoia for comfort ^^ */
7776 				}
7777 				continue;
7778 			}
7779 			return 1;
7780 		}
7781 
7782 		/* Process 'F' for questor accept/spawn flags */
7783 		if (buf[0] == 'F') {
7784 			int aalos, aaint, talk, despawn, invinc;
7785 
7786 			if (lc_flagsacc == QI_QUESTORS) return 1;
7787 			if (lc_flagsacc >= q_ptr->questors) return 1; /* each 'F' line must succed somewhere after its 'Q' line */
7788 			q_questor = init_quest_questor(error_idx, lc_flagsacc);
7789 			s = buf + 2;
7790 
7791 			if (5 != sscanf(s, "%d:%d:%d:%d:%d",
7792 			    &aalos, &aaint, &talk, &despawn, &invinc)) return (1);
7793 			q_questor->accept_los = (aalos != 0);
7794 			q_questor->accept_interact = (aaint != 0);
7795 			q_questor->talkable = (talk != 0);
7796 			q_questor->despawned = (despawn != 0);
7797 			q_questor->invincible = (invinc != 0);
7798 
7799 			init_F[lc_flagsacc] = TRUE;
7800 			lc_flagsacc++;
7801 			continue;
7802 		}
7803 		//--------------------------------------------------------------------------------------------
7804 
7805 		/* Process 'D' for dungeon/tower to spawn for this quest */
7806 		if (buf[0] == 'D') {
7807 			/* we have 2 sub-types of 'D' lines */
7808 			if (buf[1] == ':') { /* init */
7809 				int base, max, tow, hard, stor, theme, stat, keep, tx, ty;
7810 				u32b flags1, flags2, flags3;
7811 
7812 				s = buf + 2;
7813 				if (13 > (j = sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d:%u:%u:%u:%79[^:]:%d:%d",
7814 				    &stage, &base, &max, &tow, &hard, &stor, &theme, tmpbuf2, &stat, &keep, &flags1, &flags2, &flags3, tmpbuf, &tx, &ty)))
7815 					return (1);
7816 
7817 				if (stage < 0 || stage >= QI_STAGES) return 1;
7818 				q_stage = init_quest_stage(error_idx, stage);
7819 
7820 				q_stage->dun_base = base;
7821 				q_stage->dun_max = max;
7822 				q_stage->dun_tower = (tow != 0);
7823 				q_stage->dun_hard = hard;
7824 				q_stage->dun_stores = stor;
7825 				q_stage->dun_theme = theme;
7826 				if (tmpbuf2[0] != '-') {
7827 					c = (char*)malloc((strlen(tmpbuf2) + 1) * sizeof(char));
7828 					strcpy(c, tmpbuf2);
7829 					q_stage->dun_name = c;
7830 				}
7831 				q_stage->dun_static = (stat != 0);
7832 				q_stage->dun_keep = (keep != 0);
7833 				q_stage->dun_flags1 = flags1;
7834 				q_stage->dun_flags2 = flags2;
7835 				q_stage->dun_flags3 = flags3;
7836 				if (j >= 14) {
7837 					q_stage->dun_final_tpref = NULL;
7838 					if (tmpbuf[0] != '-') {
7839 						c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
7840 						strcpy(c, tmpbuf);
7841 						q_stage->dun_final_tpref = c;
7842 						if (j >= 15) {
7843 							q_stage->dun_final_tpref_x = tx;
7844 							q_stage->dun_final_tpref_y = ty;
7845 						} else {
7846 							q_stage->dun_final_tpref_x = 0;
7847 							q_stage->dun_final_tpref_y = 0;
7848 						}
7849 					}
7850 				}
7851 				continue;
7852 			} else if (buf[1] == 'l') { /* location */
7853 				int loc, towns, wx, wy, terr, sx, sy, rad, tpx, tpy;
7854 				u32b terrtype;
7855 
7856 				s = buf + 3;
7857 				if (13 != sscanf(s, "%d:%d:%d:%u:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d",
7858 				    &stage, &loc, &terrtype, &towns, &wx, &wy, &terr, &sx, &sy, &rad, tmpbuf, &tpx, &tpy)) return (1);
7859 
7860 				if (stage < 0 || stage >= QI_STAGES) return 1;
7861 				q_stage = init_quest_stage(error_idx, stage);
7862 
7863 				q_stage->dun_loc.s_location_type = (byte)loc;
7864 				q_stage->dun_loc.s_terrains = terrtype;
7865 				q_stage->dun_loc.s_towns_array = (u16b)towns;
7866 				q_stage->dun_loc.start_wpos.wx = (char)wx;
7867 				q_stage->dun_loc.start_wpos.wy = (char)wy;
7868 				q_stage->dun_loc.start_wpos.wz = 0;
7869 				q_stage->dun_loc.terrain_patch = (terr != 0);
7870 				q_stage->dun_loc.start_x = sx;
7871 				q_stage->dun_loc.start_y = sy;
7872 				q_stage->dun_loc.radius = rad;
7873 
7874 				q_stage->dun_loc.tpref = NULL;
7875 				if (tmpbuf[0] != '-') {
7876 					c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
7877 					strcpy(c, tmpbuf);
7878 					q_stage->dun_loc.tpref = c;
7879 					q_stage->dun_loc.tpref_x = tpx;
7880 					q_stage->dun_loc.tpref_y = tpy;
7881 				}
7882 				continue;
7883 			}
7884 			return 1;
7885 		}
7886 
7887 		/* Process 'm' for monster spawning for this quest */
7888 		if (buf[0] == 'm') {
7889 			/* we have 3 sub-types of 'm' lines */
7890 			if (buf[1] == ':') { /* init */
7891 				int amt, grp, scat, clo, ridx, lvmin, lvmax;
7892 				char rchar, rattr;
7893 
7894 				s = buf + 2;
7895 				if (11 > (j = sscanf(s, "%d:%d:%d:%d:%d:%d:%c:%c:%d:%d%79[^:]",
7896 				    &stage, &amt, &grp, &scat, &clo, &ridx, &rchar, &rattr, &lvmin, &lvmax, tmpbuf)))
7897 					return (1);
7898 
7899 				if (stage < 0 || stage >= QI_STAGES) return 1;
7900 				q_stage = init_quest_stage(error_idx, stage);
7901 				if (q_stage->mspawns >= QI_STAGE_AUTO_MSPAWNS) return 1;
7902 				q_mspawn = init_quest_monsterspawn(error_idx, stage, q_stage->mspawns);
7903 
7904 				q_mspawn->amount = amt;
7905 				q_mspawn->groups = (grp != 0);
7906 				q_mspawn->scatter = (scat != 0);
7907 				q_mspawn->clones = clo;
7908 				q_mspawn->ridx = ridx;
7909 				q_mspawn->rchar = rchar == '-' ? 255 : rchar;
7910 				q_mspawn->rattr = rattr == '-' ? 255 : color_char_to_attr(rattr);
7911 				q_mspawn->rlevmin = lvmin;
7912 				q_mspawn->rlevmax = lvmax;
7913 				if (tmpbuf[0] != '-') {
7914 					c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
7915 					strcpy(c, tmpbuf);
7916 					q_mspawn->name = c;
7917 				}
7918 				continue;
7919 			} else if (buf[1] == 'l') { /* location */
7920 				int loc, towns, wx, wy, terr, sx, sy, rad, tpx, tpy;
7921 				u32b terrtype;
7922 
7923 				s = buf + 3;
7924 				if (13 != sscanf(s, "%d:%d:%d:%u:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d",
7925 				    &stage, &loc, &terrtype, &towns, &wx, &wy, &terr, &sx, &sy, &rad, tmpbuf, &tpx, &tpy)) return (1);
7926 
7927 				if (stage < 0 || stage >= QI_STAGES) return 1;
7928 				q_stage = init_quest_stage(error_idx, stage);
7929 				lc = q_stage->mspawns;
7930 				if (!lc) return 1;
7931 				q_mspawn = &q_stage->mspawn[lc - 1]; /* grab latest one */
7932 
7933 				q_mspawn->loc.s_location_type = (byte)loc;
7934 				q_mspawn->loc.s_terrains = terrtype;
7935 				q_mspawn->loc.s_towns_array = (u16b)towns;
7936 				q_mspawn->loc.start_wpos.wx = (char)wx;
7937 				q_mspawn->loc.start_wpos.wy = (char)wy;
7938 				q_mspawn->loc.start_wpos.wz = 0;
7939 				q_mspawn->loc.terrain_patch = (terr != 0);
7940 				q_mspawn->loc.start_x = sx;
7941 				q_mspawn->loc.start_y = sy;
7942 				q_mspawn->loc.radius = rad;
7943 
7944 				q_mspawn->loc.tpref = NULL;
7945 				if (tmpbuf[0] != '-') {
7946 					c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
7947 					strcpy(c, tmpbuf);
7948 					q_mspawn->loc.tpref = c;
7949 					q_mspawn->loc.tpref_x = tpx;
7950 					q_mspawn->loc.tpref_y = tpy;
7951 				}
7952 				continue;
7953 			} else if (buf[1] == 'h') { /* hostility details */
7954 				int hostp, hostq, invincp, invincq, targetp, targetq;
7955 
7956 				s = buf + 3;
7957 				if (7 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d",
7958 				    &stage, &hostp, &hostq, &invincp, &invincq, &targetp, &targetq)) return (1);
7959 
7960 				if (stage < 0 || stage >= QI_STAGES) return 1;
7961 				q_stage = init_quest_stage(error_idx, stage);
7962 				lc = q_stage->mspawns;
7963 				if (!lc) return 1;
7964 				q_mspawn = &q_stage->mspawn[lc - 1]; /* grab latest one */
7965 
7966 				q_mspawn->hostile_player = (hostp != 0);
7967 				q_mspawn->hostile_questor = (hostq != 0);
7968 				q_mspawn->invincible_player = (invincp != 0);
7969 				q_mspawn->invincible_questor = (invincq != 0);
7970 				q_mspawn->target_player = (targetp != 0);
7971 				q_mspawn->target_questor = (targetq != 0);
7972 				continue;
7973 			}
7974 			return 1;
7975 		}
7976 
7977 		/* Process 'A' for automatic things in a stage: spawn new quest, (timed) stage changes, quiet change (no dialogue)? */
7978 		if (buf[0] == 'A') {
7979 			/* we have 2 sub-types of 'A' lines */
7980 			if (buf[1] == ':') { /* init */
7981 				int aq, aa, cs, tsi, tsia, tsr, qcs, genox, genoy, genoz;
7982 
7983 				s = buf + 2;
7984 				if (12 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%16[^:]:%d:%d:%d",
7985 				    &stage, &aq, &aa, &cs, &tsi, &tsia, &tsr, &qcs, flagbuf, &genox, &genoy, &genoz)) return (1);
7986 				if (stage < 0 || stage >= QI_STAGES) return 1;
7987 				q_stage = init_quest_stage(error_idx, stage);
7988 
7989 				q_stage->activate_quest = aq;
7990 				q_stage->auto_accept = (aa != 0);
7991 				q_stage->auto_accept_quiet = (aq == 2);
7992 
7993 				q_stage->change_stage = cs;
7994 #if 0
7995 				q_stage->timed_ingame = tsi;
7996 #else /* kill compiler -_- */
7997 				k = tsi;
7998 #endif
7999 				q_stage->timed_ingame_abs = tsia;
8000 				q_stage->timed_real = tsr;
8001 				q_stage->quiet_change = (qcs != 0);
8002 
8003 				cc = flagbuf;
8004 				if (*cc == '-') *cc = 0;
8005 				while (*cc) {
8006 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) {
8007 						q_stage->setflags |= (0x1 << (*cc - 'A')); /* set flag */
8008 					} else if (*cc >= 'a' && *cc < 'a' + QI_FLAGS) {
8009 						q_stage->clearflags |= (0x1 << (*cc - 'a')); /* clear flag */
8010 					} else return 1;
8011 					cc++;
8012 				}
8013 
8014 				q_stage->geno_wpos.wx = genox;
8015 				q_stage->geno_wpos.wy = genoy;
8016 				q_stage->geno_wpos.wz = genoz;
8017 
8018 				/* important hack: initialise the target stage!
8019 				   This is done to fill that stage with default values,
8020 				   which are important when the quest actually enters that stage,
8021 				   even -or especially if- it is just an empty, final stage.
8022 				   For example it would call activate_quest >:). */
8023 				if (cs != 255) {
8024 					if (cs >= 0) {
8025 						if (cs >= QI_STAGES) return 1;
8026 						(void)init_quest_stage(error_idx, cs);
8027 					} else {
8028 						if (stage - cs >= QI_STAGES) return 1;
8029 						for (i = stage + 1; i <= stage - cs; i++)
8030 							(void)init_quest_stage(error_idx, i);
8031 					}
8032 				}
8033 				continue;
8034 			} else if (buf[1] == 'f') {
8035 				int qwpos, qiwpos, wx, wy, wz, x, y, feat;
8036 
8037 				s = buf + 3;
8038 				if (9 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d",
8039 				    &stage, &qwpos, &qiwpos, &wx, &wy, &wz, &x, &y, &feat)) return (1);
8040 				if (stage < 0 || stage >= QI_STAGES) return 1;
8041 				q_stage = init_quest_stage(error_idx, stage);
8042 				q_feat = init_quest_feature(error_idx, stage, q_stage->feats); /* pop up a new one */
8043 
8044 				q_feat->wpos_questor = qwpos;
8045 				q_feat->wpos_questitem = qiwpos;
8046 				q_feat->wpos.wx = wx;
8047 				q_feat->wpos.wy = wy;
8048 				q_feat->wpos.wz = wz;
8049 				q_feat->x = x;
8050 				q_feat->y = y;
8051 				q_feat->feat = feat;
8052 				continue;
8053 			}
8054 			return -1;
8055 		}
8056 
8057 		/* Process 'S' for questor changes/polymorphing/hostility */
8058 		if (buf[0] == 'S') {
8059 			int q, talk, despawn, invinc, dfail, ridx, lev;
8060 			char rchar, rattr;
8061 
8062 			s = buf + 2;
8063 			if (11 != sscanf(s, "%d:%d:%d:%d:%d:%d:%79[^:]:%d:%c:%c:%d",
8064 			    &stage, &q, &talk, &despawn, &invinc, &dfail, tmpbuf, &ridx, &rchar, &rattr, &lev)) return (1);
8065 
8066 			if (stage < 0 || stage >= QI_STAGES) return 1;
8067 			if (q < 0 || q > q_ptr->questors) return 1;
8068 			q_qmorph = init_quest_qmorph(error_idx, stage, questor);
8069 			q_qmorph->talkable = (talk != 0);
8070 			q_qmorph->despawned = (despawn != 0);
8071 			q_qmorph->invincible = (invinc != 0);
8072 			q_qmorph->death_fail = dfail;
8073 			if (strcmp(tmpbuf, "-")) {
8074 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8075 				strcpy(c, tmpbuf);
8076 				q_qmorph->name = c;
8077 			}
8078 			if (ridx) q_qmorph->ridx = ridx;
8079 			if (rchar == '-') q_qmorph->rchar = 255; /* keep */
8080 			else q_qmorph->rchar = rchar;
8081 			if (rattr == '-') q_qmorph->rattr = 255; /* keep */
8082 			else q_qmorph->rattr = color_char_to_attr(rattr);
8083 			q_qmorph->rlev = lev;
8084 			continue;
8085 		}
8086 
8087 		/* Process 'H' for questor hostility changes? (or just use S-line for this too) */
8088 		if (buf[0] == 'H') {
8089 			int q, unq, hp, hm, hrhp, hrtia, hrtr, cs, qcs;
8090 
8091 			s = buf + 2;
8092 			if (10 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
8093 			    &stage, &q, &unq, &hp, &hm, &hrhp, &hrtia, &hrtr, &cs, &qcs)) return (1);
8094 
8095 			if (stage < 0 || stage >= QI_STAGES) return 1;
8096 			if (q < 0 || q > q_ptr->questors) return 1;
8097 			q_qhost = init_quest_qhostility(error_idx, stage, questor);
8098 			q_qhost->unquestor = (unq != 0);
8099 			q_qhost->hostile_player = (hp != 0);
8100 			q_qhost->hostile_monster = (hm != 0);
8101 			q_qhost->hostile_revert_hp = hrhp;
8102 			q_qhost->hostile_revert_timed_ingame_abs = hrtia;
8103 			q_qhost->hostile_revert_timed_real = hrtr;
8104 			q_qhost->change_stage = cs;
8105 			q_qhost->quiet_change = (qcs != 0);
8106 
8107 			/* important hack: initialise the target stage!
8108 			   This is done to fill that stage with default values,
8109 			   which are important when the quest actually enters that stage,
8110 			   even -or especially if- it is just an empty, final stage.
8111 			   For example it would call activate_quest >:). */
8112 			if (cs != 255) {
8113 				if (cs >= 0) {
8114 					if (cs >= QI_STAGES) return 1;
8115 					(void)init_quest_stage(error_idx, cs);
8116 				} else {
8117 					if (stage - cs >= QI_STAGES) return 1;
8118 					for (i = stage + 1; i <= stage - cs; i++)
8119 						(void)init_quest_stage(error_idx, i);
8120 				}
8121 			}
8122 			continue;
8123 		}
8124 
8125 		/* Process 'J' for questor movement/teleportation/teleplayer */
8126 		if (buf[0] == 'J') {
8127 			int q, tpwx, tpwy, tpwz, tpx, tpy, tppywx, tppywy, tppywz, tppyx, tppyy, spd, x, y, cs, qcs;
8128 
8129 			s = buf + 2;
8130 			if (17 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
8131 			    &stage, &q, &tpwx, &tpwy, &tpwz, &tpx, &tpy, &tppywx, &tppywy, &tppywz, &tppyx, &tppyy, &spd, &x, &y, &cs, &qcs)) return (1);
8132 
8133 			if (stage < 0 || stage >= QI_STAGES) return 1;
8134 			if (q < 0 || q > q_ptr->questors) return 1;
8135 			q_qact = init_quest_qact(error_idx, stage, questor);
8136 
8137 			q_qact->tp_wpos.wx = tpwx;
8138 			q_qact->tp_wpos.wx = tpwy;
8139 			q_qact->tp_wpos.wx = tpwz;
8140 			q_qact->tp_x = tpx;
8141 			q_qact->tp_y = tpy;
8142 			q_qact->tppy_wpos.wx = tppywx;
8143 			q_qact->tppy_wpos.wx = tppywy;
8144 			q_qact->tppy_wpos.wx = tppywz;
8145 			q_qact->tppy_x = tppyx;
8146 			q_qact->tppy_y = tppyy;
8147 			q_qact->walk_speed = spd;
8148 			q_qact->walk_destx = x;
8149 			q_qact->walk_desty = y;
8150 			q_qact->change_stage = cs;
8151 			q_qact->quiet_change = (qcs != 0);
8152 
8153 			/* important hack: initialise the target stage!
8154 			   This is done to fill that stage with default values,
8155 			   which are important when the quest actually enters that stage,
8156 			   even -or especially if- it is just an empty, final stage.
8157 			   For example it would call activate_quest >:). */
8158 			if (cs != 255) {
8159 				if (cs >= 0) {
8160 					if (cs >= QI_STAGES) return 1;
8161 					(void)init_quest_stage(error_idx, cs);
8162 				} else {
8163 					if (stage - cs >= QI_STAGES) return 1;
8164 					for (i = stage + 1; i <= stage - cs; i++)
8165 						(void)init_quest_stage(error_idx, i);
8166 				}
8167 			}
8168 			continue;
8169 		}
8170 
8171 		/* Process 'X' for narrative text */
8172 		if (buf[0] == 'X') {
8173 			s = buf + 2;
8174 			if (3 != sscanf(s, "%d:%16[^:]:%79[^:]",//QI_FLAGS
8175 			    &stage, flagbuf, tmpbuf)) return (1);
8176 
8177 			if (stage < 0 || stage >= QI_STAGES) return 1;
8178 			q_stage = init_quest_stage(error_idx, stage);
8179 			if ((lc = q_stage->narration_lines) == QI_TALK_LINES) return 1;
8180 
8181 			c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8182 			strcpy(c, tmpbuf);
8183 			q_stage->narration[lc] = c;
8184 
8185 			cc = flagbuf;
8186 			if (*cc == '-') *cc = 0;
8187 			while (*cc) {
8188 				if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) { /* flags that must be set to display this convo line */
8189 					q_stage->narration_flags[lc] |= (0x1 << (*cc - 'A')); /* set flag */
8190 				} else return 1;
8191 				cc++;
8192 			}
8193 
8194 			q_stage->narration_lines++;
8195 			continue;
8196 		}
8197 
8198 		/* Process 'W' for conversation */
8199 		if (buf[0] == 'W') {
8200 			/* we have 2 sub-types of 'X' lines */
8201 			if (buf[1] == ':') { /* init */
8202 				int examine;
8203 
8204 				s = buf + 2;
8205 				C_WIPE(flagbuf, QI_FLAGS + 1, byte);
8206 
8207 				j = sscanf(s, "%d:%d:%d:%16[^:]:%79[^:]",//QI_FLAGS
8208 				    &questor, &stage, &examine, flagbuf, tmpbuf);
8209 				if (j != 5 && !(j == 3 && stage == -1)) return 1;
8210 
8211 				if (questor < 0 || questor >= QI_QUESTORS) return 1;
8212 				if (stage < 0 || stage >= QI_STAGES) return 1;
8213 				q_stage = init_quest_stage(error_idx, stage);
8214 
8215 				/* hack: examine = -stage => use previous stage */
8216 				if (examine < 0) {
8217 					if (-examine >= QI_STAGES) return 1;
8218 					q_stage->talk_examine[questor] = 1 - examine;
8219 					/* make sure it is initialised (to avoid paranoia and panic) */
8220 					(void)init_quest_stage(error_idx, -examine);
8221 					continue;
8222 				}
8223 
8224 				lc = q_stage->talk_lines[questor];
8225 				if (lc == QI_TALK_LINES) return 1;
8226 
8227 #if 0 /* allow full colour codes */
8228 				/* replace '{' by \377 */
8229 				while ((cc = strchr(tmpbuf, '{'))) *cc = '\377';
8230 #else /* just allow highlighting */
8231 				while ((cc = strstr(tmpbuf, "[["))) { *cc = '\377'; *(cc + 1) = 'y'; }
8232 				while ((cc = strstr(tmpbuf, "]]"))) { *cc = '\377'; *(cc + 1) = '-'; }
8233 #endif
8234 
8235 				q_stage->talk[questor] = (cptr*)realloc(q_stage->talk[questor], sizeof(cptr*) * (lc + 1));
8236 				q_stage->talk_flags[questor] = (u16b*)realloc(q_stage->talk_flags[questor], sizeof(u16b*) * (lc + 1));
8237 				q_stage->talk_flags[questor][lc] = 0x0000;//init newly realloc'ed mem
8238 
8239 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8240 				strcpy(c, tmpbuf);
8241 				q_stage->talk[questor][lc] = c;
8242 
8243 				cc = flagbuf;
8244 				if (*cc == '-') *cc = 0;
8245 				while (*cc) {
8246 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) { /* flags that must be set to display this convo line */
8247 						q_stage->talk_flags[questor][lc] |= (0x1 << (*cc - 'A')); /* set flag */
8248 					} else return 1;
8249 					cc++;
8250 				}
8251 
8252 				q_stage->talk_examine[questor] = examine;
8253 
8254 				q_stage->talk_lines[questor]++;
8255 				continue;
8256 			} else if (buf[1] == 'r') {
8257 				s = buf + 3;
8258 
8259 				if (3 != sscanf(s, "%d:%d:%79[^:]",
8260 				    &questor, &stage, tmpbuf)) return (1);
8261 
8262 				if (questor < 0 || questor >= QI_QUESTORS) return 1;
8263 				if (stage < 0 || stage >= QI_STAGES) return 1;
8264 				q_stage = init_quest_stage(error_idx, stage);
8265 
8266 #if 0 /* allow full colour codes */
8267 				/* replace '{' by \377 */
8268 				while ((cc = strchr(tmpbuf, '{'))) *cc = '\377';
8269 #else /* just allow highlighting */
8270 				while ((cc = strstr(tmpbuf, "[["))) { *cc = '\377'; *(cc + 1) = 'y'; }
8271 				while ((cc = strstr(tmpbuf, "]]"))) { *cc = '\377'; *(cc + 1) = '-'; }
8272 #endif
8273 
8274 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8275 				strcpy(c, tmpbuf);
8276 				q_stage->default_reply[questor] = c;
8277 				continue;
8278 			}
8279 		}
8280 
8281 		/* Process 'Y' for conversation keywords */
8282 		if (buf[0] == 'Y') {
8283 			/* we have 3 sub-types of 'Y' lines */
8284 			if (buf[1] == ':') { /* init */
8285 				s = buf + 2;
8286 				if (6 != sscanf(s, "%d:%d:%16[^:]:%29[^:]:%16[^:]:%d", //QI_FLAGS,QI_KEYWORD_LEN
8287 				    &questor, &stage, flagbuf, tmpbuf, flagbuf2, &nextstage)) return (1);
8288 
8289 				/* "-1" stands for 'all' */
8290 				if (questor < -1 || questor >= QI_QUESTORS) return 1;
8291 				if (stage < -1 || stage >= QI_STAGES) return 1;
8292 //				if (nextstage == stage) return 1; /* disallow reflexive stage changes for now */
8293 
8294 				lc = q_ptr->keywords;
8295 				if (lc >= QI_KEYWORDS) return 1;
8296 				q_key = init_quest_keyword(error_idx, lc);
8297 
8298 				/* hack: '~' denotes the empty keyword (since scanf cannot handle empty matches..) */
8299 				if (!strcmp(tmpbuf, "~")) tmpbuf[0] = 0;
8300 				strcpy(q_key->keyword, tmpbuf);
8301 				if (questor != -1) q_key->questor_ok[questor] = TRUE;
8302 				else for (i = 0; i < QI_QUESTORS; i++) q_key->questor_ok[i] = TRUE;
8303 				if (stage != -1) q_key->stage_ok[stage] = TRUE;
8304 				else {
8305 					q_key->any_stage = TRUE;
8306 					for (i = 0; i < QI_STAGES; i++) q_key->stage_ok[i] = TRUE;
8307 				}
8308 				q_key->stage = nextstage;
8309 
8310 				cc = flagbuf;
8311 				if (*cc == '-') *cc = 0;
8312 				while (*cc) {
8313 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) { /* flags that must be set to display this convo line */
8314 						q_key->flags |= (0x1 << (*cc - 'A')); /* set flag */
8315 					} else return 1;
8316 					cc++;
8317 				}
8318 				cc = flagbuf2;
8319 				if (*cc == '-') *cc = 0;
8320 				while (*cc) {
8321 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) {
8322 						q_key->setflags |= (0x1 << (*cc - 'A')); /* set flag */
8323 					} else if (*cc >= 'a' && *cc < 'a' + QI_FLAGS) {
8324 						q_key->clearflags |= (0x1 << (*cc - 'a')); /* clear flag */
8325 					} else return 1;
8326 					cc++;
8327 				}
8328 
8329 				/* important hack: initialise the keyword's target stage!
8330 				   This is done to fill that stage with default values,
8331 				   which are important when the quest actually enters that stage,
8332 				   even -or especially if- it is just an empty, final stage.
8333 				   For example it would call activate_quest >:). */
8334 				if (nextstage != 255) {
8335 					if (nextstage >= 0) {
8336 						if (nextstage >= QI_STAGES) return 1;
8337 						(void)init_quest_stage(error_idx, nextstage);
8338 					} else {
8339 						if (stage - nextstage >= QI_STAGES) return 1;
8340 						for (i = stage + 1; i <= stage - nextstage; i++)
8341 							(void)init_quest_stage(error_idx, i);
8342 					}
8343 				}
8344 				continue;
8345 			} else if (buf[1] == 'Q') { /* add more questors to the list */
8346 				s = buf + 3;
8347 
8348 				lc = q_ptr->keywords;
8349 				if (!lc) return 1;
8350 				q_key = init_quest_keyword(error_idx, lc - 1); /* use newest one */
8351 
8352 				/* read list of numbers, separated by colons */
8353 				while (*s >= '0' && *s <= '9') {
8354 					j = atoi(s);
8355 					if (j < 0 || j >= QI_QUESTORS) return 1;
8356 
8357 					q_key->questor_ok[j] = TRUE;
8358 
8359 					if (!(s = strchr(s, ':'))) break;
8360 					s++;
8361 					while (*s == ' ') s++; /* paranoia for comfort ^^ */
8362 				}
8363 				continue;
8364 			} else if (buf[1] == 'S') { /* add more stages to the list */
8365 				s = buf + 3;
8366 
8367 				lc = q_ptr->keywords;
8368 				if (!lc) return 1;
8369 				q_key = init_quest_keyword(error_idx, lc - 1); /* use newest one */
8370 
8371 				/* read list of numbers, separated by colons */
8372 				while (*s >= '0' && *s <= '9') {
8373 					j = atoi(s);
8374 					if (j < 0 || j >= QI_STAGES) return 1;
8375 
8376 					q_key->stage_ok[j] = TRUE;
8377 
8378 					if (!(s = strchr(s, ':'))) break;
8379 					s++;
8380 					while (*s == ' ') s++; /* paranoia for comfort ^^ */
8381 				}
8382 				continue;
8383 			}
8384 			return 1;
8385 		}
8386 
8387 		/* Process 'y' for replies to keywords (depending on flags) */
8388 		if (buf[0] == 'y') {
8389 			/* we have 5 sub-types of 'y' lines */
8390 			if (buf[1] == ':') { /* init */
8391 				s = buf + 2;
8392 				if (4 != sscanf(s, "%d:%d:%16[^:]:%29[^:]", //QI_FLAGS,QI_KEYWORD_LEN
8393 				    &questor, &stage, flagbuf, tmpbuf2)) return (1);
8394 
8395 				/* "-1" stands for 'all' */
8396 				if (questor < -1 || questor >= QI_QUESTORS) return 1;
8397 				if (stage < -1 || stage >= QI_STAGES) return 1;
8398 
8399 				lc = q_ptr->kwreplies;
8400 				if (lc >= QI_KEYWORD_REPLIES) return 1;
8401 				q_kwr = init_quest_kwreply(error_idx, lc);
8402 
8403 				/* find out the keyword's index */
8404 				for (i = 0; i < q_ptr->keywords; i++) {
8405 					if (!strcmp(q_ptr->keyword[i].keyword, tmpbuf2)) break;
8406 				}
8407 				/* keyword not found -> error */
8408 				if (i == q_ptr->keywords) return 1;
8409 
8410 				q_kwr->keyword_idx[0] = i;
8411 				if (questor != -1) q_kwr->questor_ok[questor] = TRUE;
8412 				else for (i = 0; i < QI_QUESTORS; i++) q_kwr->questor_ok[i] = TRUE;
8413 				if (stage != -1) q_kwr->stage_ok[stage] = TRUE;
8414 				else for (i = 0; i < QI_STAGES; i++) q_kwr->stage_ok[i] = TRUE;
8415 
8416 				cc = flagbuf;
8417 				if (*cc == '-') *cc = 0;
8418 				flags = 0x0000;
8419 				while (*cc) {
8420 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) { /* flags that must be set to display this convo line */
8421 						flags |= (0x1 << (*cc - 'A')); /* set flag */
8422 					} else return 1;
8423 					cc++;
8424 				}
8425 				q_kwr->flags = flags;
8426 				continue;
8427 			} else if (buf[1] == 'Y') { /* add more keywords to the list */
8428 				s = buf + 3;
8429 
8430 				lc = q_ptr->kwreplies;
8431 				if (!lc) return 1;
8432 				q_kwr = init_quest_kwreply(error_idx, lc - 1); /* use newest one */
8433 
8434 				/* read list of strings, separated by colons */
8435 				k = 1; //counter
8436 				while (*s && k < QI_KEYWORDS_PER_REPLY) {
8437 					i = 0; //strlen
8438 					tmpbuf[0] = 0;
8439 					while (i < 29 && *s && *s != ':')//QI_KEYWORD_LEN
8440 						tmpbuf[i++] = *s++;
8441 					tmpbuf[29] = 0;
8442 
8443 					for (j = 0; j < q_ptr->keywords; j++)
8444 						if (!strcmp(q_ptr->keyword[j].keyword, tmpbuf))
8445 							q_kwr->keyword_idx[k] = j;
8446 					k++;
8447 
8448 					if (*s) s++;
8449 				}
8450 				continue;
8451 			} else if (buf[1] == 'Q') { /* add more questors to the list */
8452 				s = buf + 3;
8453 
8454 				lc = q_ptr->kwreplies;
8455 				if (!lc) return 1;
8456 				q_kwr = init_quest_kwreply(error_idx, lc - 1); /* use newest one */
8457 
8458 				/* read list of numbers, separated by colons */
8459 				while (*s >= '0' && *s <= '9') {
8460 					j = atoi(s);
8461 					if (j < 0 || j >= QI_QUESTORS) return 1;
8462 
8463 					q_kwr->questor_ok[j] = TRUE;
8464 
8465 					if (!(s = strchr(s, ':'))) break;
8466 					s++;
8467 					while (*s == ' ') s++; /* paranoia for comfort ^^ */
8468 				}
8469 				continue;
8470 			} else if (buf[1] == 'S') { /* add more stages to the list */
8471 				s = buf + 3;
8472 
8473 				lc = q_ptr->kwreplies;
8474 				if (!lc) return 1;
8475 				q_kwr = init_quest_kwreply(error_idx, lc - 1); /* use newest one */
8476 
8477 				/* read list of numbers, separated by colons */
8478 				while (*s >= '0' && *s <= '9') {
8479 					j = atoi(s);
8480 					if (j < 0 || j >= QI_STAGES) return 1;
8481 
8482 					q_kwr->stage_ok[j] = TRUE;
8483 
8484 					if (!(s = strchr(s, ':'))) break;
8485 					s++;
8486 					while (*s == ' ') s++; /* paranoia for comfort ^^ */
8487 				}
8488 				continue;
8489 			} else if (buf[1] == 'R') { /* actual reply lines */
8490 				s = buf + 3;
8491 				if (2 != sscanf(s, "%16[^:]:%79[^:]", //QI_FLAGS
8492 				    flagbuf, tmpbuf)) return (1);
8493 
8494 				lc = q_ptr->kwreplies;
8495 				if (!lc) return 1;
8496 				q_kwr = init_quest_kwreply(error_idx, lc - 1); /* use newest one */
8497 
8498 				if (q_kwr->lines == QI_TALK_LINES) return 1;
8499 
8500 #if 0 /* allow full colour codes */
8501 				/* replace '{' by \377 */
8502 				while ((cc = strchr(tmpbuf, '{'))) *cc = '\377';
8503 #else /* just allow highlighting */
8504 				while ((cc = strstr(tmpbuf, "[["))) { *cc = '\377'; *(cc + 1) = 'y'; }
8505 				while ((cc = strstr(tmpbuf, "]]"))) { *cc = '\377'; *(cc + 1) = '-'; }
8506 #endif
8507 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8508 				strcpy(c, tmpbuf);
8509 				q_kwr->reply[q_kwr->lines] = c;
8510 
8511 				cc = flagbuf;
8512 				if (*cc == '-') *cc = 0;
8513 				flags = 0x0000;
8514 				while (*cc) {
8515 					if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) { /* flags that must be set to display this convo line */
8516 						flags |= (0x1 << (*cc - 'A')); /* set flag */
8517 					} else return 1;
8518 					cc++;
8519 				}
8520 				q_kwr->replyflags[q_kwr->lines] = flags;
8521 
8522 				q_kwr->lines++;
8523 				continue;
8524 			}
8525 			return 1;
8526 		}
8527 
8528 		/* Process 'k' for kill quest goal */
8529 		if (buf[0] == 'k') {
8530 			/* now we have 4 sub-types of 'k' lines -_- uhh */
8531 			if (buf[1] == ':') { /* init */
8532 				int minlev, maxlev, num;
8533 				s = buf + 2;
8534 				if (5 != sscanf(s, "%d:%d:%d:%d:%d",
8535 				    &stage, &goal, &minlev, &maxlev, &num))
8536 					return (1);
8537 
8538 				if (stage < 0 || stage >= QI_STAGES) return 1;
8539 				if (ABS(goal) > QI_GOALS) return 1;
8540 				q_kill = init_quest_kill(error_idx, stage, goal);
8541 				q_kill->rlevmin = minlev;
8542 				q_kill->rlevmax = maxlev;
8543 				q_kill->number = num;
8544 				continue;
8545 			} else if (buf[1] == 'I') { /* specify race-indices */
8546 				int ridx[10];
8547 
8548 				s = buf + 3;
8549 				if (3 > (k = sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
8550 				    &stage, &goal, &ridx[0], &ridx[1], &ridx[2], &ridx[3], &ridx[4], &ridx[5], &ridx[6], &ridx[7], &ridx[8], &ridx[9])))
8551 					return (1);
8552 				k = k - 2;
8553 
8554 				if (stage < 0 || stage >= QI_STAGES) return 1;
8555 				if (ABS(goal) > QI_GOALS) return 1;
8556 				q_kill = init_quest_kill(error_idx, stage, goal);
8557 				for (j = 0; j < k; j++) q_kill->ridx[j] = ridx[j];
8558 				/* disable the unused criteria */
8559 				for (j = k; j < 10; j++) q_kill->ridx[j] = 0;
8560 				continue;
8561 			} else if (buf[1] == 'V') { /* specify visuals */
8562 				char rchar[5], rattr[5];
8563 				s = buf + 3;
8564 				if (4 > (k = sscanf(s, "%d:%d:%c:%c:%c:%c:%c:%c:%c:%c:%c:%c",
8565 				    &stage, &goal, &rchar[0], &rattr[0], &rchar[1], &rattr[1], &rchar[2], &rattr[2], &rchar[3], &rattr[3], &rchar[4], &rattr[4])))
8566 					return (1);
8567 				k = (k - 2) / 2;
8568 
8569 				if (stage < 0 || stage >= QI_STAGES) return 1;
8570 				if (ABS(goal) > QI_GOALS) return 1;
8571 				q_kill = init_quest_kill(error_idx, stage, goal);
8572 				for (j = 0; j < k; j++) {
8573 					if (rchar[j] == '-') rchar[j] = 254; /* any */
8574 					q_kill->rchar[j] = rchar[j];
8575 
8576 					if (rattr[j] == '-') q_kill->rattr[j] = 254; /* any */
8577 					else q_kill->rattr[j] = color_char_to_attr(rattr[j]);
8578 				}
8579 				/* disable the unused criteria */
8580 				for (j = k; j < 5; j++) {
8581 					q_kill->rchar[j] = 255;
8582 					q_kill->rattr[j] = 255;
8583 				}
8584 				continue;
8585 			} else if (buf[1] == 'N') { /* partial name */
8586 				s = buf + 3;
8587 				if (2 > sscanf(s, "%d:%d", &stage, &goal)) return (1);
8588 
8589 				if (stage < 0 || stage >= QI_STAGES) return 1;
8590 				if (ABS(goal) > QI_GOALS) return 1;
8591 				q_kill = init_quest_kill(error_idx, stage, goal);
8592 
8593 				/* read list of partial names, separated by colons */
8594 				j = 0;
8595 				while (*s && j < 5) {
8596 					c = strchr(s, ':');
8597 					if (!c) c = s + strlen(s);
8598 					else c++;
8599 					s[strlen(s)] = 0;
8600 
8601 					cc = (char*)malloc((strlen(s) + 1) * sizeof(char));
8602 					strcpy(cc, s);
8603 					q_kill->name[j] = cc;
8604 
8605 					s = c;
8606 					j++;
8607 				}
8608 				continue;
8609 			}
8610 			return -1;
8611 		}
8612 
8613 		/* Process 'r' for retrieve quest goal */
8614 		if (buf[0] == 'r') {
8615 			/* now we have 4 sub-types of 'r' lines too =P */
8616 			if (buf[1] == ':') { /* init */
8617 				int minval, num, owok;
8618 
8619 				s = buf + 2;
8620 				if (5 != sscanf(s, "%d:%d:%d:%d:%d",
8621 				    &stage, &goal, &minval, &num, &owok))
8622 					return (1);
8623 
8624 				if (stage < 0 || stage >= QI_STAGES) return 1;
8625 				if (ABS(goal) > QI_GOALS) return 1;
8626 				q_ret = init_quest_retrieve(error_idx, stage, goal);
8627 				q_ret->ovalue = minval;
8628 				q_ret->number = num;
8629 				q_ret->allow_owned = (owok != 0);
8630 				continue;
8631 			} else if (buf[1] == 'I') { /* specify race-indices */
8632 				int tval[10], sval[10];
8633 
8634 				s = buf + 3;
8635 				if (4 > (k = sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
8636 				    &stage, &goal,
8637 				    &tval[0], &sval[0], &tval[1], &sval[1], &tval[2], &sval[2], &tval[3], &sval[3], &tval[4], &sval[4],
8638 				    &tval[5], &sval[5], &tval[6], &sval[6], &tval[7], &sval[7], &tval[8], &sval[8], &tval[9], &sval[9])))
8639 					return (1);
8640 				k = (k - 2) / 2;
8641 
8642 				if (stage < 0 || stage >= QI_STAGES) return 1;
8643 				if (ABS(goal) > QI_GOALS) return 1;
8644 				q_ret = init_quest_retrieve(error_idx, stage, goal);
8645 				for (j = 0; j < k; j++) {
8646 					q_ret->otval[j] = tval[j];
8647 					q_ret->osval[j] = sval[j];
8648 				}
8649 				/* disable the unused criteria */
8650 				for (j = k; j < 10; j++) {
8651 					q_ret->otval[j] = 0;
8652 					q_ret->osval[j] = 0;
8653 				}
8654 				continue;
8655 			} else if (buf[1] == 'V') { /* specify visuals */
8656 				int pval[5], bpval[5], name1[5], name2[5], name2b[5], j;
8657 				char attr[5];
8658 
8659 				s = buf + 3;
8660 				if (8 > (k = sscanf(s, "%d:%d:%d:%d:%c:%d:%d:%d:%d:%d:%c:%d:%d:%d:%d:%d:%c:%d:%d:%d:%d:%d:%c:%d:%d:%d:%d:%d:%c:%d:%d:%d",
8661 				    &stage, &goal,
8662 				    &pval[0], &bpval[0], &attr[0], &name1[0], &name2[0], &name2b[0],
8663 				    &pval[1], &bpval[1], &attr[1], &name1[1], &name2[1], &name2b[1],
8664 				    &pval[2], &bpval[2], &attr[2], &name1[2], &name2[2], &name2b[2],
8665 				    &pval[3], &bpval[3], &attr[3], &name1[3], &name2[3], &name2b[3],
8666 				    &pval[4], &bpval[4], &attr[4], &name1[4], &name2[4], &name2b[4])))
8667 					return (1);
8668 				k = (k - 2) / 6;
8669 
8670 				if (stage < 0 || stage >= QI_STAGES) return 1;
8671 				if (ABS(goal) > QI_GOALS) return 1;
8672 				q_ret = init_quest_retrieve(error_idx, stage, goal);
8673 				for (j = 0; j < k; j++) {
8674 					q_ret->opval[j] = pval[j];
8675 					q_ret->obpval[j] = bpval[j];
8676 					if (attr[j] == '-') q_ret->oattr[j] = 254; /* any */
8677 					else q_ret->oattr[j] = color_char_to_attr(attr[j]);
8678 					q_ret->oname1[j] = name1[j];
8679 					q_ret->oname2[j] = name2[j];
8680 					q_ret->oname2b[j] = name2b[j];
8681 				}
8682 				/* disable the unused criteria */
8683 				for (j = k; j < 5; j++) {
8684 					q_ret->opval[j] = 9999;
8685 					q_ret->obpval[j] = 9999;
8686 					q_ret->oattr[j] = 255;
8687 					q_ret->oname1[j] = -3;
8688 					q_ret->oname2[j] = -3;
8689 					q_ret->oname2b[j] = -3;
8690 				}
8691 				continue;
8692 			} else if (buf[1] == 'N') { /* partial name */
8693 				s = buf + 3;
8694 				if (2 > sscanf(s, "%d:%d", &stage, &goal)) return (1);
8695 
8696 				if (stage < 0 || stage >= QI_STAGES) return 1;
8697 				if (ABS(goal) > QI_GOALS) return 1;
8698 				q_ret = init_quest_retrieve(error_idx, stage, goal);
8699 
8700 				/* read list of partial names, separated by colons */
8701 				j = 0;
8702 				while (*s && j < 5) {
8703 					c = strchr(s, ':');
8704 					if (!c) c = s + strlen(s);
8705 					else c++;
8706 					s[strlen(s)] = 0;
8707 
8708 					cc = (char*)malloc((strlen(s) + 1) * sizeof(char));
8709 					strcpy(cc, s);
8710 					q_ret->name[j] = cc;
8711 
8712 					s = c;
8713 					j++;
8714 				}
8715 				continue;
8716 			}
8717 			return -1;
8718 		}
8719 
8720 		/* Process 'P' for position at which a kill/retrieve quest has to be executed */
8721 		if (buf[0] == 'P') {
8722 			int wx, wy, wz, terr, x, y, rad, tpx, tpy;
8723 
8724 			s = buf + 2;
8725 			if (12 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d",
8726 			    &stage, &goal, &wx, &wy, &wz, &terr, &x, &y, &rad, tmpbuf, &tpx, &tpy)) return (1);
8727 
8728 			if (stage < 0 || stage >= QI_STAGES) return 1;
8729 			q_stage = init_quest_stage(error_idx, stage);
8730 			if (ABS(goal) > QI_GOALS) return 1;
8731 			q_goal = init_quest_goal(error_idx, stage, goal);
8732 			q_goal->target_pos = TRUE;
8733 			q_goal->target_wpos.wx = (char)wx;
8734 			q_goal->target_wpos.wy = (char)wy;
8735 			q_goal->target_wpos.wz = (char)wz;
8736 			q_goal->target_terrain_patch = (terr != 0);
8737 			q_goal->target_pos_x = x;
8738 			q_goal->target_pos_y = y;
8739 			q_goal->target_pos_radius = rad;
8740 
8741 			if (tmpbuf[0] == '-') q_goal->target_tpref = NULL;
8742 			else {
8743 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8744 				strcpy(c, tmpbuf);
8745 				q_goal->target_tpref = c;
8746 				q_goal->target_tpref_x = tpx;
8747 				q_goal->target_tpref_y = tpy;
8748 			}
8749 			continue;
8750 		}
8751 
8752 		/* Process 'M' for move-to-location to finish a quest stage whose goals have already been fulfilled */
8753 		if (buf[0] == 'M') {
8754 			int tq, wx, wy, wz, x, y, terr, rad, tpx, tpy;
8755 
8756 			s = buf + 2;
8757 			if (13 != sscanf(s, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d",
8758 			    &stage, &goal, &tq, &wx, &wy, &wz, &terr, &x, &y, &rad, tmpbuf, &tpx, &tpy)) return (1);
8759 
8760 			if (stage < 0 || stage >= QI_STAGES) return 1;
8761 			if (ABS(goal) > QI_GOALS) return 1;
8762 			q_del = init_quest_deliver(error_idx, stage, goal);
8763 			q_del->return_to_questor = tq == -1 ? 255 : tq;
8764 			q_del->wpos.wx = (char)wx;
8765 			q_del->wpos.wy = (char)wy;
8766 			q_del->wpos.wz = (char)wz;
8767 			q_del->terrain_patch = (terr != 0);
8768 			q_del->pos_x = x;
8769 			q_del->pos_y = y;
8770 			q_del->radius = rad;
8771 
8772 			if (tmpbuf[0] == '-') q_del->tpref = NULL;
8773 			else {
8774 				c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8775 				strcpy(c, tmpbuf);
8776 				q_del->tpref = c;
8777 				q_del->tpref_x = tpx;
8778 				q_del->tpref_y = tpy;
8779 			}
8780 			continue;
8781 		}
8782 
8783 		/* Process 'B' to spawn a custom quest item somewhere */
8784 		if (buf[0] == 'B') {
8785 			/* we have 2 sub-types of 'B' lines */
8786 			if (buf[1] == ':') { /* init, object feats */
8787 				int pval, lev, wgt;
8788 				char ochar, oattr;
8789 
8790 				s = buf + 2;
8791 				if (7 != sscanf(s, "%d:%d:%c:%c:%d:%d:%79[^:]",
8792 				    &stage, &pval, &ochar, &oattr, &wgt, &lev, tmpbuf))
8793 					return (1);
8794 
8795 				if (stage < 0 || stage >= QI_STAGES) return 1;
8796 				q_stage = init_quest_stage(error_idx, stage);
8797 				q_qitem = init_quest_questitem(error_idx, stage, q_stage->qitems); /* pop up a new one */
8798 
8799 				q_qitem->opval = pval;
8800 				q_qitem->ochar = ochar;
8801 				q_qitem->oattr = color_char_to_attr(oattr);
8802 				q_qitem->oweight = wgt;
8803 				q_qitem->olev = lev;
8804 				strcpy(q_qitem->name, tmpbuf);
8805 				continue;
8806 			} else if (buf[1] == 'l') { /* location */
8807 				int q, loc, towns, wx, wy, wz, terr, sx, sy, rad, tpx, tpy;
8808 				u32b terrtype;
8809 
8810 				s = buf + 3;
8811 				if (15 != sscanf(s, "%d:%d:%d:%d:%u:%d:%d:%d:%d:%d:%d:%d:%79[^:]:%d:%d",
8812 				    &stage, &q, &loc, &terrtype, &towns, &wx, &wy, &wz, &terr, &sx, &sy, &rad, tmpbuf, &tpx, &tpy)) return (1);
8813 
8814 				if (stage < 0 || stage >= QI_STAGES) return 1;
8815 				q_stage = init_quest_stage(error_idx, stage);
8816 
8817 				lc = q_stage->qitems;
8818 				if (!lc) return 1; /* so an Bl-line must always follow somewhere after its B line */
8819 				q_qitem = init_quest_questitem(error_idx, stage, lc - 1); /* pick the newest, already existing one */
8820 
8821 				q_qitem->questor_gives = (q == -1 ? 255 : q);
8822 				q_qitem->q_loc.s_location_type = (byte)loc;
8823 				q_qitem->q_loc.s_terrains = terrtype;
8824 				q_qitem->q_loc.s_towns_array = (u16b)towns;
8825 				q_qitem->q_loc.start_wpos.wx = (char)wx;
8826 				q_qitem->q_loc.start_wpos.wy = (char)wy;
8827 				q_qitem->q_loc.start_wpos.wz = (char)wz;
8828 				q_qitem->q_loc.terrain_patch = (terr != 0);
8829 				q_qitem->q_loc.start_x = sx;
8830 				q_qitem->q_loc.start_y = sy;
8831 				q_qitem->q_loc.radius = rad;
8832 
8833 				q_qitem->q_loc.tpref = NULL;
8834 				if (tmpbuf[0] != '-') {
8835 					c = (char*)malloc((strlen(tmpbuf) + 1) * sizeof(char));
8836 					strcpy(c, tmpbuf);
8837 					q_qitem->q_loc.tpref = c;
8838 					q_qitem->q_loc.tpref_x = tpx;
8839 					q_qitem->q_loc.tpref_y = tpy;
8840 				}
8841 				continue;
8842 			}
8843 		}
8844 
8845 		/* Process 'Z' for how completed stage goals will change 'quest flags' */
8846 		if (buf[0] == 'Z') {
8847 			s = buf + 2;
8848 			if (3 != sscanf(s, "%d:%d:%16[^:]", &stage, &goal, flagbuf)) return (1);
8849 
8850 			if (stage < 0 || stage >= QI_STAGES) return 1;
8851 			if (ABS(goal) > QI_GOALS) return 1;
8852 			q_goal = init_quest_goal(error_idx, stage, goal);
8853 
8854 			cc = flagbuf;
8855 			if (*cc == '-') *cc = 0;
8856 			while (*cc) {
8857 				if (*cc >= 'A' && *cc < 'A' + QI_FLAGS) {
8858 					q_goal->setflags |= (0x1 << (*cc - 'A')); /* set flag */
8859 				} else if (*cc >= 'a' && *cc < 'a' + QI_FLAGS) {
8860 					q_goal->clearflags |= (0x1 << (*cc - 'a')); /* clear flag */
8861 				} else return 1;
8862 				cc++;
8863 			}
8864 			continue;
8865 		}
8866 
8867 		/* Process 'G', which goal combinations (up to QI_STAGE_GOALS different goals per combination) are
8868 		   required to advance to which stage (up to QI_FOLLOWUP_STAGES different ones, each has a goal-combo) */
8869 		if (buf[0] == 'G') {
8870 			/* first number is the stage, second the next stage */
8871 			stage = atoi(buf + 2);
8872 			if (stage < 0 || stage >= QI_STAGES) return 1;
8873 
8874 			q_stage = init_quest_stage(error_idx, stage);
8875 
8876 			if (!(c = strchr(buf + 2, ':'))) return 1;
8877 			c++;
8878 			nextstage = atoi(c);
8879 			if (!(c = strchr(c, ':'))) return 1;
8880 			c++;
8881 
8882 //			if (nextstage == stage) return 1; /* disallow reflexive stage changes for now */
8883 
8884 
8885 			/* already defined the max amount of different QI_FOLLOWUP_STAGES? */
8886 			for (k = 0; k < QI_FOLLOWUP_STAGES; k++) {
8887 				/* reusing a stage we've already found? */
8888 				if (q_stage->next_stage_from_goals[k] == nextstage) break;
8889 				/* found a free follow-up stage to use? */
8890 				if (q_stage->next_stage_from_goals[k] == 255) {
8891 					q_stage->next_stage_from_goals[k] = nextstage;
8892 					break;
8893 				}
8894 			}
8895 			if (k == QI_FOLLOWUP_STAGES) return -1; /* out of space */
8896 
8897 			/* read list of numbers, separated by colons */
8898 			l = 0;
8899 			while (*c >= '0' && *c <= '9' && l < QI_STAGE_GOALS) {
8900 				j = atoi(c);
8901 				if (j < 1 || j > QI_GOALS) return 1; /* no optional goals allowed */
8902 				q_stage->goals_for_stage[k][l] = j - 1;
8903 
8904 				if (!(c = strchr(c, ':'))) break;
8905 				c++;
8906 				while (*c == ' ') c++; /* paranoia for comfort ^^ */
8907 
8908 				l++;
8909 			}
8910 
8911 			/* important hack: initialise the target stage!
8912 			   This is done to fill that stage with default values,
8913 			   which are important when the quest actually enters that stage,
8914 			   even -or especially if- it is just an empty, final stage.
8915 			   For example it would call activate_quest >:). */
8916 			if (nextstage >= 0) {
8917 				if (nextstage >= QI_STAGES) return 1;
8918 				(void)init_quest_stage(error_idx, nextstage);
8919 			} else {
8920 				if (stage - nextstage >= QI_STAGES) return 1;
8921 				for (i = stage + 1; i <= stage - nextstage; i++)
8922 					(void)init_quest_stage(error_idx, i);
8923 			}
8924 			continue;
8925 		}
8926 
8927 		/* Process 'O', which main+optional goal combinations (up to QI_REWARD_GOALS different goals per combination) are
8928 		   required to obtain a reward (up to QI_STAGE_REWARDS different ones, each has a goal-combo).
8929 		   If this line is omitted, all rewards are handed out 'for free' in this stage. */
8930 		if (buf[0] == 'O') {
8931 			int reward;
8932 
8933 			/* first number is the stage, second the reward */
8934 			stage = atoi(buf + 2);
8935 			if (stage < 0 || stage >= QI_STAGES) return -1;
8936 			q_stage = quest_qi_stage(error_idx, stage);
8937 
8938 			if (!(c = strchr(buf + 2, ':'))) return 1;
8939 			c++;
8940 			reward = atoi(c);
8941 			if (reward >= QI_STAGE_REWARDS) return -1; /* out of space */
8942 
8943 			if (!(c = strchr(c, ':'))) return 1;
8944 			c++;
8945 
8946 			/* read list of numbers, separated by colons */
8947 			l = 0;
8948 			while (*c >= '0' && *c <= '9' && l < QI_REWARD_GOALS) {
8949 				j = atoi(c);
8950 				if (ABS(j) > QI_GOALS) return 1;
8951 				(void)init_quest_goal(error_idx, stage, j);
8952 				q_stage->goals_for_reward[reward][l] = ABS(j) - 1;
8953 
8954 				if (!(c = strchr(c, ':'))) break;
8955 				c++;
8956 				while (*c == ' ') c++; /* paranoia for comfort ^^ */
8957 
8958 				l++;
8959 			}
8960 			continue;
8961 		}
8962 
8963 		/* Process 'R', quest reward definitions */
8964 		if (buf[0] == 'R') {
8965 			int good, great, vgreat, createreward, rstatus;
8966 			int otval, osval, opval, obpval, oname1, oname2, oname2b;
8967 
8968 			/* first number is the stage */
8969 			s = buf + 2;
8970 			stage = atoi(s);
8971 			if (stage < 0 || stage >= QI_STAGES) return -1;
8972 			q_stage = init_quest_stage(error_idx, stage);
8973 
8974 			if ((lc = q_stage->rewards) == QI_STAGE_REWARDS) return 1;
8975 			q_rew = init_quest_reward(error_idx, stage, lc);
8976 
8977 			if (!(c = strchr(s, ':'))) return 1;
8978 			c++;
8979 
8980 			if (14 != sscanf(c, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
8981 			    &otval, &osval, &opval, &obpval, &oname1, &oname2, &oname2b,
8982 			    &good, &great, &vgreat, &createreward,
8983 			    &q_rew->gold, &q_rew->exp, &rstatus))
8984 				return (1);
8985 
8986 			q_rew->otval = otval;
8987 			q_rew->osval = osval;
8988 			q_rew->opval = opval;
8989 			q_rew->obpval = obpval;
8990 			q_rew->oname1 = oname1;
8991 			q_rew->oname2 = oname2;
8992 			q_rew->oname2b = oname2b;
8993 			q_rew->ogood = (good != 0);
8994 			q_rew->ogreat = (great != 0);
8995 			q_rew->ovgreat = (vgreat != 0);
8996 			q_rew->oreward = createreward;
8997 			q_rew->statuseffect = rstatus;
8998 			continue;
8999 		}
9000 
9001 		/* Oops */
9002 		return (6);
9003 	}
9004 
9005 	/* Complete the "name" and "text" sizes */
9006 	++q_head->name_size;
9007 	++q_head->text_size;
9008 
9009 	/* No version yet */
9010 	if (!okay) return (2);
9011 
9012 	/* Hack -- acquire total number */
9013 	max_q_idx = ++error_idx;
9014 
9015 #if DEBUG_LEVEL > 2
9016 	/* Debug -- print total no. */
9017 	s_printf("q_info total: %d\n", max_q_idx);
9018 #endif	// DEBUG_LEVEL
9019 
9020 	/* Success */
9021 	return (0);
9022 }
9023 
9024 
9025 
9026 #else	/* ALLOW_TEMPLATES */
9027 
9028 #ifdef MACINTOSH
9029 static int i = 0;
9030 #endif
9031 
9032 #endif	/* ALLOW_TEMPLATES */
9033 
9034 
9035 /*
9036  * Another big lump of ToME parts, for loading maps/quests
9037  * Most part is undone yet, but at least it can read town definition files.
9038  * - Jir -
9039  */
9040 
9041 /* Random dungeon grid effects */
9042 #define RANDOM_NONE         0x00
9043 #define RANDOM_FEATURE      0x01
9044 #define RANDOM_MONSTER      0x02
9045 #define RANDOM_OBJECT       0x04
9046 #define RANDOM_EGO          0x08
9047 #define RANDOM_ARTIFACT     0x10
9048 #define RANDOM_TRAP         0x20
9049 
9050 
9051 typedef struct dungeon_grid dungeon_grid;
9052 
9053 struct dungeon_grid
9054 {
9055 	int		feature;		/* Terrain feature */
9056 	int		monster;		/* Monster */
9057 	int		object;			/* Object */
9058 	int		ego;			/* Ego-Item */
9059 	int		artifact;		/* Artifact */
9060 	int		trap;			/* Trap */
9061 	int		cave_info;		/* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
9062 	int		special;		/* Reserved for special terrain info */
9063 	int		random;			/* Number of the random effect */
9064 	int             bx, by;                 /* For between gates */
9065 	int             mimic;                  /* Mimiced features */
9066 	bool            ok;
9067 	bool            defined;
9068 };
9069 static bool meta_sleep = TRUE;
9070 
9071 static dungeon_grid letter[255];
9072 
9073 /*
9074  * Parse a sub-file of the "extra info"
9075  */
9076 bool process_dungeon_file_full = FALSE;
9077 //static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalstart, int ymax, int xmax)
process_dungeon_file_aux(char * buf,worldpos * wpos,int * yval,int * xval,int xvalstart,int ymax,int xmax)9078 static errr process_dungeon_file_aux(char *buf, worldpos *wpos, int *yval, int *xval, int xvalstart, int ymax, int xmax) {
9079 	int i;
9080 	char *zz[33]; /* was 33 */
9081 
9082 	int dun_level = getlevel(wpos);
9083 	c_special *cs_ptr;
9084 	cave_type **zcave;
9085 	zcave = getcave(wpos);
9086 
9087 	if (!zcave) return (-1);	/* maybe SIGSEGV soon anyway */
9088 
9089 	/* Skip "empty" lines */
9090 	if (!buf[0]) return (0);
9091 	/* Skip "blank" lines */
9092 	if (isspace(buf[0])) return (0);
9093 	/* Skip comments */
9094 	if (buf[0] == '#') return (0);
9095 	/* Require "?:*" format */
9096 	if (buf[1] != ':') return (1);
9097 
9098 	/* Process "%:<fname>" */
9099 	if (buf[0] == '%') {
9100 		/* Attempt to Process the given file */
9101 		return (process_dungeon_file(buf + 2, wpos, yval, xval, ymax, xmax, FALSE));
9102 	}
9103 
9104 	/* Process "N:<sleep>" */
9105 	if (buf[0] == 'N') {
9106 		int num;
9107 
9108 		if ((num = tokenize(buf + 2, 1, zz, ':', '/')) > 0)
9109 			meta_sleep = atoi(zz[0]);
9110 
9111 		return (0);
9112 	}
9113 
9114 	/* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>:<mimic>" -- info for dungeon grid */
9115 	if (buf[0] == 'F') {
9116 		int num;
9117 
9118 		if ((num = tokenize(buf + 2, 10, zz, ':', '/')) > 1) {
9119 			int index = zz[0][0];
9120 
9121 			/* Reset the feature */
9122 			letter[index].feature = 0;
9123 			letter[index].monster = 0;
9124 			letter[index].object = 0;
9125 			letter[index].ego = 0;
9126 			letter[index].artifact = 0;
9127 			letter[index].trap = 0;
9128 			letter[index].cave_info = 0;
9129 			letter[index].special = 0;
9130 			letter[index].random = 0;
9131 			letter[index].mimic = 0;
9132 			letter[index].ok = TRUE;
9133 			letter[index].defined = TRUE;
9134 
9135 			if (num > 1) {
9136 				if (zz[1][0] == '*') {
9137 					letter[index].random |= RANDOM_FEATURE;
9138 					if (zz[1][1]) {
9139 						zz[1]++;
9140 						letter[index].feature = atoi(zz[1]);
9141 					}
9142 				} else letter[index].feature = atoi(zz[1]);
9143 			}
9144 
9145 			if (num > 2)
9146 				letter[index].cave_info = atoi(zz[2]);
9147 
9148 			/* Monster */
9149 			if (num > 3) {
9150 				if (zz[3][0] == '*') {
9151 					letter[index].random |= RANDOM_MONSTER;
9152 					if (zz[3][1]) {
9153 						zz[3]++;
9154 						letter[index].monster = atoi(zz[3]);
9155 					}
9156 				} else letter[index].monster = atoi(zz[3]);
9157 			}
9158 
9159 			/* Object */
9160 			if (num > 4) {
9161 				if (zz[4][0] == '*') {
9162 					letter[index].random |= RANDOM_OBJECT;
9163 
9164 					if (zz[4][1]) {
9165 						zz[4]++;
9166 						letter[index].object = atoi(zz[4]);
9167 					}
9168 				} else letter[index].object = atoi(zz[4]);
9169 			}
9170 
9171 			/* Ego-Item */
9172 			if (num > 5) {
9173 				if (zz[5][0] == '*') {
9174 					letter[index].random |= RANDOM_EGO;
9175 
9176 					if (zz[5][1]) {
9177 						zz[5]++;
9178 						letter[index].ego = atoi(zz[5]);
9179 					}
9180 				} else letter[index].ego = atoi(zz[5]);
9181 			}
9182 
9183 			/* Artifact */
9184 			if (num > 6) {
9185 				if (zz[6][0] == '*') {
9186 					letter[index].random |= RANDOM_ARTIFACT;
9187 
9188 					if (zz[6][1]) {
9189 						zz[6]++;
9190 						letter[index].artifact = atoi(zz[6]);
9191 					}
9192 				} else letter[index].artifact = atoi(zz[6]);
9193 			}
9194 
9195 			if (num > 7) {
9196 				if (zz[7][0] == '*') {
9197 					letter[index].random |= RANDOM_TRAP;
9198 
9199 					if (zz[7][1]) {
9200 						zz[7]++;
9201 						letter[index].trap = atoi(zz[7]);
9202 					}
9203 				} else letter[index].trap = atoi(zz[7]);
9204 			}
9205 
9206 #if 0
9207 			if (num > 8) {
9208 				/* Quests can be defined by name only */
9209 				if (zz[8][0] == '"') {
9210 					int i;
9211 
9212 					/* Hunt & shoot the ending " */
9213 					i = strlen(zz[8]) - 1;
9214 					if (zz[8][i] == '"') zz[8][i] = '\0';
9215 					letter[index].special = 0;
9216 					for (i = 0; i < max_xo_idx; i++) {
9217 						if (!strcmp(&zz[8][1], quest[i].name)) {
9218 							letter[index].special = i;
9219 							break;
9220 						}
9221 					}
9222 				}
9223 				else letter[index].special = atoi(zz[8]);
9224 			}
9225 #else	// 0
9226 			if (num > 8) {
9227 				/* Quests can be defined by name only */
9228 				if (zz[8][0] == '"') {
9229 #if 0	// later for quest
9230 					int i;
9231 
9232 					/* Hunt & shoot the ending " */
9233 					i = strlen(zz[8]) - 1;
9234 					if (zz[8][i] == '"') zz[8][i] = '\0';
9235 					letter[index].special = 0;
9236 					for (i = 0; i < max_xo_idx; i++) {
9237 						if (!strcmp(&zz[8][1], quest[i].name)) {
9238 							letter[index].special = i;
9239 							break;
9240 						}
9241 					}
9242 #endif	// 0
9243 				}
9244 				else letter[index].special = atoi(zz[8]);
9245 			}
9246 #endif	// 0
9247 
9248 			if (num > 9)
9249 				letter[index].mimic = atoi(zz[9]);
9250 
9251 			return (0);
9252 		}
9253 	}
9254 
9255 	/* Process "D:<dungeon>" -- info for the cave grids */
9256 	else if (buf[0] == 'D') {
9257 		int x;
9258 		object_type object_type_body;
9259 
9260 		/* Acquire the text */
9261 		char *s = buf + 2;
9262 
9263 		/* Length of the text */
9264 		int len = strlen(s);
9265 
9266 		int y = *yval;
9267 		*xval = xvalstart;
9268 		for (x = *xval, i = 0; ((x < xmax) && (i < len)); x++, s++, i++) {
9269 			/* Access the grid */
9270 			cave_type *c_ptr = &zcave[y][x];
9271 			int idx = s[0];
9272 			int object_index = letter[idx].object;
9273 			int monster_index = letter[idx].monster;/* rudimentary support till actual code (see further below what i mean) has been looked at, too lazy atm - C. Blue */
9274 			int random = letter[idx].random;
9275 			int artifact_index = letter[idx].artifact;
9276 
9277 			if (!letter[idx].ok) s_printf("Warning '%c' not defined but used.\n", idx);
9278 
9279 //			if (init_flags & INIT_GET_SIZE) continue;
9280 
9281 			/* use the plasma generator wilderness */
9282 //			if (((!dun_level) || (!letter[idx].defined)) && (idx == ' ')) continue;
9283 #if 1 /* use this! (see explanation below) */
9284 			if (((!wpos->wz) || (!letter[idx].defined)) && (idx == ' ')) continue;
9285 #else
9286 			/* also allow separate floor pre-generation in dungeons (for dungeon towns).
9287 			   However, this means that templates using the 'default floor' feat "F: :..."
9288 			   will no longer work properly, since that feat would get ignored.
9289 			   This concerns arenas. So instead, generate floor _after_ loading a
9290 			   template, and check for c_ptr->feat==0 to do so. - C. Blue */
9291 			if (idx == ' ') continue;
9292 #endif
9293 
9294 			/* Clear some info */
9295 			c_ptr->info = 0;
9296 
9297 			/* Lay down a floor */
9298 //			c_ptr->mimic = letter[idx].mimic;
9299 
9300 			/* seasons hack: replace trees/bushes on world surface according to season! - C. Blue */
9301 			if (istown(wpos) && !wpos->wz &&
9302 			    (letter[idx].feature == FEAT_TREE || letter[idx].feature == FEAT_BUSH)) {
9303 				cave_set_feat(wpos, y, x, get_seasonal_tree());
9304 //				c_ptr->feat = get_seasonal_tree();
9305 			} else {
9306 				cave_set_feat(wpos, y, x, letter[idx].feature);
9307 //				c_ptr->feat = letter[idx].feature;
9308 			}
9309 
9310 			/* TERAHACK -- memorize stair locations XXX XXX */
9311 			if (c_ptr->feat == FEAT_LESS) {	// '<'
9312 				new_level_down_y(wpos, y);
9313 				new_level_down_x(wpos, x);
9314 			} else if (c_ptr->feat == FEAT_MORE) {
9315 				new_level_up_y(wpos, y);
9316 				new_level_up_x(wpos, x);
9317 			}
9318 
9319 			/* Cave info */
9320 			c_ptr->info |= letter[idx].cave_info;
9321 
9322 			/* Create a monster */
9323 			if (random & RANDOM_MONSTER) {
9324 				int level = monster_level;
9325 
9326 //				monster_level = quest[p_ptr->inside_quest].level + monster_index;
9327 				monster_level = getlevel(wpos) + monster_level;
9328 
9329 				place_monster(wpos, y, x, meta_sleep, FALSE);
9330 
9331 				monster_level = level;
9332 			}
9333 #if 0
9334 			else if (monster_index) {
9335 				/* Place it */
9336 				m_allow_special[monster_index] = TRUE;
9337 				place_monster_aux(y, x, monster_index, meta_sleep, FALSE, MSTATUS_ENEMY, 0);
9338 				m_allow_special[monster_index] = FALSE;
9339 			}
9340 #else /* rudimentary support till above code has been looked at, too lazy atm - C. Blue */
9341 			else if (monster_index) {
9342 				summon_override_checks = SO_ALL; /* disable all checks */
9343 				place_monster_aux(wpos, y, x, monster_index, FALSE, FALSE, 0, 0);
9344 //				place_monster_one(wpos, y, x, monster_index, 0, 0, FALSE, 0, 0);
9345 				summon_override_checks = SO_NONE; /* re-enable default */
9346 			}
9347 #endif	// 0
9348 
9349 			/* Object (and possible trap) */
9350 			if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP)) {
9351 				int level = object_level;
9352 //				object_level = quest[p_ptr->inside_quest].level;
9353 				object_level = dun_level;
9354 
9355 				/*
9356 				 * Random trap and random treasure defined
9357 				 * 25% chance for trap and 75% chance for object
9358 				 */
9359 				if (rand_int(100) < 75)
9360 					place_object(wpos, y, x, FALSE, FALSE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9361 				// else
9362 				if (rand_int(100) < 25)
9363 					place_trap(wpos, y, x, 0);
9364 
9365 				object_level = level;
9366 			} else if (random & RANDOM_OBJECT) {
9367 				/* Create an out of deep object */
9368 				if (object_index) {
9369 					int level = object_level;
9370 
9371 //					object_level = quest[p_ptr->inside_quest].level + object_index;
9372 					object_level = getlevel(wpos) + object_index;
9373 					if (rand_int(100) < 75)
9374 						place_object(wpos, y, x, FALSE, FALSE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9375 					else if (rand_int(100) < 80)
9376 						place_object(wpos, y, x, TRUE, FALSE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9377 					else
9378 						place_object(wpos, y, x, TRUE, TRUE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9379 
9380 					object_level = level;
9381 				} else if (rand_int(100) < 75)
9382 					place_object(wpos, y, x, FALSE, FALSE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9383 				else if (rand_int(100) < 80)
9384 					place_object(wpos, y, x, TRUE, FALSE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9385 				else
9386 					place_object(wpos, y, x, TRUE, TRUE, FALSE, RESF_NONE, default_obj_theme, 0, ITEM_REMOVAL_NEVER);
9387 			}
9388 			/* Random trap */
9389 			else if (random & RANDOM_TRAP)
9390 				place_trap(wpos, y, x, 0);
9391 #if 0
9392 			else if (object_index) {
9393 				/* Get local object */
9394 				object_type *o_ptr = &object_type_body;
9395 
9396 				k_allow_special[object_index] = TRUE;
9397 
9398 				/* Create the item */
9399 				object_prep(o_ptr, object_index);
9400 
9401 				/* Apply magic (no messages, no artifacts) */
9402 				apply_magic(wpos, o_ptr, dun_level, FALSE, TRUE, FALSE, FALSE, RESF_NONE);
9403 
9404 				k_allow_special[object_index] = FALSE;
9405 
9406 				drop_near(o_ptr, -1, wpos, y, x);
9407 			}
9408 #else /* rudimentary support yada yada yada - C. Blue */
9409 			else if (object_index) {
9410 				object_type *o_ptr = &object_type_body;
9411 				object_prep(o_ptr, object_index);
9412 				if (o_ptr->tval == TV_GOLD) {
9413 					o_ptr->pval = letter[idx].special; /* support for 'money' objects ^^ */
9414 					o_ptr->k_idx = gold_colour(o_ptr->pval, TRUE, FALSE);
9415 					o_ptr->sval = k_info[o_ptr->k_idx].sval;
9416 				}
9417 				apply_magic(wpos, o_ptr, dun_level, FALSE, TRUE, FALSE, FALSE, RESF_NONE);
9418 				drop_near(o_ptr, -1, wpos, y, x);
9419 			}
9420 #endif	// 0
9421 
9422 			/* Artifact */
9423 			if (artifact_index) {
9424 #if 0
9425 				int I_kind = 0;
9426 
9427 				artifact_type *a_ptr = &a_info[artifact_index];
9428 
9429 				object_type forge;
9430 
9431 				/* Get local object */
9432 				object_type *q_ptr = &forge;
9433 
9434 				a_allow_special[artifact_index] = TRUE;
9435 
9436 				/* Wipe the object */
9437 				object_wipe(q_ptr);
9438 
9439 				/* Acquire the "kind" index */
9440 				I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
9441 
9442 				/* Create the artifact */
9443 				object_prep(q_ptr, I_kind);
9444 
9445 				/* Save the name */
9446 				q_ptr->name1 = artifact_index;
9447 
9448 				/* Extract the fields */
9449 				q_ptr->pval = a_ptr->pval;
9450 				q_ptr->ac = a_ptr->ac;
9451 				q_ptr->dd = a_ptr->dd;
9452 				q_ptr->ds = a_ptr->ds;
9453 				q_ptr->to_a = a_ptr->to_a;
9454 				q_ptr->to_h = a_ptr->to_h;
9455 				q_ptr->to_d = a_ptr->to_d;
9456 				q_ptr->weight = a_ptr->weight;
9457 
9458 				random_artifact_resistance(q_ptr);
9459 
9460 				handle_art_inum(artifact_index);
9461 
9462 				a_allow_special[artifact_index] = FALSE;
9463 
9464 				/* Drop the artifact */
9465 				drop_near(q_ptr, -1, y, x);
9466 #endif
9467 			}
9468 
9469 #if 0
9470 			/* Terrain special */
9471 			if (letter[idx].special == -1) {
9472 				if (!letter[idx].bx) {
9473 					letter[idx].bx = x;
9474 					letter[idx].by = y;
9475 				} else {
9476 					c_ptr->special = (letter[idx].by << 8) + letter[idx].bx;
9477 					cave[letter[idx].by][letter[idx].bx].special = (y << 8) + x;
9478 				}
9479 			} else
9480 				c_ptr->special = letter[idx].special;
9481 #else
9482 			/* Terrain special */
9483 			if (letter[idx].special == -1) {
9484  #if 0
9485 				if (!letter[idx].bx) {
9486 					letter[idx].bx = x;
9487 					letter[idx].by = y;
9488 				} else {
9489 					c_ptr->special = (letter[idx].by << 8) + letter[idx].bx;
9490 					cave[letter[idx].by][letter[idx].bx].special = (y << 8) + x;
9491 				}
9492  #endif
9493 			} else {
9494 				/* MEGAHACK -- let's just make stores available */
9495 				if (letter[idx].feature == FEAT_SHOP) {
9496 					if ((cs_ptr = AddCS(c_ptr, CS_SHOP))) {
9497 						/* MEGAHACK till st_info is implemented */
9498 						int store = letter[idx].special;
9499 						// if (store > 8) store = 8;
9500 
9501 						/* hack for dungeon stores: add +70 for basic town stores */
9502 						if (wpos->wz && store >= STORE_GENERAL && store <= STORE_RUNE)
9503 							store += STORE_GENERAL_DUN;
9504 
9505 						cs_ptr->sc.omni = store;
9506 					}
9507 				}
9508 //				c_ptr->special = letter[idx].special;
9509 			}
9510 #endif
9511 		}
9512 		if ((process_dungeon_file_full) && (*xval < x)) *xval = x;
9513 		(*yval)++;
9514 
9515 		return (0);
9516 	}
9517 
9518 	/* Process "W:<command>: ..." -- info for the wilderness */
9519 	else if (buf[0] == 'W') {
9520 		return (0);
9521 #if 0
9522 		/* Process "W:D:<layout> */
9523 		/* Layout of the wilderness */
9524 		if (buf[2] == 'D') {
9525 			int x;
9526 			char i;
9527 
9528 			/* Acquire the text */
9529 			char *s = buf+4;
9530 			int y = *yval;
9531 
9532 			for(x = 0; x < max_wild_x; x++) {
9533 				if (1 != sscanf(s + x, "%c", &i)) return (1);
9534 				wild_map[y][x].feat = wildc2i[(int)i];
9535 			}
9536 
9537 			(*yval)++;
9538 
9539 			return (0);
9540 		}
9541 		/* Process "M:<plus>:<line>" -- move line lines */
9542 		else if (buf[2] == 'M') {
9543 			if (tokenize(buf+4, 2, zz, ':', '/') == 2) {
9544 				if (atoi(zz[0])) (*yval) += atoi(zz[1]);
9545 				else (*yval) -= atoi(zz[1]);
9546 			} else return (1);
9547 			return (0);
9548 		}
9549 		/* Process "W:P:<x>:<y> - starting position in the wilderness */
9550 		else if (buf[2] == 'P') {
9551 			if ((p_ptr->wilderness_x == 0) &&
9552 			    (p_ptr->wilderness_y == 0)) {
9553 				if (tokenize(buf+4, 2, zz, ':', '/') == 2) {
9554 					p_ptr->wilderness_x = atoi(zz[0]);
9555 					p_ptr->wilderness_y = atoi(zz[1]);
9556 				} else return (1);
9557 			}
9558 
9559 			return (0);
9560 		}
9561 		/* Process "W:E:<dungeon>:<y>:<x> - entrance to the dungeon <dungeon> */
9562 		else if (buf[2] == 'E') {
9563 			if (tokenize(buf+4, 3, zz, ':', '/') == 3)
9564 				wild_map[atoi(zz[1])][atoi(zz[2])].entrance = 1000 + atoi(zz[0]);
9565 			else
9566 				return (1);
9567 
9568 			return (0);
9569 		}
9570 #endif	// 0
9571 	}
9572 
9573 	/* Process "P:<x>:<y>" -- player position */
9574 	else if (buf[0] == 'P') {
9575 #if 0	// It'll be needed very soon maybe
9576 		if (init_flags & INIT_CREATE_DUNGEON) {
9577 			if (tokenize(buf + 2, 2, zz, ':', '/') == 2) {
9578 				/* Place player in a quest level */
9579 				if (p_ptr->inside_quest || (init_flags & INIT_POSITION)) {
9580 					py = atoi(zz[0]);
9581 					px = atoi(zz[1]);
9582 				}
9583 				/* Place player in the town */
9584 				else if ((p_ptr->oldpx == 0) && (p_ptr->oldpy == 0)) {
9585 					p_ptr->oldpy = atoi(zz[0]);
9586 					p_ptr->oldpx = atoi(zz[1]);
9587 				}
9588 			}
9589 		}
9590 #else	// 0.. quick Hack
9591 		if (tokenize(buf + 2, 2, zz, ':', '/') == 2) {
9592 			int yy = atoi(zz[0]);
9593 			int xx = atoi(zz[1]);
9594 			new_level_rand_y(wpos, yy);
9595 			new_level_rand_x(wpos, xx);
9596 
9597 			/* for dungeon towns in ironman dungeons - C. Blue */
9598 			if (wpos->wz) {
9599 				new_level_down_y(wpos, yy);
9600 				new_level_down_x(wpos, xx);
9601 				new_level_up_y(wpos, yy);
9602 				new_level_up_x(wpos, xx);
9603 			}
9604  #if 0
9605 			new_level_down_y(wpos, yy);
9606 			new_level_down_x(wpos, xx);
9607 			new_level_up_y(wpos, yy);
9608 			new_level_up_x(wpos, xx);
9609  #endif	// 0
9610 		}
9611 #endif
9612 		return (0);
9613 	}
9614 
9615 	/* Process "M:<type>:<maximum>" -- set maximum values */
9616 	else if (buf[0] == 'M') {
9617 		return (0);
9618 
9619 #if 0	// It's very nice code - this should be transmitted to the client, tho
9620 		if (tokenize(buf + 2, 3, zz, ':', '/') >= 2) {
9621 			/* Maximum towns */
9622 			if (zz[0][0] == 'T')
9623 				max_towns = atoi(zz[1]);
9624 			/* Maximum real towns */
9625 			if (zz[0][0] == 't')
9626 				max_real_towns = atoi(zz[1]);
9627 			/* Maximum r_idx */
9628 			else if (zz[0][0] == 'R')
9629 				max_r_idx = atoi(zz[1]);
9630 			/* Maximum re_idx */
9631 			else if (zz[0][0] == 'r')
9632 				max_re_idx = atoi(zz[1]);
9633 			/* Maximum s_idx */
9634 			else if (zz[0][0] == 'k') {
9635 				max_s_idx = atoi(zz[1]);
9636 				if (max_s_idx > MAX_SKILLS) return (1);
9637 			}
9638 			/* Maximum k_idx */
9639 			else if (zz[0][0] == 'K')
9640 				max_k_idx = atoi(zz[1]);
9641 			/* Maximum v_idx */
9642 			else if (zz[0][0] == 'V')
9643 				max_v_idx = atoi(zz[1]);
9644 			/* Maximum f_idx */
9645 			else if (zz[0][0] == 'F')
9646 				max_f_idx = atoi(zz[1]);
9647 			/* Maximum a_idx */
9648 			else if (zz[0][0] == 'A')
9649 				max_a_idx = atoi(zz[1]);
9650 			/* Maximum e_idx */
9651 			else if (zz[0][0] == 'E')
9652 				max_e_idx = atoi(zz[1]);
9653 			/* Maximum ra_idx */
9654 			else if (zz[0][0] == 'Z')
9655 				max_ra_idx = atoi(zz[1]);
9656 			/* Maximum o_idx */
9657 			else if (zz[0][0] == 'O')
9658 				max_o_idx = atoi(zz[1]);
9659 			/* Maximum player types */
9660 			else if (zz[0][0] == 'P') {
9661 				if (zz[1][0] == 'R')
9662 					max_rp_idx = atoi(zz[2]);
9663 				else if (zz[1][0] == 'S')
9664 					max_rmp_idx = atoi(zz[2]);
9665 				else if (zz[1][0] == 'C')
9666 					max_c_idx = atoi(zz[2]);
9667 				else if (zz[1][0] == 'M')
9668 					max_mc_idx = atoi(zz[2]);
9669 				else if (zz[1][0] == 'H')
9670 					max_bg_idx = atoi(zz[2]);
9671 			}
9672 			/* Maximum m_idx */
9673 			else if (zz[0][0] == 'M')
9674 				max_m_idx = atoi(zz[1]);
9675 			/* Maximum tr_idx */
9676 			else if (zz[0][0] == 'U')
9677 				max_t_idx = atoi(zz[1]);
9678 			/* Maximum wf_idx */
9679 			else if (zz[0][0] == 'W')
9680 				max_wf_idx = atoi(zz[1]);
9681 			/* Maximum ba_idx */
9682 			else if (zz[0][0] == 'B')
9683 				max_ba_idx = atoi(zz[1]);
9684 			/* Maximum st_idx */
9685 			else if (zz[0][0] == 'S')
9686 				max_st_idx = atoi(zz[1]);
9687 			/* Maximum set_idx */
9688 			else if (zz[0][0] == 's')
9689 				max_set_idx = atoi(zz[1]);
9690 			/* Maximum ow_idx */
9691 			else if (zz[0][0] == 'N')
9692 				max_ow_idx = atoi(zz[1]);
9693 			/* Maximum wilderness x size */
9694 			else if (zz[0][0] == 'X')
9695 				max_wild_x = atoi(zz[1]);
9696 			/* Maximum wilderness y size */
9697 			else if (zz[0][0] == 'Y')
9698 				max_wild_y = atoi(zz[1]);
9699 			/* Maximum d_idx */
9700 			else if (zz[0][0] == 'D')
9701 				max_d_idx = atoi(zz[1]);
9702 			return (0);
9703 		}
9704 #endif
9705 	}
9706 
9707 	/* Failure */
9708 	return (1);
9709 }
9710 
9711 
9712 
9713 
9714 /*
9715  * Helper function for "process_dungeon_file()"
9716  */
9717 #if 0
9718 static cptr process_dungeon_file_expr(char **sp, char *fp)
9719 {
9720 	cptr v;
9721 
9722 	char *b;
9723 	char *s;
9724 
9725 	char b1 = '[';
9726 	char b2 = ']';
9727 
9728 	char f = ' ';
9729 
9730 	/* Initial */
9731 	s = (*sp);
9732 
9733 	/* Skip spaces */
9734 	while (isspace(*s)) s++;
9735 
9736 	/* Save start */
9737 	b = s;
9738 
9739 	/* Default */
9740 	v = "?o?o?";
9741 
9742 	/* Analyze */
9743 	if (*s == b1)
9744 	{
9745 		const char *p;
9746 		const char *t;
9747 
9748 		/* Skip b1 */
9749 		s++;
9750 
9751 		/* First */
9752 		t = process_dungeon_file_expr(&s, &f);
9753 
9754 		/* Oops */
9755 		if (!*t)
9756 		{
9757 			/* Nothing */
9758 		}
9759 
9760 		/* Function: IOR */
9761 		else if (streq(t, "IOR"))
9762 		{
9763 			v = "0";
9764 			while (*s && (f != b2))
9765 			{
9766 				t = process_dungeon_file_expr(&s, &f);
9767 				if (*t && !streq(t, "0")) v = "1";
9768 			}
9769 		}
9770 
9771 		/* Function: AND */
9772 		else if (streq(t, "AND"))
9773 		{
9774 			v = "1";
9775 			while (*s && (f != b2))
9776 			{
9777 				t = process_dungeon_file_expr(&s, &f);
9778 				if (*t && streq(t, "0")) v = "0";
9779 			}
9780 		}
9781 
9782 		/* Function: NOT */
9783 		else if (streq(t, "NOT"))
9784 		{
9785 			v = "1";
9786 			while (*s && (f != b2))
9787 			{
9788 				t = process_dungeon_file_expr(&s, &f);
9789 				if (*t && streq(t, "1")) v = "0";
9790 			}
9791 		}
9792 
9793 		/* Function: EQU */
9794 		else if (streq(t, "EQU"))
9795 		{
9796 			v = "1";
9797 			if (*s && (f != b2))
9798 			{
9799 				t = process_dungeon_file_expr(&s, &f);
9800 			}
9801 			while (*s && (f != b2))
9802 			{
9803 				p = t;
9804 				t = process_dungeon_file_expr(&s, &f);
9805 				if (*t && !streq(p, t)) v = "0";
9806 			}
9807 		}
9808 
9809 		/* Function: LEQ */
9810 		else if (streq(t, "LEQ"))
9811 		{
9812 			v = "1";
9813 			if (*s && (f != b2))
9814 			{
9815 				t = process_dungeon_file_expr(&s, &f);
9816 			}
9817 			while (*s && (f != b2))
9818 			{
9819 				p = t;
9820 				t = process_dungeon_file_expr(&s, &f);
9821 				if (*t && (strcmp(p, t) > 0)) v = "0";
9822 			}
9823 		}
9824 
9825 		/* Function: GEQ */
9826 		else if (streq(t, "GEQ"))
9827 		{
9828 			v = "1";
9829 			if (*s && (f != b2))
9830 			{
9831 				t = process_dungeon_file_expr(&s, &f);
9832 			}
9833 			while (*s && (f != b2))
9834 			{
9835 				p = t;
9836 				t = process_dungeon_file_expr(&s, &f);
9837 				if (*t && (strcmp(p, t) < 0)) v = "0";
9838 			}
9839 		}
9840 
9841 		/* Oops */
9842 		else
9843 		{
9844 			while (*s && (f != b2))
9845 			{
9846 				t = process_dungeon_file_expr(&s, &f);
9847 			}
9848 		}
9849 
9850 		/* Verify ending */
9851 		if (f != b2) v = "?x?x?";
9852 
9853 		/* Extract final and Terminate */
9854 		if ((f = *s) != '\0') *s++ = '\0';
9855 	}
9856 
9857 	/* Other */
9858 	else
9859         {
9860                 bool text_mode = FALSE;
9861 
9862 		/* Accept all printables except spaces and brackets */
9863                 while (isprint(*s))
9864                 {
9865                         if (*s == '"') text_mode = !text_mode;
9866                         if (!text_mode)
9867                         {
9868                                 if (strchr(" []", *s))
9869                                         break;
9870                         }
9871                         else
9872                         {
9873                                 if (strchr("[]", *s))
9874                                         break;
9875                         }
9876 
9877                         ++s;
9878                 }
9879 
9880 		/* Extract final and Terminate */
9881 		if ((f = *s) != '\0') *s++ = '\0';
9882 
9883 		/* Variable */
9884 		if (*b == '$')
9885 		{
9886 			/* System */
9887 			if (streq(b+1, "SYS"))
9888 			{
9889 				v = ANGBAND_SYS;
9890 			}
9891 
9892 			/* Graphics */
9893 			else if (streq(b+1, "GRAF"))
9894 			{
9895 				v = ANGBAND_GRAF;
9896 			}
9897 
9898 			/* Race */
9899 			else if (streq(b+1, "RACE"))
9900 			{
9901 				v = rp_ptr->title + rp_name;
9902 			}
9903 
9904 			/* Race Mod */
9905 			else if (streq(b+1, "RACEMOD"))
9906 			{
9907 				v = rmp_ptr->title + rmp_name;
9908 			}
9909 
9910 			/* Class */
9911 			else if (streq(b+1, "CLASS"))
9912 			{
9913 				v = cp_ptr->title + c_name;
9914 			}
9915 
9916 			/* Player */
9917 			else if (streq(b+1, "PLAYER"))
9918 			{
9919 				v = player_base;
9920 			}
9921 
9922 			/* Town */
9923 			else if (streq(b+1, "TOWN"))
9924 			{
9925 				strnfmt(pref_tmp_value, 8, "%d", p_ptr->town_num);
9926 				v = pref_tmp_value;
9927 			}
9928 
9929 			/* Town destroyed */
9930 			else if (prefix(b+1, "TOWN_DESTROY"))
9931                         {
9932 				strnfmt(pref_tmp_value, 8, "%d", town_info[atoi(b + 13)].destroyed);
9933 				v = pref_tmp_value;
9934 			}
9935 
9936 			/* Current quest number */
9937 			else if (streq(b+1, "QUEST_NUMBER"))
9938 			{
9939 				strnfmt(pref_tmp_value, 8, "%d", p_ptr->inside_quest);
9940 				v = pref_tmp_value;
9941 			}
9942 
9943 			/* Number of last quest */
9944 			else if (streq(b+1, "LEAVING_QUEST"))
9945 			{
9946 				strnfmt(pref_tmp_value, 8, "%d", leaving_quest);
9947 				v = pref_tmp_value;
9948 			}
9949 
9950 			/* DAYTIME status */
9951 			else if (prefix(b+1, "DAYTIME"))
9952 			{
9953 				if ((bst(HOUR, turn) >= SUNRISE) && (bst(HOUR, turn) < NIGHTFALL))
9954 					v = "1";
9955 				else
9956 					v = "0";
9957 			}
9958 
9959 			/* Quest status */
9960 			else if (prefix(b+1, "QUEST"))
9961 			{
9962 				/* "QUEST" uses a special parameter to determine the number of the quest */
9963 				if (*(b + 6) != '"')
9964 					strnfmt(pref_tmp_value, 8, "%d", quest[atoi(b+6)].status);
9965 				else
9966 				{
9967 					char c[80];
9968 					int i;
9969 
9970 					/* Copy it to temp array, so that we can modify it safely */
9971 					strcpy(c, b + 7);
9972 
9973                                         /* Hunt & shoot the ending " */
9974 					for (i = 0; (c[i] != '"') && (c[i] != '\0'); i++);
9975 					if (c[i] == '"') c[i] = '\0';
9976 					strcpy(pref_tmp_value, "-1");
9977 					for (i = 0; i < max_xo_idx; i++)
9978 					{
9979                                                 if (streq(c, quest[i].name))
9980                                                 {
9981 							strnfmt(pref_tmp_value, 8, "%d", quest[i].status);
9982 							break;
9983 						}
9984                                         }
9985 				}
9986 				v = pref_tmp_value;
9987 			}
9988 
9989 			/* Variant name */
9990 			else if (streq(b+1, "VARIANT"))
9991 			{
9992 				v = "ToME";
9993 			}
9994 
9995 			/* Wilderness */
9996 			else if (streq(b+1, "WILDERNESS"))
9997 			{
9998 				if (vanilla_town) v = "NONE";
9999 				else v = "NORMAL";
10000 			}
10001 		}
10002 
10003 		/* Constant */
10004 		else
10005 		{
10006 			v = b;
10007 		}
10008 	}
10009 
10010 	/* Save */
10011 	(*fp) = f;
10012 
10013 	/* Save */
10014 	(*sp) = s;
10015 
10016 	/* Result */
10017 	return (v);
10018 }
10019 #endif	// 0
10020 
10021 
10022 //errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int xmax, bool init)
process_dungeon_file(cptr name,worldpos * wpos,int * yval,int * xval,int ymax,int xmax,bool init)10023 errr process_dungeon_file(cptr name, worldpos *wpos, int *yval, int *xval, int ymax, int xmax, bool init)
10024 {
10025 	FILE *fp;
10026 	char buf[1024];
10027 	int num = -1, i;
10028 	errr err = 0;
10029 	bool bypass = FALSE;
10030 
10031 	/* Save the start since it ought to be modified */
10032 	int xmin = *xval;
10033 
10034 	cave_type **zcave;
10035 	zcave = getcave(wpos);
10036 	if (!zcave) return (-1);	/* maybe SIGSEGV soon anyway */
10037 
10038 	if (init) {
10039 		meta_sleep = TRUE;
10040 		for (i = 0; i < 255; i++) {
10041 			letter[i].defined = FALSE;
10042 			if (i == ' ') letter[i].ok = TRUE;
10043 			else letter[i].ok = FALSE;
10044 			letter[i].bx = 0;
10045 			letter[i].by = 0;
10046 		}
10047 	}
10048 
10049 	/* Build the filename */
10050 //	path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
10051 	path_build(buf, 1024, ANGBAND_DIR_GAME, name);
10052 
10053 	/* Grab permission */
10054 //	safe_setuid_grab();
10055 
10056 	/* Open the file */
10057 	fp = my_fopen(buf, "r");
10058 
10059 	/* Drop permission */
10060 //	safe_setuid_drop();
10061 
10062 	/* No such file */
10063 	if (!fp) {
10064 		s_printf("Cannot find file %s at %s\n", name, buf);
10065 		return (-1);
10066 	}
10067 
10068 	/* Process the file */
10069 	while (0 == my_fgets(fp, buf, 1024, FALSE)) {
10070 		/* Count lines */
10071 		num++;
10072 
10073 
10074 		/* Skip "empty" lines */
10075 		if (!buf[0]) continue;
10076 
10077 		/* Skip "blank" lines */
10078 		if (isspace(buf[0])) continue;
10079 
10080 		/* Skip comments */
10081 		if (buf[0] == '#') continue;
10082 
10083 
10084 		/* Process "?:<expr>" */
10085 		if ((buf[0] == '?') && (buf[1] == ':'))
10086 		{
10087 #if 0	// later
10088 			char f;
10089 			cptr v;
10090 			char *s;
10091 
10092 			/* Start */
10093 			s = buf + 2;
10094 
10095 			/* Parse the expr */
10096 			v = process_dungeon_file_expr(&s, &f);
10097 
10098 			/* Set flag */
10099 			bypass = (streq(v, "0") ? TRUE : FALSE);
10100 #endif // 0
10101 
10102 			/* Continue */
10103 			continue;
10104 		}
10105 
10106 		/* Apply conditionals */
10107 		if (bypass) continue;
10108 
10109 
10110 		/* Process "%:<file>" */
10111 		if (buf[0] == '%')
10112 		{
10113 			/* Process that file if allowed */
10114 			(void)process_dungeon_file(buf + 2, wpos, yval, xval, ymax, xmax, FALSE);
10115 
10116 			/* Continue */
10117 			continue;
10118 		}
10119 
10120 
10121 		/* Process the line */
10122 		err = process_dungeon_file_aux(buf, wpos, yval, xval, xmin, ymax, xmax);
10123 
10124 		/* Oops */
10125 		if (err) break;
10126 	}
10127 
10128 
10129 	/* Error */
10130 	if (err)
10131 	{
10132 		/* Useful error message */
10133 		s_printf("Error %d in line %d of file '%s'.\n", err, num, name);
10134 		s_printf("Parsing '%s'\n", buf);
10135 	}
10136 
10137 	/* Close the file */
10138 	my_fclose(fp);
10139 
10140 	/* update player maps */
10141 	for (i = 1; i <= NumPlayers; i++) {
10142 		/* Only for players on the level */
10143 		if (inarea(wpos, &Players[i]->wpos)) Players[i]->redraw |= PR_MAP;
10144 	}
10145 
10146 	/* Result */
10147 	return (err);
10148 }
10149