home *** CD-ROM | disk | FTP | other *** search
- /* 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. */
- /* makedefs.c - NetHack version 3.1 */
-
- #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"
-
- /* 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
-
- #ifdef NULL
- #undef NULL
- #endif
- #define NULL ((char *)0)
-
- #if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
- static const char SCCS_Id[] = "@(#)makedefs.c\t3.1\t93/05/15";
- #endif
-
- #ifdef MICRO
- # undef exit
- extern void FDECL(exit, (int));
- #endif
-
- #define WRMODE "w+"
- #define RDMODE "r"
- /* the quest.dat file is binary, while everything else is text... */
- #if (defined(MICRO) && !defined(AMIGA)) || defined(THINK_C)
- # define WRBMODE "w+b"
- #else
- # define WRBMODE "w+"
- #endif
-
- #ifndef SEEK_SET
- # define SEEK_SET 0
- #endif
- #ifndef SEEK_END
- # define SEEK_END 2
- #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 INCLUDE_TEMPLATE "Incl:t.%s"
- # define SOURCE_TEMPLATE "NHS:%s"
- # define DATA_TEMPLATE "Dat:%s"
- #else
- # ifdef MAC
- # define INCLUDE_TEMPLATE ":include:%s"
- # define SOURCE_TEMPLATE ":src:%s"
- # define DATA_TEMPLATE ":dat:%s"
- # else /* MAC */
- # define INCLUDE_TEMPLATE "../include/%s"
- # define SOURCE_TEMPLATE "../src/%s"
- # define DATA_TEMPLATE "../dat/%s"
- # 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 {
- long incarnation;
- long features;
- } 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[30];
-
- #ifdef MACsansMPWTOOL
- void FDECL(macstart, (void));
- int FDECL(main, (void));
- #else
- int FDECL(main, (int, char **));
- #endif
- int FDECL(do_makedefs, (int, 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(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 *));
-
- #ifdef MULDGN
- static boolean FDECL(qt_comment, (char *));
- static boolean FDECL(qt_control, (char *));
- static int FDECL(get_hdr, (CHAR_P));
- static boolean FDECL(known_id, (CHAR_P));
- static boolean FDECL(new_id, (CHAR_P));
- static boolean FDECL(known_msg, (CHAR_P, char *));
- static void FDECL(new_msg, (char *));
- 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);
- #endif
-
- #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));
-
- /* input, output, tmp */
-
- static FILE *ifp, *ofp, *tfp;
-
- #ifdef MACsansMPWTOOL
- char mac_opt;
-
- void
- macstart()
- {
- static char buf[100];
- static char *ptr = NULL;
-
- again :
- if (!ptr || !*ptr) {
- Fprintf(stderr, "Options: otdemvpqrhz\n");
- buf[0] = 0;
- fgets(buf, 100, stdin);
- ptr = buf;
- }
-
- do {
- mac_opt = *ptr++;
- } while (mac_opt && isspace(mac_opt));
-
- if (!mac_opt) {
- Fprintf(stderr, "Makedefs done.\n");
- exit(0);
- }
- }
- #endif /* MAC */
-
-
- int
- #ifdef MACsansMPWTOOL
- main(void)
- {
- int argc;
- char **argv;
- #else /* ! MAC */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- #endif /* MAC */
- /* 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();
-
- #ifdef MACsansMPWTOOL
- while (1) {
- macstart();
- do_makedefs(argc, argv);
- }
- #else
- if (do_makedefs(argc, argv))
- exit(1);
- #endif
- #ifndef VMS
- return 0;
- #else
- return 1; /* vms success */
- #endif /*VMS*/
- }
-
- int
- do_makedefs(arrgc, arrgv)
- int arrgc;
- char *arrgv[];
- {
- #ifdef MACsansMPWTOOL
- if (1) {
- Fprintf(stderr, "makedefs -%c\n", mac_opt);
- switch (mac_opt) {
- #else /* !MAC */
- if (arrgc == 2) {
- char *option = arrgv[1];
- switch (option[1]) {
- #endif /* MAC */
- case 'o':
- case 'O': do_objs();
- break;
- case 't': /* this may go away... */
- case 'T': Fprintf(stderr, "`-t' option is obsolete.\n");
- 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",
- #ifdef MACsansMPWTOOL
- mac_opt
- #else /* MAC */
- option[1]
- #endif /* MAC */
- );
- (void) fflush(stderr);
- return(1);
- }
- return 0;
- } else {
- Fprintf(stderr, "Bad arg count (%d).\n", arrgc-1);
- (void) fflush(stderr);
- return 1;
- }
- }
-
-
- /* 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[30];
- long true_rumor_size;
-
- Sprintf(filename, DATA_TEMPLATE, RUMOR_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,Dont_Edit_Data);
-
- Strcat(strcpy(infile, filename), ".tru");
- if (!(ifp = fopen(infile, RDMODE))) {
- perror(infile);
- Fclose(ofp);
- Unlink(filename); /* kill empty output file */
- exit(1);
- }
-
- /* 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) != NULL)
- 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) != NULL)
- (void) fputs(xcrypt(in_line), ofp);
-
- Fclose(ifp);
- Strcat(strcpy(infile, filename), ".fal");
- if (!(ifp = fopen(infile, RDMODE))) {
- perror(infile);
- Fclose(ofp);
- Unlink(filename); /* kill incomplete output file */
- exit(1);
- }
-
- /* copy false rumors */
- while(fgets(in_line,sizeof(in_line),ifp) != NULL)
- (void) fputs(xcrypt(in_line), ofp);
-
- Fclose(ifp);
- Fclose(ofp);
- return;
- }
-
- static void
- make_version()
- {
- /*
- * integer version number
- */
- version.incarnation = ((long)VERSION_MAJOR << 24) |
- ((long)VERSION_MINOR << 16) |
- ((long)PATCHLEVEL << 8) |
- ((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.features = 0
- /* levels and/or topology (0..4) */
- #ifdef MULDGN
- | (1L << 0)
- #endif
- #ifdef REINCARNATION
- | (1L << 1)
- #endif
- #ifdef SINKS
- | (1L << 2)
- #endif
- /* monsters (5..9) */
- #ifdef ARMY
- | (1L << 5)
- #endif
- #ifdef KOPS
- | (1L << 6)
- #endif
- #ifdef MAIL
- | (1L << 7)
- #endif
- /* objects (10..14) */
- #ifdef TOURIST
- | (1L << 10)
- #endif
- #ifdef TUTTI_FRUTTI
- | (1L << 11)
- #endif
- #ifdef WALKIES
- | (1L << 12)
- #endif
- /* flag bits and/or other global variables (15..26) */
- #ifdef MUSE
- | (1L << 15)
- #endif
- #ifdef POLYSELF
- | (1L << 16)
- #endif
- #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
- /* data format [COMPRESS excluded] (27..31) */
- #ifdef ZEROCOMP
- | (1L << 27)
- #endif
- #ifdef RLECOMP
- | (1L << 28)
- #endif
- ;
- return;
- }
-
- void
- do_date()
- {
- long clocktim;
- char cbuf[30], *c;
-
- Sprintf(filename, INCLUDE_TEMPLATE, DATE_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.1\t92/04/07 */\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 != '\n'; c++); *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");
- Fprintf(ofp,"#define VERSION_NUMBER 0x%08lxL\n", version.incarnation);
- Fprintf(ofp,"#define VERSION_FEATURES 0x%08lxL\n", version.features);
- Fprintf(ofp,"\n");
- #ifdef AMIGA
- {
- struct tm *tm = localtime((time_t *) &clocktim);
- Fprintf(ofp,"#ifdef AMIGA\n");
- Fprintf(ofp,"const char 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);
- Fprintf(ofp,"#endif\n");
- }
- #endif
- Fclose(ofp);
- return;
- }
-
- static const char *build_opts[] = {
- #ifdef AMIGA_WBENCH
- "Amiga WorkBench support",
- #endif
- #ifdef ANSI_DEFAULT
- "ANSI default terminal",
- #endif
- #ifdef ARMY
- "armies",
- #endif
- #ifdef TEXTCOLOR
- "color",
- #endif
- #ifdef COM_COMPL
- "command line completion",
- #endif
- #ifdef COMPRESS
- "data file compression",
- #endif
- #ifdef WIZARD
- "debug mode",
- #endif
- #ifdef ELBERETH
- "Elbereth",
- #endif
- #ifdef EXP_ON_BOTL
- "experience points on status line",
- #endif
- #ifdef EXPLORE_MODE
- "explore mode",
- #endif
- #ifdef MFLOPPY
- "floppy drive support",
- #endif
- #ifdef TUTTI_FRUTTI
- "fruit names",
- #endif
- #ifdef INSURANCE
- "insurance against game crashes",
- #endif
- #ifdef KOPS
- "Keystone Kops",
- #endif
- #ifdef WALKIES
- "leashes",
- #endif
- #ifdef LOGFILE
- "log file",
- #endif
- #ifdef MAIL
- "mail daemon",
- #endif
- #ifdef MUSE
- "monster item use",
- #endif
- #ifdef GNUDOS
- "MSDOS protected mode",
- #endif
- #ifdef NEWS
- "news file",
- #endif
- #ifdef OVERLAY
- "overlays",
- #endif
- #ifdef MULDGN
- "quest dungeon",
- #endif
- #ifdef REDO
- "redo command",
- #endif
- #ifdef REINCARNATION
- "rogue level",
- #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_BIOS
- "screen control via BIOS",
- # endif
- # ifdef SCREEN_DJGPPFAST
- "screen control via DJGPP fast",
- # endif
- # ifdef WIN32CON
- "screen control via WIN32 console I/O",
- # endif
- #endif
- #ifdef SEDUCE
- "seduction",
- #endif
- #ifdef POLYSELF
- "self-polymorph",
- #endif
- #ifdef SHELL
- "shell command",
- #endif
- #ifdef SINKS
- "sinks",
- #endif
- #ifdef SOUNDS
- "sounds",
- #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 TOURIST
- "tourists",
- #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 MAC
- "Mac",
- #endif
- #ifdef AMIGA_INTUITION
- "Amiga Intuition",
- #endif
- NULL
- };
-
- void
- do_options()
- {
- register int i, length;
- register const char *str, *indent = " ";
-
- Sprintf(filename, DATA_TEMPLATE, OPTIONS_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
-
- 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 */
- #ifndef ARMY
- { static int ignore_army = 0;
-
- switch (ignore_army) {
- case 0: if (!strcmp(line, "*soldier")) ignore_army = 1;
- break; /* 0 => not in army related data */
- case 1: if (*line <= ' ') ignore_army = 2;
- break; /* 1 => in army name list */
- case 2: if (*line > ' ') ignore_army = 0;
- break; /* 2 => in army descriptive text */
- }
- if (ignore_army) return TRUE;
- }
- #endif
- 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[30], tempfile[30];
- boolean ok;
- long txt_offset;
- unsigned entry_cnt, line_cnt;
-
- Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
- Sprintf(filename, DATA_TEMPLATE, DATA_FILE);
- Strcat(strcpy(infile, filename),
- #ifdef SHORT_FILENAMES
- ".bas"
- #else
- ".base"
- #endif
- );
- if (!(ifp = fopen(infile, RDMODE))) { /* data.base */
- perror(infile);
- exit(1);
- }
- if (!(ofp = fopen(filename, WRMODE))) { /* data */
- perror(filename);
- Fclose(ifp);
- exit(1);
- }
- if (!(tfp = fopen(tempfile, WRMODE))) { /* database.tmp */
- perror(tempfile);
- Fclose(ifp);
- Fclose(ofp);
- Unlink(filename);
- exit(1);
- }
-
- /* 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(1);
- }
-
- /* 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[30], tempfile[30];
- boolean in_oracle, ok;
- long txt_offset, offset, fpos;
- unsigned oracle_cnt;
- register int i;
-
- Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
- Sprintf(filename, DATA_TEMPLATE, ORACLE_FILE);
- Strcat(strcpy(infile, filename), ".txt");
- if (!(ifp = fopen(infile, RDMODE))) {
- perror(infile);
- exit(1);
- }
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- Fclose(ifp);
- exit(1);
- }
- if (!(tfp = fopen(tempfile, WRMODE))) { /* oracles.tmp */
- perror(tempfile);
- Fclose(ifp);
- Fclose(ofp);
- Unlink(filename);
- exit(1);
- }
-
- /* 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, (int)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;
- 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(1);
- }
-
- /* all done */
- Fclose(ofp);
-
- return;
- }
-
-
- static struct deflist {
-
- const char *defname;
- boolean true_or_false;
- } deflist[] = {
- #ifdef REINCARNATION
- { "REINCARNATION", TRUE },
- #else
- { "REINCARNATION", FALSE },
- #endif
- #ifdef MULDGN
- { "MULDGN", TRUE },
- #else
- { "MULDGN", 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_TEMPLATE, DGN_I_FILE);
- if (!(ifp = fopen(filename, RDMODE))) {
- perror(filename);
- exit(1);
- }
- Sprintf(filename, DATA_TEMPLATE, DGN_O_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,Dont_Edit_Data);
-
- while(fgets(in_line,sizeof(in_line),ifp) != NULL) {
-
- 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))
- 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(1);
- }
- } 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)
- #ifdef POLYSELF
- || (tmp2 == AD_WERE)
- #endif
- ) 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"
- */
- Sprintf(filename, SOURCE_TEMPLATE, MON_STR_C);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,Dont_Edit_Code);
- Fprintf(ofp,"#include \"config.h\"\n");
- Fprintf(ofp,"\nint 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;
-
- Sprintf(filename, INCLUDE_TEMPLATE, MONST_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.1\t92/01/04 */\n\n");
- Fprintf(ofp,Dont_Edit_Code);
- Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");
-
- 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;
- }
-
- #ifdef MULDGN
- /* 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(!in_msg && strlen(s) == NO_MSG);
- }
-
- static boolean
- qt_control(s)
-
- char *s;
- {
- return(s[0] == '%' && (s[1] == 'C' || s[1] == 'E'));
- }
-
- static int
- get_hdr(c)
-
- char c;
- {
- int i;
-
- for(i = 0; i < qt_hdr.n_hdr; i++)
- if(c == qt_hdr.id[i]) return (++i);
-
- return(0);
- }
-
- static boolean
- known_id(c)
-
- char c;
- {
- return(get_hdr(c) > 0);
- }
-
- static boolean
- new_id(c)
-
- char c;
- {
- if(qt_hdr.n_hdr >= N_HDR) {
-
- Fprintf(stderr, OUT_OF_HEADERS, qt_line);
- return(FALSE);
- }
-
- qt_hdr.id[qt_hdr.n_hdr] = c;
- msg_hdr[qt_hdr.n_hdr].n_msg = 0;
- qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
- return(TRUE);
- }
-
- static boolean
- known_msg(c, s)
-
- char c, *s;
- {
- int i = get_hdr(c) - 1,
- j, n = atoi(s);
-
- for(j = 0; j < msg_hdr[i].n_msg; j++)
- if(msg_hdr[i].qt_msg[j].msgnum == n) return(TRUE);
-
- return(FALSE);
- }
-
-
- static void
- new_msg(s)
- char *s;
- {
- struct qtmsg *qt_msg;
- int i = get_hdr(s[4]) - 1;
-
- if(msg_hdr[i].n_msg >= N_MSG) {
- Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
- } else {
- qt_msg = &(msg_hdr[i].qt_msg[msg_hdr[i].n_msg++]);
- qt_msg->msgnum = atoi(s+5);
- qt_msg->delivery = s[2];
- qt_msg->offset = qt_msg->size = 0L;
-
- curr_msg = qt_msg;
- }
- }
-
- static void
- do_qt_control(s)
-
- char *s;
- {
- switch(s[1]) {
-
- case 'C': if(in_msg) {
- Fprintf(stderr, CREC_IN_MSG, qt_line);
- break;
- } else {
- in_msg = TRUE;
- if(!known_id(s[4]))
- if(!new_id(s[4])) break;
- if(known_msg(s[4],&s[5]))
- Fprintf(stderr, DUP_MSG, qt_line);
- else new_msg(s);
- }
- 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);
- }
-
- static void
- adjust_qt_hdrs() {
-
- int i, j;
- long count = 0L,
- hdr_offset = sizeof(int) +
- (sizeof(char) + 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;
- }
- }
-
- static void
- put_qt_hdrs() {
-
- int i;
-
- /*
- * The main header record.
- */
- #ifdef DEBUG
- Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
- #endif
- (void) fwrite(&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
- (void) fwrite(&(qt_hdr.id[0]), sizeof(char), qt_hdr.n_hdr, ofp);
- (void) fwrite(&(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(&(msg_hdr[i].n_msg), sizeof(int), 1, ofp);
- (void) fwrite(&(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_TEMPLATE, QTXT_I_FILE);
- if(!(ifp = fopen(filename, RDMODE))) {
- perror(filename);
- exit(1);
- }
-
- Sprintf(filename, DATA_TEMPLATE, QTXT_O_FILE);
- if(!(ofp = fopen(filename, WRBMODE))) {
- perror(filename);
- Fclose(ifp);
- exit(1);
- }
-
- qt_hdr.n_hdr = 0;
- qt_line = 0;
- in_msg = FALSE;
-
- while(fgets(in_line, 80, ifp) != NULL) {
-
- 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) != NULL) {
-
- 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;
- }
- #else /* not MULDGN */
-
- void
- do_questtxt()
- {
- Fprintf(stderr, "makedefs: `-q' option ignored.\n");
- /* create an empty file to satisfy `make' */
- Sprintf(filename, DATA_TEMPLATE, QTXT_O_FILE);
- ofp = fopen(filename, WRBMODE);
- Fclose(ofp);
- return;
- }
-
- #endif /* MULDGN */
-
- 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;
-
- Sprintf(filename, INCLUDE_TEMPLATE, ONAME_FILE);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.1\t92/11/01 */\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\tNROFOBJECTS\t%d\n", i-1);
-
- 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(1);
- return;
- }
-
- static char *
- tmpdup(str)
- const char *str;
- {
- static char buf[128];
-
- if (!str) return (char *)0;
- (void)strncpy(buf, str, 127);
- return buf;
- }
-
-
- /*
- * macros used to control vision algorithms:
- * VISION_TABLES => generate tables
- * BRACES => table elements should be enclosed in "{ }"
- */
-
- 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"
- */
- Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- exit(1);
- }
- 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"
- */
- Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
- if (!(ofp = fopen(filename, WRMODE))) {
- perror(filename);
- Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
- Unlink(filename);
- exit(1);
- }
- 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;
- }
-
- # ifdef BRACES
- # define L_BRACE "{"
- # define R_BRACE "},"
- # else
- # define L_BRACE ""
- # define R_BRACE ""
- # endif /* BRACES */
-
- 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;
-
- 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*/ %s",dx, L_BRACE);
-
- no_more = 0;
- for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
- if (no_more) {
- Fprintf(ofp,CLOSE_OFF_TABLE_STRING);
- 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,",i-block_col);
- }
- Fprintf(ofp,"%s\n", R_BRACE);
- }
- 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;
-
- 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)*/ %s",dx, L_BRACE);
-
- for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
- this_row++) {
- /* Find first col that we can see. */
- for (i = 0; i <= block_col; i++) {
-
- SpinCursor(3);
-
- if (clear_path(src_row,src_col,this_row,i)) break;
- }
-
- if (block_col-i < 0)
- Fprintf(ofp,FAR_OFF_TABLE_STRING);
- else
- Fprintf(ofp,"%2d,",block_col-i);
- }
- Fprintf(ofp,"%s\n", R_BRACE);
- }
- 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 of 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 */
-
- /*makedefs.c*/
-