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);
551 char *c, cbuf[256], buf[BUFSZ];
556 Strcat(filename,file_prefix);
558 Sprintf(eos(filename), INCLUDE_TEMPLATE, DATE_FILE);
559 if (!(ofp = fopen(filename, WRTMODE))) {
563 Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.4\t2002/02/03 */\n\n");
564 Fprintf(ofp,Dont_Edit_Code);
567 (void) time(&clocktim);
568 Strcpy(cbuf, ctime(&clocktim));
570 (void) time((time_t *)&clocktim);
571 Strcpy(cbuf, ctime((time_t *)&clocktim));
573 for (c = cbuf; *c; c++) if (*c == '\n') break;
574 *c = '\0'; /* strip off the '\n' */
575 Fprintf(ofp,"#define BUILD_DATE \"%s\"\n", cbuf);
576 Fprintf(ofp,"#define BUILD_TIME (%ldL)\n", clocktim);
583 Fprintf(ofp,"#define VERSION_NUMBER 0x%08lx%s\n",
584 version.incarnation, ul_sfx);
585 Fprintf(ofp,"#define VERSION_FEATURES 0x%08lx%s\n",
586 version.feature_set, ul_sfx);
587 #ifdef IGNORED_FEATURES
588 Fprintf(ofp,"#define IGNORED_FEATURES 0x%08lx%s\n",
589 (unsigned long) IGNORED_FEATURES, ul_sfx);
591 Fprintf(ofp,"#define VERSION_SANITY1 0x%08lx%s\n",
592 version.entity_count, ul_sfx);
593 Fprintf(ofp,"#define VERSION_SANITY2 0x%08lx%s\n",
594 version.struct_sizes, ul_sfx);
596 Fprintf(ofp,"#define VERSION_STRING \"%s\"\n", version_string(buf));
597 Fprintf(ofp,"#define VERSION_ID \\\n \"%s\"\n",
598 version_id_string(buf, cbuf));
602 struct tm *tm = localtime((time_t *) &clocktim);
603 Fprintf(ofp,"#define AMIGA_VERSION_STRING ");
604 Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
605 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
606 tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900);
613 static char save_bones_compat_buf[BUFSZ];
616 build_savebones_compat_string()
618 #ifdef VERSION_COMPATIBILITY
619 unsigned long uver = VERSION_COMPATIBILITY;
621 Strcpy(save_bones_compat_buf,
622 "save and bones files accepted from version");
623 #ifdef VERSION_COMPATIBILITY
624 Sprintf(eos(save_bones_compat_buf), "s %lu.%lu.%lu through %d.%d.%d",
625 ((uver & 0xFF000000L) >> 24), ((uver & 0x00FF0000L) >> 16),
626 ((uver & 0x0000FF00L) >> 8),
627 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
629 Sprintf(eos(save_bones_compat_buf), " %d.%d.%d only",
630 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
634 static const char *build_opts[] = {
636 "Amiga WorkBench support",
639 "ANSI default terminal",
641 #ifdef AUTOPICKUP_EXCEPTIONS
642 "autopickup_exceptions",
648 "command line completion",
651 "data file compression",
663 "experience points on status line",
666 "floppy drive support",
669 "gold object in inventories",
672 "insurance files for recovering from crashes",
677 #ifdef HOLD_LOCKFILE_OPEN
678 "exclusive lock on level 0 file",
687 "MSDOS protected mode",
710 "saddles and riding",
713 "score on status line",
720 "screen control via mactty",
723 "screen control via BIOS",
725 # ifdef SCREEN_DJGPPFAST
726 "screen control via DJGPP fast",
729 "screen control via VGA graphics",
731 # ifndef MSWIN_GRAPHICS
733 "screen control via WIN32 console I/O",
750 "terminal info library",
752 # if defined(TERMLIB) || ((!defined(MICRO) && !defined(WIN32)) && defined(TTY_GRAPHICS))
753 "terminal capability library",
757 "timed wait for display effects",
763 # ifdef USER_SOUNDS_REGEX
764 "user sounds via regular expressions",
766 "user sounds via pmatch",
769 #ifdef PREFIXES_IN_USE
770 "variable playground",
775 #ifdef WALLIFIED_MAZE
779 "zero-compressed save files",
781 save_bones_compat_buf,
782 "basic NetHack features"
785 static const char *window_opts[] = {
787 "traditional tty-based graphics",
795 #ifdef GNOME_GRAPHICS
801 #ifdef AMIGA_INTUITION
807 #ifdef MSWIN_GRAPHICS
819 register int i, length;
820 register const char *str, *indent = " ";
824 Strcat(filename,file_prefix);
826 Sprintf(eos(filename), DATA_TEMPLATE, OPTIONS_FILE);
827 if (!(ofp = fopen(filename, WRTMODE))) {
832 build_savebones_compat_string();
835 "\n NetHack version %d.%d.%d [beta]\n",
837 "\n NetHack version %d.%d.%d\n",
839 VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
841 Fprintf(ofp,"\nOptions compiled into this edition:\n");
843 length = COLNO + 1; /* force 1st item onto new line */
844 for (i = 0; i < SIZE(build_opts); i++) {
846 if (length + strlen(str) > COLNO - 5)
847 Fprintf(ofp,"\n%s", indent), length = strlen(indent);
849 Fprintf(ofp," "), length++;
850 Fprintf(ofp,"%s", str), length += strlen(str);
851 Fprintf(ofp,(i < SIZE(build_opts) - 1) ? "," : "."), length++;
854 Fprintf(ofp,"\n\nSupported windowing systems:\n");
856 length = COLNO + 1; /* force 1st item onto new line */
857 for (i = 0; i < SIZE(window_opts) - 1; i++) {
858 str = window_opts[i];
859 if (length + strlen(str) > COLNO - 5)
860 Fprintf(ofp,"\n%s", indent), length = strlen(indent);
862 Fprintf(ofp," "), length++;
863 Fprintf(ofp,"%s", str), length += strlen(str);
864 Fprintf(ofp, ","), length++;
866 Fprintf(ofp, "\n%swith a default of %s.", indent, DEFAULT_WINDOW_SYS);
873 /* routine to decide whether to discard something from data.base */
878 if (*line == '#') return TRUE; /* ignore comment lines */
884 New format (v3.1) of 'data' file which allows much faster lookups [pr]
885 "do not edit" first record is a comment line
886 01234567 hexadecimal formatted offset to text area
887 name-a first name of interest
888 123,4 offset to name's text, and number of lines for it
889 name-b next name of interest
890 name-c multiple names which share same description also
891 456,7 share a single offset,count line
892 . sentinel to mark end of names
893 789,0 dummy record containing offset, count of EOF
894 text-a 4 lines of descriptive text for name-a
895 text-a at file position 0x01234567L + 123L
898 text-b/text-c 7 lines of text for names-b and -c
899 text-b/text-c at fseek(0x01234567L + 456L)
907 char infile[60], tempfile[60];
910 int entry_cnt, line_cnt;
912 Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
915 Strcat(filename,file_prefix);
917 Sprintf(eos(filename), DATA_TEMPLATE, DATA_FILE);
918 Sprintf(infile, DATA_IN_TEMPLATE, DATA_FILE);
920 #ifdef SHORT_FILENAMES
926 if (!(ifp = fopen(infile, RDTMODE))) { /* data.base */
930 if (!(ofp = fopen(filename, WRTMODE))) { /* data */
935 if (!(tfp = fopen(tempfile, WRTMODE))) { /* database.tmp */
943 /* output a dummy header record; we'll rewind and overwrite it later */
944 Fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, 0L);
946 entry_cnt = line_cnt = 0;
947 /* read through the input file and split it into two sections */
948 while (fgets(in_line, sizeof in_line, ifp)) {
949 if (d_filter(in_line)) continue;
950 if (*in_line > ' ') { /* got an entry name */
951 /* first finish previous entry */
952 if (line_cnt) Fprintf(ofp, "%d\n", line_cnt), line_cnt = 0;
953 /* output the entry name */
954 (void) fputs(in_line, ofp);
955 entry_cnt++; /* update number of entries */
956 } else if (entry_cnt) { /* got some descriptive text */
957 /* update previous entry with current text offset */
958 if (!line_cnt) Fprintf(ofp, "%ld,", ftell(tfp));
959 /* save the text line in the scratch file */
960 (void) fputs(in_line, tfp);
961 line_cnt++; /* update line counter */
964 /* output an end marker and then record the current position */
965 if (line_cnt) Fprintf(ofp, "%d\n", line_cnt);
966 Fprintf(ofp, ".\n%ld,%d\n", ftell(tfp), 0);
967 txt_offset = ftell(ofp);
968 Fclose(ifp); /* all done with original input file */
970 /* reprocess the scratch file; 1st format an error msg, just in case */
971 Sprintf(in_line, "rewind of \"%s\"", tempfile);
972 if (rewind(tfp) != 0) goto dead_data;
973 /* copy all lines of text from the scratch file into the output file */
974 while (fgets(in_line, sizeof in_line, tfp))
975 (void) fputs(in_line, ofp);
977 /* finished with scratch file */
979 Unlink(tempfile); /* remove it */
981 /* update the first record of the output file; prepare error msg 1st */
982 Sprintf(in_line, "rewind of \"%s\"", filename);
983 ok = (rewind(ofp) == 0);
985 Sprintf(in_line, "header rewrite of \"%s\"", filename);
986 ok = (fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, txt_offset) >= 0);
989 dead_data: perror(in_line); /* report the problem */
990 /* close and kill the aborted output file, then give up */
1002 /* routine to decide whether to discard something from oracles.txt */
1007 static boolean skip = FALSE;
1008 char tag[sizeof in_line];
1012 if (*line == '#') return TRUE; /* ignore comment lines */
1013 if (sscanf(line, "----- %s", tag) == 1) {
1016 if (!strcmp(tag, "SINKS")) skip = TRUE;
1019 if (!strcmp(tag, "ELBERETH")) skip = TRUE;
1021 } else if (skip && !strncmp(line, "-----", 5))
1026 static const char *special_oracle[] = {
1027 "\"...it is rather disconcerting to be confronted with the",
1028 "following theorem from [Baker, Gill, and Solovay, 1975].",
1030 "Theorem 7.18 There exist recursive languages A and B such that",
1031 " (1) P(A) == NP(A), and",
1032 " (2) P(B) != NP(B)",
1034 "This provides impressive evidence that the techniques that are",
1035 "currently available will not suffice for proving that P != NP or ",
1036 "that P == NP.\" [Garey and Johnson, p. 185.]"
1040 The oracle file consists of a "do not edit" comment, a decimal count N
1041 and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
1042 records, separated by "---" lines. The first oracle is a special case.
1043 The input data contains just those multi-line records, separated by
1050 char infile[60], tempfile[60];
1051 boolean in_oracle, ok;
1052 long txt_offset, offset, fpos;
1056 Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
1059 Strcat(filename, file_prefix);
1061 Sprintf(eos(filename), DATA_TEMPLATE, ORACLE_FILE);
1062 Sprintf(infile, DATA_IN_TEMPLATE, ORACLE_FILE);
1063 Strcat(infile, ".txt");
1064 if (!(ifp = fopen(infile, RDTMODE))) {
1068 if (!(ofp = fopen(filename, WRTMODE))) {
1073 if (!(tfp = fopen(tempfile, WRTMODE))) { /* oracles.tmp */
1081 /* output a dummy header record; we'll rewind and overwrite it later */
1082 Fprintf(ofp, "%s%5d\n", Dont_Edit_Data, 0);
1084 /* handle special oracle; it must come first */
1085 (void) fputs("---\n", tfp);
1086 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* start pos of special oracle */
1087 for (i = 0; i < SIZE(special_oracle); i++) {
1088 (void) fputs(xcrypt(special_oracle[i]), tfp);
1089 (void) fputc('\n', tfp);
1094 (void) fputs("---\n", tfp);
1095 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* start pos of first oracle */
1098 while (fgets(in_line, sizeof in_line, ifp)) {
1101 if (h_filter(in_line)) continue;
1102 if (!strncmp(in_line, "-----", 5)) {
1103 if (!in_oracle) continue;
1106 (void) fputs("---\n", tfp);
1107 Fprintf(ofp, "%05lx\n", ftell(tfp));
1108 /* start pos of this oracle */
1111 (void) fputs(xcrypt(in_line), tfp);
1115 if (in_oracle) { /* need to terminate last oracle */
1117 (void) fputs("---\n", tfp);
1118 Fprintf(ofp, "%05lx\n", ftell(tfp)); /* eof position */
1121 /* record the current position */
1122 txt_offset = ftell(ofp);
1123 Fclose(ifp); /* all done with original input file */
1125 /* reprocess the scratch file; 1st format an error msg, just in case */
1126 Sprintf(in_line, "rewind of \"%s\"", tempfile);
1127 if (rewind(tfp) != 0) goto dead_data;
1128 /* copy all lines of text from the scratch file into the output file */
1129 while (fgets(in_line, sizeof in_line, tfp))
1130 (void) fputs(in_line, ofp);
1132 /* finished with scratch file */
1134 Unlink(tempfile); /* remove it */
1136 /* update the first record of the output file; prepare error msg 1st */
1137 Sprintf(in_line, "rewind of \"%s\"", filename);
1138 ok = (rewind(ofp) == 0);
1140 Sprintf(in_line, "header rewrite of \"%s\"", filename);
1141 ok = (fprintf(ofp, "%s%5d\n", Dont_Edit_Data, oracle_cnt) >=0);
1144 Sprintf(in_line, "data rewrite of \"%s\"", filename);
1145 for (i = 0; i <= oracle_cnt; i++) {
1146 #ifndef VMS /* alpha/vms v1.0; this fflush seems to confuse ftell */
1147 if (!(ok = (fflush(ofp) == 0))) break;
1149 if (!(ok = (fpos = ftell(ofp)) >= 0)) break;
1150 if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
1151 if (!(ok = (fscanf(ofp, "%5lx", &offset) == 1))) break;
1155 MetroWerks CodeWarrior Pro 1's (AKA CW12) version of MSL
1156 (ANSI C Libraries) needs this rewind or else the fprintf
1157 stops working. This may also be true for CW11, but has
1163 if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
1164 if (!(ok = (fprintf(ofp, "%05lx\n", offset + txt_offset) >= 0)))
1169 dead_data: perror(in_line); /* report the problem */
1170 /* close and kill the aborted output file, then give up */
1183 static struct deflist {
1185 const char *defname;
1186 boolean true_or_false;
1188 #ifdef REINCARNATION
1189 { "REINCARNATION", TRUE },
1191 { "REINCARNATION", FALSE },
1201 if(s[0] != '%') return(-1);
1203 for(i = 0; deflist[i].defname; i++)
1204 if(!strncmp(deflist[i].defname, s+1, strlen(deflist[i].defname)))
1214 return(s + 1 + strlen(deflist[check_control(in_line)].defname));
1222 Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
1223 if (!(ifp = fopen(filename, RDTMODE))) {
1229 Strcat(filename, file_prefix);
1231 Sprintf(eos(filename), DGN_TEMPLATE, DGN_O_FILE);
1232 if (!(ofp = fopen(filename, WRTMODE))) {
1236 Fprintf(ofp,Dont_Edit_Data);
1238 while (fgets(in_line, sizeof in_line, ifp) != 0) {
1242 if(in_line[0] == '#') continue; /* discard comments */
1244 if(in_line[0] == '%') {
1245 int i = check_control(in_line);
1247 if(!deflist[i].true_or_false) {
1248 while (fgets(in_line, sizeof in_line, ifp) != 0)
1249 if(check_control(in_line) != i) goto recheck;
1251 (void) fputs(without_control(in_line),ofp);
1253 Fprintf(stderr, "Unknown control option '%s' in file %s at line %d.\n",
1254 in_line, DGN_I_FILE, rcnt);
1258 (void) fputs(in_line,ofp);
1267 ranged_attk(ptr) /* returns TRUE if monster can attack at range */
1268 register struct permonst *ptr;
1271 register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);
1273 for(i = 0; i < NATTK; i++) {
1274 if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
1281 /* This routine is designed to return an integer value which represents
1282 * an approximation of monster strength. It uses a similar method of
1283 * determination as "experience()" to arrive at the strength.
1287 struct permonst *ptr;
1289 int i, tmp2, n, tmp = ptr->mlevel;
1291 if(tmp > 49) /* special fixed hp monster */
1292 tmp = 2*(tmp - 6) / 4;
1294 /* For creation in groups */
1295 n = (!!(ptr->geno & G_SGROUP));
1296 n += (!!(ptr->geno & G_LGROUP)) << 1;
1298 /* For ranged attacks */
1299 if (ranged_attk(ptr)) n++;
1301 /* For higher ac values */
1305 /* For very fast monsters */
1306 n += (ptr->mmove >= 18);
1308 /* For each attack and "special" attack */
1309 for(i = 0; i < NATTK; i++) {
1311 tmp2 = ptr->mattk[i].aatyp;
1313 n += (tmp2 == AT_MAGC);
1314 n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG));
1317 /* For each "special" damage type */
1318 for(i = 0; i < NATTK; i++) {
1320 tmp2 = ptr->mattk[i].adtyp;
1321 if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST)
1322 || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO) || (tmp2 == AD_WERE))
1324 else if (strcmp(ptr->mname, "grid bug")) n += (tmp2 != AD_PHYS);
1325 n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
1328 /* Leprechauns are special cases. They have many hit dice so they
1329 can hit and are hard to kill, but they don't really do much damage. */
1330 if (!strcmp(ptr->mname, "leprechaun")) n -= 2;
1332 /* Finally, adjust the monster level 0 <= n <= 24 (approx.) */
1334 else if(n >= 6) tmp += ( n / 2 );
1335 else tmp += ( n / 3 + 1);
1337 return((tmp >= 0) ? tmp : 0);
1343 register struct permonst *ptr;
1347 * create the source file, "monstr.c"
1351 Strcat(filename, file_prefix);
1353 Sprintf(eos(filename), SOURCE_TEMPLATE, MON_STR_C);
1354 if (!(ofp = fopen(filename, WRTMODE))) {
1358 Fprintf(ofp,Dont_Edit_Code);
1359 Fprintf(ofp,"#include \"config.h\"\n");
1360 Fprintf(ofp,"\nconst int monstr[] = {\n");
1361 for (ptr = &mons[0], j = 0; ptr->mlet; ptr++) {
1366 Fprintf(ofp,"%2d,%c", i, (++j & 15) ? ' ' : '\n');
1368 /* might want to insert a final 0 entry here instead of just newline */
1369 Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");
1371 Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
1372 Fprintf(ofp,"\nvoid\n");
1373 Fprintf(ofp,"monstr_init()\n");
1375 Fprintf(ofp," return;\n");
1377 Fprintf(ofp,"\n/*monstr.c*/\n");
1391 Strcat(filename, file_prefix);
1393 Sprintf(eos(filename), INCLUDE_TEMPLATE, MONST_FILE);
1394 if (!(ofp = fopen(filename, WRTMODE))) {
1398 Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.4\t2002/02/03 */\n\n");
1399 Fprintf(ofp,Dont_Edit_Code);
1400 Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");
1402 if (strcmp(mons[0].mname, "playermon") != 0)
1403 Fprintf(ofp,"\n#define\tPM_PLAYERMON\t(-1)");
1405 for (i = 0; mons[i].mlet; i++) {
1408 Fprintf(ofp,"\n#define\tPM_");
1409 if (mons[i].mlet == S_HUMAN &&
1410 !strncmp(mons[i].mname, "were", 4))
1411 Fprintf(ofp, "HUMAN_");
1412 for (nam = c = tmpdup(mons[i].mname); *c; c++)
1413 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1414 else if (*c < 'A' || *c > 'Z') *c = '_';
1415 Fprintf(ofp,"%s\t%d", nam, i);
1417 Fprintf(ofp,"\n\n#define\tNUMMONS\t%d\n", i);
1418 Fprintf(ofp,"\n#endif /* PM_H */\n");
1424 /* Start of Quest text file processing. */
1427 static struct qthdr qt_hdr;
1428 static struct msghdr msg_hdr[N_HDR];
1429 static struct qtmsg *curr_msg;
1433 static boolean in_msg;
1434 #define NO_MSG 1 /* strlen of a null line returned by fgets() */
1440 if(s[0] == '#') return(TRUE);
1441 return((boolean)(!in_msg && strlen(s) == NO_MSG));
1448 return((boolean)(s[0] == '%' && (s[1] == 'C' || s[1] == 'E')));
1457 for(i = 0; i < qt_hdr.n_hdr; i++)
1458 if(!strncmp(code, qt_hdr.id[i], LEN_HDR)) return (++i);
1467 if(qt_hdr.n_hdr >= N_HDR) {
1468 Fprintf(stderr, OUT_OF_HEADERS, qt_line);
1472 strncpy(&qt_hdr.id[qt_hdr.n_hdr][0], code, LEN_HDR);
1473 msg_hdr[qt_hdr.n_hdr].n_msg = 0;
1474 qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
1484 for(i = 0; i < msg_hdr[num].n_msg; i++)
1485 if(msg_hdr[num].qt_msg[i].msgnum == id) return(TRUE);
1496 struct qtmsg *qt_msg;
1498 if(msg_hdr[num].n_msg >= N_MSG) {
1499 Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
1501 qt_msg = &(msg_hdr[num].qt_msg[msg_hdr[num].n_msg++]);
1502 qt_msg->msgnum = id;
1503 qt_msg->delivery = s[2];
1504 qt_msg->offset = qt_msg->size = 0L;
1519 case 'C': if(in_msg) {
1520 Fprintf(stderr, CREC_IN_MSG, qt_line);
1524 if (sscanf(&s[4], "%s %5d", code, &id) != 2) {
1525 Fprintf(stderr, UNREC_CREC, qt_line);
1528 num = get_hdr(code);
1529 if (!num && !new_id(code))
1531 num = get_hdr(code)-1;
1532 if(known_msg(num, id))
1533 Fprintf(stderr, DUP_MSG, qt_line);
1534 else new_msg(s, num, id);
1538 case 'E': if(!in_msg) {
1539 Fprintf(stderr, END_NOT_IN_MSG, qt_line);
1541 } else in_msg = FALSE;
1544 default: Fprintf(stderr, UNREC_CREC, qt_line);
1554 Fprintf(stderr, TEXT_NOT_IN_MSG, qt_line);
1556 curr_msg->size += strlen(s);
1564 long count = 0L, hdr_offset = sizeof(int) +
1565 (sizeof(char)*LEN_HDR + sizeof(long)) * qt_hdr.n_hdr;
1567 for(i = 0; i < qt_hdr.n_hdr; i++) {
1568 qt_hdr.offset[i] = hdr_offset;
1569 hdr_offset += sizeof(int) + sizeof(struct qtmsg) * msg_hdr[i].n_msg;
1572 for(i = 0; i < qt_hdr.n_hdr; i++)
1573 for(j = 0; j < msg_hdr[i].n_msg; j++) {
1575 msg_hdr[i].qt_msg[j].offset = hdr_offset + count;
1576 count += msg_hdr[i].qt_msg[j].size;
1587 * The main header record.
1590 Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
1592 (void) fwrite((genericptr_t)&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
1593 (void) fwrite((genericptr_t)&(qt_hdr.id[0][0]), sizeof(char)*LEN_HDR,
1595 (void) fwrite((genericptr_t)&(qt_hdr.offset[0]), sizeof(long),
1598 for(i = 0; i < qt_hdr.n_hdr; i++)
1599 Fprintf(stderr, "%c @ %ld, ", qt_hdr.id[i], qt_hdr.offset[i]);
1601 Fprintf(stderr, "\n");
1605 * The individual class headers.
1607 for(i = 0; i < qt_hdr.n_hdr; i++) {
1610 Fprintf(stderr, "%ld: %c header info.\n", ftell(ofp),
1613 (void) fwrite((genericptr_t)&(msg_hdr[i].n_msg), sizeof(int),
1615 (void) fwrite((genericptr_t)&(msg_hdr[i].qt_msg[0]),
1616 sizeof(struct qtmsg), msg_hdr[i].n_msg, ofp);
1619 for(j = 0; j < msg_hdr[i].n_msg; j++)
1620 Fprintf(stderr, "msg %d @ %ld (%ld)\n",
1621 msg_hdr[i].qt_msg[j].msgnum,
1622 msg_hdr[i].qt_msg[j].offset,
1623 msg_hdr[i].qt_msg[j].size);
1632 Sprintf(filename, DATA_IN_TEMPLATE, QTXT_I_FILE);
1633 if(!(ifp = fopen(filename, RDTMODE))) {
1640 Strcat(filename, file_prefix);
1642 Sprintf(eos(filename), DATA_TEMPLATE, QTXT_O_FILE);
1643 if(!(ofp = fopen(filename, WRBMODE))) {
1653 while (fgets(in_line, 80, ifp) != 0) {
1657 if(qt_control(in_line)) do_qt_control(in_line);
1658 else if(qt_comment(in_line)) continue;
1659 else do_qt_text(in_line);
1666 while (fgets(in_line, 80, ifp) != 0) {
1668 if(qt_control(in_line)) {
1669 in_msg = (in_line[1] == 'C');
1671 } else if(qt_comment(in_line)) continue;
1673 Fprintf(stderr, "%ld: %s", ftell(stdout), in_line);
1675 (void) fputs(xcrypt(in_line), ofp);
1683 static char temp[32];
1686 limit(name,pref) /* limit a name to 30 characters length */
1690 (void) strncpy(temp, name, pref ? 26 : 30);
1691 temp[pref ? 26 : 30] = 0;
1703 boolean sumerr = FALSE;
1707 Strcat(filename, file_prefix);
1709 Sprintf(eos(filename), INCLUDE_TEMPLATE, ONAME_FILE);
1710 if (!(ofp = fopen(filename, WRTMODE))) {
1714 Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.4\t2002/02/03 */\n\n");
1715 Fprintf(ofp,Dont_Edit_Code);
1716 Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n");
1718 for(i = 0; !i || objects[i].oc_class != ILLOBJ_CLASS; i++) {
1721 objects[i].oc_name_idx = objects[i].oc_descr_idx = i; /* init */
1722 if (!(objnam = tmpdup(OBJ_NAME(objects[i])))) continue;
1724 /* make sure probabilities add up to 1000 */
1725 if(objects[i].oc_class != class) {
1726 if (sum && sum != 1000) {
1727 Fprintf(stderr, "prob error for class %d (%d%%)",
1729 (void) fflush(stderr);
1732 class = objects[i].oc_class;
1736 for (c = objnam; *c; c++)
1737 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1738 else if (*c < 'A' || *c > 'Z') *c = '_';
1742 Fprintf(ofp,"#define\tWAN_"); prefix = 1; break;
1744 Fprintf(ofp,"#define\tRIN_"); prefix = 1; break;
1746 Fprintf(ofp,"#define\tPOT_"); prefix = 1; break;
1748 Fprintf(ofp,"#define\tSPE_"); prefix = 1; nspell++; break;
1750 Fprintf(ofp,"#define\tSCR_"); prefix = 1; break;
1752 /* avoid trouble with stupid C preprocessors */
1753 Fprintf(ofp,"#define\t");
1754 if(objects[i].oc_material == PLASTIC) {
1755 Fprintf(ofp,"FAKE_AMULET_OF_YENDOR\t%d\n", i);
1761 /* avoid trouble with stupid C preprocessors */
1762 if(objects[i].oc_material == GLASS) {
1763 Fprintf(ofp,"/* #define\t%s\t%d */\n",
1769 Fprintf(ofp,"#define\t");
1772 Fprintf(ofp,"%s\t%d\n", limit(objnam, prefix), i);
1775 sum += objects[i].oc_prob;
1778 /* check last set of probabilities */
1779 if (sum && sum != 1000) {
1780 Fprintf(stderr, "prob error for class %d (%d%%)", class, sum);
1781 (void) fflush(stderr);
1785 Fprintf(ofp,"#define\tLAST_GEM\t(JADE)\n");
1786 Fprintf(ofp,"#define\tMAXSPELL\t%d\n", nspell+1);
1787 Fprintf(ofp,"#define\tNUM_OBJECTS\t%d\n", i);
1789 Fprintf(ofp, "\n/* Artifacts (unique objects) */\n\n");
1791 for (i = 1; artifact_names[i]; i++) {
1794 for (c = objnam = tmpdup(artifact_names[i]); *c; c++)
1795 if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
1796 else if (*c < 'A' || *c > 'Z') *c = '_';
1798 if (!strncmp(objnam, "THE_", 4))
1801 /* fudge _platinum_ YENDORIAN EXPRESS CARD */
1802 if (!strncmp(objnam, "PLATINUM_", 9))
1805 Fprintf(ofp,"#define\tART_%s\t%d\n", limit(objnam, 1), i);
1808 Fprintf(ofp, "#define\tNROFARTIFACTS\t%d\n", i-1);
1809 Fprintf(ofp,"\n#endif /* ONAMES_H */\n");
1811 if (sumerr) exit(EXIT_FAILURE);
1819 static char buf[128];
1821 if (!str) return (char *)0;
1822 (void)strncpy(buf, str, 127);
1835 * macro used to control vision algorithms:
1836 * VISION_TABLES => generate tables
1842 #ifdef VISION_TABLES
1845 /* Everything is clear. xclear may be malloc'ed.
1846 * Block the upper left corner (BLOCK_HEIGHTxBLOCK_WIDTH)
1848 for (i = 0; i < MAX_ROW; i++)
1849 for (j = 0; j < MAX_COL; j++)
1850 if (i < BLOCK_HEIGHT && j < BLOCK_WIDTH)
1851 xclear[i][j] = '\000';
1853 xclear[i][j] = '\001';
1854 #endif /* VISION_TABLES */
1859 * create the include file, "vis_tab.h"
1863 Strcat(filename, file_prefix);
1865 Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
1866 if (!(ofp = fopen(filename, WRTMODE))) {
1870 Fprintf(ofp,Dont_Edit_Code);
1871 Fprintf(ofp,"#ifdef VISION_TABLES\n");
1872 #ifdef VISION_TABLES
1875 #endif /* VISION_TABLES */
1876 Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
1882 * create the source file, "vis_tab.c"
1886 Strcat(filename, file_prefix);
1888 Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
1889 if (!(ofp = fopen(filename, WRTMODE))) {
1891 Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
1895 Fprintf(ofp,Dont_Edit_Code);
1896 Fprintf(ofp,"#include \"config.h\"\n");
1897 Fprintf(ofp,"#ifdef VISION_TABLES\n");
1898 Fprintf(ofp,"#include \"vis_tab.h\"\n");
1902 #ifdef VISION_TABLES
1905 Fprintf(ofp,"\nvoid vis_tab_init() { return; }\n");
1906 #endif /* VISION_TABLES */
1910 Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
1911 Fprintf(ofp,"\n/*vis_tab.c*/\n");
1917 #ifdef VISION_TABLES
1919 /*-------------- vision tables --------------*\
1921 * Generate the close and far tables. This is done by setting up a
1922 * fake dungeon and moving our source to different positions relative
1923 * to a block and finding the first/last visible position. The fake
1924 * dungeon is all clear execpt for the upper left corner (BLOCK_HEIGHT
1925 * by BLOCK_WIDTH) is blocked. Then we move the source around relative
1926 * to the corner of the block. For each new position of the source
1927 * we check positions on rows "kittycorner" from the source. We check
1928 * positions until they are either in sight or out of sight (depends on
1929 * which table we are generating). The picture below shows the setup
1930 * for the generation of the close table. The generation of the far
1931 * table would switch the quadrants of the '@' and the "Check rows
1935 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1936 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1937 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,, Check rows here ,,,,,,,,,,,,
1938 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1939 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXB,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1940 * ...............................
1941 * ...............................
1942 * .........@.....................
1943 * ...............................
1945 * Table generation figure (close_table). The 'X's are blocked points.
1946 * The 'B' is a special blocked point. The '@' is the source. The ','s
1947 * are the target area. The '.' are just open areas.
1950 * Example usage of close_table[][][].
1952 * The table is as follows:
1954 * dy = |row of '@' - row of 'B'| - 1
1955 * dx = |col of '@' - col of 'B'|
1957 * The first indices are the deltas from the source '@' and the block 'B'.
1958 * You must check for the value inside the abs value bars being zero. If
1959 * so then the block is on the same row and you don't need to do a table
1960 * lookup. The last value:
1962 * dcy = |row of block - row to be checked|
1964 * Is the value of the first visible spot on the check row from the
1967 * first visible col = close_table[dy][dx][dcy] + col of 'B'
1969 \*-------------- vision tables --------------*/
1974 Fprintf(ofp,"\n/* Close */\n");
1975 Fprintf(ofp,"#define CLOSE_MAX_SB_DY %2d\t/* |src row - block row| - 1\t*/\n",
1977 Fprintf(ofp,"#define CLOSE_MAX_SB_DX %2d\t/* |src col - block col|\t*/\n",
1979 Fprintf(ofp,"#define CLOSE_MAX_BC_DY %2d\t/* |block row - check row|\t*/\n",
1981 Fprintf(ofp,"typedef struct {\n");
1982 Fprintf(ofp," unsigned char close[CLOSE_MAX_SB_DX][CLOSE_MAX_BC_DY];\n");
1983 Fprintf(ofp,"} close2d;\n");
1984 Fprintf(ofp,"extern close2d close_table[CLOSE_MAX_SB_DY];\n");
1991 Fprintf(ofp,"\n/* Far */\n");
1992 Fprintf(ofp,"#define FAR_MAX_SB_DY %2d\t/* |src row - block row|\t*/\n",
1994 Fprintf(ofp,"#define FAR_MAX_SB_DX %2d\t/* |src col - block col| - 1\t*/\n",
1996 Fprintf(ofp,"#define FAR_MAX_BC_DY %2d\t/* |block row - check row| - 1\t*/\n",
1998 Fprintf(ofp,"typedef struct {\n");
1999 Fprintf(ofp," unsigned char far_q[FAR_MAX_SB_DX][FAR_MAX_BC_DY];\n");
2000 Fprintf(ofp,"} far2d;\n");
2001 Fprintf(ofp,"extern far2d far_table[FAR_MAX_SB_DY];\n");
2009 int src_row, src_col; /* source */
2010 int block_row, block_col; /* block */
2015 block_row = BLOCK_HEIGHT-1;
2016 block_col = BLOCK_WIDTH-1;
2018 Fprintf(ofp,"\n#ifndef FAR_TABLE_ONLY\n");
2019 Fprintf(ofp,"\nclose2d close_table[CLOSE_MAX_SB_DY] = {\n");
2020 #ifndef no_vision_progress
2021 Fprintf(stderr,"\nclose:");
2024 for (dy = 1; dy < TEST_HEIGHT; dy++) {
2025 src_row = block_row + dy;
2026 Fprintf(ofp, "/* DY = %2d (- 1)*/\n {{\n", dy);
2027 #ifndef no_vision_progress
2028 Fprintf(stderr," %2d",dy), (void)fflush(stderr);
2030 for (dx = 0; dx < TEST_WIDTH; dx++) {
2031 src_col = block_col - dx;
2032 Fprintf(ofp, " /*%2d*/ {", dx);
2035 for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
2036 delim = (this_row < TEST_HEIGHT - 1) ? "," : "";
2038 Fprintf(ofp, "%s%s", CLOSE_OFF_TABLE_STRING, delim);
2043 /* Find the first column that we can see. */
2044 for (i = block_col+1; i < MAX_COL; i++) {
2045 if (clear_path(src_row,src_col,block_row-this_row,i))
2049 if (i == MAX_COL) no_more = 1;
2050 Fprintf(ofp, "%2d%s", i - block_col, delim);
2052 Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
2054 Fprintf(ofp," }},\n");
2057 Fprintf(ofp,"}; /* close_table[] */\n"); /* closing brace for table */
2058 Fprintf(ofp,"#endif /* !FAR_TABLE_ONLY */\n");
2059 #ifndef no_vision_progress
2060 Fprintf(stderr,"\n");
2069 int src_row, src_col; /* source */
2070 int block_row, block_col; /* block */
2074 block_row = BLOCK_HEIGHT-1;
2075 block_col = BLOCK_WIDTH-1;
2077 Fprintf(ofp,"\n#ifndef CLOSE_TABLE_ONLY\n");
2078 Fprintf(ofp,"\nfar2d far_table[FAR_MAX_SB_DY] = {\n");
2079 #ifndef no_vision_progress
2080 Fprintf(stderr,"\n_far_:");
2083 for (dy = 0; dy < TEST_HEIGHT; dy++) {
2084 src_row = block_row - dy;
2085 Fprintf(ofp, "/* DY = %2d */\n {{\n", dy);
2086 #ifndef no_vision_progress
2087 Fprintf(stderr," %2d",dy), (void)fflush(stderr);
2089 for (dx = 1; dx < TEST_WIDTH; dx++) {
2090 src_col = block_col + dx;
2091 Fprintf(ofp, " /*%2d(-1)*/ {", dx);
2093 for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
2095 delim = (this_row < block_row + TEST_HEIGHT - 1) ? "," : "";
2098 /* Find first col that we can see. */
2099 for (i = 0; i <= block_col; i++) {
2100 if (clear_path(src_row,src_col,this_row,i)) break;
2103 if (block_col-i < 0)
2104 Fprintf(ofp, "%s%s", FAR_OFF_TABLE_STRING, delim);
2106 Fprintf(ofp, "%2d%s", block_col - i, delim);
2108 Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
2110 Fprintf(ofp," }},\n");
2113 Fprintf(ofp,"}; /* far_table[] */\n"); /* closing brace for table */
2114 Fprintf(ofp,"#endif /* !CLOSE_TABLE_ONLY */\n");
2115 #ifndef no_vision_progress
2116 Fprintf(stderr,"\n");
2122 * "Draw" a line from the hero to the given location. Stop if we hit a
2125 * Generalized integer Bresenham's algorithm (fast line drawing) for
2126 * all quadrants. From _Procedural Elements for Computer Graphics_, by
2127 * David F. Rogers. McGraw-Hill, 1985.
2129 * I have tried a little bit of optimization by pulling compares out of
2132 * NOTE: This had better *not* be called from a position on the
2133 * same row as the hero.
2136 clear_path(you_row,you_col,y2,x2)
2137 int you_row, you_col, y2, x2;
2140 register int i, error, x, y, dxs, dys;
2142 x = you_col; y = you_row;
2143 dx = abs(x2-you_col); dy = abs(y2-you_row);
2144 s1 = sign(x2-you_col); s2 = sign(y2-you_row);
2146 if (s1 == 0) { /* same column */
2147 if (s2 == 1) { /* below (larger y2 value) */
2148 for (i = you_row+1; i < y2; i++)
2149 if (!xclear[i][you_col]) return 0;
2150 } else { /* above (smaller y2 value) */
2151 for (i = y2+1; i < you_row; i++)
2152 if (!xclear[i][you_col]) return 0;
2158 * Lines at 0 and 90 degrees have been weeded out.
2161 error = dx; dx = dy; dy = error; /* swap the values */
2162 dxs = dx << 1; /* save the shifted values */
2164 error = dys - dx; /* NOTE: error is used as a temporary above */
2166 for (i = 0; i < dx; i++) {
2167 if (!xclear[y][x]) return 0; /* plot point */
2169 while (error >= 0) {
2177 dxs = dx << 1; /* save the shifted values */
2181 for (i = 0; i < dx; i++) {
2182 if (!xclear[y][x]) return 0; /* plot point */
2184 while (error >= 0) {
2194 #endif /* VISION_TABLES */
2196 #ifdef STRICT_REF_DEF
2197 NEARDATA struct flag flags;
2199 struct attribs attrmax, attrmin;
2201 #endif /* STRICT_REF_DEF */