1 /* File: init2.c */
2 
3 
4 /*
5  * Copyright (c) 1997 Ben Harrison
6  *
7  * This software may be copied and distributed for educational, research,
8  * and not for profit purposes provided that this copyright and statement
9  * are included in all such copies.  Other copyrights may also apply.
10  */
11 
12 #include "angband.h"
13 
14 #include "script.h"
15 
16 #include "init.h"
17 
18 #ifdef CHECK_MODIFICATION_TIME
19 #ifndef RISCOS
20 #ifdef MACINTOSH
21 #include <stat.h>
22 #else
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #endif /* MACINTOSH */
26 #endif /* !RISCOS */
27 #endif /* CHECK_MODIFICATION_TIME */
28 
29 #ifdef HAVE_MMAP
30 #include <sys/mman.h>
31 #endif
32 
33 
34 /*
35  * This file is used to initialize various variables and arrays for the
36  * Angband game.  Note the use of "fd_read()" and "fd_write()" to bypass
37  * the common limitation of "read()" and "write()" to only 32767 bytes
38  * at a time.
39  *
40  * Several of the arrays for Angband are built from "template" files in
41  * the "lib/file" directory, from which quick-load binary "image" files
42  * are constructed whenever they are not present in the "lib/data"
43  * directory, or if those files become obsolete, if we are allowed.
44  *
45  * Warning -- the "ascii" file parsers use a minor hack to collect the
46  * name and text information in a single pass.  Thus, the game will not
47  * be able to load any template file with more than 20K of names or 60K
48  * of text, even though technically, up to 64K should be legal.
49  *
50  * The "init1.c" file is used only to parse the ascii template files,
51  * to create the binary image files.  If you include the binary image
52  * files instead of the ascii template files, then you can undefine
53  * "ALLOW_TEMPLATES", saving about 20K by removing "init1.c".  Note
54  * that the binary image files are extremely system dependant.
55  */
56 
57 
58 
59 /*
60  * Find the default paths to all of our important sub-directories.
61  *
62  * The purpose of each sub-directory is described in "variable.c".
63  *
64  * All of the sub-directories should, by default, be located inside
65  * the main "lib" directory, whose location is very system dependant.
66  *
67  * This function takes a writable buffer, initially containing the
68  * "path" to the "lib" directory, for example, "/pkg/lib/angband/",
69  * or a system dependant string, for example, ":lib:".  The buffer
70  * must be large enough to contain at least 32 more characters.
71  *
72  * Various command line options may allow some of the important
73  * directories to be changed to user-specified directories, most
74  * importantly, the "info" and "user" and "save" directories,
75  * but this is done after this function, see "main.c".
76  *
77  * In general, the initial path should end in the appropriate "PATH_SEP"
78  * string.  All of the "sub-directory" paths (created below or supplied
79  * by the user) will NOT end in the "PATH_SEP" string, see the special
80  * "path_build()" function in "util.c" for more information.  (Note that
81  * we call this via the path_make() macro in defines.h)
82  *
83  * Mega-Hack -- support fat raw files under NEXTSTEP, using special
84  * "suffixed" directories for the "ANGBAND_DIR_DATA" directory, but
85  * requiring the directories to be created by hand by the user.
86  *
87  * Hack -- first we free all the strings, since this is known
88  * to succeed even if the strings have not been allocated yet,
89  * as long as the variables start out as "NULL".  This allows
90  * this function to be called multiple times, for example, to
91  * try several base "path" values until a good one is found.
92  */
init_file_paths(char * path)93 void init_file_paths(char *path)
94 {
95 	char *tail;
96 
97 #ifdef PRIVATE_USER_PATH
98 	char buf[1024];
99 #endif /* PRIVATE_USER_PATH */
100 
101 	/*** Free everything ***/
102 
103 	/* Free the main path */
104 	string_free(ANGBAND_DIR);
105 
106 	/* Free the sub-paths */
107 	string_free(ANGBAND_DIR_APEX);
108 	string_free(ANGBAND_DIR_BONE);
109 	string_free(ANGBAND_DIR_DATA);
110 	string_free(ANGBAND_DIR_EDIT);
111 	string_free(ANGBAND_DIR_SCRIPT);
112 	string_free(ANGBAND_DIR_FILE);
113 	string_free(ANGBAND_DIR_HELP);
114 	string_free(ANGBAND_DIR_INFO);
115 	string_free(ANGBAND_DIR_SAVE);
116 	string_free(ANGBAND_DIR_PREF);
117 	string_free(ANGBAND_DIR_USER);
118 	string_free(ANGBAND_DIR_XTRA);
119 
120 
121 	/*** Prepare the "path" ***/
122 
123 	/* Hack -- save the main directory */
124 	ANGBAND_DIR = string_make(path);
125 
126 	/* Prepare to append to the Base Path */
127 	tail = path + strlen(path);
128 
129 
130 #ifdef VM
131 
132 
133 	/*** Use "flat" paths with VM/ESA ***/
134 
135 	/* Use "blank" path names */
136 	ANGBAND_DIR_APEX = string_make("");
137 	ANGBAND_DIR_BONE = string_make("");
138 	ANGBAND_DIR_DATA = string_make("");
139 	ANGBAND_DIR_EDIT = string_make("");
140 	ANGBAND_DIR_SCRIPT = string_make("");
141 	ANGBAND_DIR_FILE = string_make("");
142 	ANGBAND_DIR_HELP = string_make("");
143 	ANGBAND_DIR_INFO = string_make("");
144 	ANGBAND_DIR_SAVE = string_make("");
145 	ANGBAND_DIR_PREF = string_make("");
146 	ANGBAND_DIR_USER = string_make("");
147 	ANGBAND_DIR_XTRA = string_make("");
148 
149 
150 #else  /* VM */
151 
152 
153 	/*** Build the sub-directory names ***/
154 
155 	/* Build a path name */
156 	strcpy(tail, "edit");
157 	ANGBAND_DIR_EDIT = string_make(path);
158 
159 	/* Build a path name */
160 	strcpy(tail, "script");
161 	ANGBAND_DIR_SCRIPT = string_make(path);
162 
163 	/* Build a path name */
164 	strcpy(tail, "file");
165 	ANGBAND_DIR_FILE = string_make(path);
166 
167 	/* Build a path name */
168 	strcpy(tail, "help");
169 	ANGBAND_DIR_HELP = string_make(path);
170 
171 	/* Build a path name */
172 	strcpy(tail, "info");
173 	ANGBAND_DIR_INFO = string_make(path);
174 
175 	/* Build a path name */
176 	strcpy(tail, "pref");
177 	ANGBAND_DIR_PREF = string_make(path);
178 
179 #ifdef PRIVATE_USER_PATH
180 
181 	/* Build the path to the user specific directory */
182 	path_make(buf, PRIVATE_USER_PATH, VERSION_NAME);
183 
184 	/* Build a relative path name */
185 	ANGBAND_DIR_USER = string_make(buf);
186 
187 #else  /* PRIVATE_USER_PATH */
188 
189 	/* Build a path name */
190 	strcpy(tail, "user");
191 	ANGBAND_DIR_USER = string_make(path);
192 
193 #endif /* PRIVATE_USER_PATH */
194 
195 #ifdef USE_PRIVATE_PATHS
196 
197 	/* Build a path name */
198 	path_make(buf, ANGBAND_DIR_USER, "scores");
199 	ANGBAND_DIR_APEX = string_make(buf);
200 
201 	/* Build a path name */
202 	path_make(buf, ANGBAND_DIR_USER, "bone");
203 	ANGBAND_DIR_BONE = string_make(buf);
204 
205 	/* Build a path name */
206 	path_make(buf, ANGBAND_DIR_USER, "data");
207 	ANGBAND_DIR_DATA = string_make(buf);
208 
209 	/* Build a path name */
210 	path_make(buf, ANGBAND_DIR_USER, "save");
211 	ANGBAND_DIR_SAVE = string_make(buf);
212 
213 #else /* USE_PRIVATE_PATHS */
214 
215 	/* Build a path name */
216 	strcpy(tail, "apex");
217 	ANGBAND_DIR_APEX = string_make(path);
218 
219 	/* Build a path name */
220 	strcpy(tail, "bone");
221 	ANGBAND_DIR_BONE = string_make(path);
222 
223 	/* Build a path name */
224 	strcpy(tail, "data");
225 	ANGBAND_DIR_DATA = string_make(path);
226 
227 	/* Build a path name */
228 	strcpy(tail, "save");
229 	ANGBAND_DIR_SAVE = string_make(path);
230 
231 #endif /* USE_PRIVATE_PATHS */
232 
233 	/* Build a path name */
234 	strcpy(tail, "xtra");
235 	ANGBAND_DIR_XTRA = string_make(path);
236 
237 #endif /* VM */
238 }
239 
240 
241 
242 #ifdef ALLOW_TEMPLATES
243 
244 
245 /*
246  * Hack -- help give useful error messages
247  */
248 int error_idx;
249 int error_line;
250 
251 
252 /*
253  * Standard error message text
254  */
255 cptr err_str[PARSE_ERROR_MAX] =
256 {
257 	NULL,
258 	"parse error",
259 	"obsolete file",
260 	"missing record header",
261 	"non-sequential records",
262 	"invalid flag specification",
263 	"undefined directive",
264 	"out of memory",
265 	"value out of bounds",
266 	"too few arguments",
267 	"too many arguments",
268 	"too many allocation entries",
269 	"invalid spell frequency",
270 	"invalid number of items (0-99)",
271 	"too many entries",
272 };
273 
274 
275 #endif /* ALLOW_TEMPLATES */
276 
277 
278 #ifndef RISCOS
279 #ifdef CHECK_MODIFICATION_TIME
280 
check_modification_date(int fd,cptr template_file)281 extern errr check_modification_date(int fd, cptr template_file)
282 {
283 	char buf[1024];
284 
285 	struct stat txt_stat, raw_stat;
286 
287 	/* Build the filename */
288 	path_make(buf, ANGBAND_DIR_EDIT, template_file);
289 
290 	/* Access stats on text file */
291 	if (stat(buf, &txt_stat))
292 	{
293 		/* No text file - continue */
294 	}
295 
296 	/* Access stats on raw file */
297 	else if (fstat(fd, &raw_stat))
298 	{
299 		/* Error */
300 		return (-1);
301 	}
302 
303 	/* Ensure text file is not newer than raw file */
304 	else if (txt_stat.st_mtime > raw_stat.st_mtime)
305 	{
306 		/* Reprocess text file */
307 		return (-1);
308 	}
309 
310 	return (0);
311 }
312 
313 #endif /* CHECK_MODIFICATION_TIME */
314 #endif /* !RISCOS */
315 
316 /*
317  * File headers
318  */
319 header z_head;
320 header v_head;
321 header f_head;
322 header k_head;
323 header a_head;
324 header e_head;
325 header r_head;
326 
327 
328 
329 /*** Initialize from binary image files ***/
330 
331 
332 /*
333  * Initialize a "*_info" array, by parsing a binary "image" file
334  *
335  * If possible, just mmap() the image file directory into memory.
336  * This is faster than reading it from disk, because it delays
337  * the loading until it's actually accessed. It may also save memory.
338  */
init_info_raw(int fd,header * head)339 static errr init_info_raw(int fd, header *head)
340 {
341 	header test;
342 #ifdef HAVE_MMAP
343 	char *data;
344 #endif /* HAVE_MMAP */
345 
346 	/* Read and verify the header */
347 	if (fd_read(fd, (char *)(&test), sizeof(header)) ||
348 		(test.v_major != head->v_major) ||
349 		(test.v_minor != head->v_minor) ||
350 		(test.v_patch != head->v_patch) ||
351 		(test.v_extra != head->v_extra) ||
352 		(test.info_num != head->info_num) ||
353 		(test.info_len != head->info_len) ||
354 		(test.head_size != head->head_size) ||
355 		(test.info_size != head->info_size))
356 	{
357 		/* Error */
358 		return (-1);
359 	}
360 
361 
362 	/* Accept the header */
363 	COPY(head, &test, header);
364 
365 #ifdef HAVE_MMAP
366 	data = mmap(NULL, sizeof(header) + head->info_size +
367 		head->name_size + head->text_size,
368 		PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
369 
370 	if (data != MAP_FAILED)
371 	{
372 		head->mmap_base = data;
373 
374 		/* Skip the header */
375 		data += sizeof(header);
376 
377 		/* Save a pointer to the info */
378 		head->info_ptr = data;
379 		data += head->info_size;
380 
381 		/* Save a pointer to the names */
382 		head->name_ptr = data;
383 		data += head->name_size;
384 
385 		/* Save a pointer to the text */
386 		head->text_ptr = data;
387 	}
388 	else
389 	{
390 #endif /* HAVE_MMAP */
391 
392 		head->mmap_base = NULL;
393 
394 		/* Allocate the "*_info" array */
395 		C_MAKE(head->info_ptr, head->info_size, char);
396 
397 		/* Read the "*_info" array */
398 		fd_read(fd, head->info_ptr, head->info_size);
399 
400 		if (head->name_size)
401 		{
402 			/* Allocate the "*_name" array */
403 			C_MAKE(head->name_ptr, head->name_size, char);
404 
405 			/* Read the "*_name" array */
406 			fd_read(fd, head->name_ptr, head->name_size);
407 		}
408 
409 		if (head->text_size)
410 		{
411 			/* Allocate the "*_text" array */
412 			C_MAKE(head->text_ptr, head->text_size, char);
413 
414 			/* Read the "*_text" array */
415 			fd_read(fd, head->text_ptr, head->text_size);
416 		}
417 
418 #ifdef HAVE_MMAP
419 	}
420 #endif /* HAVE_MMAP */
421 
422 	/* Success */
423 	return (0);
424 }
425 
426 
427 /*
428  * Initialize the header of an *_info.raw file.
429  */
init_header(header * head,int num,int len)430 static void init_header(header *head, int num, int len)
431 {
432 	/* Save the "version" */
433 	head->v_major = VER_MAJOR;
434 	head->v_minor = VER_MINOR;
435 	head->v_patch = VER_PATCH;
436 	head->v_extra = VER_EXTRA;
437 
438 	/* Save the "record" information */
439 	head->info_num = num;
440 	head->info_len = len;
441 
442 	/* Save the size of "*_head" and "*_info" */
443 	head->head_size = sizeof(header);
444 	head->info_size = head->info_num * head->info_len;
445 }
446 
447 
448 #ifdef ALLOW_TEMPLATES
449 
450 /*
451  * Display a parser error message.
452  */
display_parse_error(cptr filename,errr err,cptr buf)453 static void display_parse_error(cptr filename, errr err, cptr buf)
454 {
455 	cptr oops;
456 
457 	/* Error string */
458 	oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
459 
460 	/* Oops */
461 	msgf("Error at line %d of '%s'.", error_line, filename);
462 	msgf("Record %d contains a '%s' error.", error_idx, oops);
463 	msgf("Parsing '%s'.", buf);
464 	message_flush();
465 
466 	/* Quit */
467 	quit_fmt("Error in '%s.txt' file.", filename);
468 }
469 
470 #endif /* ALLOW_TEMPLATES */
471 
472 
473 /*
474  * Initialize a "*_info" array
475  *
476  * Note that we let each entry have a unique "name" and "text" string,
477  * even if the string happens to be empty (everyone has a unique '\0').
478  */
init_info(cptr filename,header * head,void ** info,char ** name,char ** text)479 static errr init_info(cptr filename, header *head,
480                       void **info, char **name, char **text)
481 {
482 	int fd;
483 
484 	errr err = 1;
485 
486 	FILE *fp;
487 
488 	/* General buffer */
489 	char buf[1024];
490 
491 
492 #ifdef ALLOW_TEMPLATES
493 
494 	/*** Load the binary image file ***/
495 
496 	/* Build the filename */
497 	path_make(buf, ANGBAND_DIR_DATA, format("%s.raw", filename));
498 
499 	/* Attempt to open the "raw" file */
500 	fd = fd_open(buf, O_RDONLY);
501 
502 	/* Process existing "raw" file */
503 	if (fd >= 0)
504 	{
505 #ifdef CHECK_MODIFICATION_TIME
506 
507 		err = check_modification_date(fd, format("%s.txt", filename));
508 
509 #endif /* CHECK_MODIFICATION_TIME */
510 
511 		/* Attempt to parse the "raw" file */
512 		if (!err)
513 			err = init_info_raw(fd, head);
514 
515 		/* Close it */
516 		fd_close(fd);
517 	}
518 
519 	/* Do we have to parse the *.txt file? */
520 	if (err)
521 	{
522 		/*** Make the fake arrays ***/
523 
524 		/* Allocate the "*_info" array */
525 		C_MAKE(head->info_ptr, head->info_size, char);
526 
527 		/* Hack -- make "fake" arrays */
528 		if (name)
529 			C_MAKE(head->name_ptr, z_info->fake_name_size, char);
530 
531 		if (text)
532 			C_MAKE(head->text_ptr, z_info->fake_text_size, char);
533 
534 		if (info) (*info) = head->info_ptr;
535 		if (name) (*name) = head->name_ptr;
536 		if (text) (*text) = head->text_ptr;
537 
538 		/*** Load the ascii template file ***/
539 
540 		/* Build the filename */
541 		path_make(buf, ANGBAND_DIR_EDIT, format("%s.txt", filename));
542 
543 		/* Open the file */
544 		fp = my_fopen(buf, "r");
545 
546 		/* Parse it */
547 		if (!fp) quit_fmt("Cannot open '%s.txt' file.", filename);
548 
549 		/* Parse the file */
550 		err = init_info_txt(fp, buf, head, head->parse_info_txt);
551 
552 		/* Close it */
553 		my_fclose(fp);
554 
555 		/* Errors */
556 		if (err) display_parse_error(filename, err, buf);
557 
558 
559 		/*** Dump the binary image file ***/
560 
561 		/* File type is "DATA" */
562 		FILE_TYPE(FILE_TYPE_DATA);
563 
564 		/* Build the filename */
565 		path_make(buf, ANGBAND_DIR_DATA, format("%s.raw", filename));
566 
567 
568 		/* Attempt to open the file */
569 		fd = fd_open(buf, O_RDONLY);
570 
571 		/* Failure */
572 		if (fd < 0)
573 		{
574 			int mode = 0644;
575 
576 			/* Grab permissions */
577 			safe_setuid_grab();
578 
579 			/* Create a new file */
580 			fd = fd_make(buf, mode);
581 
582 			/* Drop permissions */
583 			safe_setuid_drop();
584 
585 			/* Failure */
586 			if (fd < 0)
587 			{
588 				/* Crash and burn */
589 				quit_fmt("Cannot create the '%s' file!", buf);
590 			}
591 		}
592 
593 		/* Close it */
594 		fd_close(fd);
595 
596 		/* Grab permissions */
597 		safe_setuid_grab();
598 
599 		/* Attempt to create the raw file */
600 		fd = fd_open(buf, O_WRONLY);
601 
602 		/* Drop permissions */
603 		safe_setuid_drop();
604 
605 		/* Dump to the file */
606 		if (fd >= 0)
607 		{
608 			/* Dump it */
609 			fd_write(fd, (cptr)head, head->head_size);
610 
611 			/* Dump the "*_info" array */
612 			fd_write(fd, head->info_ptr, head->info_size);
613 
614 			/* Dump the "*_name" array */
615 			fd_write(fd, head->name_ptr, head->name_size);
616 
617 			/* Dump the "*_text" array */
618 			fd_write(fd, head->text_ptr, head->text_size);
619 
620 			/* Close */
621 			fd_close(fd);
622 		}
623 
624 
625 		/*** Kill the fake arrays ***/
626 
627 		/* Free the "*_info" array */
628 		KILL(head->info_ptr);
629 
630 		/* Hack -- Free the "fake" arrays */
631 		if (name)
632 			KILL(head->name_ptr);
633 
634 		if (text)
635 			KILL(head->text_ptr);
636 
637 #endif /* ALLOW_TEMPLATES */
638 
639 
640 		/*** Load the binary image file ***/
641 
642 		/* Build the filename */
643 		path_make(buf, ANGBAND_DIR_DATA, format("%s.raw", filename));
644 
645 		/* Attempt to open the "raw" file */
646 		fd = fd_open(buf, O_RDONLY);
647 
648 		/* Process existing "raw" file */
649 		if (fd < 0) quit_fmt("Cannot load '%s.raw' file.", filename);
650 
651 		/* Attempt to parse the "raw" file */
652 		err = init_info_raw(fd, head);
653 
654 		/* Close it */
655 		fd_close(fd);
656 
657 		/* Error */
658 		if (err) quit_fmt("Cannot parse '%s.raw' file.", filename);
659 
660 #ifdef ALLOW_TEMPLATES
661 	}
662 #endif /* ALLOW_TEMPLATES */
663 
664 	if (info) (*info) = head->info_ptr;
665 	if (name) (*name) = head->name_ptr;
666 	if (text) (*text) = head->text_ptr;
667 
668 	/* Success */
669 	return (0);
670 }
671 
672 
673 /*
674  * Free the allocated memory for the info-, name-, and text- arrays.
675  */
free_info(header * head)676 static errr free_info(header *head)
677 {
678 #ifdef HAVE_MMAP
679 	if (head->mmap_base)
680 	{
681 		munmap(head->mmap_base, sizeof(header) + head->info_size +
682 			head->name_size + head->text_size);
683 
684 		/* Success */
685 		return (0);
686 	}
687 #endif /* HAVE_MMAP */
688 
689 	if (head->info_size)
690 		FREE(head->info_ptr);
691 
692 	if (head->name_size)
693 		FREE(head->name_ptr);
694 
695 	if (head->text_size)
696 		FREE(head->text_ptr);
697 
698 	/* Success */
699 	return (0);
700 }
701 
702 
703 /*
704  * Initialize the "z_info" array
705  */
init_z_info(void)706 static errr init_z_info(void)
707 {
708 	/* Init the header */
709 	init_header(&z_head, 1, sizeof(maxima));
710 
711 #ifdef ALLOW_TEMPLATES
712 
713 	/* Save a pointer to the parsing function */
714 	z_head.parse_info_txt = parse_z_info;
715 
716 #endif /* ALLOW_TEMPLATES */
717 
718 	return init_info("misc", &z_head, (void *)&z_info, NULL, NULL);
719 }
720 
721 
722 /*
723  * Initialize the "f_info" array
724  */
init_f_info(void)725 static errr init_f_info(void)
726 {
727 	/* Init the header */
728 	init_header(&f_head, z_info->f_max, sizeof(feature_type));
729 
730 #ifdef ALLOW_TEMPLATES
731 
732 	/* Save a pointer to the parsing function */
733 	f_head.parse_info_txt = parse_f_info;
734 
735 #endif /* ALLOW_TEMPLATES */
736 
737 	return init_info("f_info", &f_head,
738 					 (void *)&f_info, (void *)&f_name, (void *)&f_text);
739 }
740 
741 
742 
743 /*
744  * Initialize the "k_info" array
745  */
init_k_info(void)746 static errr init_k_info(void)
747 {
748 	/* Init the header */
749 	init_header(&k_head, z_info->k_max, sizeof(object_kind));
750 
751 #ifdef ALLOW_TEMPLATES
752 
753 	/* Save a pointer to the parsing function */
754 	k_head.parse_info_txt = parse_k_info;
755 
756 #endif /* ALLOW_TEMPLATES */
757 
758 	return init_info("k_info", &k_head,
759 					 (void *)&k_info, (void *)&k_name, (void *)&k_text);
760 }
761 
762 
763 
764 /*
765  * Initialize the "a_info" array
766  */
init_a_info(void)767 static errr init_a_info(void)
768 {
769 	/* Init the header */
770 	init_header(&a_head, z_info->a_max, sizeof(artifact_type));
771 
772 #ifdef ALLOW_TEMPLATES
773 
774 	/* Save a pointer to the parsing function */
775 	a_head.parse_info_txt = parse_a_info;
776 
777 #endif /* ALLOW_TEMPLATES */
778 
779 	return init_info("a_info", &a_head,
780 					 (void *)&a_info, (void *)&a_name, (void *)&a_text);
781 }
782 
783 
784 
785 /*
786  * Initialize the "e_info" array
787  */
init_e_info(void)788 static errr init_e_info(void)
789 {
790 	/* Init the header */
791 	init_header(&e_head, z_info->e_max, sizeof(ego_item_type));
792 
793 #ifdef ALLOW_TEMPLATES
794 
795 	/* Save a pointer to the parsing function */
796 	e_head.parse_info_txt = parse_e_info;
797 
798 #endif /* ALLOW_TEMPLATES */
799 
800 	return init_info("e_info", &e_head,
801 					 (void *)&e_info, (void *)&e_name, (void *)&e_text);
802 }
803 
804 
805 
806 /*
807  * Initialize the "r_info" array
808  */
init_r_info(void)809 static errr init_r_info(void)
810 {
811 	/* Init the header */
812 	init_header(&r_head, z_info->r_max, sizeof(monster_race));
813 
814 #ifdef ALLOW_TEMPLATES
815 
816 	/* Save a pointer to the parsing function */
817 	r_head.parse_info_txt = parse_r_info;
818 
819 #endif /* ALLOW_TEMPLATES */
820 
821 	return init_info("r_info", &r_head,
822 					 (void *)&r_info, (void *)&r_name, (void *)&r_text);
823 }
824 
825 
826 
827 /*
828  * Initialize the "v_info" array
829  */
init_v_info(void)830 static errr init_v_info(void)
831 {
832 	/* Init the header */
833 	init_header(&v_head, z_info->v_max, sizeof(vault_type));
834 
835 #ifdef ALLOW_TEMPLATES
836 
837 	/* Save a pointer to the parsing function */
838 	v_head.parse_info_txt = parse_v_info;
839 
840 #endif /* ALLOW_TEMPLATES */
841 
842 	return init_info("v_info", &v_head,
843 					 (void *)&v_info, (void *)&v_name, (void *)&v_text);
844 }
845 
846 
847 
848 
849 /*** Initialize others ***/
850 
851 
852 
853 
854 /*
855  * Initialize the "wild_choice_tree" array and the
856  * "wild_gen_data" array.
857  *
858  */
init_w_info(void)859 errr init_w_info(void)
860 {
861 	errr err;
862 
863 	FILE *fp;
864 
865 	/* General buffer */
866 	char buf[1024];
867 
868 
869 	/* Later must add in raw file support later. */
870 	C_MAKE(wild_choice_tree, z_info->wn_max, wild_choice_tree_type);
871 	C_MAKE(wild_gen_data, z_info->wt_max, wild_gen_data_type);
872 
873 	/*** Load the ascii template file ***/
874 
875 	/* Build the filename */
876 	path_make(buf, ANGBAND_DIR_EDIT, "w_info.txt");
877 
878 	/* Open the file */
879 	fp = my_fopen(buf, "r");
880 
881 	/* Parse it */
882 	if (!fp) quit("Cannot open 'w_info.txt' file.");
883 
884 	/* Parse the file */
885 	err = init_w_info_txt(fp, buf);
886 
887 	/* Close it */
888 	my_fclose(fp);
889 
890 	/* Errors */
891 	if (err)
892 	{
893 		cptr oops;
894 
895 		/* Error string */
896 		oops =
897 			(((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
898 
899 		/* Oops */
900 		msgf("Error %d at line %d of 'w_info.txt'.", err, error_line);
901 		msgf("Record %d contains a '%s' error.", error_idx, oops);
902 		msgf("Parsing '%s'.", buf);
903 		message_flush();
904 
905 		/* Quit */
906 		quit("Error in 'w_info.txt' file.");
907 	}
908 
909 	/* Success */
910 	return (0);
911 }
912 
913 /*
914  * Initialize the field data structures
915  */
init_t_info(void)916 errr init_t_info(void)
917 {
918 	errr err;
919 
920 	FILE *fp;
921 
922 	/* General buffer */
923 	char buf[1024];
924 
925 	/* Later must add in python support. */
926 	C_MAKE(t_info, z_info->t_max, field_thaum);
927 	C_MAKE(fld_list, z_info->fld_max, field_type);
928 
929 
930 	/*** Load the ascii template file ***/
931 
932 	/* Build the filename */
933 	path_make(buf, ANGBAND_DIR_EDIT, "t_info.txt");
934 
935 	/* Open the file */
936 	fp = my_fopen(buf, "r");
937 
938 	/* Parse it */
939 	if (!fp) quit("Cannot open 't_info.txt' file.");
940 
941 	/* Parse the file */
942 	err = init_t_info_txt(fp, buf);
943 
944 	/* Close it */
945 	my_fclose(fp);
946 
947 	/* Errors */
948 	if (err)
949 	{
950 		cptr oops;
951 
952 		/* Error string */
953 		oops =
954 			(((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
955 
956 		/* Oops */
957 		msgf("Error %d at line %d of 't_info.txt'.", err, error_line);
958 		msgf("Record %d contains a '%s' error.", error_idx, oops);
959 		msgf("Parsing '%s'.", buf);
960 		message_flush();
961 
962 		/* Quit */
963 		quit("Error in 't_info.txt' file.");
964 	}
965 
966 	/* Success */
967 	return (0);
968 }
969 
970 /*
971  * The list of available format functions
972  *
973  * (They should be in order of most-called
974  *  through to least-called.)
975  */
976 static vstrnfmt_aux_func my_format_functions[9] =
977 {
978 	set_message_type,
979 	object_fmt,
980 	object_store_fmt,
981 	monster_fmt,
982 	stat_format,
983 	center_string,
984 	likert,
985 	binary_fmt,
986 	NULL
987 };
988 
989 
990 /*
991  * Initialize some other arrays
992  */
init_other(void)993 static errr init_other(void)
994 {
995 	int i, j, k, n;
996 
997 	/*** Pre-allocate space for the "format()" buffer ***/
998 
999 	/* Hack -- Just call the "format()" function */
1000 	(void)format("%s (%s).", "Steven Fuerst", MAINTAINER);
1001 
1002 	/* Initialise the "%v" user-defined format function list */
1003 	register_format_funcs(my_format_functions);
1004 
1005 
1006 	/*** Prepare the various "bizarre" arrays ***/
1007 
1008 	/* Macro variables */
1009 	C_MAKE(macro__pat, MACRO_MAX, cptr);
1010 	C_MAKE(macro__act, MACRO_MAX, cptr);
1011 	C_MAKE(macro__cmd, MACRO_MAX, bool);
1012 
1013 	/* Macro action buffer */
1014 	C_MAKE(macro__buf, 1024, char);
1015 
1016 
1017 	/* Clear the spell colour strings */
1018 	(void)C_WIPE(gf_color, MAX_GF, cptr);
1019 
1020 
1021 	/* Initialize the "quark" package */
1022 	(void)quarks_init();
1023 
1024 	/* Initialize the "message" package */
1025 	(void)messages_init();
1026 
1027 
1028 	/*** Prepare region list ***/
1029 	C_MAKE(rg_list, z_info->rg_max, region_type);
1030 	C_MAKE(ri_list, z_info->rg_max, region_info);
1031 
1032 
1033 	/*** Hack - Allocate the player information for each grid ***/
1034 	for (i = 0; i < MAX_HGT; i++)
1035 	{
1036 		/* Allocate one row of the cave */
1037 		C_MAKE(p_ptr->pcave[i], MAX_WID, pcave_type);
1038 	}
1039 
1040 	/*** Prepare wilderness stuff ***/
1041 
1042 	/* Allocate temporary wilderness block */
1043 	for (i = 0; i < WILD_BLOCK_SIZE + 1; i++)
1044 	{
1045 		/* Allocate one row of the temp_block */
1046 		C_MAKE(temp_block[i], WILD_BLOCK_SIZE + 1, u16b);
1047 	}
1048 
1049 	/* Make the list of pointers to blocks */
1050 	C_MAKE(wild_cache, WILD_CACHE, blk_ptr);
1051 
1052 	/* Allocate each block */
1053 	for (i = 0; i < WILD_CACHE; i++)
1054 	{
1055 		/* Allocate block */
1056 		C_MAKE(wild_cache[i], WILD_BLOCK_SIZE, cave_type *);
1057 
1058 		/* Allocate rows of a block */
1059 		for (j = 0; j < WILD_BLOCK_SIZE; j++)
1060 		{
1061 			C_MAKE(wild_cache[i][j], WILD_BLOCK_SIZE, cave_type);
1062 		}
1063 	}
1064 
1065 	/* Allocate the player information for each grid (wilderness) */
1066 
1067 	/* Allocate WILD_VIEW by WILD_VIEW blocks */
1068 	C_MAKE(p_ptr->pwild, WILD_VIEW, pblk_ptr *);
1069 
1070 	for (i = 0; i < WILD_VIEW; i++)
1071 	{
1072 		C_MAKE(p_ptr->pwild[i], WILD_VIEW, pblk_ptr);
1073 
1074 		/* Allocate each block */
1075 		for (j = 0; j < WILD_VIEW; j++)
1076 		{
1077 			C_MAKE(p_ptr->pwild[i][j], WILD_BLOCK_SIZE, pcave_type *);
1078 
1079 			for (k = 0; k < WILD_BLOCK_SIZE; k++)
1080 			{
1081 				C_MAKE(p_ptr->pwild[i][j][k], WILD_BLOCK_SIZE, pcave_type);
1082 			}
1083 		}
1084 	}
1085 
1086 	/* Allocate the wilderness itself */
1087 	C_MAKE(wild, WILD_SIZE, wild_type *);
1088 	C_MAKE(wild_grid, WILD_SIZE, blk_ptr *);
1089 	C_MAKE(wild_refcount, WILD_SIZE, int *);
1090 
1091 	for (i = 0; i < WILD_SIZE; i++)
1092 	{
1093 		/* Allocate one row of the wilderness */
1094 		C_MAKE(wild[i], WILD_SIZE, wild_type);
1095 		C_MAKE(wild_grid[i], WILD_SIZE, blk_ptr);
1096 		C_MAKE(wild_refcount[i], WILD_SIZE, int);
1097 	}
1098 
1099 	/*** Prepare "vinfo" array ***/
1100 
1101 	/* Used by "update_view()" */
1102 	(void)vinfo_init();
1103 
1104 
1105 	/*** Prepare entity arrays ***/
1106 
1107 	/* Objects */
1108 	C_MAKE(o_list, z_info->o_max, object_type);
1109 
1110 	/* Monsters */
1111 	C_MAKE(m_list, z_info->m_max, monster_type);
1112 
1113 	/*** Prepare the options ***/
1114 
1115 
1116 	init_options(OPT_FLAG_BIRTH | OPT_FLAG_SERVER | OPT_FLAG_PLAYER);
1117 
1118 	/* Initialize the options */
1119 	for (i = 0; i < OPT_MAX; i++)
1120 	{
1121 		if (option_info[i].o_text)
1122 		{
1123 			/* Accept */
1124 			option_mask[i / 32] |= (1L << (i % 32));
1125 		}
1126 	}
1127 
1128 
1129 	/* Initialize the window flags */
1130 	for (n = 0; n < ANGBAND_TERM_MAX; n++)
1131 	{
1132 		/* Analyze the options */
1133 		for (i = 0; i < 32; i++)
1134 		{
1135 			/* Accept */
1136 			if (window_flag_desc[i])
1137 			{
1138 				/* Accept */
1139 				window_mask[n] |= (1L << i);
1140 			}
1141 		}
1142 	}
1143 
1144 
1145 	/*** Make store stock cache ***/
1146 
1147 	C_MAKE(store_cache, STORE_CACHE_AMNT, store_type *);
1148 
1149 	/* Allocate the towns */
1150 	C_MAKE(place, z_info->wp_max, place_type);
1151 
1152 	/* Get size of shop owner name arrays */
1153 	for (i = 0; owner_names[i]; i++)
1154 	{
1155 		/* Do nothing */
1156 	}
1157 	owner_names_max = i;
1158 
1159 	for (i = 0; owner_suffix[i]; i++)
1160 	{
1161 		/* Do nothing */
1162 	}
1163 	owner_suffix_max = i;
1164 
1165 
1166 	/* Success */
1167 	return (0);
1168 }
1169 
1170 
1171 
1172 /*
1173  * Initialize some other arrays
1174  */
init_alloc(void)1175 static errr init_alloc(void)
1176 {
1177 	int i;
1178 	monster_race *r_ptr;
1179 
1180 	alloc_entry *table;
1181 	s16b num[MAX_DEPTH];
1182 	s16b aux[MAX_DEPTH];
1183 
1184 	/*** Analyze monster allocation info ***/
1185 
1186 	/* Clear the "aux" array */
1187 	(void)C_WIPE(&aux, MAX_DEPTH, s16b);
1188 
1189 	/* Clear the "num" array */
1190 	(void)C_WIPE(&num, MAX_DEPTH, s16b);
1191 
1192 	/* Size of "alloc_race_table" */
1193 	alloc_race_size = 0;
1194 
1195 	/* Scan the monsters (not the ghost) */
1196 	for (i = 1; i < z_info->r_max - 1; i++)
1197 	{
1198 		/* Get the i'th race */
1199 		r_ptr = &r_info[i];
1200 
1201 		/* Legal monsters */
1202 		if (r_ptr->rarity)
1203 		{
1204 			/* Count the entries */
1205 			alloc_race_size++;
1206 
1207 			/* Group by level */
1208 			num[r_ptr->level]++;
1209 		}
1210 	}
1211 
1212 	/* Collect the level indexes */
1213 	for (i = 1; i < MAX_DEPTH; i++)
1214 	{
1215 		/* Group by level */
1216 		num[i] += num[i - 1];
1217 	}
1218 
1219 	/* Paranoia */
1220 	if (!num[0]) quit("No town monsters!");
1221 
1222 
1223 	/*** Initialize monster allocation info ***/
1224 
1225 	/* Allocate the alloc_race_table */
1226 	C_MAKE(alloc_race_table, alloc_race_size, alloc_entry);
1227 
1228 	/* Get the table entry */
1229 	table = alloc_race_table;
1230 
1231 	/* Scan the monsters */
1232 	for (i = 1; i < z_info->r_max; i++)
1233 	{
1234 		/* Get the i'th race */
1235 		r_ptr = &r_info[i];
1236 
1237 		/* Count valid pairs */
1238 		if (r_ptr->rarity)
1239 		{
1240 			int p, x, y, z;
1241 
1242 			/* Extract the base level */
1243 			x = r_ptr->level;
1244 
1245 			/* Extract the base probability */
1246 			p = (100 / r_ptr->rarity);
1247 
1248 			/* Skip entries preceding our locale */
1249 			y = (x > 0) ? num[x - 1] : 0;
1250 
1251 			/* Skip previous entries at this locale */
1252 			z = y + aux[x];
1253 
1254 			/* Load the entry */
1255 			table[z].index = i;
1256 			table[z].level = x;
1257 			table[z].prob1 = p;
1258 			table[z].prob2 = p;
1259 			table[z].prob3 = p;
1260 
1261 			/* Another entry complete for this locale */
1262 			aux[x]++;
1263 		}
1264 	}
1265 
1266 	/* Init "alloc_kind_table" and "alloc_ego_table" */
1267 	(void)init_object_alloc();
1268 
1269 	/* Success */
1270 	return (0);
1271 }
1272 
1273 
1274 /*
1275  * Hack -- take notes on line 23
1276  */
note(cptr str)1277 static void note(cptr str)
1278 {
1279 	clear_row(23);
1280 	put_fstr(20, 23, str);
1281 	Term_fresh();
1282 }
1283 
1284 
1285 
1286 /*
1287  * Hack -- Explain a broken "lib" folder and quit (see below).
1288  *
1289  * XXX XXX XXX This function is "messy" because various things
1290  * may or may not be initialized, but the "plog()" and "quit()"
1291  * functions are "supposed" to work under any conditions.
1292  */
init_angband_fail(void)1293 static void init_angband_fail(void)
1294 {
1295 	/* Explain */
1296 	plog("The 'lib' directory is probably missing or broken.");
1297 
1298 	/* More details */
1299 	plog("Perhaps the archive was not extracted correctly.");
1300 
1301 	/* Explain */
1302 	plog("See the 'README' file for more information.");
1303 
1304 	/* Quit with error */
1305 	quit("Fatal Error.");
1306 }
1307 
1308 
1309 /*
1310  * Hack -- main Angband initialization entry point
1311  *
1312  * Verify some files, display the "news.txt" file, create
1313  * the high score file, initialize all internal arrays, and
1314  * load the basic "user pref files".
1315  *
1316  * Be very careful to keep track of the order in which things
1317  * are initialized, in particular, the only thing *known* to
1318  * be available when this function is called is the "z-term.c"
1319  * package, and that may not be fully initialized until the
1320  * end of this function, when the default "user pref files"
1321  * are loaded and "Term_xtra(TERM_XTRA_REACT,0)" is called.
1322  *
1323  * Note that this function attempts to verify the "news" file,
1324  * and the game aborts (cleanly) on failure, since without the
1325  * "news" file, it is likely that the "lib" folder has not been
1326  * correctly located.  Otherwise, the news file is displayed for
1327  * the user.
1328  *
1329  * Note that this function attempts to verify (or create) the
1330  * "high score" file, and the game aborts (cleanly) on failure,
1331  * since one of the most common "extraction" failures involves
1332  * failing to extract all sub-directories (even empty ones), such
1333  * as by failing to use the "-d" option of "pkunzip", or failing
1334  * to use the "save empty directories" option with "Compact Pro".
1335  * This error will often be caught by the "high score" creation
1336  * code below, since the "lib/apex" directory, being empty in the
1337  * standard distributions, is most likely to be "lost", making it
1338  * impossible to create the high score file.
1339  *
1340  * Note that various things are initialized by this function,
1341  * including everything that was once done by "init_some_arrays".
1342  *
1343  * This initialization involves the parsing of special files
1344  * in the "lib/data" and sometimes the "lib/edit" directories.
1345  *
1346  * Note that the "template" files are initialized first, since they
1347  * often contain errors.  This means that macros and message recall
1348  * and things like that are not available until after they are done.
1349  *
1350  * We load the default "user pref files" here in case any "color"
1351  * changes are needed before character creation.
1352  *
1353  * Note that the "graf-xxx.prf" file must be loaded separately,
1354  * if needed, in the first (?) pass through "TERM_XTRA_REACT".
1355  */
init_angband(void)1356 void init_angband(void)
1357 {
1358 	int fd = -1;
1359 
1360 	int mode = 0644;
1361 
1362 	FILE *fp;
1363 
1364 	char buf[1024];
1365 
1366 
1367 	/*** Verify the "news" file ***/
1368 
1369 	/* Build the filename */
1370 	path_make(buf, ANGBAND_DIR_FILE, "news.txt");
1371 
1372 	/* Attempt to open the file */
1373 	fd = fd_open(buf, O_RDONLY);
1374 
1375 	/* Failure */
1376 	if (fd < 0)
1377 	{
1378 		/* Message */
1379 		plog_fmt("Cannot access the '%s' file!", buf);
1380 
1381 		/* Crash and burn */
1382 		init_angband_fail();
1383 	}
1384 
1385 	/* Close it */
1386 	(void)fd_close(fd);
1387 
1388 
1389 	/*** Display the "news" file ***/
1390 
1391 	/* Clear screen */
1392 	Term_clear();
1393 
1394 	/* Build the filename */
1395 	path_make(buf, ANGBAND_DIR_FILE, "news.txt");
1396 
1397 	/* Open the News file */
1398 	fp = my_fopen(buf, "r");
1399 
1400 	/* Dump */
1401 	if (fp)
1402 	{
1403 		int i = 0;
1404 
1405 		/* Dump the file to the screen */
1406 		while (0 == my_fgets(fp, buf, 1024))
1407 		{
1408 			/* Display and advance */
1409 			put_fstr(0, i++, buf);
1410 		}
1411 
1412 		/* Close */
1413 		my_fclose(fp);
1414 	}
1415 
1416 	/* Display version number */
1417 	put_fstr(42, 3, "%d.%d.%d", VER_MAJOR, VER_MINOR, VER_PATCH);
1418 
1419 	/* Flush it */
1420 	Term_fresh();
1421 
1422 
1423 	/*** Verify (or create) the "high score" file ***/
1424 
1425 	/* Build the filename */
1426 	path_make(buf, ANGBAND_DIR_APEX, "scores.raw");
1427 
1428 	/* Attempt to open the high score file */
1429 	fd = fd_open(buf, O_RDONLY);
1430 
1431 	/* Failure */
1432 	if (fd < 0)
1433 	{
1434 		/* File type is "DATA" */
1435 		FILE_TYPE(FILE_TYPE_DATA);
1436 
1437 		/* Grab permissions */
1438 		safe_setuid_grab();
1439 
1440 		/* Create a new high score file */
1441 		fd = fd_make(buf, mode);
1442 
1443 		/* Drop permissions */
1444 		safe_setuid_drop();
1445 
1446 		/* Failure */
1447 		if (fd < 0)
1448 		{
1449 			/* Message */
1450 			plog_fmt("Cannot create the '%s' file!", buf);
1451 
1452 			/* Crash and burn */
1453 			init_angband_fail();
1454 		}
1455 	}
1456 
1457 	/* Close it */
1458 	(void)fd_close(fd);
1459 
1460 
1461 	/*** Initialize some arrays ***/
1462 
1463 	/* Init the interface callbacks */
1464 	init_term_callbacks();
1465 
1466 	/* Initialize size info */
1467 	note("[Initializing array sizes...]");
1468 	if (init_z_info()) quit("Cannot initialize sizes");
1469 
1470 	/* Initialize scripting */
1471 	note("[Initializing scripts... (scripts)]");
1472 	if (script_init()) quit("Cannot initialize scripts");
1473 
1474 	/* Initialize feature info */
1475 	note("[Initializing arrays... (features)]");
1476 	if (init_f_info()) quit("Cannot initialize features");
1477 
1478 	/* Initialize object info */
1479 	note("[Initializing arrays... (objects)]");
1480 	if (init_k_info()) quit("Cannot initialize objects");
1481 
1482 	/* Initialize artifact info */
1483 	note("[Initializing arrays... (artifacts)]");
1484 	if (init_a_info()) quit("Cannot initialize artifacts");
1485 
1486 	/* Initialize ego-item info */
1487 	note("[Initializing arrays... (ego-items)]");
1488 	if (init_e_info()) quit("Cannot initialize ego-items");
1489 
1490 	/* Initialize monster info */
1491 	note("[Initializing arrays... (monsters)]");
1492 	if (init_r_info()) quit("Cannot initialize monsters");
1493 
1494 	/* Initialize feature info */
1495 	note("[Initializing arrays... (vaults)]");
1496 	if (init_v_info()) quit("Cannot initialize vaults");
1497 
1498 	/* Initialize quest array */
1499 	note("[Initializing arrays... (quests)]");
1500 	if (init_quests()) quit("Cannot initialize quests");
1501 
1502 	/* Initialize some other arrays */
1503 	note("[Initializing arrays... (other)]");
1504 	if (init_other()) quit("Cannot initialize other stuff");
1505 
1506 	/* Initialize some other arrays */
1507 	note("[Initializing arrays... (alloc)]");
1508 	if (init_alloc()) quit("Cannot initialize alloc stuff");
1509 
1510 
1511 	/*** Load default user pref files ***/
1512 
1513 	/* Initialize feature info */
1514 	note("[Initializing user pref files...]");
1515 
1516 	/* Access the "basic" pref file */
1517 	(void)process_pref_file("pref.prf");
1518 
1519 	/* Access the "user" pref file */
1520 	(void)process_pref_file("user.prf");
1521 
1522 	/* Initialise the fake monochrome flag */
1523 	fake_monochrome = (!use_graphics
1524 					   || streq(ANGBAND_SYS, "ibm")) ? TRUE : FALSE;
1525 
1526 	/* Initialise the overhead map */
1527 	init_overhead_map();
1528 
1529 	/* Done */
1530 	note("[Initialization complete]");
1531 }
1532 
1533 
1534 
1535 
cleanup_angband(void)1536 void cleanup_angband(void)
1537 {
1538 	int i, j;
1539 
1540 	/* Free the macros */
1541 	for (i = 0; i < macro__num; ++i)
1542 	{
1543 		string_free(macro__pat[i]);
1544 		string_free(macro__act[i]);
1545 	}
1546 
1547 	FREE((void *)macro__pat);
1548 	FREE((void *)macro__act);
1549 
1550 	/* Free the keymaps */
1551 	for (i = 0; i < KEYMAP_MODES; ++i)
1552 	{
1553 		for (j = 0; j < 256; ++j)
1554 		{
1555 			string_free(keymap_act[i][j]);
1556 		}
1557 	}
1558 
1559 	/* Free the allocation tables */
1560 	FREE(alloc_ego_table);
1561 	FREE(alloc_race_table);
1562 	FREE(alloc_kind_table);
1563 
1564 	/* Free the towns */
1565 	FREE(place);
1566 
1567 	/* Free the stores */
1568 	FREE(store_cache);
1569 
1570 	/* Free the quest list */
1571 	FREE(quest);
1572 
1573 	/* Free the lore, monster, and object lists */
1574 	FREE(m_list);
1575 	FREE(o_list);
1576 
1577 #ifdef MONSTER_FLOW
1578 
1579 	/* Flow arrays */
1580 	FREE(cave_when);
1581 	FREE(cave_cost);
1582 
1583 #endif /* MONSTER_FLOW */
1584 
1585 	/* Delete the overhead map */
1586 	del_overhead_map();
1587 
1588 /*
1589  * Note that this causes problems if Zangband exits due to an error
1590  * parsing the info files since at that point the wilderness is not
1591  * initiated. It works fine thereafter.
1592  */
1593 #if 0
1594 
1595 	This code is wrong - the wilderness works differently now. - SF -
1596 		/* Free the wilderness */
1597 	for (i = 0; i < WILD_SIZE; i++)
1598 	{
1599 		/* Free one row of the wilderness */
1600 		FREE(wild[i]);
1601 	}
1602 
1603 	/* Free the wilderness itself */
1604 	FREE(wild);
1605 
1606 
1607 	/* Free cache of wilderness blocks */
1608 	for (i = 0; i < WILD_BLOCKS; i++)
1609 	{
1610 		/* Free rows of a block */
1611 		for (j = 0; j < WILD_BLOCK_SIZE; j++)
1612 		{
1613 			FREE(wild_cache[i][j]);
1614 		}
1615 
1616 		/* Free block */
1617 		FREE(wild_cache[i]);
1618 	}
1619 
1620 	/* Free temporary wilderness block */
1621 	for (i = 0; i < WILD_BLOCK_SIZE + 1; i++)
1622 	{
1623 		/* Allocate one row of the temp_block */
1624 		FREE(temp_block[i]);
1625 	}
1626 
1627 	/* Free the cave */
1628 	for (i = 0; i < MAX_HGT; i++)
1629 	{
1630 		/* Allocate one row of the cave */
1631 		FREE(cave[i]);
1632 	}
1633 #endif /* 0 */
1634 
1635 	/* Free the messages */
1636 	messages_free();
1637 
1638 	/* Free the "quarks" */
1639 	quarks_free();
1640 
1641 	/* Free the info, name, and text arrays */
1642 	free_info(&v_head);
1643 	free_info(&r_head);
1644 	free_info(&e_head);
1645 	free_info(&a_head);
1646 	free_info(&k_head);
1647 	free_info(&f_head);
1648 	free_info(&z_head);
1649 
1650 	/* Free the interface callbacks */
1651 	free_term_callbacks();
1652 
1653 	/* Free the directories */
1654 	string_free(ANGBAND_DIR);
1655 	string_free(ANGBAND_DIR_APEX);
1656 	string_free(ANGBAND_DIR_BONE);
1657 	string_free(ANGBAND_DIR_DATA);
1658 	string_free(ANGBAND_DIR_EDIT);
1659 	string_free(ANGBAND_DIR_SCRIPT);
1660 	string_free(ANGBAND_DIR_FILE);
1661 	string_free(ANGBAND_DIR_HELP);
1662 	string_free(ANGBAND_DIR_INFO);
1663 	string_free(ANGBAND_DIR_SAVE);
1664 	string_free(ANGBAND_DIR_PREF);
1665 	string_free(ANGBAND_DIR_USER);
1666 	string_free(ANGBAND_DIR_XTRA);
1667 }
1668