1 /* SCCS Id: @(#)makedefs.c 3.4 2002/08/14 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* Copyright (c) M. Stephenson, 1990, 1991. */
4 /* Copyright (c) Dean Luick, 1990. */
5 /* NetHack may be freely redistributed. See license for details. */
7 #define MAKEDEFS_C /* use to conditionally include file sections */
8 /* #define DEBUG */ /* uncomment for debugging info */
22 /* version information */
23 #ifdef SHORT_FILENAMES
26 #include "patchlevel.h"
30 # if defined(__SC__) || defined(__MRC__) /* MPW compilers */
32 #include <CursorCtl.h>
35 # else /* MAC without MPWTOOL */
36 # define MACsansMPWTOOL
41 # define SpinCursor(x)
44 #define Fprintf (void) fprintf
45 #define Fclose (void) fclose
46 #define Unlink (void) unlink
47 #if !defined(AMIGA) || defined(AZTEC_C)
48 #define rewind(fp) fseek((fp),0L,SEEK_SET) /* guarantee a return value */
51 #if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
52 static const char SCCS_Id[] = "@(#)makedefs.c\t3.4\t2002/02/03";
55 /* names of files to be generated */
56 #define DATE_FILE "date.h"
57 #define MONST_FILE "pm.h"
58 #define ONAME_FILE "onames.h"
60 #define OPTIONS_FILE "options"
62 #define ORACLE_FILE "oracles"
63 #define DATA_FILE "data"
64 #define RUMOR_FILE "rumors"
65 #define DGN_I_FILE "dungeon.def"
66 #define DGN_O_FILE "dungeon.pdf"
67 #define MON_STR_C "monstr.c"
68 #define QTXT_I_FILE "quest.txt"
69 #define QTXT_O_FILE "quest.dat"
70 #define VIS_TAB_H "vis_tab.h"
71 #define VIS_TAB_C "vis_tab.c"
72 /* locations for those files */
75 # define INCLUDE_TEMPLATE "NH:include/t.%s"
76 # define SOURCE_TEMPLATE "NH:src/%s"
77 # define DGN_TEMPLATE "NH:dat/%s" /* where dungeon.pdf file goes */
78 # define DATA_TEMPLATE "NH:slib/%s"
79 # define DATA_IN_TEMPLATE "NH:dat/%s"
81 # if defined(MAC) && !defined(__MACH__)
82 /* MacOS 9 or earlier */
83 # define INCLUDE_TEMPLATE ":include:%s"
84 # define SOURCE_TEMPLATE ":src:%s"
85 # define DGN_TEMPLATE ":dat:%s" /* where dungeon.pdf file goes */
86 # if __SC__ || __MRC__
87 # define DATA_TEMPLATE ":Dungeon:%s"
89 # define DATA_TEMPLATE ":lib:%s"
90 # endif /* __SC__ || __MRC__ */
91 # define DATA_IN_TEMPLATE ":dat:%s"
92 # else /* neither AMIGA nor MAC */
94 # define INCLUDE_TEMPLATE "..\\include\\%s"
95 # define SOURCE_TEMPLATE "..\\src\\%s"
96 # define DGN_TEMPLATE "..\\dat\\%s" /* where dungeon.pdf file goes */
97 # define DATA_TEMPLATE "..\\dat\\%s"
98 # define DATA_IN_TEMPLATE "..\\dat\\%s"
99 # else /* not AMIGA, MAC, or OS2 */
100 # define INCLUDE_TEMPLATE "../include/%s"
101 # define SOURCE_TEMPLATE "../src/%s"
102 # define DGN_TEMPLATE "../dat/%s" /* where dungeon.pdf file goes */
103 # define DATA_TEMPLATE "../dat/%s"
104 # define DATA_IN_TEMPLATE "../dat/%s"
105 # endif /* else !OS2 */
106 # endif /* else !MAC */
107 #endif /* else !AMIGA */
111 "/* This source file is generated by 'makedefs'. Do not edit. */\n",
113 "#\tThis data file is generated by 'makedefs'. Do not edit. \n";
115 static struct version_info version;
117 /* definitions used for vision tables */
118 #define TEST_WIDTH COLNO
119 #define TEST_HEIGHT ROWNO
120 #define BLOCK_WIDTH (TEST_WIDTH + 10)
121 #define BLOCK_HEIGHT TEST_HEIGHT /* don't need extra spaces */
122 #define MAX_ROW (BLOCK_HEIGHT + TEST_HEIGHT)
123 #define MAX_COL (BLOCK_WIDTH + TEST_WIDTH)
124 /* Use this as an out-of-bound value in the close table. */
125 #define CLOSE_OFF_TABLE_STRING "99" /* for the close table */
126 #define FAR_OFF_TABLE_STRING "0xff" /* for the far table */
128 #define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
130 static char xclear[MAX_ROW][MAX_COL];
132 /*-end of vision defs-*/
134 static char in_line[256], filename[60];
137 /* if defined, a first argument not starting with - is
138 * taken as a text string to be prepended to any
139 * output filename generated */
140 char *file_prefix="";
143 #ifdef MACsansMPWTOOL
144 int FDECL(main, (void));
146 int FDECL(main, (int,char **));
148 void FDECL(do_makedefs, (char *));
151 void NDECL(do_dungeon);
153 void NDECL(do_options);
154 void NDECL(do_monstr);
155 void NDECL(do_permonst);
156 void NDECL(do_questtxt);
157 void NDECL(do_rumors);
158 void NDECL(do_oracles);
159 void NDECL(do_vision);
161 extern void NDECL(monst_init); /* monst.c */
162 extern void NDECL(objects_init); /* objects.c */
164 static void NDECL(make_version);
165 static char *FDECL(version_string, (char *));
166 static char *FDECL(version_id_string, (char *,const char *));
167 static char *FDECL(xcrypt, (const char *));
168 static int FDECL(check_control, (char *));
169 static char *FDECL(without_control, (char *));
170 static boolean FDECL(d_filter, (char *));
171 static boolean FDECL(h_filter, (char *));
172 static boolean FDECL(ranged_attk,(struct permonst*));
173 static int FDECL(mstrength,(struct permonst *));
174 static void NDECL(build_savebones_compat_string);
176 static boolean FDECL(qt_comment, (char *));
177 static boolean FDECL(qt_control, (char *));
178 static int FDECL(get_hdr, (char *));
179 static boolean FDECL(new_id, (char *));
180 static boolean FDECL(known_msg, (int,int));
181 static void FDECL(new_msg, (char *,int,int));
182 static void FDECL(do_qt_control, (char *));
183 static void FDECL(do_qt_text, (char *));
184 static void NDECL(adjust_qt_hdrs);
185 static void NDECL(put_qt_hdrs);
188 static void NDECL(H_close_gen);
189 static void NDECL(H_far_gen);
190 static void NDECL(C_close_gen);
191 static void NDECL(C_far_gen);
192 static int FDECL(clear_path, (int,int,int,int));
195 static char *FDECL(tmpdup, (const char *));
196 static char *FDECL(limit, (char *,int));
197 static char *FDECL(eos, (char *));
199 /* input, output, tmp */
200 static FILE *ifp, *ofp, *tfp;
202 #if defined(__BORLANDC__) && !defined(_WIN32)
203 extern unsigned _stklen = STKSIZ;
207 #ifdef MACsansMPWTOOL
211 const char *def_options = "odemvpqrhz";
215 printf("Enter options to run: [%s] ", def_options);
217 fgets(buf, 100, stdin);
220 Strcpy(buf, def_options);
222 buf[len-1] = 0; /* remove return */
241 Fprintf(stderr, "Bad arg count (%d).\n", argc-1);
242 (void) fflush(stderr);
247 if(argc >=2 && argv[1][0]!='-'){
252 do_makedefs(&argv[1][1]);
264 boolean more_than_one;
266 /* Note: these initializers don't do anything except guarantee that
267 we're linked properly.
272 /* construct the current version number */
276 more_than_one = strlen(options) > 1;
279 Fprintf(stderr, "makedefs -%c\n", *options);
289 case 'E': do_dungeon();
292 case 'M': do_monstr();
299 case 'P': do_permonst();
302 case 'Q': do_questtxt();
305 case 'R': do_rumors();
308 case 'H': do_oracles();
311 case 'Z': do_vision();
314 default: Fprintf(stderr, "Unknown option '%c'.\n",
316 (void) fflush(stderr);
322 if (more_than_one) Fprintf(stderr, "Completed.\n"); /* feedback */
327 /* trivial text encryption routine which can't be broken with `tr' */
331 { /* duplicated in src/hacklib.c */
332 static char buf[BUFSZ];
333 register const char *p;
335 register int bitmask;
337 for (bitmask = 1, p = str, q = buf; *p; q++) {
339 if (*q & (32|64)) *q ^= bitmask;
340 if ((bitmask <<= 1) >= 32) bitmask = 1;
350 long true_rumor_size;
354 Strcat(filename,file_prefix);
356 Sprintf(eos(filename), DATA_TEMPLATE, RUMOR_FILE);
357 if (!(ofp = fopen(filename, WRTMODE))) {
361 Fprintf(ofp,Dont_Edit_Data);
363 Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
364 Strcat(infile, ".tru");
365 if (!(ifp = fopen(infile, RDTMODE))) {
368 Unlink(filename); /* kill empty output file */
372 /* get size of true rumors file */
374 (void) fseek(ifp, 0L, SEEK_END);
375 true_rumor_size = ftell(ifp);
377 /* seek+tell is only valid for stream format files; since rumors.%%%
378 might be in record format, count the actual data bytes instead.
381 while (fgets(in_line, sizeof in_line, ifp) != 0)
382 true_rumor_size += strlen(in_line); /* includes newline */
384 Fprintf(ofp,"%06lx\n", true_rumor_size);
385 (void) fseek(ifp, 0L, SEEK_SET);
387 /* copy true rumors */
388 while (fgets(in_line, sizeof in_line, ifp) != 0)
389 (void) fputs(xcrypt(in_line), ofp);
393 Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
394 Strcat(infile, ".fal");
395 if (!(ifp = fopen(infile, RDTMODE))) {
398 Unlink(filename); /* kill incomplete output file */
402 /* copy false rumors */
403 while (fgets(in_line, sizeof in_line, ifp) != 0)
404 (void) fputs(xcrypt(in_line), ofp);
412 * 3.4.1: way back in 3.2.1 `flags.nap' became unconditional but
413 * TIMED_DELAY was erroneously left in VERSION_FEATURES and has
414 * been there up through 3.4.0. Simply removing it now would
415 * break save file compatibility with 3.4.0 files, so we will
416 * explicitly mask it out during version checks.
417 * This should go away in the next version update.
419 #define IGNORED_FEATURES ( 0L \
420 | (1L << 23) /* TIMED_DELAY */ \
429 * integer version number
431 version.incarnation = ((unsigned long)VERSION_MAJOR << 24) |
432 ((unsigned long)VERSION_MINOR << 16) |
433 ((unsigned long)PATCHLEVEL << 8) |
434 ((unsigned long)EDITLEVEL);
436 * encoded feature list
437 * Note: if any of these magic numbers are changed or reassigned,
438 * EDITLEVEL in patchlevel.h should be incremented at the same time.
439 * The actual values have no special meaning, and the category
440 * groupings are just for convenience.
442 version.feature_set = (unsigned long)(0L
443 /* levels and/or topology (0..4) */
450 /* monsters (5..9) */
457 /* objects (10..14) */
467 /* flag bits and/or other global variables (15..26) */
483 /* data format [COMPRESS excluded] (27..31) */
492 * Value used for object & monster sanity check.
493 * (NROFARTIFACTS<<24) | (NUM_OBJECTS<<12) | (NUMMONS<<0)
495 for (i = 1; artifact_names[i]; i++) continue;
496 version.entity_count = (unsigned long)(i - 1);
497 for (i = 1; objects[i].oc_class != ILLOBJ_CLASS; i++) continue;
498 version.entity_count = (version.entity_count << 12) | (unsigned long)i;
499 for (i = 0; mons[i].mlet; i++) continue;
500 version.entity_count = (version.entity_count << 12) | (unsigned long)i;
502 * Value used for compiler (word size/field alignment/padding) check.
504 version.struct_sizes = (((unsigned long)sizeof (struct flag) << 24) |
505 ((unsigned long)sizeof (struct obj) << 17) |
506 ((unsigned long)sizeof (struct monst) << 10) |
507 ((unsigned long)sizeof (struct you)));
512 version_string(outbuf)
515 Sprintf(outbuf, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
517 Sprintf(eos(outbuf), "-%d", EDITLEVEL);
523 version_id_string(outbuf, build_date)
525 const char *build_date;
527 char subbuf[64], versbuf[64];
532 Strcpy(&subbuf[1], PORT_SUB_ID);
535 Strcat(subbuf, " Beta");
538 Sprintf(outbuf, "%s NetHack%s Version %s - last build %s.",
539 PORT_ID, subbuf, version_string(versbuf), build_date);
547 char *c, cbuf[60], buf[BUFSZ];
552 Strcat(filename,file_prefix);
554 Sprintf(eos(filename), INCLUDE_TEMPLATE, DATE_FILE);
555 if (!(ofp = fopen(filename, WRTMODE))) {
559 Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.4\t2002/02/03 */\n\n");
560 Fprintf(ofp,Dont_Edit_Code);
563 (void) time(&clocktim);
564 Strcpy(cbuf, ctime(&clocktim));
566 (void) time((time_t *)&clocktim);
567 Strcpy(cbuf, ctime((time_t *)&clocktim));
569 for (c = cbuf; *c; c++) if (*c == '\n') break;
570 *c = '\0'; /* strip off the '\n' */
571 Fprintf(ofp,"#define BUILD_DATE \"%s\"\n", cbuf);
572 Fprintf(ofp,"#define BUILD_TIME (%ldL)\n", clocktim);
579 Fprintf(ofp,"#define VERSION_NUMBER 0x%08lx%s\n",
580 version.incarnation, ul_sfx);
581 Fprintf(ofp,"#define VERSION_FEATURES 0x%08lx%s\n",
582 version.feature_set, ul_sfx);
583 #ifdef IGNORED_FEATURES
584 Fprintf(ofp,"#define IGNORED_FEATURES 0x%08lx%s\n",
585 (unsigned long) IGNORED_FEATURES, ul_sfx);
587 Fprintf(ofp,"#define VERSION_SANITY1 0x%08lx%s\n",
588 version.entity_count, ul_sfx);
589 Fprintf(ofp,"#define VERSION_SANITY2 0x%08lx%s\n",
590 version.struct_sizes, ul_sfx);
592 Fprintf(ofp,"#define VERSION_STRING \"%s\"\n", version_string(buf));
593 Fprintf(ofp,"#define VERSION_ID \\\n \"%s\"\n",
594 version_id_string(buf, cbuf));
598 struct tm *tm = localtime((time_t *) &clocktim);
599 Fprintf(ofp,"#define AMIGA_VERSION_STRING ");
600 Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
601 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
602 tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900);
609 static char save_bones_compat_buf[BUFSZ];
612 build_savebones_compat_string()
614 #ifdef VERSION_COMPATIBILITY
615 unsigned long uver = VERSION_COMPATIBILITY;
617 Strcpy(save_bones_compat_buf,
618 "save and bones files accepted from version");
619 #ifdef VERSION_COMPATIBILITY
620 Sprintf(eos(save_bones_compat_buf), "s %lu.%lu.%lu through %d.%d.%d",
621 ((uver & 0xFF000000L) >> 24), ((uver & 0x00FF0000L) >> 16),
622 ((uver & 0x0000FF00L) >> 8),
623 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
625 Sprintf(eos(save_bones_compat_buf), " %d.%d.%d only",
626 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
630 static const char *build_opts[] = {
632 "Amiga WorkBench support",
635 "ANSI default terminal",
637 #ifdef AUTOPICKUP_EXCEPTIONS
638 "autopickup_exceptions",
644 "command line completion",
647 "data file compression",
659 "experience points on status line",
662 "floppy drive support",
665 "gold object in inventories",
668 "insurance files for recovering from crashes",
673 #ifdef HOLD_LOCKFILE_OPEN
674 "exclusive lock on level 0 file",
683 "MSDOS protected mode",
706 "saddles and riding",
709 "score on status line",
716 "screen control via mactty",
719 "screen control via BIOS",
721 # ifdef SCREEN_DJGPPFAST
722 "screen control via DJGPP fast",
725 "screen control via VGA graphics",
727 # ifndef MSWIN_GRAPHICS
729 "screen control via WIN32 console I/O",
746 "terminal info library",
748 # if defined(TERMLIB) || ((!defined(MICRO) && !defined(WIN32)) && defined(TTY_GRAPHICS))
749 "terminal capability library",
753 "timed wait for display effects",
759 # ifdef USER_SOUNDS_REGEX
760 "user sounds via regular expressions",
762 "user sounds via pmatch",
765 #ifdef PREFIXES_IN_USE
766 "variable playground",
771 #ifdef WALLIFIED_MAZE
775 "zero-compressed save files",
777 save_bones_compat_buf,
778 "basic NetHack features"
781 static const char *window_opts[] = {
783 "traditional tty-based graphics",
791 #ifdef GNOME_GRAPHICS
797 #ifdef AMIGA_INTUITION
803 #ifdef MSWIN_GRAPHICS
815 register int i, length;
816 register const char *str, *indent = " ";
820 Strcat(filename,file_prefix);
822 Sprintf(eos(filename), DATA_TEMPLATE, OPTIONS_FILE);
823 if (!(ofp = fopen(filename, WRTMODE))) {
828 build_savebones_compat_string();
831 "\n NetHack version %d.%d.%d [beta]\n",
833 "\n NetHack version %d.%d.%d\n",
835 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
837 Fprintf(ofp,"\nOptions compiled into this edition:\n");
839 length = COLNO + 1; /* force 1st item onto new line */
840 for (i = 0; i < SIZE(build_opts); i++) {
842 if (length + strlen(str) > COLNO - 5)
843 Fprintf(ofp,"\n%s", indent), length = strlen(indent);
845 Fprintf(ofp," "), length++;
846 Fprintf(ofp,"%s", str), length += strlen(str);
847 Fprintf(ofp,(i < SIZE(build_opts) - 1) ? "," : "."), length++;
850 Fprintf(ofp,"\n\nSupported windowing systems:\n");
852 length = COLNO + 1; /* force 1st item onto new line */
853 for (i = 0; i < SIZE(window_opts) - 1; i++) {
854 str = window_opts[i];
855 if (length + strlen(str) > COLNO - 5)
856 Fprintf(ofp,"\n%s", indent), length = strlen(indent);
858 Fprintf(ofp," "), length++;
859 Fprintf(ofp,"%s", str), length += strlen(str);
860 Fprintf(ofp, ","), length++;
862 Fprintf(ofp, "\n%swith a default of %s.", indent, DEFAULT_WINDOW_SYS);
869 /* routine to decide whether to discard something from data.base */
874 if (*line == '#') return TRUE; /* ignore comment lines */
880 New format (v3.1) of 'data' file which allows much faster lookups [pr]
881 "do not edit" first record is a comment line
882 01234567 hexadecimal formatted offset to text area
883 name-a first name of interest
884 123,4 offset to name's text, and number of lines for it
885 name-b next name of interest
886 name-c multiple names which share same description also
887 456,7 share a single offset,count line
888 . sentinel to mark end of names
889 789,0 dummy record containing offset, count of EOF
890 text-a 4 lines of descriptive text for name-a
891 text-a at file position 0x01234567L + 123L
894 text-b/text-c 7 lines of text for names-b and -c
895 text-b/text-c at fseek(0x01234567L + 456L)
903 char infile[60], tempfile[60];
906 int entry_cnt, line_cnt;
908 Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
911 Strcat(filename,file_prefix);
913 Sprintf(eos(filename), DATA_TEMPLATE, DATA_FILE);
914 Sprintf(infile, DATA_IN_TEMPLATE, DATA_FILE);
916 #ifdef SHORT_FILENAMES
922 if (!(ifp = fopen(infile, RDTMODE))) { /* data.base */
926 if (!(ofp = fopen(filename, WRTMODE))) { /* data */
931 if (!(tfp = fopen(tempfile, WRTMODE))) { /* database.tmp */
939 /* output a dummy header record; we'll rewind and overwrite it later */
940 Fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, 0L);
942 entry_cnt = line_cnt = 0;
943 /* read through the input file and split it into two sections */
944 while (fgets(in_line, sizeof in_line, ifp)) {
945 if (d_filter(in_line)) continue;
946 if (*in_line > ' ') { /* got an entry name */
947 /* first finish previous entry */
948 if (line_cnt) Fprintf(ofp, "%d\n", line_cnt), line_cnt = 0;
949 /* output the entry name */
950 (void) fputs(in_line, ofp);
951 entry_cnt++; /* update number of entries */
952 } else if (entry_cnt) { /* got some descriptive text */
953 /* update previous entry with current text offset */
954 if (!line_cnt) Fprintf(ofp, "%ld,", ftell(tfp));
955 /* save the text line in the scratch file */
956 (void) fputs(in_line, tfp);
957 line_cnt++; /* update line counter */
960 /* output an end marker and then record the current position */
961 if (line_cnt) Fprintf(ofp, "%d\n", line_cnt);
962 Fprintf(ofp, ".\n%ld,%d\n", ftell(tfp), 0);
963 txt_offset = ftell(ofp);
964 Fclose(ifp); /* all done with original input file */
966 /* reprocess the scratch file; 1st format an error msg, just in case */
967 Sprintf(in_line, "rewind of \"%s\"", tempfile);
968 if (rewind(tfp) != 0) goto dead_data;
969 /* copy all lines of text from the scratch file into the output file */
970 while (fgets(in_line, sizeof in_line, tfp))
971 (void) fputs(in_line, ofp);
973 /* finished with scratch file */
975 Unlink(tempfile); /* remove it */
977 /* update the first record of the output file; prepare error msg 1st */
978 Sprintf(in_line, "rewind of \"%s\"", filename);
979 ok = (rewind(ofp) == 0);
981 Sprintf(in_line, "header rewrite of \"%s\"", filename);
982 ok = (fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, txt_offset) >= 0);
985 dead_data: perror(in_line); /* report the problem */
986 /* close and kill the aborted output file, then give up */
998 /* routine to decide whether to discard something from oracles.txt */
1003 static boolean skip = FALSE;
1004 char tag[sizeof in_line];
1008 if (*line == '#') return TRUE; /* ignore comment lines */
1009 if (sscanf(line, "----- %s", tag) == 1) {
1012 if (!strcmp(tag, "SINKS")) skip = TRUE;
1015 if (!strcmp(tag, "ELBERETH")) skip = TRUE;
1017 } else if (skip && !strncmp(line, "-----", 5))
1022 static const char *special_oracle[] = {
1023 "\"...it is rather disconcerting to be confronted with the",
1024 "following theorem from [Baker, Gill, and Solovay, 1975].",
1026 "Theorem 7.18 There exist recursive languages A and B such that",
1027 " (1) P(A) == NP(A), and",
1028 " (2) P(B) != NP(B)",
1030 "This provides impressive evidence that the techniques that are",
1031 "currently available will not suffice for proving that P != NP or ",
1032 "that P == NP.\" [Garey and Johnson, p. 185.]"
1036 The oracle file consists of a "do not edit" comment, a decimal count N
1037 and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
1038 records, separated by "---" lines. The first oracle is a special case.
1039 The input data contains just those multi-line records, separated by
1046 char infile[60], tempfile[60];
1047 boolean in_oracle, ok;
1048 long txt_offset, offset, fpos;
1052 Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
1055 Strcat(filename, file_prefix);
1057 Sprintf(eos(filename), DATA_TEMPLATE, ORACLE_FILE);
1058 Sprintf(infile, DATA_IN_TEMPLATE, ORACLE_FILE);
1059 Strcat(infile, ".txt");
1060 if (!(ifp = fopen(infile, RDTMODE))) {
1064 if (!(ofp = fopen(filename, WRTMODE))) {
1069 if (!(tfp = fopen(tempfile, WRTMODE))) { /* oracles.tmp */
1077 /* output a dummy header record; we'll rewind and overwrite it later */
1078 Fprintf(ofp, "%s%5d\n", Dont_Edit_Data, 0);
1080 /* handle special oracle; it must come first */
1081 (void) fputs("---\n", tfp);
1082 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* start pos of special oracle */
1083 for (i = 0; i < SIZE(special_oracle); i++) {
1084 (void) fputs(xcrypt(special_oracle[i]), tfp);
1085 (void) fputc('\n', tfp);
1090 (void) fputs("---\n", tfp);
1091 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* start pos of first oracle */
1094 while (fgets(in_line, sizeof in_line, ifp)) {
1097 if (h_filter(in_line)) continue;
1098 if (!strncmp(in_line, "-----", 5)) {
1099 if (!in_oracle) continue;
1102 (void) fputs("---\n", tfp);
1103 Fprintf(ofp, "%05lx\n", ftell(tfp));
1104 /* start pos of this oracle */
1107 (void) fputs(xcrypt(in_line), tfp);
1111 if (in_oracle) { /* need to terminate last oracle */
1113 (void) fputs("---\n", tfp);
1114 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* eof position */
1117 /* record the current position */
1118 txt_offset = ftell(ofp);
1119 Fclose(ifp); /* all done with original input file */
1121 /* reprocess the scratch file; 1st format an error msg, just in case */
1122 Sprintf(in_line, "rewind of \"%s\"", tempfile);
1123 if (rewind(tfp) != 0) goto dead_data;
1124 /* copy all lines of text from the scratch file into the output file */
1125 while (fgets(in_line, sizeof in_line, tfp))
1126 (void) fputs(in_line, ofp);
1128 /* finished with scratch file */
1130 Unlink(tempfile); /* remove it */
1132 /* update the first record of the output file; prepare error msg 1st */
1133 Sprintf(in_line, "rewind of \"%s\"", filename);
1134 ok = (rewind(ofp) == 0);
1136 Sprintf(in_line, "header rewrite of \"%s\"", filename);
1137 ok = (fprintf(ofp, "%s%5d\n", Dont_Edit_Data, oracle_cnt) >=0);
1140 Sprintf(in_line, "data rewrite of \"%s\"", filename);
1141 for (i = 0; i <= oracle_cnt; i++) {
1142 #ifndef VMS /* alpha/vms v1.0; this fflush seems to confuse ftell */
1143 if (!(ok = (fflush(ofp) == 0))) break;
1145 if (!(ok = (fpos = ftell(ofp)) >= 0)) break;
1146 if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
1147 if (!(ok = (fscanf(ofp, "%5lx", &offset) == 1))) break;
1151 MetroWerks CodeWarrior Pro 1's (AKA CW12) version of MSL
1152 (ANSI C Libraries) needs this rewind or else the fprintf
1153 stops working. This may also be true for CW11, but has
1159 if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
1160 if (!(ok = (fprintf(ofp, "%05lx\n", offset + txt_offset) >= 0)))
1165 dead_data: perror(in_line); /* report the problem */
1166 /* close and kill the aborted output file, then give up */
1179 static struct deflist {
1181 const char *defname;
1182 boolean true_or_false;
1184 #ifdef REINCARNATION
1185 { "REINCARNATION", TRUE },
1187 { "REINCARNATION", FALSE },
1197 if(s[0] != '%') return(-1);
1199 for(i = 0; deflist[i].defname; i++)
1200 if(!strncmp(deflist[i].defname, s+1, strlen(deflist[i].defname)))
1210 return(s + 1 + strlen(deflist[check_control(in_line)].defname));
1218 Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
1219 if (!(ifp = fopen(filename, RDTMODE))) {
1225 Strcat(filename, file_prefix);
1227 Sprintf(eos(filename), DGN_TEMPLATE, DGN_O_FILE);
1228 if (!(ofp = fopen(filename, WRTMODE))) {
1232 Fprintf(ofp,Dont_Edit_Data);
1234 while (fgets(in_line, sizeof in_line, ifp) != 0) {
1238 if(in_line[0] == '#') continue; /* discard comments */
1240 if(in_line[0] == '%') {
1241 int i = check_control(in_line);
1243 if(!deflist[i].true_or_false) {
1244 while (fgets(in_line, sizeof in_line, ifp) != 0)
1245 if(check_control(in_line) != i) goto recheck;
1247 (void) fputs(without_control(in_line),ofp);
1249 Fprintf(stderr, "Unknown control option '%s' in file %s at line %d.\n",
1250 in_line, DGN_I_FILE, rcnt);
1254 (void) fputs(in_line,ofp);
1263 ranged_attk(ptr) /* returns TRUE if monster can attack at range */
1264 register struct permonst *ptr;
1267 register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);
1269 for(i = 0; i < NATTK; i++) {
1270 if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
1277 /* This routine is designed to return an integer value which represents
1278 * an approximation of monster strength. It uses a similar method of
1279 * determination as "experience()" to arrive at the strength.
1283 struct permonst *ptr;
1285 int i, tmp2, n, tmp = ptr->mlevel;
1287 if(tmp > 49) /* special fixed hp monster */
1288 tmp = 2*(tmp - 6) / 4;
1290 /* For creation in groups */
1291 n = (!!(ptr->geno & G_SGROUP));
1292 n += (!!(ptr->geno & G_LGROUP)) << 1;
1294 /* For ranged attacks */
1295 if (ranged_attk(ptr)) n++;
1297 /* For higher ac values */
1301 /* For very fast monsters */
1302 n += (ptr->mmove >= 18);
1304 /* For each attack and "special" attack */
1305 for(i = 0; i < NATTK; i++) {
1307 tmp2 = ptr->mattk[i].aatyp;
1309 n += (tmp2 == AT_MAGC);
1310 n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG));
1313 /* For each "special" damage type */
1314 for(i = 0; i < NATTK; i++) {
1316 tmp2 = ptr->mattk[i].adtyp;
1317 if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST)
1318 || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO) || (tmp2 == AD_WERE))
1320 else if (strcmp(ptr->mname, "grid bug")) n += (tmp2 != AD_PHYS);
1321 n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
1324 /* Leprechauns are special cases. They have many hit dice so they
1325 can hit and are hard to kill, but they don't really do much damage. */
1326 if (!strcmp(ptr->mname, "leprechaun")) n -= 2;
1328 /* Finally, adjust the monster level 0 <= n <= 24 (approx.) */
1330 else if(n >= 6) tmp += ( n / 2 );
1331 else tmp += ( n / 3 + 1);
1333 return((tmp >= 0) ? tmp : 0);
1339 register struct permonst *ptr;
1343 * create the source file, "monstr.c"
1347 Strcat(filename, file_prefix);
1349 Sprintf(eos(filename), SOURCE_TEMPLATE, MON_STR_C);
1350 if (!(ofp = fopen(filename, WRTMODE))) {
1354 Fprintf(ofp,Dont_Edit_Code);
1355 Fprintf(ofp,"#include \"config.h\"\n");
1356 Fprintf(ofp,"\nconst int monstr[] = {\n");
1357 for (ptr = &mons[0], j = 0; ptr->mlet; ptr++) {
1362 Fprintf(ofp,"%2d,%c", i, (++j & 15) ? ' ' : '\n');
1364 /* might want to insert a final 0 entry here instead of just newline */
1365 Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");
1367 Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
1368 Fprintf(ofp,"\nvoid\n");
1369 Fprintf(ofp,"monstr_init()\n");
1371 Fprintf(ofp," return;\n");
1373 Fprintf(ofp,"\n/*monstr.c*/\n");
1387 Strcat(filename, file_prefix);
1389 Sprintf(eos(filename), INCLUDE_TEMPLATE, MONST_FILE);
1390 if (!(ofp = fopen(filename, WRTMODE))) {
1394 Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.4\t2002/02/03 */\n\n");
1395 Fprintf(ofp,Dont_Edit_Code);
1396 Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");
1398 if (strcmp(mons[0].mname, "playermon") != 0)
1399 Fprintf(ofp,"\n#define\tPM_PLAYERMON\t(-1)");
1401 for (i = 0; mons[i].mlet; i++) {
1404 Fprintf(ofp,"\n#define\tPM_");
1405 if (mons[i].mlet == S_HUMAN &&
1406 !strncmp(mons[i].mname, "were", 4))
1407 Fprintf(ofp, "HUMAN_");
1408 for (nam = c = tmpdup(mons[i].mname); *c; c++)
1409 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1410 else if (*c < 'A' || *c > 'Z') *c = '_';
1411 Fprintf(ofp,"%s\t%d", nam, i);
1413 Fprintf(ofp,"\n\n#define\tNUMMONS\t%d\n", i);
1414 Fprintf(ofp,"\n#endif /* PM_H */\n");
1420 /* Start of Quest text file processing. */
1423 static struct qthdr qt_hdr;
1424 static struct msghdr msg_hdr[N_HDR];
1425 static struct qtmsg *curr_msg;
1429 static boolean in_msg;
1430 #define NO_MSG 1 /* strlen of a null line returned by fgets() */
1436 if(s[0] == '#') return(TRUE);
1437 return((boolean)(!in_msg && strlen(s) == NO_MSG));
1444 return((boolean)(s[0] == '%' && (s[1] == 'C' || s[1] == 'E')));
1453 for(i = 0; i < qt_hdr.n_hdr; i++)
1454 if(!strncmp(code, qt_hdr.id[i], LEN_HDR)) return (++i);
1463 if(qt_hdr.n_hdr >= N_HDR) {
1464 Fprintf(stderr, OUT_OF_HEADERS, qt_line);
1468 strncpy(&qt_hdr.id[qt_hdr.n_hdr][0], code, LEN_HDR);
1469 msg_hdr[qt_hdr.n_hdr].n_msg = 0;
1470 qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
1480 for(i = 0; i < msg_hdr[num].n_msg; i++)
1481 if(msg_hdr[num].qt_msg[i].msgnum == id) return(TRUE);
1492 struct qtmsg *qt_msg;
1494 if(msg_hdr[num].n_msg >= N_MSG) {
1495 Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
1497 qt_msg = &(msg_hdr[num].qt_msg[msg_hdr[num].n_msg++]);
1498 qt_msg->msgnum = id;
1499 qt_msg->delivery = s[2];
1500 qt_msg->offset = qt_msg->size = 0L;
1515 case 'C': if(in_msg) {
1516 Fprintf(stderr, CREC_IN_MSG, qt_line);
1520 if (sscanf(&s[4], "%s %5d", code, &id) != 2) {
1521 Fprintf(stderr, UNREC_CREC, qt_line);
1524 num = get_hdr(code);
1525 if (!num && !new_id(code))
1527 num = get_hdr(code)-1;
1528 if(known_msg(num, id))
1529 Fprintf(stderr, DUP_MSG, qt_line);
1530 else new_msg(s, num, id);
1534 case 'E': if(!in_msg) {
1535 Fprintf(stderr, END_NOT_IN_MSG, qt_line);
1537 } else in_msg = FALSE;
1540 default: Fprintf(stderr, UNREC_CREC, qt_line);
1550 Fprintf(stderr, TEXT_NOT_IN_MSG, qt_line);
1552 curr_msg->size += strlen(s);
1560 long count = 0L, hdr_offset = sizeof(int) +
1561 (sizeof(char)*LEN_HDR + sizeof(long)) * qt_hdr.n_hdr;
1563 for(i = 0; i < qt_hdr.n_hdr; i++) {
1564 qt_hdr.offset[i] = hdr_offset;
1565 hdr_offset += sizeof(int) + sizeof(struct qtmsg) * msg_hdr[i].n_msg;
1568 for(i = 0; i < qt_hdr.n_hdr; i++)
1569 for(j = 0; j < msg_hdr[i].n_msg; j++) {
1571 msg_hdr[i].qt_msg[j].offset = hdr_offset + count;
1572 count += msg_hdr[i].qt_msg[j].size;
1583 * The main header record.
1586 Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
1588 (void) fwrite((genericptr_t)&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
1589 (void) fwrite((genericptr_t)&(qt_hdr.id[0][0]), sizeof(char)*LEN_HDR,
1591 (void) fwrite((genericptr_t)&(qt_hdr.offset[0]), sizeof(long),
1594 for(i = 0; i < qt_hdr.n_hdr; i++)
1595 Fprintf(stderr, "%c @ %ld, ", qt_hdr.id[i], qt_hdr.offset[i]);
1597 Fprintf(stderr, "\n");
1601 * The individual class headers.
1603 for(i = 0; i < qt_hdr.n_hdr; i++) {
1606 Fprintf(stderr, "%ld: %c header info.\n", ftell(ofp),
1609 (void) fwrite((genericptr_t)&(msg_hdr[i].n_msg), sizeof(int),
1611 (void) fwrite((genericptr_t)&(msg_hdr[i].qt_msg[0]),
1612 sizeof(struct qtmsg), msg_hdr[i].n_msg, ofp);
1615 for(j = 0; j < msg_hdr[i].n_msg; j++)
1616 Fprintf(stderr, "msg %d @ %ld (%ld)\n",
1617 msg_hdr[i].qt_msg[j].msgnum,
1618 msg_hdr[i].qt_msg[j].offset,
1619 msg_hdr[i].qt_msg[j].size);
1628 Sprintf(filename, DATA_IN_TEMPLATE, QTXT_I_FILE);
1629 if(!(ifp = fopen(filename, RDTMODE))) {
1636 Strcat(filename, file_prefix);
1638 Sprintf(eos(filename), DATA_TEMPLATE, QTXT_O_FILE);
1639 if(!(ofp = fopen(filename, WRBMODE))) {
1649 while (fgets(in_line, 80, ifp) != 0) {
1653 if(qt_control(in_line)) do_qt_control(in_line);
1654 else if(qt_comment(in_line)) continue;
1655 else do_qt_text(in_line);
1662 while (fgets(in_line, 80, ifp) != 0) {
1664 if(qt_control(in_line)) {
1665 in_msg = (in_line[1] == 'C');
1667 } else if(qt_comment(in_line)) continue;
1669 Fprintf(stderr, "%ld: %s", ftell(stdout), in_line);
1671 (void) fputs(xcrypt(in_line), ofp);
1679 static char temp[32];
1682 limit(name,pref) /* limit a name to 30 characters length */
1686 (void) strncpy(temp, name, pref ? 26 : 30);
1687 temp[pref ? 26 : 30] = 0;
1699 boolean sumerr = FALSE;
1703 Strcat(filename, file_prefix);
1705 Sprintf(eos(filename), INCLUDE_TEMPLATE, ONAME_FILE);
1706 if (!(ofp = fopen(filename, WRTMODE))) {
1710 Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.4\t2002/02/03 */\n\n");
1711 Fprintf(ofp,Dont_Edit_Code);
1712 Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n");
1714 for(i = 0; !i || objects[i].oc_class != ILLOBJ_CLASS; i++) {
1717 objects[i].oc_name_idx = objects[i].oc_descr_idx = i; /* init */
1718 if (!(objnam = tmpdup(OBJ_NAME(objects[i])))) continue;
1720 /* make sure probabilities add up to 1000 */
1721 if(objects[i].oc_class != class) {
1722 if (sum && sum != 1000) {
1723 Fprintf(stderr, "prob error for class %d (%d%%)",
1725 (void) fflush(stderr);
1728 class = objects[i].oc_class;
1732 for (c = objnam; *c; c++)
1733 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1734 else if (*c < 'A' || *c > 'Z') *c = '_';
1738 Fprintf(ofp,"#define\tWAN_"); prefix = 1; break;
1740 Fprintf(ofp,"#define\tRIN_"); prefix = 1; break;
1742 Fprintf(ofp,"#define\tPOT_"); prefix = 1; break;
1744 Fprintf(ofp,"#define\tSPE_"); prefix = 1; nspell++; break;
1746 Fprintf(ofp,"#define\tSCR_"); prefix = 1; break;
1748 /* avoid trouble with stupid C preprocessors */
1749 Fprintf(ofp,"#define\t");
1750 if(objects[i].oc_material == PLASTIC) {
1751 Fprintf(ofp,"FAKE_AMULET_OF_YENDOR\t%d\n", i);
1757 /* avoid trouble with stupid C preprocessors */
1758 if(objects[i].oc_material == GLASS) {
1759 Fprintf(ofp,"/* #define\t%s\t%d */\n",
1765 Fprintf(ofp,"#define\t");
1768 Fprintf(ofp,"%s\t%d\n", limit(objnam, prefix), i);
1771 sum += objects[i].oc_prob;
1774 /* check last set of probabilities */
1775 if (sum && sum != 1000) {
1776 Fprintf(stderr, "prob error for class %d (%d%%)", class, sum);
1777 (void) fflush(stderr);
1781 Fprintf(ofp,"#define\tLAST_GEM\t(JADE)\n");
1782 Fprintf(ofp,"#define\tMAXSPELL\t%d\n", nspell+1);
1783 Fprintf(ofp,"#define\tNUM_OBJECTS\t%d\n", i);
1785 Fprintf(ofp, "\n/* Artifacts (unique objects) */\n\n");
1787 for (i = 1; artifact_names[i]; i++) {
1790 for (c = objnam = tmpdup(artifact_names[i]); *c; c++)
1791 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1792 else if (*c < 'A' || *c > 'Z') *c = '_';
1794 if (!strncmp(objnam, "THE_", 4))
1797 /* fudge _platinum_ YENDORIAN EXPRESS CARD */
1798 if (!strncmp(objnam, "PLATINUM_", 9))
1801 Fprintf(ofp,"#define\tART_%s\t%d\n", limit(objnam, 1), i);
1804 Fprintf(ofp, "#define\tNROFARTIFACTS\t%d\n", i-1);
1805 Fprintf(ofp,"\n#endif /* ONAMES_H */\n");
1807 if (sumerr) exit(EXIT_FAILURE);
1815 static char buf[128];
1817 if (!str) return (char *)0;
1818 (void)strncpy(buf, str, 127);
1831 * macro used to control vision algorithms:
1832 * VISION_TABLES => generate tables
1838 #ifdef VISION_TABLES
1841 /* Everything is clear. xclear may be malloc'ed.
1842 * Block the upper left corner (BLOCK_HEIGHTxBLOCK_WIDTH)
1844 for (i = 0; i < MAX_ROW; i++)
1845 for (j = 0; j < MAX_COL; j++)
1846 if (i < BLOCK_HEIGHT && j < BLOCK_WIDTH)
1847 xclear[i][j] = '\000';
1849 xclear[i][j] = '\001';
1850 #endif /* VISION_TABLES */
1855 * create the include file, "vis_tab.h"
1859 Strcat(filename, file_prefix);
1861 Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
1862 if (!(ofp = fopen(filename, WRTMODE))) {
1866 Fprintf(ofp,Dont_Edit_Code);
1867 Fprintf(ofp,"#ifdef VISION_TABLES\n");
1868 #ifdef VISION_TABLES
1871 #endif /* VISION_TABLES */
1872 Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
1878 * create the source file, "vis_tab.c"
1882 Strcat(filename, file_prefix);
1884 Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
1885 if (!(ofp = fopen(filename, WRTMODE))) {
1887 Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
1891 Fprintf(ofp,Dont_Edit_Code);
1892 Fprintf(ofp,"#include \"config.h\"\n");
1893 Fprintf(ofp,"#ifdef VISION_TABLES\n");
1894 Fprintf(ofp,"#include \"vis_tab.h\"\n");
1898 #ifdef VISION_TABLES
1901 Fprintf(ofp,"\nvoid vis_tab_init() { return; }\n");
1902 #endif /* VISION_TABLES */
1906 Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
1907 Fprintf(ofp,"\n/*vis_tab.c*/\n");
1913 #ifdef VISION_TABLES
1915 /*-------------- vision tables --------------*\
1917 * Generate the close and far tables. This is done by setting up a
1918 * fake dungeon and moving our source to different positions relative
1919 * to a block and finding the first/last visible position. The fake
1920 * dungeon is all clear execpt for the upper left corner (BLOCK_HEIGHT
1921 * by BLOCK_WIDTH) is blocked. Then we move the source around relative
1922 * to the corner of the block. For each new position of the source
1923 * we check positions on rows "kittycorner" from the source. We check
1924 * positions until they are either in sight or out of sight (depends on
1925 * which table we are generating). The picture below shows the setup
1926 * for the generation of the close table. The generation of the far
1927 * table would switch the quadrants of the '@' and the "Check rows
1931 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1932 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1933 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,, Check rows here ,,,,,,,,,,,,
1934 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1935 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXB,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1936 * ...............................
1937 * ...............................
1938 * .........@.....................
1939 * ...............................
1941 * Table generation figure (close_table). The 'X's are blocked points.
1942 * The 'B' is a special blocked point. The '@' is the source. The ','s
1943 * are the target area. The '.' are just open areas.
1946 * Example usage of close_table[][][].
1948 * The table is as follows:
1950 * dy = |row of '@' - row of 'B'| - 1
1951 * dx = |col of '@' - col of 'B'|
1953 * The first indices are the deltas from the source '@' and the block 'B'.
1954 * You must check for the value inside the abs value bars being zero. If
1955 * so then the block is on the same row and you don't need to do a table
1956 * lookup. The last value:
1958 * dcy = |row of block - row to be checked|
1960 * Is the value of the first visible spot on the check row from the
1963 * first visible col = close_table[dy][dx][dcy] + col of 'B'
1965 \*-------------- vision tables --------------*/
1970 Fprintf(ofp,"\n/* Close */\n");
1971 Fprintf(ofp,"#define CLOSE_MAX_SB_DY %2d\t/* |src row - block row| - 1\t*/\n",
1973 Fprintf(ofp,"#define CLOSE_MAX_SB_DX %2d\t/* |src col - block col|\t*/\n",
1975 Fprintf(ofp,"#define CLOSE_MAX_BC_DY %2d\t/* |block row - check row|\t*/\n",
1977 Fprintf(ofp,"typedef struct {\n");
1978 Fprintf(ofp," unsigned char close[CLOSE_MAX_SB_DX][CLOSE_MAX_BC_DY];\n");
1979 Fprintf(ofp,"} close2d;\n");
1980 Fprintf(ofp,"extern close2d close_table[CLOSE_MAX_SB_DY];\n");
1987 Fprintf(ofp,"\n/* Far */\n");
1988 Fprintf(ofp,"#define FAR_MAX_SB_DY %2d\t/* |src row - block row|\t*/\n",
1990 Fprintf(ofp,"#define FAR_MAX_SB_DX %2d\t/* |src col - block col| - 1\t*/\n",
1992 Fprintf(ofp,"#define FAR_MAX_BC_DY %2d\t/* |block row - check row| - 1\t*/\n",
1994 Fprintf(ofp,"typedef struct {\n");
1995 Fprintf(ofp," unsigned char far_q[FAR_MAX_SB_DX][FAR_MAX_BC_DY];\n");
1996 Fprintf(ofp,"} far2d;\n");
1997 Fprintf(ofp,"extern far2d far_table[FAR_MAX_SB_DY];\n");
2005 int src_row, src_col; /* source */
2006 int block_row, block_col; /* block */
2011 block_row = BLOCK_HEIGHT-1;
2012 block_col = BLOCK_WIDTH-1;
2014 Fprintf(ofp,"\n#ifndef FAR_TABLE_ONLY\n");
2015 Fprintf(ofp,"\nclose2d close_table[CLOSE_MAX_SB_DY] = {\n");
2016 #ifndef no_vision_progress
2017 Fprintf(stderr,"\nclose:");
2020 for (dy = 1; dy < TEST_HEIGHT; dy++) {
2021 src_row = block_row + dy;
2022 Fprintf(ofp, "/* DY = %2d (- 1)*/\n {{\n", dy);
2023 #ifndef no_vision_progress
2024 Fprintf(stderr," %2d",dy), (void)fflush(stderr);
2026 for (dx = 0; dx < TEST_WIDTH; dx++) {
2027 src_col = block_col - dx;
2028 Fprintf(ofp, " /*%2d*/ {", dx);
2031 for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
2032 delim = (this_row < TEST_HEIGHT - 1) ? "," : "";
2034 Fprintf(ofp, "%s%s", CLOSE_OFF_TABLE_STRING, delim);
2039 /* Find the first column that we can see. */
2040 for (i = block_col+1; i < MAX_COL; i++) {
2041 if (clear_path(src_row,src_col,block_row-this_row,i))
2045 if (i == MAX_COL) no_more = 1;
2046 Fprintf(ofp, "%2d%s", i - block_col, delim);
2048 Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
2050 Fprintf(ofp," }},\n");
2053 Fprintf(ofp,"}; /* close_table[] */\n"); /* closing brace for table */
2054 Fprintf(ofp,"#endif /* !FAR_TABLE_ONLY */\n");
2055 #ifndef no_vision_progress
2056 Fprintf(stderr,"\n");
2065 int src_row, src_col; /* source */
2066 int block_row, block_col; /* block */
2070 block_row = BLOCK_HEIGHT-1;
2071 block_col = BLOCK_WIDTH-1;
2073 Fprintf(ofp,"\n#ifndef CLOSE_TABLE_ONLY\n");
2074 Fprintf(ofp,"\nfar2d far_table[FAR_MAX_SB_DY] = {\n");
2075 #ifndef no_vision_progress
2076 Fprintf(stderr,"\n_far_:");
2079 for (dy = 0; dy < TEST_HEIGHT; dy++) {
2080 src_row = block_row - dy;
2081 Fprintf(ofp, "/* DY = %2d */\n {{\n", dy);
2082 #ifndef no_vision_progress
2083 Fprintf(stderr," %2d",dy), (void)fflush(stderr);
2085 for (dx = 1; dx < TEST_WIDTH; dx++) {
2086 src_col = block_col + dx;
2087 Fprintf(ofp, " /*%2d(-1)*/ {", dx);
2089 for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
2091 delim = (this_row < block_row + TEST_HEIGHT - 1) ? "," : "";
2094 /* Find first col that we can see. */
2095 for (i = 0; i <= block_col; i++) {
2096 if (clear_path(src_row,src_col,this_row,i)) break;
2099 if (block_col-i < 0)
2100 Fprintf(ofp, "%s%s", FAR_OFF_TABLE_STRING, delim);
2102 Fprintf(ofp, "%2d%s", block_col - i, delim);
2104 Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
2106 Fprintf(ofp," }},\n");
2109 Fprintf(ofp,"}; /* far_table[] */\n"); /* closing brace for table */
2110 Fprintf(ofp,"#endif /* !CLOSE_TABLE_ONLY */\n");
2111 #ifndef no_vision_progress
2112 Fprintf(stderr,"\n");
2118 * "Draw" a line from the hero to the given location. Stop if we hit a
2121 * Generalized integer Bresenham's algorithm (fast line drawing) for
2122 * all quadrants. From _Procedural Elements for Computer Graphics_, by
2123 * David F. Rogers. McGraw-Hill, 1985.
2125 * I have tried a little bit of optimization by pulling compares out of
2128 * NOTE: This had better *not* be called from a position on the
2129 * same row as the hero.
2132 clear_path(you_row,you_col,y2,x2)
2133 int you_row, you_col, y2, x2;
2136 register int i, error, x, y, dxs, dys;
2138 x = you_col; y = you_row;
2139 dx = abs(x2-you_col); dy = abs(y2-you_row);
2140 s1 = sign(x2-you_col); s2 = sign(y2-you_row);
2142 if (s1 == 0) { /* same column */
2143 if (s2 == 1) { /* below (larger y2 value) */
2144 for (i = you_row+1; i < y2; i++)
2145 if (!xclear[i][you_col]) return 0;
2146 } else { /* above (smaller y2 value) */
2147 for (i = y2+1; i < you_row; i++)
2148 if (!xclear[i][you_col]) return 0;
2154 * Lines at 0 and 90 degrees have been weeded out.
2157 error = dx; dx = dy; dy = error; /* swap the values */
2158 dxs = dx << 1; /* save the shifted values */
2160 error = dys - dx; /* NOTE: error is used as a temporary above */
2162 for (i = 0; i < dx; i++) {
2163 if (!xclear[y][x]) return 0; /* plot point */
2165 while (error >= 0) {
2173 dxs = dx << 1; /* save the shifted values */
2177 for (i = 0; i < dx; i++) {
2178 if (!xclear[y][x]) return 0; /* plot point */
2180 while (error >= 0) {
2190 #endif /* VISION_TABLES */
2192 #ifdef STRICT_REF_DEF
2193 NEARDATA struct flag flags;
2195 struct attribs attrmax, attrmin;
2197 #endif /* STRICT_REF_DEF */