]> granicus.if.org Git - nethack/commitdiff
*** empty log message ***
authorjwalz <jwalz>
Sat, 5 Jan 2002 21:06:00 +0000 (21:06 +0000)
committerjwalz <jwalz>
Sat, 5 Jan 2002 21:06:00 +0000 (21:06 +0000)
util/makedefs.c [new file with mode: 0644]

diff --git a/util/makedefs.c b/util/makedefs.c
new file mode 100644 (file)
index 0000000..bd0e14b
--- /dev/null
@@ -0,0 +1,2143 @@
+/*     SCCS Id: @(#)makedefs.c 3.3     1999/08/16      */
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* Copyright (c) M. Stephenson, 1990, 1991.                      */
+/* Copyright (c) Dean Luick, 1990.                               */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#define MAKEDEFS_C     /* use to conditionally include file sections */
+/* #define DEBUG */    /* uncomment for debugging info */
+
+#include "config.h"
+#include "permonst.h"
+#include "objclass.h"
+#include "monsym.h"
+#include "artilist.h"
+#include "dungeon.h"
+#include "obj.h"
+#include "monst.h"
+#include "you.h"
+#include "flag.h"
+#include "dlb.h"
+
+/* version information */
+#ifdef SHORT_FILENAMES
+#include "patchlev.h"
+#else
+#include "patchlevel.h"
+#endif
+
+#ifdef MAC
+# ifdef applec /* Means the MPW compiler, I hope */
+#  define MPWTOOL
+#include <CursorCtl.h>
+#include <string.h>
+#include <ctype.h>
+# else         /* MAC without MPWTOOL */
+#  define MACsansMPWTOOL
+# endif
+#endif /* MAC */
+
+#ifndef MPWTOOL
+# define SpinCursor(x)
+#endif
+
+#define Fprintf        (void) fprintf
+#define Fclose (void) fclose
+#define Unlink (void) unlink
+#if !defined(AMIGA) || defined(AZTEC_C)
+#define rewind(fp) fseek((fp),0L,SEEK_SET)     /* guarantee a return value */
+#endif
+
+#if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
+static const char      SCCS_Id[] = "@(#)makedefs.c\t3.3\t1999/08/16";
+#endif
+
+       /* names of files to be generated */
+#define DATE_FILE      "date.h"
+#define MONST_FILE     "pm.h"
+#define ONAME_FILE     "onames.h"
+#define OPTIONS_FILE   "options"
+#define ORACLE_FILE    "oracles"
+#define DATA_FILE      "data"
+#define RUMOR_FILE     "rumors"
+#define DGN_I_FILE     "dungeon.def"
+#define DGN_O_FILE     "dungeon.pdf"
+#define MON_STR_C      "monstr.c"
+#define QTXT_I_FILE    "quest.txt"
+#define QTXT_O_FILE    "quest.dat"
+#define VIS_TAB_H      "vis_tab.h"
+#define VIS_TAB_C      "vis_tab.c"
+       /* locations for those files */
+#ifdef AMIGA
+# define FILE_PREFIX
+# define INCLUDE_TEMPLATE      "NH:include/t.%s"
+# define SOURCE_TEMPLATE       "NH:src/%s"
+# define DGN_TEMPLATE          "NH:dat/%s"  /* where dungeon.pdf file goes */
+# define DATA_TEMPLATE         "NH:slib/%s"
+# define DATA_IN_TEMPLATE      "NH:dat/%s"
+#else
+# ifdef MAC
+#   define INCLUDE_TEMPLATE    ":include:%s"
+#   define SOURCE_TEMPLATE     ":src:%s"
+#   define DGN_TEMPLATE                ":dat:%s"  /* where dungeon.pdf file goes */
+#   define DATA_TEMPLATE       ":lib:%s"
+#   define DATA_IN_TEMPLATE    ":dat:%s"
+# else /* MAC */
+#  ifdef OS2
+#   define INCLUDE_TEMPLATE    "..\\include\\%s"
+#   define SOURCE_TEMPLATE     "..\\src\\%s"
+#   define DGN_TEMPLATE                "..\\dat\\%s"  /* where dungeon.pdf file goes */
+#   define DATA_TEMPLATE       "..\\dat\\%s"
+#   define DATA_IN_TEMPLATE    "..\\dat\\%s"
+#  else /* OS2 */
+#   define INCLUDE_TEMPLATE    "../include/%s"
+#   define SOURCE_TEMPLATE     "../src/%s"
+#   define DGN_TEMPLATE                "../dat/%s"  /* where dungeon.pdf file goes */
+#   define DATA_TEMPLATE       "../dat/%s"
+#   define DATA_IN_TEMPLATE    "../dat/%s"
+#  endif /* OS2 */
+# endif /* MAC */
+#endif /* AMIGA */
+
+static const char
+    *Dont_Edit_Code =
+       "/* This source file is generated by 'makedefs'.  Do not edit. */\n",
+    *Dont_Edit_Data =
+       "#\tThis data file is generated by 'makedefs'.  Do not edit. \n";
+
+static struct version_info version;
+
+/* definitions used for vision tables */
+#define TEST_WIDTH  COLNO
+#define TEST_HEIGHT ROWNO
+#define BLOCK_WIDTH (TEST_WIDTH + 10)
+#define BLOCK_HEIGHT TEST_HEIGHT       /* don't need extra spaces */
+#define MAX_ROW (BLOCK_HEIGHT + TEST_HEIGHT)
+#define MAX_COL (BLOCK_WIDTH + TEST_WIDTH)
+/* Use this as an out-of-bound value in the close table.  */
+#define CLOSE_OFF_TABLE_STRING "99"    /* for the close table */
+#define FAR_OFF_TABLE_STRING "0xff"    /* for the far table */
+
+#define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
+#ifdef VISION_TABLES
+static char xclear[MAX_ROW][MAX_COL];
+#endif
+/*-end of vision defs-*/
+
+static char    in_line[256], filename[60];
+
+#ifdef FILE_PREFIX
+               /* if defined, a first argument not starting with - is
+                * taken as a text string to be prepended to any
+                * output filename generated */
+char *file_prefix="";
+#endif
+
+#ifdef MACsansMPWTOOL
+int FDECL(main, (void));
+#else
+int FDECL(main, (int,char **));
+#endif
+void FDECL(do_makedefs, (char *));
+void NDECL(do_objs);
+void NDECL(do_data);
+void NDECL(do_dungeon);
+void NDECL(do_date);
+void NDECL(do_options);
+void NDECL(do_monstr);
+void NDECL(do_permonst);
+void NDECL(do_questtxt);
+void NDECL(do_rumors);
+void NDECL(do_oracles);
+void NDECL(do_vision);
+
+extern void NDECL(monst_init);         /* monst.c */
+extern void NDECL(objects_init);       /* objects.c */
+
+static void NDECL(make_version);
+static char *FDECL(version_string, (char *));
+static char *FDECL(version_id_string, (char *,const char *));
+static char *FDECL(xcrypt, (const char *));
+static int FDECL(check_control, (char *));
+static char *FDECL(without_control, (char *));
+static boolean FDECL(d_filter, (char *));
+static boolean FDECL(h_filter, (char *));
+static boolean FDECL(ranged_attk,(struct permonst*));
+static int FDECL(mstrength,(struct permonst *));
+
+static boolean FDECL(qt_comment, (char *));
+static boolean FDECL(qt_control, (char *));
+static int FDECL(get_hdr, (char *));
+static boolean FDECL(new_id, (char *));
+static boolean FDECL(known_msg, (int,int));
+static void FDECL(new_msg, (char *,int,int));
+static void FDECL(do_qt_control, (char *));
+static void FDECL(do_qt_text, (char *));
+static void NDECL(adjust_qt_hdrs);
+static void NDECL(put_qt_hdrs);
+
+#ifdef VISION_TABLES
+static void NDECL(H_close_gen);
+static void NDECL(H_far_gen);
+static void NDECL(C_close_gen);
+static void NDECL(C_far_gen);
+static int FDECL(clear_path, (int,int,int,int));
+#endif
+
+static char *FDECL(tmpdup, (const char *));
+static char *FDECL(limit, (char *,int));
+static char *FDECL(eos, (char *));
+
+/* input, output, tmp */
+static FILE *ifp, *ofp, *tfp;
+
+#if defined(__BORLANDC__) && !defined(_WIN32)
+extern unsigned _stklen = STKSIZ;
+#endif
+
+
+#ifdef MACsansMPWTOOL
+int
+main(void)
+{
+    const char *def_options = "odemvpqrhz";
+    char buf[100];
+    int len;
+
+    printf("Enter options to run: [%s] ", def_options);
+    fflush(stdout);
+    fgets(buf, 100, stdin);
+    len = strlen(buf);
+    if (len <= 1)
+       Strcpy(buf, def_options);
+    else
+       buf[len-1] = 0;                 /* remove return */
+
+    do_makedefs(buf);
+    exit(EXIT_SUCCESS);
+    return 0;
+}
+
+#else /* ! MAC */
+
+int
+main(argc, argv)
+int    argc;
+char   *argv[];
+{
+       if ( (argc != 2)
+#ifdef FILE_PREFIX
+               && (argc != 3)
+#endif
+       ) {
+           Fprintf(stderr, "Bad arg count (%d).\n", argc-1);
+           (void) fflush(stderr);
+           return 1;
+       }
+
+#ifdef FILE_PREFIX
+       if(argc >=2 && argv[1][0]!='-'){
+           file_prefix=argv[1];
+           argc--;argv++;
+       }
+#endif
+       do_makedefs(&argv[1][1]);
+       exit(EXIT_SUCCESS);
+       /*NOTREACHED*/
+       return 0;
+}
+
+#endif
+
+void
+do_makedefs(options)
+char   *options;
+{
+       boolean more_than_one;
+
+       /* Note:  these initializers don't do anything except guarantee that
+               we're linked properly.
+       */
+       monst_init();
+       objects_init();
+
+       /* construct the current version number */
+       make_version();
+
+
+       more_than_one = strlen(options) > 1;
+       while (*options) {
+           if (more_than_one)
+               Fprintf(stderr, "makedefs -%c\n", *options);
+
+           switch (*options) {
+               case 'o':
+               case 'O':       do_objs();
+                               break;
+               case 'd':
+               case 'D':       do_data();
+                               break;
+               case 'e':
+               case 'E':       do_dungeon();
+                               break;
+               case 'm':
+               case 'M':       do_monstr();
+                               break;
+               case 'v':
+               case 'V':       do_date();
+                               do_options();
+                               break;
+               case 'p':
+               case 'P':       do_permonst();
+                               break;
+               case 'q':
+               case 'Q':       do_questtxt();
+                               break;
+               case 'r':
+               case 'R':       do_rumors();
+                               break;
+               case 'h':
+               case 'H':       do_oracles();
+                               break;
+               case 'z':
+               case 'Z':       do_vision();
+                               break;
+
+               default:        Fprintf(stderr, "Unknown option '%c'.\n",
+                                       *options);
+                               (void) fflush(stderr);
+                               exit(EXIT_FAILURE);
+               
+           }
+           options++;
+       }
+       if (more_than_one) Fprintf(stderr, "Completed.\n");     /* feedback */
+
+}
+
+
+/* trivial text encryption routine which can't be broken with `tr' */
+static
+char *xcrypt(str)
+const char *str;
+{                              /* duplicated in src/hacklib.c */
+       static char buf[BUFSZ];
+       register const char *p;
+       register char *q;
+       register int bitmask;
+
+       for (bitmask = 1, p = str, q = buf; *p; q++) {
+               *q = *p++;
+               if (*q & (32|64)) *q ^= bitmask;
+               if ((bitmask <<= 1) >= 32) bitmask = 1;
+       }
+       *q = '\0';
+       return buf;
+}
+
+void
+do_rumors()
+{
+       char    infile[60];
+       long    true_rumor_size;
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename,file_prefix);
+#endif
+       Sprintf(eos(filename), DATA_TEMPLATE, RUMOR_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       Fprintf(ofp,Dont_Edit_Data);
+
+       Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
+       Strcat(infile, ".tru");
+       if (!(ifp = fopen(infile, RDTMODE))) {
+               perror(infile);
+               Fclose(ofp);
+               Unlink(filename);       /* kill empty output file */
+               exit(EXIT_FAILURE);
+       }
+
+       /* get size of true rumors file */
+#ifndef VMS
+       (void) fseek(ifp, 0L, SEEK_END);
+       true_rumor_size = ftell(ifp);
+#else
+       /* seek+tell is only valid for stream format files; since rumors.%%%
+          might be in record format, count the actual data bytes instead.
+        */
+       true_rumor_size = 0;
+       while (fgets(in_line, sizeof in_line, ifp) != 0)
+               true_rumor_size += strlen(in_line);     /* includes newline */
+#endif /* VMS */
+       Fprintf(ofp,"%06lx\n", true_rumor_size);
+       (void) fseek(ifp, 0L, SEEK_SET);
+
+       /* copy true rumors */
+       while (fgets(in_line, sizeof in_line, ifp) != 0)
+               (void) fputs(xcrypt(in_line), ofp);
+
+       Fclose(ifp);
+
+       Sprintf(infile, DATA_IN_TEMPLATE, RUMOR_FILE);
+       Strcat(infile, ".fal");
+       if (!(ifp = fopen(infile, RDTMODE))) {
+               perror(infile);
+               Fclose(ofp);
+               Unlink(filename);       /* kill incomplete output file */
+               exit(EXIT_FAILURE);
+       }
+
+       /* copy false rumors */
+       while (fgets(in_line, sizeof in_line, ifp) != 0)
+               (void) fputs(xcrypt(in_line), ofp);
+
+       Fclose(ifp);
+       Fclose(ofp);
+       return;
+}
+
+static void
+make_version()
+{
+       register int i;
+
+       /*
+        * integer version number
+        */
+       version.incarnation = ((unsigned long)VERSION_MAJOR << 24) |
+                               ((unsigned long)VERSION_MINOR << 16) |
+                               ((unsigned long)PATCHLEVEL << 8) |
+                               ((unsigned long)EDITLEVEL);
+       /*
+        * encoded feature list
+        * Note:  if any of these magic numbers are changed or reassigned,
+        * EDITLEVEL in patchlevel.h should be incremented at the same time.
+        * The actual values have no special meaning, and the category
+        * groupings are just for convenience.
+        */
+       version.feature_set = (unsigned long)(0L
+               /* levels and/or topology (0..4) */
+#ifdef REINCARNATION
+                       | (1L <<  1)
+#endif
+#ifdef SINKS
+                       | (1L <<  2)
+#endif
+               /* monsters (5..9) */
+#ifdef KOPS
+                       | (1L <<  6)
+#endif
+#ifdef MAIL
+                       | (1L <<  7)
+#endif
+               /* objects (10..14) */
+#ifdef TOURIST
+                       | (1L << 10)
+#endif
+#ifdef STEED
+                       | (1L << 11)
+#endif
+#ifdef GOLDOBJ
+                       | (1L << 12)
+#endif
+               /* flag bits and/or other global variables (15..26) */
+#ifdef TEXTCOLOR
+                       | (1L << 17)
+#endif
+#ifdef INSURANCE
+                       | (1L << 18)
+#endif
+#ifdef ELBERETH
+                       | (1L << 19)
+#endif
+#ifdef EXP_ON_BOTL
+                       | (1L << 20)
+#endif
+#ifdef SCORE_ON_BOTL
+                       | (1L << 21)
+#endif
+#ifdef TIMED_DELAY
+                       | (1L << 23)
+#endif
+               /* data format [COMPRESS excluded] (27..31) */
+#ifdef ZEROCOMP
+                       | (1L << 27)
+#endif
+#ifdef RLECOMP
+                       | (1L << 28)
+#endif
+                       );
+       /*
+        * Value used for object & monster sanity check.
+        *    (NROFARTIFACTS<<24) | (NUM_OBJECTS<<12) | (NUMMONS<<0)
+        */
+       for (i = 1; artifact_names[i]; i++) continue;
+       version.entity_count = (unsigned long)(i - 1);
+       for (i = 1; objects[i].oc_class != ILLOBJ_CLASS; i++) continue;
+       version.entity_count = (version.entity_count << 12) | (unsigned long)i;
+       for (i = 0; mons[i].mlet; i++) continue;
+       version.entity_count = (version.entity_count << 12) | (unsigned long)i;
+       /*
+        * Value used for compiler (word size/field alignment/padding) check.
+        */
+       version.struct_sizes = (((unsigned long)sizeof (struct flag)  << 24) |
+                               ((unsigned long)sizeof (struct obj)   << 17) |
+                               ((unsigned long)sizeof (struct monst) << 10) |
+                               ((unsigned long)sizeof (struct you)));
+       return;
+}
+
+static char *
+version_string(outbuf)
+char *outbuf;
+{
+    Sprintf(outbuf, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
+#ifdef BETA
+    Sprintf(eos(outbuf), "-%d", EDITLEVEL);
+#endif
+    return outbuf;
+}
+
+static char *
+version_id_string(outbuf, build_date)
+char *outbuf;
+const char *build_date;
+{
+    char subbuf[64], versbuf[64];
+
+    subbuf[0] = '\0';
+#ifdef PORT_SUB_ID
+    subbuf[0] = ' ';
+    Strcpy(&subbuf[1], PORT_SUB_ID);
+#endif
+#ifdef BETA
+    Strcat(subbuf, " Beta");
+#endif
+
+    Sprintf(outbuf, "%s NetHack%s Version %s - last build %s.",
+           PORT_ID, subbuf, version_string(versbuf), build_date);
+    return outbuf;
+}
+
+void
+do_date()
+{
+       long clocktim = 0;
+       char *c, cbuf[60], buf[BUFSZ];
+       const char *ul_sfx;
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename,file_prefix);
+#endif
+       Sprintf(eos(filename), INCLUDE_TEMPLATE, DATE_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.3\t1996/05/17 */\n\n");
+       Fprintf(ofp,Dont_Edit_Code);
+
+#ifdef KR1ED
+       (void) time(&clocktim);
+       Strcpy(cbuf, ctime(&clocktim));
+#else
+       (void) time((time_t *)&clocktim);
+       Strcpy(cbuf, ctime((time_t *)&clocktim));
+#endif
+       for (c = cbuf; *c; c++) if (*c == '\n') break;
+       *c = '\0';      /* strip off the '\n' */
+       Fprintf(ofp,"#define BUILD_DATE \"%s\"\n", cbuf);
+       Fprintf(ofp,"#define BUILD_TIME (%ldL)\n", clocktim);
+       Fprintf(ofp,"\n");
+#ifdef NHSTDC
+       ul_sfx = "UL";
+#else
+       ul_sfx = "L";
+#endif
+       Fprintf(ofp,"#define VERSION_NUMBER 0x%08lx%s\n",
+               version.incarnation, ul_sfx);
+       Fprintf(ofp,"#define VERSION_FEATURES 0x%08lx%s\n",
+               version.feature_set, ul_sfx);
+       Fprintf(ofp,"#define VERSION_SANITY1 0x%08lx%s\n",
+               version.entity_count, ul_sfx);
+       Fprintf(ofp,"#define VERSION_SANITY2 0x%08lx%s\n",
+               version.struct_sizes, ul_sfx);
+       Fprintf(ofp,"\n");
+       Fprintf(ofp,"#define VERSION_STRING \"%s\"\n", version_string(buf));
+       Fprintf(ofp,"#define VERSION_ID \\\n \"%s\"\n",
+               version_id_string(buf, cbuf));
+       Fprintf(ofp,"\n");
+#ifdef AMIGA
+       {
+       struct tm *tm = localtime((time_t *) &clocktim);
+       Fprintf(ofp,"#define AMIGA_VERSION_STRING ");
+       Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
+               VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
+               tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900);
+       }
+#endif
+       Fclose(ofp);
+       return;
+}
+
+static const char *build_opts[] = {
+#ifdef AMIGA_WBENCH
+               "Amiga WorkBench support",
+#endif
+#ifdef ANSI_DEFAULT
+               "ANSI default terminal",
+#endif
+#ifdef TEXTCOLOR
+               "color",
+#endif
+#ifdef COM_COMPL
+               "command line completion",
+#endif
+#ifdef COMPRESS
+               "data file compression",
+#endif
+#ifdef DLB
+               "data librarian",
+#endif
+#ifdef WIZARD
+               "debug mode",
+#endif
+#ifdef ELBERETH
+               "Elbereth",
+#endif
+#ifdef EXP_ON_BOTL
+               "experience points on status line",
+#endif
+#ifdef MFLOPPY
+               "floppy drive support",
+#endif
+#ifdef GOLDOBJ
+               "gold object in inventories",
+#endif
+#ifdef INSURANCE
+               "insurance files for recovering from crashes",
+#endif
+#ifdef KOPS
+               "Keystone Kops",
+#endif
+#ifdef LOGFILE
+               "log file",
+#endif
+#ifdef MAIL
+               "mail daemon",
+#endif
+#ifdef GNUDOS
+               "MSDOS protected mode",
+#endif
+#ifdef NEWS
+               "news file",
+#endif
+#ifdef OVERLAY
+# ifdef MOVERLAY
+               "MOVE overlays",
+# else
+#  ifdef VROOMM
+               "VROOMM overlays",
+#  else
+               "overlays",
+#  endif
+# endif
+#endif
+#ifdef REDO
+               "redo command",
+#endif
+#ifdef REINCARNATION
+               "rogue level",
+#endif
+#ifdef STEED
+               "saddles and riding",
+#endif
+#ifdef SCORE_ON_BOTL
+               "score on status line",
+#endif
+#ifdef CLIPPING
+               "screen clipping",
+#endif
+#ifdef NO_TERMS
+# ifdef MAC
+               "screen control via mactty",
+# endif
+# ifdef SCREEN_8514
+               "screen control via 8514/A graphics",
+# endif
+# ifdef SCREEN_BIOS
+               "screen control via BIOS",
+# endif
+# ifdef SCREEN_DJGPPFAST
+               "screen control via DJGPP fast",
+# endif
+# ifdef SCREEN_VESA
+               "screen control via VESA graphics",
+# endif
+# ifdef SCREEN_VGA
+               "screen control via VGA graphics",
+# endif
+# ifdef WIN32CON
+               "screen control via WIN32 console I/O",
+# endif
+#endif
+#ifdef SEDUCE
+               "seduction",
+#endif
+#ifdef SHELL
+               "shell command",
+#endif
+#ifdef SINKS
+               "sinks",
+#endif
+#ifdef SUSPEND
+               "suspend command",
+#endif
+#ifdef TERMINFO
+               "terminal info library",
+#else
+# if defined(TERMLIB) || (!defined(MICRO) && defined(TTY_GRAPHICS))
+               "terminal capability library",
+# endif
+#endif
+#ifdef TIMED_DELAY
+               "timed wait for display effects",
+#endif
+#ifdef TOURIST
+               "tourists",
+#endif
+#ifdef PREFIXES_IN_USE
+               "variable playground",
+#endif
+#ifdef VISION_TABLES
+               "vision tables",
+#endif
+#ifdef WALLIFIED_MAZE
+               "walled mazes",
+#endif
+#ifdef ZEROCOMP
+               "zero-compressed save files",
+#endif
+               "basic NetHack features"
+       };
+
+static const char *window_opts[] = {
+#ifdef TTY_GRAPHICS
+               "traditional tty-based graphics",
+#endif
+#ifdef X11_GRAPHICS
+               "X11",
+#endif
+#ifdef QT_GRAPHICS
+               "Qt",
+#endif
+#ifdef GNOME_GRAPHICS
+               "Gnome",
+#endif
+#ifdef MAC
+               "Mac",
+#endif
+#ifdef AMIGA_INTUITION
+               "Amiga Intuition",
+#endif
+#ifdef GEM_GRAPHICS
+               "Gem",
+#endif
+#ifdef WIN32_GRAPHICS
+               "Win32",
+#endif
+#ifdef BEOS_GRAPHICS
+               "BeOS InterfaceKit",
+#endif
+               0
+       };
+
+void
+do_options()
+{
+       register int i, length;
+       register const char *str, *indent = "    ";
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename,file_prefix);
+#endif
+       Sprintf(eos(filename), DATA_TEMPLATE, OPTIONS_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+
+       Fprintf(ofp,
+#ifdef BETA
+               "\n    NetHack version %d.%d.%d [beta]\n",
+#else
+               "\n    NetHack version %d.%d.%d\n",
+#endif
+               VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
+
+       Fprintf(ofp,"\nOptions compiled into this edition:\n");
+
+       length = COLNO + 1;     /* force 1st item onto new line */
+       for (i = 0; i < SIZE(build_opts); i++) {
+           str = build_opts[i];
+           if (length + strlen(str) > COLNO - 5)
+               Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
+           else
+               Fprintf(ofp," "),  length++;
+           Fprintf(ofp,"%s", str),  length += strlen(str);
+           Fprintf(ofp,(i < SIZE(build_opts) - 1) ? "," : "."),  length++;
+       }
+
+       Fprintf(ofp,"\n\nSupported windowing systems:\n");
+
+       length = COLNO + 1;     /* force 1st item onto new line */
+       for (i = 0; i < SIZE(window_opts) - 1; i++) {
+           str = window_opts[i];
+           if (length + strlen(str) > COLNO - 5)
+               Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
+           else
+               Fprintf(ofp," "),  length++;
+           Fprintf(ofp,"%s", str),  length += strlen(str);
+           Fprintf(ofp, ","),  length++;
+       }
+       Fprintf(ofp, "\n%swith a default of %s.", indent, DEFAULT_WINDOW_SYS);
+       Fprintf(ofp,"\n\n");
+
+       Fclose(ofp);
+       return;
+}
+
+/* routine to decide whether to discard something from data.base */
+static boolean
+d_filter(line)
+    char *line;
+{
+    if (*line == '#') return TRUE;     /* ignore comment lines */
+    return FALSE;
+}
+
+   /*
+    *
+       New format (v3.1) of 'data' file which allows much faster lookups [pr]
+"do not edit"          first record is a comment line
+01234567               hexadecimal formatted offset to text area
+name-a                 first name of interest
+123,4                  offset to name's text, and number of lines for it
+name-b                 next name of interest
+name-c                 multiple names which share same description also
+456,7                  share a single offset,count line
+.                      sentinel to mark end of names
+789,0                  dummy record containing offset, count of EOF
+text-a                 4 lines of descriptive text for name-a
+text-a                 at file position 0x01234567L + 123L
+text-a
+text-a
+text-b/text-c          7 lines of text for names-b and -c
+text-b/text-c          at fseek(0x01234567L + 456L)
+...
+    *
+    */
+
+void
+do_data()
+{
+       char    infile[60], tempfile[60];
+       boolean ok;
+       long    txt_offset;
+       int     entry_cnt, line_cnt;
+
+       Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename,file_prefix);
+#endif
+       Sprintf(eos(filename), DATA_TEMPLATE, DATA_FILE);
+       Sprintf(infile, DATA_IN_TEMPLATE, DATA_FILE);
+       Strcat(infile,
+#ifdef SHORT_FILENAMES
+               ".bas"
+#else
+               ".base"
+#endif
+               );
+       if (!(ifp = fopen(infile, RDTMODE))) {          /* data.base */
+               perror(infile);
+               exit(EXIT_FAILURE);
+       }
+       if (!(ofp = fopen(filename, WRTMODE))) {        /* data */
+               perror(filename);
+               Fclose(ifp);
+               exit(EXIT_FAILURE);
+       }
+       if (!(tfp = fopen(tempfile, WRTMODE))) {        /* database.tmp */
+               perror(tempfile);
+               Fclose(ifp);
+               Fclose(ofp);
+               Unlink(filename);
+               exit(EXIT_FAILURE);
+       }
+
+       /* output a dummy header record; we'll rewind and overwrite it later */
+       Fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, 0L);
+
+       entry_cnt = line_cnt = 0;
+       /* read through the input file and split it into two sections */
+       while (fgets(in_line, sizeof in_line, ifp)) {
+           if (d_filter(in_line)) continue;
+           if (*in_line > ' ') {       /* got an entry name */
+               /* first finish previous entry */
+               if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt),  line_cnt = 0;
+               /* output the entry name */
+               (void) fputs(in_line, ofp);
+               entry_cnt++;            /* update number of entries */
+           } else if (entry_cnt) {     /* got some descriptive text */
+               /* update previous entry with current text offset */
+               if (!line_cnt)  Fprintf(ofp, "%ld,", ftell(tfp));
+               /* save the text line in the scratch file */
+               (void) fputs(in_line, tfp);
+               line_cnt++;             /* update line counter */
+           }
+       }
+       /* output an end marker and then record the current position */
+       if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt);
+       Fprintf(ofp, ".\n%ld,%d\n", ftell(tfp), 0);
+       txt_offset = ftell(ofp);
+       Fclose(ifp);            /* all done with original input file */
+
+       /* reprocess the scratch file; 1st format an error msg, just in case */
+       Sprintf(in_line, "rewind of \"%s\"", tempfile);
+       if (rewind(tfp) != 0)  goto dead_data;
+       /* copy all lines of text from the scratch file into the output file */
+       while (fgets(in_line, sizeof in_line, tfp))
+           (void) fputs(in_line, ofp);
+
+       /* finished with scratch file */
+       Fclose(tfp);
+       Unlink(tempfile);       /* remove it */
+
+       /* update the first record of the output file; prepare error msg 1st */
+       Sprintf(in_line, "rewind of \"%s\"", filename);
+       ok = (rewind(ofp) == 0);
+       if (ok) {
+          Sprintf(in_line, "header rewrite of \"%s\"", filename);
+          ok = (fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, txt_offset) >= 0);
+       }
+       if (!ok) {
+dead_data:  perror(in_line);   /* report the problem */
+           /* close and kill the aborted output file, then give up */
+           Fclose(ofp);
+           Unlink(filename);
+           exit(EXIT_FAILURE);
+       }
+
+       /* all done */
+       Fclose(ofp);
+
+       return;
+}
+
+/* routine to decide whether to discard something from oracles.txt */
+static boolean
+h_filter(line)
+    char *line;
+{
+    static boolean skip = FALSE;
+    char tag[sizeof in_line];
+
+    SpinCursor(3);
+
+    if (*line == '#') return TRUE;     /* ignore comment lines */
+    if (sscanf(line, "----- %s", tag) == 1) {
+       skip = FALSE;
+#ifndef SINKS
+       if (!strcmp(tag, "SINKS")) skip = TRUE;
+#endif
+#ifndef ELBERETH
+       if (!strcmp(tag, "ELBERETH")) skip = TRUE;
+#endif
+    } else if (skip && !strncmp(line, "-----", 5))
+       skip = FALSE;
+    return skip;
+}
+
+static const char *special_oracle[] = {
+       "\"...it is rather disconcerting to be confronted with the",
+       "following theorem from [Baker, Gill, and Solovay, 1975].",
+       "",
+       "Theorem 7.18  There exist recursive languages A and B such that",
+       "  (1)  P(A) == NP(A), and",
+       "  (2)  P(B) != NP(B)",
+       "",
+       "This provides impressive evidence that the techniques that are",
+       "currently available will not suffice for proving that P != NP or          ",
+       "that P == NP.\"  [Garey and Johnson, p. 185.]"
+};
+
+/*
+   The oracle file consists of a "do not edit" comment, a decimal count N
+   and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
+   records, separated by "---" lines.  The first oracle is a special case.
+   The input data contains just those multi-line records, separated by
+   "-----" lines.
+ */
+
+void
+do_oracles()
+{
+       char    infile[60], tempfile[60];
+       boolean in_oracle, ok;
+       long    txt_offset, offset, fpos;
+       int     oracle_cnt;
+       register int i;
+
+       Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename, file_prefix);
+#endif
+       Sprintf(eos(filename), DATA_TEMPLATE, ORACLE_FILE);
+       Sprintf(infile, DATA_IN_TEMPLATE, ORACLE_FILE);
+       Strcat(infile, ".txt");
+       if (!(ifp = fopen(infile, RDTMODE))) {
+               perror(infile);
+               exit(EXIT_FAILURE);
+       }
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               Fclose(ifp);
+               exit(EXIT_FAILURE);
+       }
+       if (!(tfp = fopen(tempfile, WRTMODE))) {        /* oracles.tmp */
+               perror(tempfile);
+               Fclose(ifp);
+               Fclose(ofp);
+               Unlink(filename);
+               exit(EXIT_FAILURE);
+       }
+
+       /* output a dummy header record; we'll rewind and overwrite it later */
+       Fprintf(ofp, "%s%5d\n", Dont_Edit_Data, 0);
+
+       /* handle special oracle; it must come first */
+       (void) fputs("---\n", tfp);
+       Fprintf(ofp, "%05lx\n", ftell(tfp));  /* start pos of special oracle */
+       for (i = 0; i < SIZE(special_oracle); i++) {
+           (void) fputs(xcrypt(special_oracle[i]), tfp);
+           (void) fputc('\n', tfp);
+       }
+       SpinCursor(3);
+
+       oracle_cnt = 1;
+       (void) fputs("---\n", tfp);
+       Fprintf(ofp, "%05lx\n", ftell(tfp));    /* start pos of first oracle */
+       in_oracle = FALSE;
+
+       while (fgets(in_line, sizeof in_line, ifp)) {
+           SpinCursor(3);
+
+           if (h_filter(in_line)) continue;
+           if (!strncmp(in_line, "-----", 5)) {
+               if (!in_oracle) continue;
+               in_oracle = FALSE;
+               oracle_cnt++;
+               (void) fputs("---\n", tfp);
+               Fprintf(ofp, "%05lx\n", ftell(tfp));
+               /* start pos of this oracle */
+           } else {
+               in_oracle = TRUE;
+               (void) fputs(xcrypt(in_line), tfp);
+           }
+       }
+
+       if (in_oracle) {        /* need to terminate last oracle */
+           oracle_cnt++;
+           (void) fputs("---\n", tfp);
+           Fprintf(ofp, "%05lx\n", ftell(tfp));        /* eof position */
+       }
+
+       /* record the current position */
+       txt_offset = ftell(ofp);
+       Fclose(ifp);            /* all done with original input file */
+
+       /* reprocess the scratch file; 1st format an error msg, just in case */
+       Sprintf(in_line, "rewind of \"%s\"", tempfile);
+       if (rewind(tfp) != 0)  goto dead_data;
+       /* copy all lines of text from the scratch file into the output file */
+       while (fgets(in_line, sizeof in_line, tfp))
+           (void) fputs(in_line, ofp);
+
+       /* finished with scratch file */
+       Fclose(tfp);
+       Unlink(tempfile);       /* remove it */
+
+       /* update the first record of the output file; prepare error msg 1st */
+       Sprintf(in_line, "rewind of \"%s\"", filename);
+       ok = (rewind(ofp) == 0);
+       if (ok) {
+           Sprintf(in_line, "header rewrite of \"%s\"", filename);
+           ok = (fprintf(ofp, "%s%5d\n", Dont_Edit_Data, oracle_cnt) >=0);
+       }
+       if (ok) {
+           Sprintf(in_line, "data rewrite of \"%s\"", filename);
+           for (i = 0; i <= oracle_cnt; i++) {
+#ifndef VMS    /* alpha/vms v1.0; this fflush seems to confuse ftell */
+               if (!(ok = (fflush(ofp) == 0))) break;
+#endif
+               if (!(ok = (fpos = ftell(ofp)) >= 0)) break;
+               if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
+               if (!(ok = (fscanf(ofp, "%5lx", &offset) == 1))) break;
+#ifdef MAC
+# ifdef __MWERKS__
+               /*
+               MetroWerks CodeWarrior Pro 1's (AKA CW12) version of MSL
+               (ANSI C Libraries) needs this rewind or else the fprintf
+               stops working.  This may also be true for CW11, but has
+               never been checked.
+               */
+               rewind(ofp);
+# endif
+#endif
+               if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
+               if (!(ok = (fprintf(ofp, "%05lx\n", offset + txt_offset) >= 0)))
+                   break;
+           }
+       }
+       if (!ok) {
+dead_data:  perror(in_line);   /* report the problem */
+           /* close and kill the aborted output file, then give up */
+           Fclose(ofp);
+           Unlink(filename);
+           exit(EXIT_FAILURE);
+       }
+
+       /* all done */
+       Fclose(ofp);
+
+       return;
+}
+
+
+static struct deflist {
+
+       const char      *defname;
+       boolean true_or_false;
+} deflist[] = {
+#ifdef REINCARNATION
+             { "REINCARNATION", TRUE },
+#else
+             { "REINCARNATION", FALSE },
+#endif
+             { 0, 0 } };
+
+static int
+check_control(s)
+       char    *s;
+{
+       int     i;
+
+       if(s[0] != '%') return(-1);
+
+       for(i = 0; deflist[i].defname; i++)
+           if(!strncmp(deflist[i].defname, s+1, strlen(deflist[i].defname)))
+               return(i);
+
+       return(-1);
+}
+
+static char *
+without_control(s)
+       char *s;
+{
+       return(s + 1 + strlen(deflist[check_control(in_line)].defname));
+}
+
+void
+do_dungeon()
+{
+       int rcnt = 0;
+
+       Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
+       if (!(ifp = fopen(filename, RDTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename, file_prefix);
+#endif
+       Sprintf(eos(filename), DGN_TEMPLATE, DGN_O_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       Fprintf(ofp,Dont_Edit_Data);
+
+       while (fgets(in_line, sizeof in_line, ifp) != 0) {
+           SpinCursor(3);
+
+           rcnt++;
+           if(in_line[0] == '#') continue;     /* discard comments */
+recheck:
+           if(in_line[0] == '%') {
+               int i = check_control(in_line);
+               if(i >= 0) {
+                   if(!deflist[i].true_or_false)  {
+                       while (fgets(in_line, sizeof in_line, ifp) != 0)
+                           if(check_control(in_line) != i) goto recheck;
+                   } else
+                       (void) fputs(without_control(in_line),ofp);
+               } else {
+                   Fprintf(stderr, "Unknown control option '%s' in file %s at line %d.\n",
+                           in_line, DGN_I_FILE, rcnt);
+                   exit(EXIT_FAILURE);
+               }
+           } else
+               (void) fputs(in_line,ofp);
+       }
+       Fclose(ifp);
+       Fclose(ofp);
+
+       return;
+}
+
+static boolean
+ranged_attk(ptr)       /* returns TRUE if monster can attack at range */
+       register struct permonst *ptr;
+{
+       register int    i, j;
+       register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);
+
+       for(i = 0; i < NATTK; i++) {
+           if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
+               return TRUE;
+       }
+
+       return(FALSE);
+}
+
+/* This routine is designed to return an integer value which represents
+ * an approximation of monster strength.  It uses a similar method of
+ * determination as "experience()" to arrive at the strength.
+ */
+static int
+mstrength(ptr)
+struct permonst *ptr;
+{
+       int     i, tmp2, n, tmp = ptr->mlevel;
+
+       if(tmp > 49)            /* special fixed hp monster */
+           tmp = 2*(tmp - 6) / 4;
+
+/*     For creation in groups */
+       n = (!!(ptr->geno & G_SGROUP));
+       n += (!!(ptr->geno & G_LGROUP)) << 1;
+
+/*     For ranged attacks */
+       if (ranged_attk(ptr)) n++;
+
+/*     For higher ac values */
+       n += (ptr->ac < 4);
+       n += (ptr->ac < 0);
+
+/*     For very fast monsters */
+       n += (ptr->mmove >= 18);
+
+/*     For each attack and "special" attack */
+       for(i = 0; i < NATTK; i++) {
+
+           tmp2 = ptr->mattk[i].aatyp;
+           n += (tmp2 > 0);
+           n += (tmp2 == AT_MAGC);
+           n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG));
+       }
+
+/*     For each "special" damage type */
+       for(i = 0; i < NATTK; i++) {
+
+           tmp2 = ptr->mattk[i].adtyp;
+           if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST)
+               || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO) || (tmp2 == AD_WERE))
+                       n += 2;
+           else if (strcmp(ptr->mname, "grid bug")) n += (tmp2 != AD_PHYS);
+           n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
+       }
+
+/*     Leprechauns are special cases.  They have many hit dice so they
+       can hit and are hard to kill, but they don't really do much damage. */
+       if (!strcmp(ptr->mname, "leprechaun")) n -= 2;
+
+/*     Finally, adjust the monster level  0 <= n <= 24 (approx.) */
+       if(n == 0) tmp--;
+       else if(n >= 6) tmp += ( n / 2 );
+       else tmp += ( n / 3 + 1);
+
+       return((tmp >= 0) ? tmp : 0);
+}
+
+void
+do_monstr()
+{
+    register struct permonst *ptr;
+    register int i, j;
+
+    /*
+     * create the source file, "monstr.c"
+     */
+    filename[0]='\0';
+#ifdef FILE_PREFIX
+    Strcat(filename, file_prefix);
+#endif
+    Sprintf(eos(filename), SOURCE_TEMPLATE, MON_STR_C);
+    if (!(ofp = fopen(filename, WRTMODE))) {
+       perror(filename);
+       exit(EXIT_FAILURE);
+    }
+    Fprintf(ofp,Dont_Edit_Code);
+    Fprintf(ofp,"#include \"config.h\"\n");
+    Fprintf(ofp,"\nconst int monstr[] = {\n");
+    for (ptr = &mons[0], j = 0; ptr->mlet; ptr++) {
+
+       SpinCursor(3);
+
+       i = mstrength(ptr);
+       Fprintf(ofp,"%2d,%c", i, (++j & 15) ? ' ' : '\n');
+    }
+    /* might want to insert a final 0 entry here instead of just newline */
+    Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");
+
+    Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
+    Fprintf(ofp,"\nvoid\n");
+    Fprintf(ofp,"monstr_init()\n");
+    Fprintf(ofp,"{\n");
+    Fprintf(ofp,"    return;\n");
+    Fprintf(ofp,"}\n");
+    Fprintf(ofp,"\n/*monstr.c*/\n");
+
+    Fclose(ofp);
+    return;
+}
+
+void
+do_permonst()
+{
+       int     i;
+       char    *c, *nam;
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename, file_prefix);
+#endif
+       Sprintf(eos(filename), INCLUDE_TEMPLATE, MONST_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.3\t1994/09/10 */\n\n");
+       Fprintf(ofp,Dont_Edit_Code);
+       Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");
+
+       if (strcmp(mons[0].mname, "playermon") != 0)
+               Fprintf(ofp,"\n#define\tPM_PLAYERMON\t(-1)");
+
+       for (i = 0; mons[i].mlet; i++) {
+               SpinCursor(3);
+
+               Fprintf(ofp,"\n#define\tPM_");
+               if (mons[i].mlet == S_HUMAN &&
+                               !strncmp(mons[i].mname, "were", 4))
+                   Fprintf(ofp, "HUMAN_");
+               for (nam = c = tmpdup(mons[i].mname); *c; c++)
+                   if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
+                   else if (*c < 'A' || *c > 'Z') *c = '_';
+               Fprintf(ofp,"%s\t%d", nam, i);
+       }
+       Fprintf(ofp,"\n\n#define\tNUMMONS\t%d\n", i);
+       Fprintf(ofp,"\n#endif /* PM_H */\n");
+       Fclose(ofp);
+       return;
+}
+
+
+/*     Start of Quest text file processing. */
+#include "qtext.h"
+
+static struct qthdr    qt_hdr;
+static struct msghdr   msg_hdr[N_HDR];
+static struct qtmsg    *curr_msg;
+
+static int     qt_line;
+
+static boolean in_msg;
+#define NO_MSG 1       /* strlen of a null line returned by fgets() */
+
+static boolean
+qt_comment(s)
+       char *s;
+{
+       if(s[0] == '#') return(TRUE);
+       return((boolean)(!in_msg  && strlen(s) == NO_MSG));
+}
+
+static boolean
+qt_control(s)
+       char *s;
+{
+       return((boolean)(s[0] == '%' && (s[1] == 'C' || s[1] == 'E')));
+}
+
+static int
+get_hdr (code)
+       char *code;
+{
+       int     i;
+
+       for(i = 0; i < qt_hdr.n_hdr; i++)
+           if(!strncmp(code, qt_hdr.id[i], LEN_HDR)) return (++i);
+
+       return(0);
+}
+
+static boolean
+new_id (code)
+       char *code;
+{
+       if(qt_hdr.n_hdr >= N_HDR) {
+           Fprintf(stderr, OUT_OF_HEADERS, qt_line);
+           return(FALSE);
+       }
+
+       strncpy(&qt_hdr.id[qt_hdr.n_hdr][0], code, LEN_HDR);
+       msg_hdr[qt_hdr.n_hdr].n_msg = 0;
+       qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
+       return(TRUE);
+}
+
+static boolean
+known_msg(num, id)
+       int num, id;
+{
+       int i;
+
+       for(i = 0; i < msg_hdr[num].n_msg; i++)
+           if(msg_hdr[num].qt_msg[i].msgnum == id) return(TRUE);
+
+       return(FALSE);
+}
+
+
+static void
+new_msg(s, num, id)
+       char *s;
+       int num, id;
+{
+       struct  qtmsg   *qt_msg;
+
+       if(msg_hdr[num].n_msg >= N_MSG) {
+               Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
+       } else {
+               qt_msg = &(msg_hdr[num].qt_msg[msg_hdr[num].n_msg++]);
+               qt_msg->msgnum = id;
+               qt_msg->delivery = s[2];
+               qt_msg->offset = qt_msg->size = 0L;
+
+               curr_msg = qt_msg;
+       }
+}
+
+static void
+do_qt_control(s)
+       char *s;
+{
+       char code[BUFSZ];
+       int num, id = 0;
+
+       switch(s[1]) {
+
+           case 'C':   if(in_msg) {
+                           Fprintf(stderr, CREC_IN_MSG, qt_line);
+                           break;
+                       } else {
+                           in_msg = TRUE;
+                           if (sscanf(&s[4], "%s %5d", code, &id) != 2) {
+                               Fprintf(stderr, UNREC_CREC, qt_line);
+                               break;
+                           }
+                           num = get_hdr(code);
+                           if (!num && !new_id(code))
+                               break;
+                           num = get_hdr(code)-1;
+                           if(known_msg(num, id))
+                               Fprintf(stderr, DUP_MSG, qt_line);
+                           else new_msg(s, num, id);
+                       }
+                       break;
+
+           case 'E':   if(!in_msg) {
+                           Fprintf(stderr, END_NOT_IN_MSG, qt_line);
+                           break;
+                       } else in_msg = FALSE;
+                       break;
+
+           default:    Fprintf(stderr, UNREC_CREC, qt_line);
+                       break;
+       }
+}
+
+static void
+do_qt_text(s)
+       char *s;
+{
+       curr_msg->size += strlen(s);
+       return;
+}
+
+static void
+adjust_qt_hdrs()
+{
+       int     i, j;
+       long count = 0L, hdr_offset = sizeof(int) +
+                       (sizeof(char)*LEN_HDR + sizeof(long)) * qt_hdr.n_hdr;
+
+       for(i = 0; i < qt_hdr.n_hdr; i++) {
+           qt_hdr.offset[i] = hdr_offset;
+           hdr_offset += sizeof(int) + sizeof(struct qtmsg) * msg_hdr[i].n_msg;
+       }
+
+       for(i = 0; i < qt_hdr.n_hdr; i++)
+           for(j = 0; j < msg_hdr[i].n_msg; j++) {
+
+               msg_hdr[i].qt_msg[j].offset = hdr_offset + count;
+               count += msg_hdr[i].qt_msg[j].size;
+           }
+       return;
+}
+
+static void
+put_qt_hdrs()
+{
+       int     i;
+
+       /*
+        *      The main header record.
+        */
+#ifdef DEBUG
+       Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
+#endif
+       (void) fwrite((genericptr_t)&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
+       (void) fwrite((genericptr_t)&(qt_hdr.id[0][0]), sizeof(char)*LEN_HDR,
+                                                       qt_hdr.n_hdr, ofp);
+       (void) fwrite((genericptr_t)&(qt_hdr.offset[0]), sizeof(long),
+                                                       qt_hdr.n_hdr, ofp);
+#ifdef DEBUG
+       for(i = 0; i < qt_hdr.n_hdr; i++)
+               Fprintf(stderr, "%c @ %ld, ", qt_hdr.id[i], qt_hdr.offset[i]);
+
+       Fprintf(stderr, "\n");
+#endif
+
+       /*
+        *      The individual class headers.
+        */
+       for(i = 0; i < qt_hdr.n_hdr; i++) {
+
+#ifdef DEBUG
+           Fprintf(stderr, "%ld: %c header info.\n", ftell(ofp),
+                   qt_hdr.id[i]);
+#endif
+           (void) fwrite((genericptr_t)&(msg_hdr[i].n_msg), sizeof(int),
+                                                       1, ofp);
+           (void) fwrite((genericptr_t)&(msg_hdr[i].qt_msg[0]),
+                           sizeof(struct qtmsg), msg_hdr[i].n_msg, ofp);
+#ifdef DEBUG
+           { int j;
+             for(j = 0; j < msg_hdr[i].n_msg; j++)
+               Fprintf(stderr, "msg %d @ %ld (%ld)\n",
+                       msg_hdr[i].qt_msg[j].msgnum,
+                       msg_hdr[i].qt_msg[j].offset,
+                       msg_hdr[i].qt_msg[j].size);
+           }
+#endif
+       }
+}
+
+void
+do_questtxt()
+{
+       Sprintf(filename, DATA_IN_TEMPLATE, QTXT_I_FILE);
+       if(!(ifp = fopen(filename, RDTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename, file_prefix);
+#endif
+       Sprintf(eos(filename), DATA_TEMPLATE, QTXT_O_FILE);
+       if(!(ofp = fopen(filename, WRBMODE))) {
+               perror(filename);
+               Fclose(ifp);
+               exit(EXIT_FAILURE);
+       }
+
+       qt_hdr.n_hdr = 0;
+       qt_line = 0;
+       in_msg = FALSE;
+
+       while (fgets(in_line, 80, ifp) != 0) {
+           SpinCursor (3);
+
+           qt_line++;
+           if(qt_control(in_line)) do_qt_control(in_line);
+           else if(qt_comment(in_line)) continue;
+           else                    do_qt_text(in_line);
+       }
+
+       (void) rewind(ifp);
+       in_msg = FALSE;
+       adjust_qt_hdrs();
+       put_qt_hdrs();
+       while (fgets(in_line, 80, ifp) != 0) {
+
+               if(qt_control(in_line)) {
+                   in_msg = (in_line[1] == 'C');
+                   continue;
+               } else if(qt_comment(in_line)) continue;
+#ifdef DEBUG
+               Fprintf(stderr, "%ld: %s", ftell(stdout), in_line);
+#endif
+               (void) fputs(xcrypt(in_line), ofp);
+       }
+       Fclose(ifp);
+       Fclose(ofp);
+       return;
+}
+
+
+static char    temp[32];
+
+static char *
+limit(name,pref)       /* limit a name to 30 characters length */
+char   *name;
+int    pref;
+{
+       (void) strncpy(temp, name, pref ? 26 : 30);
+       temp[pref ? 26 : 30] = 0;
+       return temp;
+}
+
+void
+do_objs()
+{
+       int i, sum = 0;
+       char *c, *objnam;
+       int nspell = 0;
+       int prefix = 0;
+       char class = '\0';
+       boolean sumerr = FALSE;
+
+       filename[0]='\0';
+#ifdef FILE_PREFIX
+       Strcat(filename, file_prefix);
+#endif
+       Sprintf(eos(filename), INCLUDE_TEMPLATE, ONAME_FILE);
+       if (!(ofp = fopen(filename, WRTMODE))) {
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.3\t1994/09/10 */\n\n");
+       Fprintf(ofp,Dont_Edit_Code);
+       Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n");
+
+       for(i = 0; !i || objects[i].oc_class != ILLOBJ_CLASS; i++) {
+               SpinCursor(3);
+
+               objects[i].oc_name_idx = objects[i].oc_descr_idx = i;   /* init */
+               if (!(objnam = tmpdup(OBJ_NAME(objects[i])))) continue;
+
+               /* make sure probabilities add up to 1000 */
+               if(objects[i].oc_class != class) {
+                       if (sum && sum != 1000) {
+                           Fprintf(stderr, "prob error for class %d (%d%%)",
+                                   class, sum);
+                           (void) fflush(stderr);
+                           sumerr = TRUE;
+                       }
+                       class = objects[i].oc_class;
+                       sum = 0;
+               }
+
+               for (c = objnam; *c; c++)
+                   if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
+                   else if (*c < 'A' || *c > 'Z') *c = '_';
+
+               switch (class) {
+                   case WAND_CLASS:
+                       Fprintf(ofp,"#define\tWAN_"); prefix = 1; break;
+                   case RING_CLASS:
+                       Fprintf(ofp,"#define\tRIN_"); prefix = 1; break;
+                   case POTION_CLASS:
+                       Fprintf(ofp,"#define\tPOT_"); prefix = 1; break;
+                   case SPBOOK_CLASS:
+                       Fprintf(ofp,"#define\tSPE_"); prefix = 1; nspell++; break;
+                   case SCROLL_CLASS:
+                       Fprintf(ofp,"#define\tSCR_"); prefix = 1; break;
+                   case AMULET_CLASS:
+                       /* avoid trouble with stupid C preprocessors */
+                       Fprintf(ofp,"#define\t");
+                       if(objects[i].oc_material == PLASTIC) {
+                           Fprintf(ofp,"FAKE_AMULET_OF_YENDOR\t%d\n", i);
+                           prefix = -1;
+                           break;
+                       }
+                       break;
+                   case GEM_CLASS:
+                       /* avoid trouble with stupid C preprocessors */
+                       if(objects[i].oc_material == GLASS) {
+                           Fprintf(ofp,"/* #define\t%s\t%d */\n",
+                                                       objnam, i);
+                           prefix = -1;
+                           break;
+                       }
+                   default:
+                       Fprintf(ofp,"#define\t");
+               }
+               if (prefix >= 0)
+                       Fprintf(ofp,"%s\t%d\n", limit(objnam, prefix), i);
+               prefix = 0;
+
+               sum += objects[i].oc_prob;
+       }
+
+       /* check last set of probabilities */
+       if (sum && sum != 1000) {
+           Fprintf(stderr, "prob error for class %d (%d%%)", class, sum);
+           (void) fflush(stderr);
+           sumerr = TRUE;
+       }
+
+       Fprintf(ofp,"#define\tLAST_GEM\t(JADE)\n");
+       Fprintf(ofp,"#define\tMAXSPELL\t%d\n", nspell+1);
+       Fprintf(ofp,"#define\tNUM_OBJECTS\t%d\n", i);
+
+       Fprintf(ofp, "\n/* Artifacts (unique objects) */\n\n");
+
+       for (i = 1; artifact_names[i]; i++) {
+               SpinCursor(3);
+
+               for (c = objnam = tmpdup(artifact_names[i]); *c; c++)
+                   if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
+                   else if (*c < 'A' || *c > 'Z') *c = '_';
+
+               if (!strncmp(objnam, "THE_", 4))
+                       objnam += 4;
+#ifdef TOURIST
+               /* fudge _platinum_ YENDORIAN EXPRESS CARD */
+               if (!strncmp(objnam, "PLATINUM_", 9))
+                       objnam += 9;
+#endif
+               Fprintf(ofp,"#define\tART_%s\t%d\n", limit(objnam, 1), i);
+       }
+
+       Fprintf(ofp, "#define\tNROFARTIFACTS\t%d\n", i-1);
+       Fprintf(ofp,"\n#endif /* ONAMES_H */\n");
+       Fclose(ofp);
+       if (sumerr) exit(EXIT_FAILURE);
+       return;
+}
+
+static char *
+tmpdup(str)
+const char *str;
+{
+       static char buf[128];
+
+       if (!str) return (char *)0;
+       (void)strncpy(buf, str, 127);
+       return buf;
+}
+
+static char *
+eos(str)
+char *str;
+{
+    while (*str) str++;
+    return str;
+}
+
+/*
+ * macro used to control vision algorithms:
+ *      VISION_TABLES => generate tables
+ */
+
+void
+do_vision()
+{
+#ifdef VISION_TABLES
+    int i, j;
+
+    /* Everything is clear.  xclear may be malloc'ed.
+     * Block the upper left corner (BLOCK_HEIGHTxBLOCK_WIDTH)
+     */
+    for (i = 0; i < MAX_ROW; i++)
+       for (j = 0; j < MAX_COL; j++)
+           if (i < BLOCK_HEIGHT && j < BLOCK_WIDTH)
+               xclear[i][j] = '\000';
+           else
+               xclear[i][j] = '\001';
+#endif /* VISION_TABLES */
+
+    SpinCursor(3);
+
+    /*
+     * create the include file, "vis_tab.h"
+     */
+    filename[0]='\0';
+#ifdef FILE_PREFIX
+    Strcat(filename, file_prefix);
+#endif
+    Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
+    if (!(ofp = fopen(filename, WRTMODE))) {
+       perror(filename);
+       exit(EXIT_FAILURE);
+    }
+    Fprintf(ofp,Dont_Edit_Code);
+    Fprintf(ofp,"#ifdef VISION_TABLES\n");
+#ifdef VISION_TABLES
+    H_close_gen();
+    H_far_gen();
+#endif /* VISION_TABLES */
+    Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
+    Fclose(ofp);
+
+    SpinCursor(3);
+
+    /*
+     * create the source file, "vis_tab.c"
+     */
+    filename[0]='\0';
+#ifdef FILE_PREFIX
+    Strcat(filename, file_prefix);
+#endif
+    Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
+    if (!(ofp = fopen(filename, WRTMODE))) {
+       perror(filename);
+       Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
+       Unlink(filename);
+       exit(EXIT_FAILURE);
+    }
+    Fprintf(ofp,Dont_Edit_Code);
+    Fprintf(ofp,"#include \"config.h\"\n");
+    Fprintf(ofp,"#ifdef VISION_TABLES\n");
+    Fprintf(ofp,"#include \"vis_tab.h\"\n");
+
+    SpinCursor(3);
+
+#ifdef VISION_TABLES
+    C_close_gen();
+    C_far_gen();
+    Fprintf(ofp,"\nvoid vis_tab_init() { return; }\n");
+#endif /* VISION_TABLES */
+
+    SpinCursor(3);
+
+    Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
+    Fprintf(ofp,"\n/*vis_tab.c*/\n");
+
+    Fclose(ofp);
+    return;
+}
+
+#ifdef VISION_TABLES
+
+/*--------------  vision tables  --------------*\
+ *
+ *  Generate the close and far tables.  This is done by setting up a
+ *  fake dungeon and moving our source to different positions relative
+ *  to a block and finding the first/last visible position.  The fake
+ *  dungeon is all clear execpt for the upper left corner (BLOCK_HEIGHT
+ *  by BLOCK_WIDTH) is blocked.  Then we move the source around relative
+ *  to the corner of the block.  For each new position of the source
+ *  we check positions on rows "kittycorner" from the source.  We check
+ *  positions until they are either in sight or out of sight (depends on
+ *  which table we are generating).  The picture below shows the setup
+ *  for the generation of the close table.  The generation of the far
+ *  table would switch the quadrants of the '@' and the "Check rows
+ *  here".
+ *
+ *
+ *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,, Check rows here ,,,,,,,,,,,,
+ *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXB,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ *  ...............................
+ *  ...............................
+ *  .........@.....................
+ *  ...............................
+ *
+ *      Table generation figure (close_table).  The 'X's are blocked points.
+ *      The 'B' is a special blocked point.  The '@' is the source.  The ','s
+ *      are the target area.  The '.' are just open areas.
+ *
+ *
+ *  Example usage of close_table[][][].
+ *
+ *  The table is as follows:
+ *
+ *      dy = |row of '@' - row of 'B'|  - 1
+ *      dx = |col of '@' - col of 'B'|
+ *
+ *  The first indices are the deltas from the source '@' and the block 'B'.
+ *  You must check for the value inside the abs value bars being zero.  If
+ *  so then the block is on the same row and you don't need to do a table
+ *  lookup.  The last value:
+ *
+ *      dcy = |row of block - row to be checked|
+ *
+ *  Is the value of the first visible spot on the check row from the
+ *  block column.  So
+ *
+ *  first visible col = close_table[dy][dx][dcy] + col of 'B'
+ *
+\*--------------  vision tables  --------------*/
+
+static void
+H_close_gen()
+{
+    Fprintf(ofp,"\n/* Close */\n");
+    Fprintf(ofp,"#define CLOSE_MAX_SB_DY %2d\t/* |src row - block row| - 1\t*/\n",
+           TEST_HEIGHT-1);
+    Fprintf(ofp,"#define CLOSE_MAX_SB_DX %2d\t/* |src col - block col|\t*/\n",
+           TEST_WIDTH);
+    Fprintf(ofp,"#define CLOSE_MAX_BC_DY %2d\t/* |block row - check row|\t*/\n",
+           TEST_HEIGHT);
+    Fprintf(ofp,"typedef struct {\n");
+    Fprintf(ofp,"    unsigned char close[CLOSE_MAX_SB_DX][CLOSE_MAX_BC_DY];\n");
+    Fprintf(ofp,"} close2d;\n");
+    Fprintf(ofp,"extern close2d close_table[CLOSE_MAX_SB_DY];\n");
+    return;
+}
+
+static void
+H_far_gen()
+{
+    Fprintf(ofp,"\n/* Far */\n");
+    Fprintf(ofp,"#define FAR_MAX_SB_DY %2d\t/* |src row - block row|\t*/\n",
+           TEST_HEIGHT);
+    Fprintf(ofp,"#define FAR_MAX_SB_DX %2d\t/* |src col - block col| - 1\t*/\n",
+           TEST_WIDTH-1);
+    Fprintf(ofp,"#define FAR_MAX_BC_DY %2d\t/* |block row - check row| - 1\t*/\n",
+           TEST_HEIGHT-1);
+    Fprintf(ofp,"typedef struct {\n");
+    Fprintf(ofp,"    unsigned char far_q[FAR_MAX_SB_DX][FAR_MAX_BC_DY];\n");
+    Fprintf(ofp,"} far2d;\n");
+    Fprintf(ofp,"extern far2d far_table[FAR_MAX_SB_DY];\n");
+    return;
+}
+
+static void
+C_close_gen()
+{
+    int i,dx,dy;
+    int src_row, src_col;      /* source */
+    int block_row, block_col;  /* block */
+    int this_row;
+    int no_more;
+    const char *delim;
+
+    block_row = BLOCK_HEIGHT-1;
+    block_col = BLOCK_WIDTH-1;
+
+    Fprintf(ofp,"\n#ifndef FAR_TABLE_ONLY\n");
+    Fprintf(ofp,"\nclose2d close_table[CLOSE_MAX_SB_DY] = {\n");
+#ifndef no_vision_progress
+    Fprintf(stderr,"\nclose:");
+#endif
+
+    for (dy = 1; dy < TEST_HEIGHT; dy++) {
+       src_row = block_row + dy;
+       Fprintf(ofp, "/* DY = %2d (- 1)*/\n  {{\n", dy);
+#ifndef no_vision_progress
+       Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
+#endif
+       for (dx = 0; dx < TEST_WIDTH; dx++) {
+           src_col = block_col - dx;
+           Fprintf(ofp, "  /*%2d*/ {", dx);
+
+           no_more = 0;
+           for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
+               delim = (this_row < TEST_HEIGHT - 1) ? "," : "";
+               if (no_more) {
+                   Fprintf(ofp, "%s%s", CLOSE_OFF_TABLE_STRING, delim);
+                   continue;
+               }
+               SpinCursor(3);
+
+               /* Find the first column that we can see. */
+               for (i = block_col+1; i < MAX_COL; i++) {
+                   if (clear_path(src_row,src_col,block_row-this_row,i))
+                       break;
+               }
+
+               if (i == MAX_COL) no_more = 1;
+               Fprintf(ofp, "%2d%s", i - block_col, delim);
+           }
+           Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
+       }
+       Fprintf(ofp,"  }},\n");
+    }
+
+    Fprintf(ofp,"}; /* close_table[] */\n");           /* closing brace for table */
+    Fprintf(ofp,"#endif /* !FAR_TABLE_ONLY */\n");
+#ifndef no_vision_progress
+    Fprintf(stderr,"\n");
+#endif
+    return;
+}
+
+static void
+C_far_gen()
+{
+    int i,dx,dy;
+    int src_row, src_col;      /* source */
+    int block_row, block_col;  /* block */
+    int this_row;
+    const char *delim;
+
+    block_row = BLOCK_HEIGHT-1;
+    block_col = BLOCK_WIDTH-1;
+
+    Fprintf(ofp,"\n#ifndef CLOSE_TABLE_ONLY\n");
+    Fprintf(ofp,"\nfar2d far_table[FAR_MAX_SB_DY] = {\n");
+#ifndef no_vision_progress
+    Fprintf(stderr,"\n_far_:");
+#endif
+
+    for (dy = 0; dy < TEST_HEIGHT; dy++) {
+       src_row = block_row - dy;
+       Fprintf(ofp, "/* DY = %2d */\n  {{\n", dy);
+#ifndef no_vision_progress
+       Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
+#endif
+       for (dx = 1; dx < TEST_WIDTH; dx++) {
+           src_col = block_col + dx;
+           Fprintf(ofp, "  /*%2d(-1)*/ {", dx);
+
+           for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
+                                                               this_row++) {
+               delim = (this_row < block_row + TEST_HEIGHT - 1) ? "," : "";
+
+               SpinCursor(3);
+               /* Find first col that we can see. */
+               for (i = 0; i <= block_col; i++) {
+                   if (clear_path(src_row,src_col,this_row,i)) break;
+               }
+
+               if (block_col-i < 0)
+                   Fprintf(ofp, "%s%s", FAR_OFF_TABLE_STRING, delim);
+               else
+                   Fprintf(ofp, "%2d%s", block_col - i, delim);
+           }
+           Fprintf(ofp, "}%s", (dx < TEST_WIDTH - 1) ? ",\n" : "\n");
+       }
+       Fprintf(ofp,"  }},\n");
+    }
+
+    Fprintf(ofp,"}; /* far_table[] */\n");     /* closing brace for table */
+    Fprintf(ofp,"#endif /* !CLOSE_TABLE_ONLY */\n");
+#ifndef no_vision_progress
+    Fprintf(stderr,"\n");
+#endif
+    return;
+}
+
+/*
+ *  "Draw" a line from the hero to the given location.  Stop if we hit a
+ *  wall.
+ *
+ *  Generalized integer Bresenham's algorithm (fast line drawing) for
+ *  all quadrants.  From _Procedural Elements for Computer Graphics_, by
+ *  David F. Rogers.  McGraw-Hill, 1985.
+ *
+ *  I have tried a little bit of optimization by pulling compares out of
+ *  the inner loops.
+ *
+ *  NOTE:  This had better *not* be called from a position on the
+ *  same row as the hero.
+ */
+static int
+clear_path(you_row,you_col,y2,x2)
+    int you_row, you_col, y2, x2;
+{
+    int dx, dy, s1, s2;
+    register int i, error, x, y, dxs, dys;
+
+    x  = you_col;              y  = you_row;
+    dx = abs(x2-you_col);      dy = abs(y2-you_row);
+    s1 = sign(x2-you_col);     s2 = sign(y2-you_row);
+
+    if (s1 == 0) {     /* same column */
+       if (s2 == 1) {  /* below (larger y2 value) */
+           for (i = you_row+1; i < y2; i++)
+               if (!xclear[i][you_col]) return 0;
+       } else {        /* above (smaller y2 value) */
+           for (i = y2+1; i < you_row; i++)
+               if (!xclear[i][you_col]) return 0;
+       }
+       return 1;
+    }
+
+    /*
+     *  Lines at 0 and 90 degrees have been weeded out.
+     */
+    if (dy > dx) {
+       error = dx; dx = dy; dy = error;        /* swap the values */
+       dxs = dx << 1;          /* save the shifted values */
+       dys = dy << 1;
+       error = dys - dx;       /* NOTE: error is used as a temporary above */
+
+       for (i = 0; i < dx; i++) {
+           if (!xclear[y][x]) return 0;        /* plot point */
+
+           while (error >= 0) {
+               x += s1;
+               error -= dxs;
+           }
+           y += s2;
+           error += dys;
+       }
+    } else {
+       dxs = dx << 1;          /* save the shifted values */
+       dys = dy << 1;
+       error = dys - dx;
+
+       for (i = 0; i < dx; i++) {
+           if (!xclear[y][x]) return 0;        /* plot point */
+
+           while (error >= 0) {
+               y += s2;
+               error -= dxs;
+           }
+           x += s1;
+           error += dys;
+       }
+    }
+    return 1;
+}
+#endif /* VISION_TABLES */
+
+#ifdef STRICT_REF_DEF
+NEARDATA struct flag flags;
+# ifdef ATTRIB_H
+struct attribs attrmax, attrmin;
+# endif
+#endif /* STRICT_REF_DEF */
+
+/*makedefs.c*/