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