home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / util / makedefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  46.4 KB  |  2,046 lines  |  [TEXT/R*ch]

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* Copyright (c) M. Stephenson, 1990, 1991.              */
  3. /* Copyright (c) Dean Luick, 1990.                  */
  4. /* NetHack may be freely redistributed.  See license for details. */
  5. /* makedefs.c - NetHack version 3.1 */
  6.  
  7. #define    MAKEDEFS_C    /* use to conditionally include file sections */
  8. /* #define DEBUG /* uncomment for debugging info */
  9.  
  10. #include "config.h"
  11. #include "permonst.h"
  12. #include "objclass.h"
  13. #include "monsym.h"
  14. #include "artilist.h"
  15.  
  16. /* version information */
  17. #ifdef SHORT_FILENAMES
  18. #include "patchlev.h"
  19. #else
  20. #include "patchlevel.h"
  21. #endif
  22.  
  23. #ifdef MAC
  24. # ifdef applec    /* Means the MPW compiler, I hope */
  25. #  define MPWTOOL
  26. #  include <CursorCtl.h>
  27. #  include <string.h>
  28. #  include <ctype.h>
  29. # else        /* MAC without MPWTOOL */
  30. #  define MACsansMPWTOOL
  31. # endif
  32. #endif /* MAC */
  33.  
  34. #ifndef MPWTOOL
  35. # define SpinCursor(x)
  36. #endif
  37.  
  38. #define Fprintf    (void) fprintf
  39. #define Fclose    (void) fclose
  40. #define Unlink    (void) unlink
  41. #if !defined(AMIGA) || defined(AZTEC_C)
  42. #define rewind(fp) fseek((fp),0L,SEEK_SET)    /* guarantee a return value */
  43. #endif
  44.  
  45. #ifdef NULL
  46. #undef NULL
  47. #endif
  48. #define NULL    ((char *)0)
  49.  
  50. #if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
  51. static    const char    SCCS_Id[] = "@(#)makedefs.c\t3.1\t93/05/15";
  52. #endif
  53.  
  54. #ifdef MICRO
  55. # undef    exit
  56. extern void FDECL(exit, (int));
  57. #endif
  58.  
  59. #define WRMODE  "w+"
  60. #define RDMODE  "r"
  61. /* the quest.dat file is binary, while everything else is text... */
  62. #if (defined(MICRO) && !defined(AMIGA)) || defined(THINK_C)
  63. # define WRBMODE "w+b"
  64. #else
  65. # define WRBMODE "w+"
  66. #endif
  67.  
  68. #ifndef SEEK_SET
  69. # define SEEK_SET 0
  70. #endif
  71. #ifndef SEEK_END
  72. # define SEEK_END 2
  73. #endif
  74.  
  75.     /* names of files to be generated */
  76. #define DATE_FILE    "date.h"
  77. #define MONST_FILE    "pm.h"
  78. #define ONAME_FILE    "onames.h"
  79. #define OPTIONS_FILE    "options"
  80. #define ORACLE_FILE    "oracles"
  81. #define DATA_FILE    "data"
  82. #define RUMOR_FILE    "rumors"
  83. #define DGN_I_FILE    "dungeon.def"
  84. #define DGN_O_FILE    "dungeon.pdf"
  85. #define MON_STR_C    "monstr.c"
  86. #define QTXT_I_FILE    "quest.txt"
  87. #define QTXT_O_FILE    "quest.dat"
  88. #define VIS_TAB_H    "vis_tab.h"
  89. #define VIS_TAB_C    "vis_tab.c"
  90.     /* locations for those files */
  91. #ifdef AMIGA
  92. # define INCLUDE_TEMPLATE    "Incl:t.%s"
  93. # define SOURCE_TEMPLATE    "NHS:%s"
  94. # define DATA_TEMPLATE        "Dat:%s"
  95. #else
  96. # ifdef MAC
  97. #   define INCLUDE_TEMPLATE    ":include:%s"
  98. #   define SOURCE_TEMPLATE    ":src:%s"
  99. #   define DATA_TEMPLATE    ":dat:%s"
  100. # else /* MAC */
  101. #   define INCLUDE_TEMPLATE    "../include/%s"
  102. #   define SOURCE_TEMPLATE    "../src/%s"
  103. #   define DATA_TEMPLATE    "../dat/%s"
  104. # endif /* MAC */
  105. #endif    /* AMIGA */
  106.  
  107. static const char
  108.     *Dont_Edit_Code =
  109.     "/* This source file is generated by 'makedefs'.  Do not edit. */\n",
  110.     *Dont_Edit_Data =
  111.     "#\tThis data file is generated by 'makedefs'.  Do not edit. \n";
  112.  
  113. static struct {
  114.     long    incarnation;
  115.     long    features;
  116. } version;
  117.  
  118. /* definitions used for vision tables */
  119. #define TEST_WIDTH  COLNO
  120. #define TEST_HEIGHT ROWNO
  121. #define BLOCK_WIDTH (TEST_WIDTH + 10)
  122. #define BLOCK_HEIGHT TEST_HEIGHT    /* don't need extra spaces */
  123. #define MAX_ROW (BLOCK_HEIGHT + TEST_HEIGHT)
  124. #define MAX_COL (BLOCK_WIDTH + TEST_WIDTH)
  125. /* Use this as an out-of-bound value in the close table.  */
  126. #define CLOSE_OFF_TABLE_STRING "99,"    /* for the close table */
  127. #define FAR_OFF_TABLE_STRING "0xff,"    /* for the far table */
  128.  
  129. #define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
  130. #ifdef VISION_TABLES
  131. static char xclear[MAX_ROW][MAX_COL];
  132. #endif
  133. /*-end of vision defs-*/
  134.  
  135. static char    in_line[256], filename[30];
  136.  
  137. #ifdef MACsansMPWTOOL
  138. void FDECL(macstart, (void));
  139. int FDECL(main, (void));
  140. #else
  141. int FDECL(main, (int, char **));
  142. #endif
  143. int FDECL(do_makedefs, (int, char **));
  144. void NDECL(do_objs);
  145. void NDECL(do_data);
  146. void NDECL(do_dungeon);
  147. void NDECL(do_date);
  148. void NDECL(do_options);
  149. void NDECL(do_monstr);
  150. void NDECL(do_permonst);
  151. void NDECL(do_questtxt);
  152. void NDECL(do_rumors);
  153. void NDECL(do_oracles);
  154. void NDECL(do_vision);
  155.  
  156. extern void NDECL(monst_init);        /* monst.c */
  157. extern void NDECL(objects_init);    /* objects.c */
  158.  
  159. static void NDECL(make_version);
  160. static char *FDECL(xcrypt, (const char *));
  161. static int FDECL(check_control, (char *));
  162. static char *FDECL(without_control, (char *));
  163. static boolean FDECL(d_filter, (char *));
  164. static boolean FDECL(h_filter, (char *));
  165. static boolean FDECL(ranged_attk,(struct permonst*));
  166. static int FDECL(mstrength,(struct permonst *));
  167.  
  168. #ifdef MULDGN
  169. static boolean FDECL(qt_comment, (char *));
  170. static boolean FDECL(qt_control, (char *));
  171. static int FDECL(get_hdr, (CHAR_P));
  172. static boolean FDECL(known_id, (CHAR_P));
  173. static boolean FDECL(new_id, (CHAR_P));
  174. static boolean FDECL(known_msg, (CHAR_P, char *));
  175. static void FDECL(new_msg, (char *));
  176. static void FDECL(do_qt_control, (char *));
  177. static void FDECL(do_qt_text, (char *));
  178. static void NDECL(adjust_qt_hdrs);
  179. static void NDECL(put_qt_hdrs);
  180. #endif
  181.  
  182. #ifdef VISION_TABLES
  183. static void NDECL(H_close_gen);
  184. static void NDECL(H_far_gen);
  185. static void NDECL(C_close_gen);
  186. static void NDECL(C_far_gen);
  187. static int FDECL(clear_path, (int,int,int,int));
  188. #endif
  189.  
  190. static char *FDECL(tmpdup, (const char *));
  191. static char *FDECL(limit, (char *,int));
  192.  
  193. /* input, output, tmp */
  194.  
  195. static FILE *ifp, *ofp, *tfp;
  196.  
  197. #ifdef MACsansMPWTOOL
  198. char mac_opt;
  199.  
  200. void
  201. macstart()
  202. {
  203.     static char buf[100];
  204.     static char *ptr = NULL;
  205.  
  206. again :
  207.     if (!ptr || !*ptr) {
  208.         Fprintf(stderr, "Options: otdemvpqrhz\n");
  209.         buf[0] = 0;
  210.         fgets(buf, 100, stdin);
  211.         ptr = buf;
  212.     }
  213.  
  214.     do {
  215.         mac_opt = *ptr++;
  216.     } while (mac_opt && isspace(mac_opt));
  217.  
  218.     if (!mac_opt) {
  219.         Fprintf(stderr, "Makedefs done.\n");
  220.         exit(0);
  221.     }
  222. }
  223. #endif /* MAC */
  224.  
  225.  
  226. int
  227. #ifdef MACsansMPWTOOL
  228. main(void)
  229. {
  230.     int argc;
  231.     char **argv;
  232. #else /* ! MAC */
  233. main(argc, argv)
  234. int    argc;
  235. char    *argv[];
  236. {
  237. #endif /* MAC */
  238.     /* Note:  these initializers don't do anything except guarantee that
  239.         we're linked properly.
  240.     */
  241.     monst_init();
  242.     objects_init();
  243.  
  244.     /* construct the current version number */
  245.     make_version();
  246.  
  247. #ifdef MACsansMPWTOOL
  248.     while (1) {
  249.         macstart();
  250.         do_makedefs(argc, argv);
  251.     }
  252. #else
  253.     if (do_makedefs(argc, argv))
  254.         exit(1);
  255. #endif
  256. #ifndef VMS
  257.     return 0;
  258. #else
  259.     return 1;       /* vms success */
  260. #endif /*VMS*/
  261. }
  262.  
  263. int
  264. do_makedefs(arrgc, arrgv)
  265. int    arrgc;
  266. char    *arrgv[];
  267. {
  268. #ifdef MACsansMPWTOOL
  269.     if (1) {
  270.         Fprintf(stderr, "makedefs -%c\n", mac_opt);
  271.         switch (mac_opt) {
  272. #else /* !MAC */
  273.     if (arrgc == 2) {
  274.         char *option = arrgv[1];
  275.         switch (option[1]) {
  276. #endif /* MAC */
  277.         case 'o':
  278.         case 'O':    do_objs();
  279.                 break;
  280.         case 't':            /* this may go away... */
  281.         case 'T':    Fprintf(stderr,    "`-t' option is obsolete.\n");
  282.                 break;
  283.         case 'd':
  284.         case 'D':    do_data();
  285.                 break;
  286.         case 'e':
  287.         case 'E':    do_dungeon();
  288.                 break;
  289.         case 'm':
  290.         case 'M':    do_monstr();
  291.                 break;
  292.         case 'v':
  293.         case 'V':    do_date();
  294.                 do_options();
  295.                 break;
  296.         case 'p':
  297.         case 'P':    do_permonst();
  298.                 break;
  299.         case 'q':
  300.         case 'Q':    do_questtxt();
  301.                 break;
  302.         case 'r':
  303.         case 'R':    do_rumors();
  304.                 break;
  305.         case 'h':
  306.         case 'H':    do_oracles();
  307.                 break;
  308.         case 'z':
  309.         case 'Z':    do_vision();
  310.                 break;
  311.  
  312.         default:
  313.                 Fprintf(stderr,    "Unknown option '%c'.\n",
  314. #ifdef MACsansMPWTOOL
  315.                     mac_opt
  316. #else /* MAC */
  317.                     option[1]
  318. #endif /* MAC */
  319.                     );
  320.                 (void) fflush(stderr);
  321.                 return(1);
  322.         }
  323.         return 0;
  324.     } else {
  325.         Fprintf(stderr, "Bad arg count (%d).\n", arrgc-1);
  326.         (void) fflush(stderr);
  327.         return 1;
  328.     }
  329. }
  330.  
  331.  
  332. /* trivial text encryption routine which can't be broken with `tr' */
  333. static
  334. char *xcrypt(str)
  335. const char *str;
  336. {                /* duplicated in src/hacklib.c */
  337.     static char buf[BUFSZ];
  338.     register const char *p;
  339.     register char *q;
  340.     register int bitmask;
  341.  
  342.     for (bitmask = 1, p = str, q = buf; *p; q++) {
  343.         *q = *p++;
  344.         if (*q & (32|64)) *q ^= bitmask;
  345.         if ((bitmask <<= 1) >= 32) bitmask = 1;
  346.     }
  347.     *q = '\0';
  348.     return buf;
  349. }
  350.  
  351. void
  352. do_rumors()
  353. {
  354.     char    infile[30];
  355.     long    true_rumor_size;
  356.  
  357.     Sprintf(filename, DATA_TEMPLATE, RUMOR_FILE);
  358.     if (!(ofp = fopen(filename, WRMODE))) {
  359.         perror(filename);
  360.         exit(1);
  361.     }
  362.     Fprintf(ofp,Dont_Edit_Data);
  363.  
  364.     Strcat(strcpy(infile, filename), ".tru");
  365.     if (!(ifp = fopen(infile, RDMODE))) {
  366.         perror(infile);
  367.         Fclose(ofp);
  368.         Unlink(filename);    /* kill empty output file */
  369.         exit(1);
  370.     }
  371.  
  372.     /* get size of true rumors file */
  373. #ifndef VMS
  374.     (void) fseek(ifp, 0L, SEEK_END);
  375.     true_rumor_size = ftell(ifp);
  376. #else
  377.     /* seek+tell is only valid for stream format files; since rumors.%%%
  378.        might be in record format, count the actual data bytes instead.
  379.      */
  380.     true_rumor_size = 0;
  381.     while (fgets(in_line,sizeof(in_line),ifp) != NULL)
  382.         true_rumor_size += strlen(in_line);    /* includes newline */
  383. #endif /* VMS */
  384.     Fprintf(ofp,"%06lx\n", true_rumor_size);
  385.     (void) fseek(ifp, 0L, SEEK_SET);
  386.  
  387.     /* copy true rumors */
  388.     while(fgets(in_line,sizeof(in_line),ifp) != NULL)
  389.         (void) fputs(xcrypt(in_line), ofp);
  390.  
  391.     Fclose(ifp);
  392.     Strcat(strcpy(infile, filename), ".fal");
  393.     if (!(ifp = fopen(infile, RDMODE))) {
  394.         perror(infile);
  395.         Fclose(ofp);
  396.         Unlink(filename);    /* kill incomplete output file */
  397.         exit(1);
  398.     }
  399.  
  400.     /* copy false rumors */
  401.     while(fgets(in_line,sizeof(in_line),ifp) != NULL)
  402.         (void) fputs(xcrypt(in_line), ofp);
  403.  
  404.     Fclose(ifp);
  405.     Fclose(ofp);
  406.     return;
  407. }
  408.  
  409. static void
  410. make_version()
  411. {
  412.     /*
  413.      * integer version number
  414.      */
  415.     version.incarnation = ((long)VERSION_MAJOR << 24) |
  416.                 ((long)VERSION_MINOR << 16) |
  417.                 ((long)PATCHLEVEL << 8) |
  418.                 ((long)EDITLEVEL);
  419.     /*
  420.      * encoded feature list
  421.      * Note:  if any of these magic numbers are changed or reassigned,
  422.      * EDITLEVEL in patchlevel.h should be incremented at the same time.
  423.      * The actual values have no special meaning, and the category
  424.      * groupings are just for convenience.
  425.      */
  426.     version.features = 0
  427.         /* levels and/or topology (0..4) */
  428. #ifdef MULDGN
  429.             | (1L <<  0)
  430. #endif
  431. #ifdef REINCARNATION
  432.             | (1L <<  1)
  433. #endif
  434. #ifdef SINKS
  435.             | (1L <<  2)
  436. #endif
  437.         /* monsters (5..9) */
  438. #ifdef ARMY
  439.             | (1L <<  5)
  440. #endif
  441. #ifdef KOPS
  442.             | (1L <<  6)
  443. #endif
  444. #ifdef MAIL
  445.             | (1L <<  7)
  446. #endif
  447.         /* objects (10..14) */
  448. #ifdef TOURIST
  449.             | (1L << 10)
  450. #endif
  451. #ifdef TUTTI_FRUTTI
  452.             | (1L << 11)
  453. #endif
  454. #ifdef WALKIES
  455.             | (1L << 12)
  456. #endif
  457.         /* flag bits and/or other global variables (15..26) */
  458. #ifdef MUSE
  459.             | (1L << 15)
  460. #endif
  461. #ifdef POLYSELF
  462.             | (1L << 16)
  463. #endif
  464. #ifdef TEXTCOLOR
  465.             | (1L << 17)
  466. #endif
  467. #ifdef INSURANCE
  468.             | (1L << 18)
  469. #endif
  470. #ifdef ELBERETH
  471.             | (1L << 19)
  472. #endif
  473. #ifdef EXP_ON_BOTL
  474.             | (1L << 20)
  475. #endif
  476. #ifdef SCORE_ON_BOTL
  477.             | (1L << 21)
  478. #endif
  479.         /* data format [COMPRESS excluded] (27..31) */
  480. #ifdef ZEROCOMP
  481.             | (1L << 27)
  482. #endif
  483. #ifdef RLECOMP
  484.             | (1L << 28)
  485. #endif
  486.             ;
  487.     return;
  488. }
  489.  
  490. void
  491. do_date()
  492. {
  493.     long    clocktim;
  494.     char    cbuf[30], *c;
  495.  
  496.     Sprintf(filename, INCLUDE_TEMPLATE, DATE_FILE);
  497.     if (!(ofp = fopen(filename, WRMODE))) {
  498.         perror(filename);
  499.         exit(1);
  500.     }
  501.     Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.1\t92/04/07 */\n\n");
  502.     Fprintf(ofp,Dont_Edit_Code);
  503.  
  504. #ifdef KR1ED
  505.     (void) time(&clocktim);
  506.     Strcpy(cbuf, ctime(&clocktim));
  507. #else
  508.     (void) time((time_t *)&clocktim);
  509.     Strcpy(cbuf, ctime((time_t *)&clocktim));
  510. #endif
  511.     for(c = cbuf; *c != '\n'; c++);    *c = 0; /* strip off the '\n' */
  512.     Fprintf(ofp,"#define BUILD_DATE \"%s\"\n", cbuf);
  513.     Fprintf(ofp,"#define BUILD_TIME (%ldL)\n", clocktim);
  514.     Fprintf(ofp,"\n");
  515.     Fprintf(ofp,"#define VERSION_NUMBER 0x%08lxL\n", version.incarnation);
  516.     Fprintf(ofp,"#define VERSION_FEATURES 0x%08lxL\n", version.features);
  517.     Fprintf(ofp,"\n");
  518. #ifdef AMIGA
  519.     {
  520.     struct tm *tm = localtime((time_t *) &clocktim);
  521.     Fprintf(ofp,"#ifdef AMIGA\n");
  522.     Fprintf(ofp,"const char amiga_version_string[] = ");
  523.     Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\";\n",
  524.         VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
  525.         tm->tm_mday, tm->tm_mon+1, tm->tm_year);
  526.     Fprintf(ofp,"#endif\n");
  527.     }
  528. #endif
  529.     Fclose(ofp);
  530.     return;
  531. }
  532.  
  533. static const char *build_opts[] = {
  534. #ifdef AMIGA_WBENCH
  535.         "Amiga WorkBench support",
  536. #endif
  537. #ifdef ANSI_DEFAULT
  538.         "ANSI default terminal",
  539. #endif
  540. #ifdef ARMY
  541.         "armies",
  542. #endif
  543. #ifdef TEXTCOLOR
  544.         "color",
  545. #endif
  546. #ifdef COM_COMPL
  547.         "command line completion",
  548. #endif
  549. #ifdef COMPRESS
  550.         "data file compression",
  551. #endif
  552. #ifdef WIZARD
  553.         "debug mode",
  554. #endif
  555. #ifdef ELBERETH
  556.         "Elbereth",
  557. #endif
  558. #ifdef EXP_ON_BOTL
  559.         "experience points on status line",
  560. #endif
  561. #ifdef EXPLORE_MODE
  562.         "explore mode",
  563. #endif
  564. #ifdef MFLOPPY
  565.         "floppy drive support",
  566. #endif
  567. #ifdef TUTTI_FRUTTI
  568.         "fruit names",
  569. #endif
  570. #ifdef INSURANCE
  571.         "insurance against game crashes",
  572. #endif
  573. #ifdef KOPS
  574.         "Keystone Kops",
  575. #endif
  576. #ifdef WALKIES
  577.         "leashes",
  578. #endif
  579. #ifdef LOGFILE
  580.         "log file",
  581. #endif
  582. #ifdef MAIL
  583.         "mail daemon",
  584. #endif
  585. #ifdef MUSE
  586.         "monster item use",
  587. #endif
  588. #ifdef GNUDOS
  589.         "MSDOS protected mode",
  590. #endif
  591. #ifdef NEWS
  592.         "news file",
  593. #endif
  594. #ifdef OVERLAY
  595.         "overlays",
  596. #endif
  597. #ifdef MULDGN
  598.         "quest dungeon",
  599. #endif
  600. #ifdef REDO
  601.         "redo command",
  602. #endif
  603. #ifdef REINCARNATION
  604.         "rogue level",
  605. #endif
  606. #ifdef SCORE_ON_BOTL
  607.         "score on status line",
  608. #endif
  609. #ifdef CLIPPING
  610.         "screen clipping",
  611. #endif
  612. #ifdef NO_TERMS
  613. # ifdef MAC
  614.         "screen control via mactty",
  615. # endif
  616. # ifdef SCREEN_BIOS
  617.         "screen control via BIOS",
  618. # endif
  619. # ifdef SCREEN_DJGPPFAST
  620.         "screen control via DJGPP fast",
  621. # endif
  622. # ifdef WIN32CON
  623.         "screen control via WIN32 console I/O",
  624. # endif
  625. #endif
  626. #ifdef SEDUCE
  627.         "seduction",
  628. #endif
  629. #ifdef POLYSELF
  630.         "self-polymorph",
  631. #endif
  632. #ifdef SHELL
  633.         "shell command",
  634. #endif
  635. #ifdef SINKS
  636.         "sinks",
  637. #endif
  638. #ifdef SOUNDS
  639.         "sounds",
  640. #endif
  641. #ifdef SUSPEND
  642.         "suspend command",
  643. #endif
  644. #ifdef TERMINFO
  645.         "terminal info library",
  646. #else
  647. # if defined(TERMLIB) || (!defined(MICRO) && defined(TTY_GRAPHICS))
  648.         "terminal capability library",
  649. # endif
  650. #endif
  651. #ifdef TOURIST
  652.         "tourists",
  653. #endif
  654. #ifdef VISION_TABLES
  655.         "vision tables",
  656. #endif
  657. #ifdef WALLIFIED_MAZE
  658.         "walled mazes",
  659. #endif
  660. #ifdef ZEROCOMP
  661.         "zero-compressed save files",
  662. #endif
  663.         "basic NetHack features"
  664.     };
  665.  
  666. static const char *window_opts[] = {
  667. #ifdef TTY_GRAPHICS
  668.         "traditional tty-based graphics",
  669. #endif
  670. #ifdef X11_GRAPHICS
  671.         "X11",
  672. #endif
  673. #ifdef MAC
  674.         "Mac",
  675. #endif
  676. #ifdef AMIGA_INTUITION
  677.         "Amiga Intuition",
  678. #endif
  679.         NULL
  680.     };
  681.  
  682. void
  683. do_options()
  684. {
  685.     register int i, length;
  686.     register const char *str, *indent = "    ";
  687.  
  688.     Sprintf(filename, DATA_TEMPLATE, OPTIONS_FILE);
  689.     if (!(ofp = fopen(filename, WRMODE))) {
  690.         perror(filename);
  691.         exit(1);
  692.     }
  693.  
  694.     Fprintf(ofp,
  695. #ifdef BETA
  696.         "\n    NetHack version %d.%d.%d [beta]\n",
  697. #else
  698.         "\n    NetHack version %d.%d.%d\n",
  699. #endif
  700.         VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
  701.  
  702.     Fprintf(ofp,"\nOptions compiled into this edition:\n");
  703.  
  704.     length = COLNO + 1;    /* force 1st item onto new line */
  705.     for (i = 0; i < SIZE(build_opts); i++) {
  706.         str = build_opts[i];
  707.         if (length + strlen(str) > COLNO - 5)
  708.         Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
  709.         else
  710.         Fprintf(ofp," "),  length++;
  711.         Fprintf(ofp,"%s", str),  length += strlen(str);
  712.         Fprintf(ofp,(i < SIZE(build_opts) - 1) ? "," : "."),  length++;
  713.     }
  714.  
  715.     Fprintf(ofp,"\n\nSupported windowing systems:\n");
  716.  
  717.     length = COLNO + 1;    /* force 1st item onto new line */
  718.     for (i = 0; i < SIZE(window_opts) - 1; i++) {
  719.         str = window_opts[i];
  720.         if (length + strlen(str) > COLNO - 5)
  721.         Fprintf(ofp,"\n%s", indent),  length = strlen(indent);
  722.         else
  723.         Fprintf(ofp," "),  length++;
  724.         Fprintf(ofp,"%s", str),  length += strlen(str);
  725.         Fprintf(ofp, ","),  length++;
  726.     }
  727.     Fprintf(ofp, "\n%swith a default of %s.", indent, DEFAULT_WINDOW_SYS);
  728.     Fprintf(ofp,"\n\n");
  729.  
  730.     Fclose(ofp);
  731.     return;
  732. }
  733.  
  734. /* routine to decide whether to discard something from data.base */
  735. static boolean
  736. d_filter(line)
  737.     char *line;
  738. {
  739.     if (*line == '#') return TRUE;    /* ignore comment lines */
  740. #ifndef ARMY
  741.   { static int ignore_army = 0;
  742.  
  743.     switch (ignore_army) {
  744.       case 0:   if (!strcmp(line, "*soldier")) ignore_army = 1;
  745.         break;        /* 0 => not in army related data */
  746.       case 1:   if (*line <= ' ') ignore_army = 2;
  747.         break;        /* 1 => in army name list */
  748.       case 2:   if (*line > ' ')  ignore_army = 0;
  749.         break;        /* 2 => in army descriptive text */
  750.     }
  751.     if (ignore_army) return TRUE;
  752.   }
  753. #endif
  754.     return FALSE;
  755. }
  756.  
  757.    /*
  758.     *
  759.     New format (v3.1) of 'data' file which allows much faster lookups [pr]
  760. "do not edit"        first record is a comment line
  761. 01234567        hexadecimal formatted offset to text area
  762. name-a            first name of interest
  763. 123,4            offset to name's text, and number of lines for it
  764. name-b            next name of interest
  765. name-c            multiple names which share same description also
  766. 456,7            share a single offset,count line
  767. .            sentinel to mark end of names
  768. 789,0            dummy record containing offset,count of EOF
  769. text-a            4 lines of descriptive text for name-a
  770. text-a            at file position 0x01234567L + 123L
  771. text-a
  772. text-a
  773. text-b/text-c        7 lines of text for names-b and -c
  774. text-b/text-c        at fseek(0x01234567L + 456L)
  775. ...
  776.     *
  777.     */
  778.  
  779. void
  780. do_data()
  781. {
  782.     char    infile[30], tempfile[30];
  783.     boolean ok;
  784.     long    txt_offset;
  785.     unsigned entry_cnt, line_cnt;
  786.  
  787.     Sprintf(tempfile, DATA_TEMPLATE, "database.tmp");
  788.     Sprintf(filename, DATA_TEMPLATE, DATA_FILE);
  789.     Strcat(strcpy(infile, filename),
  790. #ifdef SHORT_FILENAMES
  791.         ".bas"
  792. #else
  793.         ".base"
  794. #endif
  795.         );
  796.     if (!(ifp = fopen(infile, RDMODE))) {        /* data.base */
  797.         perror(infile);
  798.         exit(1);
  799.     }
  800.     if (!(ofp = fopen(filename, WRMODE))) {        /* data */
  801.         perror(filename);
  802.         Fclose(ifp);
  803.         exit(1);
  804.     }
  805.     if (!(tfp = fopen(tempfile, WRMODE))) {        /* database.tmp */
  806.         perror(tempfile);
  807.         Fclose(ifp);
  808.         Fclose(ofp);
  809.         Unlink(filename);
  810.         exit(1);
  811.     }
  812.  
  813.     /* output a dummy header record; we'll rewind and overwrite it later */
  814.     Fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, 0L);
  815.  
  816.     entry_cnt = line_cnt = 0;
  817.     /* read through the input file and split it into two sections */
  818.     while (fgets(in_line, sizeof in_line, ifp)) {
  819.         if (d_filter(in_line)) continue;
  820.         if (*in_line > ' ') {    /* got an entry name */
  821.         /* first finish previous entry */
  822.         if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt),  line_cnt = 0;
  823.         /* output the entry name */
  824.         (void) fputs(in_line, ofp);
  825.         entry_cnt++;        /* update number of entries */
  826.         } else if (entry_cnt) {    /* got some descriptive text */
  827.         /* update previous entry with current text offset */
  828.         if (!line_cnt)  Fprintf(ofp, "%ld,", ftell(tfp));
  829.         /* save the text line in the scratch file */
  830.         (void) fputs(in_line, tfp);
  831.         line_cnt++;        /* update line counter */
  832.         }
  833.     }
  834.     /* output an end marker and then record the current position */
  835.     if (line_cnt)  Fprintf(ofp, "%d\n", line_cnt);
  836.     Fprintf(ofp, ".\n%ld,%d\n", ftell(tfp), 0);
  837.     txt_offset = ftell(ofp);
  838.     Fclose(ifp);        /* all done with original input file */
  839.  
  840.     /* reprocess the scratch file; 1st format an error msg, just in case */
  841.     Sprintf(in_line, "rewind of \"%s\"", tempfile);
  842.     if (rewind(tfp) != 0)  goto dead_data;
  843.     /* copy all lines of text from the scratch file into the output file */
  844.     while (fgets(in_line, sizeof in_line, tfp))
  845.         (void) fputs(in_line, ofp);
  846.  
  847.     /* finished with scratch file */
  848.     Fclose(tfp);
  849.     Unlink(tempfile);    /* remove it */
  850.  
  851.     /* update the first record of the output file; prepare error msg 1st */
  852.     Sprintf(in_line, "rewind of \"%s\"", filename);
  853.     ok = (rewind(ofp) == 0);
  854.     if (ok) {
  855.        Sprintf(in_line, "header rewrite of \"%s\"", filename);
  856.        ok = (fprintf(ofp, "%s%08lx\n", Dont_Edit_Data, txt_offset) >= 0);
  857.     }
  858.     if (!ok) {
  859. dead_data:  perror(in_line);    /* report the problem */
  860.         /* close and kill the aborted output file, then give up */
  861.         Fclose(ofp);
  862.         Unlink(filename);
  863.         exit(1);
  864.     }
  865.  
  866.     /* all done */
  867.     Fclose(ofp);
  868.  
  869.     return;
  870. }
  871.  
  872. /* routine to decide whether to discard something from oracles.txt */
  873. static boolean
  874. h_filter(line)
  875.     char *line;
  876. {
  877.     static boolean skip = FALSE;
  878.     char tag[sizeof in_line];
  879.  
  880.     SpinCursor(3);
  881.  
  882.     if (*line == '#') return TRUE;    /* ignore comment lines */
  883.     if (sscanf(line, "----- %s", tag) == 1) {
  884.     skip = FALSE;
  885. #ifndef SINKS
  886.     if (!strcmp(tag, "SINKS")) skip = TRUE;
  887. #endif
  888. #ifndef ELBERETH
  889.     if (!strcmp(tag, "ELBERETH")) skip = TRUE;
  890. #endif
  891.     } else if (skip && !strncmp(line, "-----", 5))
  892.     skip = FALSE;
  893.     return skip;
  894. }
  895.  
  896. static const char *special_oracle[] = {
  897.     "\"...it is rather disconcerting to be confronted with the",
  898.     "following theorem from [Baker, Gill, and Solovay, 1975].",
  899.     "",
  900.     "Theorem 7.18  There exist recursive languages A and B such that",
  901.     "  (1)  P(A) == NP(A), and",
  902.     "  (2)  P(B) != NP(B)",
  903.     "",
  904.     "This provides impressive evidence that the techniques that are",
  905.     "currently available will not suffice for proving that P != NP or          ",
  906.     "that P == NP.\"  [Garey and Johnson, p. 185.]"
  907. };
  908.  
  909. /*
  910.    The oracle file consists of a "do not edit" comment, a decimal count N
  911.    and set of N+1 hexadecimal fseek offsets, followed by N multiple-line
  912.    records, separated by "---" lines.  The first oracle is a special case.
  913.    The input data contains just those multi-line records, separated by
  914.    "-----" lines.
  915.  */
  916.  
  917. void
  918. do_oracles()
  919. {
  920.     char    infile[30], tempfile[30];
  921.     boolean in_oracle, ok;
  922.     long    txt_offset, offset, fpos;
  923.     unsigned oracle_cnt;
  924.     register int i;
  925.  
  926.     Sprintf(tempfile, DATA_TEMPLATE, "oracles.tmp");
  927.     Sprintf(filename, DATA_TEMPLATE, ORACLE_FILE);
  928.     Strcat(strcpy(infile, filename), ".txt");
  929.     if (!(ifp = fopen(infile, RDMODE))) {
  930.         perror(infile);
  931.         exit(1);
  932.     }
  933.     if (!(ofp = fopen(filename, WRMODE))) {
  934.         perror(filename);
  935.         Fclose(ifp);
  936.         exit(1);
  937.     }
  938.     if (!(tfp = fopen(tempfile, WRMODE))) {        /* oracles.tmp */
  939.         perror(tempfile);
  940.         Fclose(ifp);
  941.         Fclose(ofp);
  942.         Unlink(filename);
  943.         exit(1);
  944.     }
  945.  
  946.     /* output a dummy header record; we'll rewind and overwrite it later */
  947.     Fprintf(ofp, "%s%5d\n", Dont_Edit_Data, 0);
  948.  
  949.     /* handle special oracle; it must come first */
  950.     (void) fputs("---\n", tfp);
  951.     Fprintf(ofp, "%05lx\n", ftell(tfp));  /* start pos of special oracle */
  952.     for (i = 0; i < SIZE(special_oracle); i++) {
  953.         (void) fputs(xcrypt(special_oracle[i]), tfp);
  954.         (void) fputc('\n', tfp);
  955.     }
  956.     SpinCursor(3);
  957.  
  958.     oracle_cnt = 1;
  959.     (void) fputs("---\n", tfp);
  960.     Fprintf(ofp, "%05lx\n", ftell(tfp));    /* start pos of first oracle */
  961.     in_oracle = FALSE;
  962.  
  963.     while (fgets(in_line, sizeof in_line, ifp)) {
  964.         SpinCursor(3);
  965.  
  966.         if (h_filter(in_line)) continue;
  967.         if (!strncmp(in_line, "-----", 5)) {
  968.         if (!in_oracle) continue;
  969.         in_oracle = FALSE;
  970.         oracle_cnt++;
  971.         (void) fputs("---\n", tfp);
  972.         Fprintf(ofp, "%05lx\n", ftell(tfp));
  973.         /* start pos of this oracle */
  974.         } else {
  975.         in_oracle = TRUE;
  976.         (void) fputs(xcrypt(in_line), tfp);
  977.         }
  978.     }
  979.  
  980.     if (in_oracle) {    /* need to terminate last oracle */
  981.         oracle_cnt++;
  982.         (void) fputs("---\n", tfp);
  983.         Fprintf(ofp, "%05lx\n", ftell(tfp));    /* eof position */
  984.     }
  985.  
  986.     /* record the current position */
  987.     txt_offset = ftell(ofp);
  988.     Fclose(ifp);        /* all done with original input file */
  989.  
  990.     /* reprocess the scratch file; 1st format an error msg, just in case */
  991.     Sprintf(in_line, "rewind of \"%s\"", tempfile);
  992.     if (rewind(tfp) != 0)  goto dead_data;
  993.     /* copy all lines of text from the scratch file into the output file */
  994.     while (fgets(in_line, sizeof in_line, tfp))
  995.         (void) fputs(in_line, ofp);
  996.  
  997.     /* finished with scratch file */
  998.     Fclose(tfp);
  999.     Unlink(tempfile);    /* remove it */
  1000.  
  1001.     /* update the first record of the output file; prepare error msg 1st */
  1002.     Sprintf(in_line, "rewind of \"%s\"", filename);
  1003.     ok = (rewind(ofp) == 0);
  1004.     if (ok) {
  1005.         Sprintf(in_line, "header rewrite of \"%s\"", filename);
  1006.         ok = (fprintf(ofp, "%s%5d\n", Dont_Edit_Data, (int)oracle_cnt) >=0);
  1007.     }
  1008.     if (ok) {
  1009.         Sprintf(in_line, "data rewrite of \"%s\"", filename);
  1010.         for (i = 0; i <= oracle_cnt; i++) {
  1011. #ifndef VMS    /* alpha/vms v1.0; this fflush seems to confuse ftell */
  1012.         if (!(ok = (fflush(ofp) == 0))) break;
  1013. #endif
  1014.         if (!(ok = (fpos = ftell(ofp)) >= 0)) break;
  1015.         if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
  1016.         if (!(ok = (fscanf(ofp, "%5lx", &offset) == 1))) break;
  1017.         if (!(ok = (fseek(ofp, fpos, SEEK_SET) >= 0))) break;
  1018.         if (!(ok = (fprintf(ofp, "%05lx\n", offset + txt_offset) >= 0)))
  1019.             break;
  1020.         }
  1021.     }
  1022.     if (!ok) {
  1023. dead_data:  perror(in_line);    /* report the problem */
  1024.         /* close and kill the aborted output file, then give up */
  1025.         Fclose(ofp);
  1026.         Unlink(filename);
  1027.         exit(1);
  1028.     }
  1029.  
  1030.     /* all done */
  1031.     Fclose(ofp);
  1032.  
  1033.     return;
  1034. }
  1035.  
  1036.  
  1037. static    struct deflist {
  1038.  
  1039.     const char    *defname;
  1040.     boolean    true_or_false;
  1041. } deflist[] = {
  1042. #ifdef REINCARNATION
  1043.           {    "REINCARNATION", TRUE },
  1044. #else
  1045.           {    "REINCARNATION", FALSE },
  1046. #endif
  1047. #ifdef MULDGN
  1048.           {    "MULDGN", TRUE },
  1049. #else
  1050.           {    "MULDGN", FALSE },
  1051. #endif
  1052.           { 0, 0 } };
  1053.  
  1054. static int
  1055. check_control(s)
  1056.     char    *s;
  1057. {
  1058.     int    i;
  1059.  
  1060.     if(s[0] != '%') return(-1);
  1061.  
  1062.     for(i = 0; deflist[i].defname; i++)
  1063.         if(!strncmp(deflist[i].defname, s+1, strlen(deflist[i].defname)))
  1064.         return(i);
  1065.  
  1066.     return(-1);
  1067. }
  1068.  
  1069. static char *
  1070. without_control(s)
  1071.     char *s;
  1072. {
  1073.     return(s + 1 + strlen(deflist[check_control(in_line)].defname));
  1074. }
  1075.  
  1076. void
  1077. do_dungeon()
  1078. {
  1079.     int rcnt = 0;
  1080.  
  1081.     Sprintf(filename, DATA_TEMPLATE, DGN_I_FILE);
  1082.     if (!(ifp = fopen(filename, RDMODE))) {
  1083.         perror(filename);
  1084.         exit(1);
  1085.     }
  1086.     Sprintf(filename, DATA_TEMPLATE, DGN_O_FILE);
  1087.     if (!(ofp = fopen(filename, WRMODE))) {
  1088.         perror(filename);
  1089.         exit(1);
  1090.     }
  1091.     Fprintf(ofp,Dont_Edit_Data);
  1092.  
  1093.     while(fgets(in_line,sizeof(in_line),ifp) != NULL) {
  1094.  
  1095.         SpinCursor(3);
  1096.  
  1097.         rcnt++;
  1098.         if(in_line[0] == '#') continue;    /* discard comments */
  1099. recheck:
  1100.         if(in_line[0] == '%') {
  1101.         int i = check_control(in_line);
  1102.         if(i >= 0) {
  1103.             if(!deflist[i].true_or_false)  {
  1104.             while(fgets(in_line,sizeof(in_line),ifp))
  1105.                 if(check_control(in_line) != i) goto recheck;
  1106.             } else
  1107.             (void) fputs(without_control(in_line),ofp);
  1108.         } else {
  1109.             Fprintf(stderr, "Unknown control option '%s' in file %s at line %d.\n",
  1110.                 in_line, DGN_I_FILE, rcnt);
  1111.             exit(1);
  1112.         }
  1113.         } else
  1114.         (void) fputs(in_line,ofp);
  1115.     }
  1116.     Fclose(ifp);
  1117.     Fclose(ofp);
  1118.  
  1119.     return;
  1120. }
  1121.  
  1122. static boolean
  1123. ranged_attk(ptr)    /* returns TRUE if monster can attack at range */
  1124.     register struct permonst *ptr;
  1125. {
  1126.     register int    i, j;
  1127.     register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);
  1128.  
  1129.     for(i = 0; i < NATTK; i++) {
  1130.         if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
  1131.         return TRUE;
  1132.     }
  1133.  
  1134.     return(FALSE);
  1135. }
  1136.  
  1137. /* This routine is designed to return an integer value which represents
  1138.  * an approximation of monster strength.  It uses a similar method of
  1139.  * determination as "experience()" to arrive at the strength.
  1140.  */
  1141. static int
  1142. mstrength(ptr)
  1143. struct permonst *ptr;
  1144. {
  1145.     int    i, tmp2, n, tmp = ptr->mlevel;
  1146.  
  1147.     if(tmp > 49)        /* special fixed hp monster */
  1148.         tmp = 2*(tmp - 6) / 4;
  1149.  
  1150. /*    For creation in groups */
  1151.     n = (!!(ptr->geno & G_SGROUP));
  1152.     n += (!!(ptr->geno & G_LGROUP)) << 1;
  1153.  
  1154. /*    For ranged attacks */
  1155.     if (ranged_attk(ptr)) n++;
  1156.  
  1157. /*    For higher ac values */
  1158.     n += (ptr->ac < 4);
  1159.     n += (ptr->ac < 0);
  1160.  
  1161. /*    For very fast monsters */
  1162.     n += (ptr->mmove >= 18);
  1163.  
  1164. /*    For each attack and "special" attack */
  1165.     for(i = 0; i < NATTK; i++) {
  1166.  
  1167.         tmp2 = ptr->mattk[i].aatyp;
  1168.         n += (tmp2 > 0);
  1169.         n += (tmp2 == AT_MAGC);
  1170.         n += (tmp2 == AT_WEAP && (ptr->mflags2 & M2_STRONG));
  1171.     }
  1172.  
  1173. /*    For each "special" damage type */
  1174.     for(i = 0; i < NATTK; i++) {
  1175.  
  1176.         tmp2 = ptr->mattk[i].adtyp;
  1177.         if((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_DRST)
  1178.             || (tmp2 == AD_DRDX) || (tmp2 == AD_DRCO)
  1179. #ifdef POLYSELF
  1180.                     || (tmp2 == AD_WERE)
  1181. #endif
  1182.                                 ) n += 2;
  1183.         else if (strcmp(ptr->mname, "grid bug")) n += (tmp2 != AD_PHYS);
  1184.         n += ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
  1185.     }
  1186.  
  1187. /*    Leprechauns are special cases.  They have many hit dice so they
  1188.     can hit and are hard to kill, but they don't really do much damage. */
  1189.     if (!strcmp(ptr->mname, "leprechaun")) n -= 2;
  1190.  
  1191. /*    Finally, adjust the monster level  0 <= n <= 24 (approx.) */
  1192.     if(n == 0) tmp--;
  1193.     else if(n >= 6) tmp += ( n / 2 );
  1194.     else tmp += ( n / 3 + 1);
  1195.  
  1196.     return((tmp >= 0) ? tmp : 0);
  1197. }
  1198.  
  1199. void
  1200. do_monstr()
  1201. {
  1202.     register struct permonst *ptr;
  1203.     register int i, j;
  1204.  
  1205.     /*
  1206.      * create the source file, "monstr.c"
  1207.      */
  1208.     Sprintf(filename, SOURCE_TEMPLATE, MON_STR_C);
  1209.     if (!(ofp = fopen(filename, WRMODE))) {
  1210.     perror(filename);
  1211.     exit(1);
  1212.     }
  1213.     Fprintf(ofp,Dont_Edit_Code);
  1214.     Fprintf(ofp,"#include \"config.h\"\n");
  1215.     Fprintf(ofp,"\nint monstr[] = {\n");
  1216.     for (ptr = &mons[0], j = 0; ptr->mlet; ptr++) {
  1217.  
  1218.     SpinCursor(3);
  1219.  
  1220.     i = mstrength(ptr);
  1221.     Fprintf(ofp,"%2d,%c", i, (++j & 15) ? ' ' : '\n');
  1222.     }
  1223.     /* might want to insert a final 0 entry here instead of just newline */
  1224.     Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");
  1225.  
  1226.     Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
  1227.     Fprintf(ofp,"\nvoid\n");
  1228.     Fprintf(ofp,"monstr_init()\n");
  1229.     Fprintf(ofp,"{\n");
  1230.     Fprintf(ofp,"    return;\n");
  1231.     Fprintf(ofp,"}\n");
  1232.     Fprintf(ofp,"\n/*monstr.c*/\n");
  1233.  
  1234.     Fclose(ofp);
  1235.     return;
  1236. }
  1237.  
  1238. void
  1239. do_permonst()
  1240. {
  1241.     int    i;
  1242.     char    *c, *nam;
  1243.  
  1244.     Sprintf(filename, INCLUDE_TEMPLATE, MONST_FILE);
  1245.     if (!(ofp = fopen(filename, WRMODE))) {
  1246.         perror(filename);
  1247.         exit(1);
  1248.     }
  1249.     Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.1\t92/01/04 */\n\n");
  1250.     Fprintf(ofp,Dont_Edit_Code);
  1251.     Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n");
  1252.  
  1253.     for(i = 0; mons[i].mlet; i++) {
  1254.  
  1255.         SpinCursor(3);
  1256.  
  1257.         Fprintf(ofp,"\n#define\tPM_");
  1258.         if (mons[i].mlet == S_HUMAN &&
  1259.                 !strncmp(mons[i].mname, "were", 4))
  1260.             Fprintf(ofp, "HUMAN_");
  1261.         for (nam = c = tmpdup(mons[i].mname); *c; c++)
  1262.             if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
  1263.             else if (*c < 'A' || *c > 'Z') *c = '_';
  1264.         Fprintf(ofp,"%s\t%d", nam, i);
  1265.     }
  1266.     Fprintf(ofp,"\n\n#define\tNUMMONS\t%d\n", i);
  1267.     Fprintf(ofp,"\n#endif /* PM_H */\n");
  1268.     Fclose(ofp);
  1269.     return;
  1270. }
  1271.  
  1272. #ifdef MULDGN
  1273. /*    Start of Quest text file processing. */
  1274. #include "qtext.h"
  1275.  
  1276. static struct qthdr    qt_hdr;
  1277. static struct msghdr    msg_hdr[N_HDR];
  1278. static struct qtmsg    *curr_msg;
  1279.  
  1280. static int    qt_line;
  1281.  
  1282. static boolean    in_msg;
  1283. #define    NO_MSG    1    /* strlen of a null line returned by fgets() */
  1284.  
  1285. static boolean
  1286. qt_comment(s)
  1287.  
  1288.     char *s;
  1289. {
  1290.     if(s[0] == '#') return(TRUE);
  1291.     return(!in_msg  && strlen(s) == NO_MSG);
  1292. }
  1293.  
  1294. static boolean
  1295. qt_control(s)
  1296.  
  1297.     char *s;
  1298. {
  1299.     return(s[0] == '%' && (s[1] == 'C' || s[1] == 'E'));
  1300. }
  1301.  
  1302. static int
  1303. get_hdr(c)
  1304.  
  1305.     char c;
  1306. {
  1307.     int    i;
  1308.  
  1309.     for(i = 0; i < qt_hdr.n_hdr; i++)
  1310.         if(c == qt_hdr.id[i]) return (++i);
  1311.  
  1312.     return(0);
  1313. }
  1314.  
  1315. static boolean
  1316. known_id(c)
  1317.  
  1318.     char c;
  1319. {
  1320.     return(get_hdr(c) > 0);
  1321. }
  1322.  
  1323. static boolean
  1324. new_id(c)
  1325.  
  1326.     char c;
  1327. {
  1328.     if(qt_hdr.n_hdr >= N_HDR) {
  1329.  
  1330.         Fprintf(stderr, OUT_OF_HEADERS, qt_line);
  1331.         return(FALSE);
  1332.     }
  1333.  
  1334.     qt_hdr.id[qt_hdr.n_hdr] = c;
  1335.     msg_hdr[qt_hdr.n_hdr].n_msg = 0;
  1336.     qt_hdr.offset[qt_hdr.n_hdr++] = 0L;
  1337.     return(TRUE);
  1338. }
  1339.  
  1340. static boolean
  1341. known_msg(c, s)
  1342.  
  1343.     char c, *s;
  1344. {
  1345.     int i = get_hdr(c) - 1,
  1346.         j, n = atoi(s);
  1347.  
  1348.     for(j = 0; j < msg_hdr[i].n_msg; j++)
  1349.         if(msg_hdr[i].qt_msg[j].msgnum == n) return(TRUE);
  1350.  
  1351.     return(FALSE);
  1352. }
  1353.  
  1354.  
  1355. static void
  1356. new_msg(s)
  1357. char *s;
  1358. {
  1359.     struct    qtmsg    *qt_msg;
  1360.     int    i = get_hdr(s[4]) - 1;
  1361.  
  1362.     if(msg_hdr[i].n_msg >= N_MSG) {
  1363.         Fprintf(stderr, OUT_OF_MESSAGES, qt_line);
  1364.     } else {
  1365.         qt_msg = &(msg_hdr[i].qt_msg[msg_hdr[i].n_msg++]);
  1366.         qt_msg->msgnum = atoi(s+5);
  1367.         qt_msg->delivery = s[2];
  1368.         qt_msg->offset = qt_msg->size = 0L;
  1369.  
  1370.         curr_msg = qt_msg;
  1371.     }
  1372. }
  1373.  
  1374. static void
  1375. do_qt_control(s)
  1376.  
  1377.     char *s;
  1378. {
  1379.     switch(s[1]) {
  1380.  
  1381.         case 'C':    if(in_msg) {
  1382.                 Fprintf(stderr, CREC_IN_MSG, qt_line);
  1383.                 break;
  1384.             } else {
  1385.                 in_msg = TRUE;
  1386.                 if(!known_id(s[4]))
  1387.                 if(!new_id(s[4])) break;
  1388.                 if(known_msg(s[4],&s[5]))
  1389.                 Fprintf(stderr, DUP_MSG, qt_line);
  1390.                 else new_msg(s);
  1391.             }
  1392.             break;
  1393.  
  1394.         case 'E':    if(!in_msg) {
  1395.                 Fprintf(stderr, END_NOT_IN_MSG, qt_line);
  1396.                 break;
  1397.             } else in_msg = FALSE;
  1398.             break;
  1399.  
  1400.         default:    Fprintf(stderr, UNREC_CREC, qt_line);
  1401.             break;
  1402.     }
  1403. }
  1404.  
  1405. static void
  1406. do_qt_text(s)
  1407.  
  1408.     char *s;
  1409. {
  1410.     curr_msg->size += strlen(s);
  1411. }
  1412.  
  1413. static void
  1414. adjust_qt_hdrs() {
  1415.  
  1416.     int    i, j;
  1417.     long    count = 0L,
  1418.         hdr_offset = sizeof(int) +
  1419.                  (sizeof(char) + sizeof(long)) * qt_hdr.n_hdr;
  1420.  
  1421.     for(i = 0; i < qt_hdr.n_hdr; i++) {
  1422.  
  1423.         qt_hdr.offset[i] = hdr_offset;
  1424.         hdr_offset += sizeof(int) + sizeof(struct qtmsg) * msg_hdr[i].n_msg;
  1425.     }
  1426.  
  1427.     for(i = 0; i < qt_hdr.n_hdr; i++)
  1428.         for(j = 0; j < msg_hdr[i].n_msg; j++) {
  1429.  
  1430.         msg_hdr[i].qt_msg[j].offset = hdr_offset + count;
  1431.         count += msg_hdr[i].qt_msg[j].size;
  1432.         }
  1433. }
  1434.  
  1435. static void
  1436. put_qt_hdrs() {
  1437.  
  1438.     int    i;
  1439.  
  1440.     /*
  1441.      *    The main header record.
  1442.      */
  1443. #ifdef DEBUG
  1444.     Fprintf(stderr, "%ld: header info.\n", ftell(ofp));
  1445. #endif
  1446.     (void) fwrite(&(qt_hdr.n_hdr), sizeof(int), 1, ofp);
  1447.     (void) fwrite(&(qt_hdr.id[0]), sizeof(char), qt_hdr.n_hdr, ofp);
  1448.     (void) fwrite(&(qt_hdr.offset[0]), sizeof(long), qt_hdr.n_hdr, ofp);
  1449. #ifdef DEBUG
  1450.     for(i = 0; i < qt_hdr.n_hdr; i++)
  1451.         Fprintf(stderr, "%c @ %ld, ", qt_hdr.id[i], qt_hdr.offset[i]);
  1452.  
  1453.     Fprintf(stderr, "\n");
  1454. #endif
  1455.  
  1456.     /*
  1457.      *    The individual class headers.
  1458.      */
  1459.     for(i = 0; i < qt_hdr.n_hdr; i++) {
  1460.  
  1461. #ifdef DEBUG
  1462.         Fprintf(stderr, "%ld: %c header info.\n", ftell(ofp),
  1463.             qt_hdr.id[i]);
  1464. #endif
  1465.         (void) fwrite(&(msg_hdr[i].n_msg), sizeof(int), 1, ofp);
  1466.         (void) fwrite(&(msg_hdr[i].qt_msg[0]), sizeof(struct qtmsg),
  1467.            msg_hdr[i].n_msg, ofp);
  1468. #ifdef DEBUG
  1469.         { int j;
  1470.           for(j = 0; j < msg_hdr[i].n_msg; j++)
  1471.         Fprintf(stderr, "msg %d @ %ld (%ld)\n",
  1472.             msg_hdr[i].qt_msg[j].msgnum,
  1473.             msg_hdr[i].qt_msg[j].offset,
  1474.             msg_hdr[i].qt_msg[j].size);
  1475.         }
  1476. #endif
  1477.     }
  1478. }
  1479.  
  1480. void
  1481. do_questtxt()
  1482. {
  1483.     Sprintf(filename, DATA_TEMPLATE, QTXT_I_FILE);
  1484.     if(!(ifp = fopen(filename, RDMODE))) {
  1485.         perror(filename);
  1486.         exit(1);
  1487.     }
  1488.  
  1489.     Sprintf(filename, DATA_TEMPLATE, QTXT_O_FILE);
  1490.     if(!(ofp = fopen(filename, WRBMODE))) {
  1491.         perror(filename);
  1492.         Fclose(ifp);
  1493.         exit(1);
  1494.     }
  1495.  
  1496.     qt_hdr.n_hdr = 0;
  1497.     qt_line = 0;
  1498.     in_msg = FALSE;
  1499.  
  1500.     while(fgets(in_line, 80, ifp) != NULL) {
  1501.  
  1502.         SpinCursor (3);
  1503.  
  1504.         qt_line++;
  1505.         if(qt_control(in_line)) do_qt_control(in_line);
  1506.         else if(qt_comment(in_line)) continue;
  1507.         else            do_qt_text(in_line);
  1508.     }
  1509.  
  1510.     (void) rewind(ifp);
  1511.     in_msg = FALSE;
  1512.     adjust_qt_hdrs(); put_qt_hdrs();
  1513.     while(fgets(in_line, 80, ifp) != NULL) {
  1514.  
  1515.         if(qt_control(in_line)) {
  1516.             in_msg = (in_line[1] == 'C');
  1517.             continue;
  1518.         } else if(qt_comment(in_line)) continue;
  1519. #ifdef DEBUG
  1520.         Fprintf(stderr, "%ld: %s", ftell(stdout), in_line);
  1521. #endif
  1522.         (void) fputs(xcrypt(in_line), ofp);
  1523.     }
  1524.     Fclose(ifp);
  1525.     Fclose(ofp);
  1526.     return;
  1527. }
  1528. #else    /* not MULDGN */
  1529.  
  1530. void
  1531. do_questtxt()
  1532. {
  1533.     Fprintf(stderr, "makedefs: `-q' option ignored.\n");
  1534.     /* create an empty file to satisfy `make' */
  1535.     Sprintf(filename, DATA_TEMPLATE, QTXT_O_FILE);
  1536.     ofp = fopen(filename, WRBMODE);
  1537.     Fclose(ofp);
  1538.     return;
  1539. }
  1540.  
  1541. #endif /* MULDGN */
  1542.  
  1543. static    char    temp[32];
  1544.  
  1545. static char *
  1546. limit(name,pref)    /* limit a name to 30 characters length */
  1547. char    *name;
  1548. int    pref;
  1549. {
  1550.     (void) strncpy(temp, name, pref ? 26 : 30);
  1551.     temp[pref ? 26 : 30] = 0;
  1552.     return temp;
  1553. }
  1554.  
  1555. void
  1556. do_objs()
  1557. {
  1558.     int i, sum = 0;
  1559.     char *c, *objnam;
  1560.     int nspell = 0;
  1561.     int prefix = 0;
  1562.     char class = '\0';
  1563.     boolean    sumerr = FALSE;
  1564.  
  1565.     Sprintf(filename, INCLUDE_TEMPLATE, ONAME_FILE);
  1566.     if (!(ofp = fopen(filename, WRMODE))) {
  1567.         perror(filename);
  1568.         exit(1);
  1569.     }
  1570.     Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.1\t92/11/01 */\n\n");
  1571.     Fprintf(ofp,Dont_Edit_Code);
  1572.     Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n");
  1573.  
  1574.     for(i = 0; !i || objects[i].oc_class != ILLOBJ_CLASS; i++) {
  1575.         SpinCursor(3);
  1576.  
  1577.         objects[i].oc_name_idx = objects[i].oc_descr_idx = i;    /* init */
  1578.         if (!(objnam = tmpdup(OBJ_NAME(objects[i])))) continue;
  1579.  
  1580.         /* make sure probabilities add up to 1000 */
  1581.         if(objects[i].oc_class != class) {
  1582.             if (sum && sum != 1000) {
  1583.                 Fprintf(stderr, "prob error for class %d (%d%%)",
  1584.                     class, sum);
  1585.                 (void) fflush(stderr);
  1586.                 sumerr = TRUE;
  1587.             }
  1588.             class = objects[i].oc_class;
  1589.             sum = 0;
  1590.         }
  1591.  
  1592.         for (c = objnam; *c; c++)
  1593.             if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
  1594.             else if (*c < 'A' || *c > 'Z') *c = '_';
  1595.  
  1596.         switch (class) {
  1597.             case WAND_CLASS:
  1598.             Fprintf(ofp,"#define\tWAN_"); prefix = 1; break;
  1599.             case RING_CLASS:
  1600.             Fprintf(ofp,"#define\tRIN_"); prefix = 1; break;
  1601.             case POTION_CLASS:
  1602.             Fprintf(ofp,"#define\tPOT_"); prefix = 1; break;
  1603.             case SPBOOK_CLASS:
  1604.             Fprintf(ofp,"#define\tSPE_"); prefix = 1; nspell++; break;
  1605.             case SCROLL_CLASS:
  1606.             Fprintf(ofp,"#define\tSCR_"); prefix = 1; break;
  1607.             case AMULET_CLASS:
  1608.             /* avoid trouble with stupid C preprocessors */
  1609.             Fprintf(ofp,"#define\t");
  1610.             if(objects[i].oc_material == PLASTIC) {
  1611.                 Fprintf(ofp,"FAKE_AMULET_OF_YENDOR\t%d\n", i);
  1612.                 prefix = -1;
  1613.                 break;
  1614.             }
  1615.             break;
  1616.             case GEM_CLASS:
  1617.             /* avoid trouble with stupid C preprocessors */
  1618.             if(objects[i].oc_material == GLASS) {
  1619.                 Fprintf(ofp,"/* #define\t%s\t%d */\n",
  1620.                             objnam, i);
  1621.                 prefix = -1;
  1622.                 break;
  1623.             }
  1624.             default:
  1625.             Fprintf(ofp,"#define\t");
  1626.         }
  1627.         if (prefix >= 0)
  1628.             Fprintf(ofp,"%s\t%d\n", limit(objnam, prefix), i);
  1629.         prefix = 0;
  1630.  
  1631.         sum += objects[i].oc_prob;
  1632.     }
  1633.  
  1634.     /* check last set of probabilities */
  1635.     if (sum && sum != 1000) {
  1636.         Fprintf(stderr, "prob error for class %d (%d%%)", class, sum);
  1637.         (void) fflush(stderr);
  1638.         sumerr = TRUE;
  1639.     }
  1640.  
  1641.     Fprintf(ofp,"#define\tLAST_GEM\t(JADE)\n");
  1642.     Fprintf(ofp,"#define\tMAXSPELL\t%d\n", nspell+1);
  1643.     Fprintf(ofp,"#define\tNROFOBJECTS\t%d\n", i-1);
  1644.  
  1645.     Fprintf(ofp, "\n/* Artifacts (unique objects) */\n\n");
  1646.  
  1647.     for (i = 1; artifact_names[i]; i++) {
  1648.         SpinCursor(3);
  1649.  
  1650.         for (c = objnam = tmpdup(artifact_names[i]); *c; c++)
  1651.             if (*c >= 'a' && *c <= 'z') *c -= (char)('a' - 'A');
  1652.             else if (*c < 'A' || *c > 'Z') *c = '_';
  1653.  
  1654.         if (!strncmp(objnam, "THE_", 4))
  1655.             objnam += 4;
  1656. #ifdef TOURIST
  1657.         /* fudge _platinum_ YENDORIAN EXPRESS CARD */
  1658.         if (!strncmp(objnam, "PLATINUM_", 9))
  1659.             objnam += 9;
  1660. #endif
  1661.         Fprintf(ofp,"#define\tART_%s\t%d\n", limit(objnam, 1), i);
  1662.     }
  1663.  
  1664.     Fprintf(ofp, "#define\tNROFARTIFACTS\t%d\n", i-1);
  1665.     Fprintf(ofp,"\n#endif /* ONAMES_H */\n");
  1666.     Fclose(ofp);
  1667.     if (sumerr) exit(1);
  1668.     return;
  1669. }
  1670.  
  1671. static char *
  1672. tmpdup(str)
  1673. const char *str;
  1674. {
  1675.     static char buf[128];
  1676.  
  1677.     if (!str) return (char *)0;
  1678.     (void)strncpy(buf, str, 127);
  1679.     return buf;
  1680. }
  1681.  
  1682.  
  1683. /*
  1684.  * macros used to control vision algorithms:
  1685.  *      VISION_TABLES => generate tables
  1686.  *      BRACES        => table elements should be enclosed in "{ }"
  1687.  */
  1688.  
  1689. void
  1690. do_vision()
  1691. {
  1692. #ifdef VISION_TABLES
  1693.     int i, j;
  1694.  
  1695.     /* Everything is clear.  xclear may be malloc'ed.
  1696.      * Block the upper left corner (BLOCK_HEIGHTxBLOCK_WIDTH)
  1697.      */
  1698.     for (i = 0; i < MAX_ROW; i++)
  1699.     for (j = 0; j < MAX_COL; j++)
  1700.         if (i < BLOCK_HEIGHT && j < BLOCK_WIDTH)
  1701.         xclear[i][j] = '\000';
  1702.         else
  1703.         xclear[i][j] = '\001';
  1704. #endif /* VISION_TABLES */
  1705.  
  1706.     SpinCursor(3);
  1707.  
  1708.     /*
  1709.      * create the include file, "vis_tab.h"
  1710.      */
  1711.     Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
  1712.     if (!(ofp = fopen(filename, WRMODE))) {
  1713.     perror(filename);
  1714.     exit(1);
  1715.     }
  1716.     Fprintf(ofp,Dont_Edit_Code);
  1717.     Fprintf(ofp,"#ifdef VISION_TABLES\n");
  1718. #ifdef VISION_TABLES
  1719.     H_close_gen();
  1720.     H_far_gen();
  1721. #endif /* VISION_TABLES */
  1722.     Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
  1723.     Fclose(ofp);
  1724.  
  1725.     SpinCursor(3);
  1726.  
  1727.     /*
  1728.      * create the source file, "vis_tab.c"
  1729.      */
  1730.     Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
  1731.     if (!(ofp = fopen(filename, WRMODE))) {
  1732.     perror(filename);
  1733.     Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
  1734.     Unlink(filename);
  1735.     exit(1);
  1736.     }
  1737.     Fprintf(ofp,Dont_Edit_Code);
  1738.     Fprintf(ofp,"#include \"config.h\"\n");
  1739.     Fprintf(ofp,"#ifdef VISION_TABLES\n");
  1740.     Fprintf(ofp,"#include \"vis_tab.h\"\n");
  1741.  
  1742.     SpinCursor(3);
  1743.  
  1744. #ifdef VISION_TABLES
  1745.     C_close_gen();
  1746.     C_far_gen();
  1747.     Fprintf(ofp,"\nvoid vis_tab_init() { return; }\n");
  1748. #endif /* VISION_TABLES */
  1749.  
  1750.     SpinCursor(3);
  1751.  
  1752.     Fprintf(ofp,"\n#endif /* VISION_TABLES */\n");
  1753.     Fprintf(ofp,"\n/*vis_tab.c*/\n");
  1754.  
  1755.     Fclose(ofp);
  1756.     return;
  1757. }
  1758.  
  1759. #ifdef VISION_TABLES
  1760.  
  1761. /*--------------  vision tables  --------------*\
  1762.  *
  1763.  *  Generate the close and far tables.  This is done by setting up a
  1764.  *  fake dungeon and moving our source to different positions relative
  1765.  *  to a block and finding the first/last visible position.  The fake
  1766.  *  dungeon is all clear execpt for the upper left corner (BLOCK_HEIGHT
  1767.  *  by BLOCK_WIDTH) is blocked.  Then we move the source around relative
  1768.  *  to the corner of the block.  For each new position of the source
  1769.  *  we check positions on rows "kittycorner" from the source.  We check
  1770.  *  positions until they are either in sight or out of sight (depends on
  1771.  *  which table we are generating).  The picture below shows the setup
  1772.  *  for the generation of the close table.  The generation of the far
  1773.  *  table would switch the quadrants of the '@' and the "Check rows
  1774.  *  here".
  1775.  *
  1776.  *
  1777.  *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
  1778.  *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
  1779.  *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,, Check rows here ,,,,,,,,,,,,
  1780.  *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
  1781.  *  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXB,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
  1782.  *  ...............................
  1783.  *  ...............................
  1784.  *  .........@.....................
  1785.  *  ...............................
  1786.  *
  1787.  *      Table generation figure (close_table).  The 'X's are blocked points.
  1788.  *      The 'B' is a special blocked point.  The '@' is the source.  The ','s
  1789.  *      are the target area.  The '.' are just open areas.
  1790.  *
  1791.  *
  1792.  *  Example usage of close_table[][][].
  1793.  *
  1794.  *  The table is as follows:
  1795.  *
  1796.  *      dy = |row of '@' - row of 'B'|  - 1
  1797.  *      dx = |col of '@' - col of 'B'|
  1798.  *
  1799.  *  The first indices are the deltas from the source '@' and the block 'B'.
  1800.  *  You must check for the value inside the abs value bars being zero.  If
  1801.  *  so then the block is on the same row and you don't need to do a table
  1802.  *  lookup.  The last value:
  1803.  *
  1804.  *      dcy = |row of block - row to be checked|
  1805.  *
  1806.  *  Is the value of the first visible spot on the check row from the
  1807.  *  block column.  So
  1808.  *
  1809.  *  first visible col = close_table[dy][dx][dcy] + col of 'B'
  1810.  *
  1811. \*--------------  vision tables  --------------*/
  1812.  
  1813. static void
  1814. H_close_gen()
  1815. {
  1816.     Fprintf(ofp,"\n/* Close */\n");
  1817.     Fprintf(ofp,"#define CLOSE_MAX_SB_DY %2d\t/* |src row - block row| - 1\t*/\n",
  1818.         TEST_HEIGHT-1);
  1819.     Fprintf(ofp,"#define CLOSE_MAX_SB_DX %2d\t/* |src col - block col|\t*/\n",
  1820.         TEST_WIDTH);
  1821.     Fprintf(ofp,"#define CLOSE_MAX_BC_DY %2d\t/* |block row - check row|\t*/\n",
  1822.         TEST_HEIGHT);
  1823.     Fprintf(ofp,"typedef struct {\n");
  1824.     Fprintf(ofp,"    unsigned char close[CLOSE_MAX_SB_DX][CLOSE_MAX_BC_DY];\n");
  1825.     Fprintf(ofp,"} close2d;\n");
  1826.     Fprintf(ofp,"extern close2d close_table[CLOSE_MAX_SB_DY];\n");
  1827.     return;
  1828. }
  1829.  
  1830. static void
  1831. H_far_gen()
  1832. {
  1833.     Fprintf(ofp,"\n/* Far */\n");
  1834.     Fprintf(ofp,"#define FAR_MAX_SB_DY %2d\t/* |src row - block row|\t*/\n",
  1835.         TEST_HEIGHT);
  1836.     Fprintf(ofp,"#define FAR_MAX_SB_DX %2d\t/* |src col - block col| - 1\t*/\n",
  1837.         TEST_WIDTH-1);
  1838.     Fprintf(ofp,"#define FAR_MAX_BC_DY %2d\t/* |block row - check row| - 1\t*/\n",
  1839.         TEST_HEIGHT-1);
  1840.     Fprintf(ofp,"typedef struct {\n");
  1841.     Fprintf(ofp,"    unsigned char far_q[FAR_MAX_SB_DX][FAR_MAX_BC_DY];\n");
  1842.     Fprintf(ofp,"} far2d;\n");
  1843.     Fprintf(ofp,"extern far2d far_table[FAR_MAX_SB_DY];\n");
  1844.     return;
  1845. }
  1846.  
  1847. # ifdef BRACES
  1848. #  define L_BRACE "{"
  1849. #  define R_BRACE "},"
  1850. # else
  1851. #  define L_BRACE ""
  1852. #  define R_BRACE ""
  1853. # endif /* BRACES */
  1854.  
  1855. static void
  1856. C_close_gen()
  1857. {
  1858.     int i,dx,dy;
  1859.     int src_row, src_col;    /* source */
  1860.     int block_row, block_col;    /* block */
  1861.     int this_row;
  1862.     int no_more;
  1863.  
  1864.     block_row = BLOCK_HEIGHT-1;
  1865.     block_col = BLOCK_WIDTH-1;
  1866.  
  1867.     Fprintf(ofp,"\n#ifndef FAR_TABLE_ONLY\n");
  1868.     Fprintf(ofp,"\nclose2d close_table[CLOSE_MAX_SB_DY] = {\n");
  1869. #ifndef no_vision_progress
  1870.     Fprintf(stderr,"\nclose:");
  1871. #endif
  1872.  
  1873.     for (dy = 1; dy < TEST_HEIGHT; dy++) {
  1874.     src_row = block_row + dy;
  1875.     Fprintf(ofp,"/* DY = %2d (- 1)*/\n  {\n",dy);
  1876. #ifndef no_vision_progress
  1877.     Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
  1878. #endif
  1879.     for (dx = 0; dx < TEST_WIDTH; dx++) {
  1880.         src_col = block_col - dx;
  1881.         Fprintf(ofp,"  /*%2d*/  %s",dx, L_BRACE);
  1882.  
  1883.         no_more = 0;
  1884.         for (this_row = 0; this_row < TEST_HEIGHT; this_row++) {
  1885.         if (no_more) {
  1886.             Fprintf(ofp,CLOSE_OFF_TABLE_STRING);
  1887.             continue;
  1888.         }
  1889.  
  1890.         SpinCursor(3);
  1891.  
  1892.         /* Find the first column that we can see. */
  1893.         for (i = block_col+1; i < MAX_COL; i++) {
  1894.  
  1895.             if (clear_path(src_row,src_col,block_row-this_row,i))
  1896.             break;
  1897.         }
  1898.  
  1899.         if (i == MAX_COL) no_more = 1;
  1900.         Fprintf(ofp,"%2d,",i-block_col);
  1901.         }
  1902.         Fprintf(ofp,"%s\n", R_BRACE);
  1903.     }
  1904.     Fprintf(ofp,"  },\n");
  1905.     }
  1906.  
  1907.     Fprintf(ofp,"}; /* close_table[] */\n");        /* closing brace for table */
  1908.     Fprintf(ofp,"#endif /* !FAR_TABLE_ONLY */\n");
  1909. #ifndef no_vision_progress
  1910.     Fprintf(stderr,"\n");
  1911. #endif
  1912.     return;
  1913. }
  1914.  
  1915. static void
  1916. C_far_gen()
  1917. {
  1918.     int i,dx,dy;
  1919.     int src_row, src_col;    /* source */
  1920.     int block_row, block_col;    /* block */
  1921.     int this_row;
  1922.  
  1923.     block_row = BLOCK_HEIGHT-1;
  1924.     block_col = BLOCK_WIDTH-1;
  1925.  
  1926.     Fprintf(ofp,"\n#ifndef CLOSE_TABLE_ONLY\n");
  1927.     Fprintf(ofp,"\nfar2d far_table[FAR_MAX_SB_DY] = {\n");
  1928. #ifndef no_vision_progress
  1929.     Fprintf(stderr,"\n_far_:");
  1930. #endif
  1931.  
  1932.     for (dy = 0; dy < TEST_HEIGHT; dy++) {
  1933.     src_row = block_row - dy;
  1934.     Fprintf(ofp,"/* DY = %2d */\n  {\n",dy);
  1935. #ifndef no_vision_progress
  1936.     Fprintf(stderr," %2d",dy),  (void)fflush(stderr);
  1937. #endif
  1938.     for (dx = 1; dx < TEST_WIDTH; dx++) {
  1939.         src_col = block_col + dx;
  1940.         Fprintf(ofp,"  /*%2d(-1)*/ %s",dx, L_BRACE);
  1941.  
  1942.         for (this_row = block_row+1; this_row < block_row+TEST_HEIGHT;
  1943.                                 this_row++) {
  1944.         /* Find first col that we can see. */
  1945.         for (i = 0; i <= block_col; i++) {
  1946.  
  1947.             SpinCursor(3);
  1948.  
  1949.             if (clear_path(src_row,src_col,this_row,i)) break;
  1950.         }
  1951.  
  1952.         if (block_col-i < 0)
  1953.             Fprintf(ofp,FAR_OFF_TABLE_STRING);
  1954.         else
  1955.             Fprintf(ofp,"%2d,",block_col-i);
  1956.         }
  1957.         Fprintf(ofp,"%s\n", R_BRACE);
  1958.     }
  1959.     Fprintf(ofp,"  },\n");
  1960.     }
  1961.  
  1962.     Fprintf(ofp,"}; /* far_table[] */\n");    /* closing brace for table */
  1963.     Fprintf(ofp,"#endif /* !CLOSE_TABLE_ONLY */\n");
  1964. #ifndef no_vision_progress
  1965.     Fprintf(stderr,"\n");
  1966. #endif
  1967.     return;
  1968. }
  1969.  
  1970. /*
  1971.  *  "Draw" a line from the hero to the given location.  Stop of we hit a
  1972.  *  wall.
  1973.  *
  1974.  *  Generalized integer Bresenham's algorithm (fast line drawing) for
  1975.  *  all quadrants.  From _Procedural Elements for Computer Graphics_, by
  1976.  *  David F. Rogers.  McGraw-Hill, 1985.
  1977.  *
  1978.  *  I have tried a little bit of optimization by pulling compares out of
  1979.  *  the inner loops.
  1980.  *
  1981.  *  NOTE:  This had better *not* be called from a position on the
  1982.  *  same row as the hero.
  1983.  */
  1984. static int
  1985. clear_path(you_row,you_col,y2,x2)
  1986.     int you_row, you_col, y2, x2;
  1987. {
  1988.     int dx, dy, s1, s2;
  1989.     register int i, error, x, y, dxs, dys;
  1990.  
  1991.     x  = you_col;        y  = you_row;
  1992.     dx = abs(x2-you_col);    dy = abs(y2-you_row);
  1993.     s1 = sign(x2-you_col);    s2 = sign(y2-you_row);
  1994.  
  1995.     if (s1 == 0) {    /* same column */
  1996.     if (s2 == 1) {    /* below (larger y2 value) */
  1997.         for (i = you_row+1; i < y2; i++)
  1998.         if (!xclear[i][you_col]) return 0;
  1999.     } else {    /* above (smaller y2 value) */
  2000.         for (i = y2+1; i < you_row; i++)
  2001.         if (!xclear[i][you_col]) return 0;
  2002.     }
  2003.     return 1;
  2004.     }
  2005.  
  2006.     /*
  2007.      *  Lines at 0 and 90 degrees have been weeded out.
  2008.      */
  2009.     if (dy > dx) {
  2010.     error = dx; dx = dy; dy = error;    /* swap the values */
  2011.     dxs = dx << 1;        /* save the shifted values */
  2012.     dys = dy << 1;
  2013.     error = dys - dx;    /* NOTE: error is used as a temporary above */
  2014.  
  2015.     for (i = 0; i < dx; i++) {
  2016.         if (!xclear[y][x]) return 0;    /* plot point */
  2017.  
  2018.         while (error >= 0) {
  2019.         x += s1;
  2020.         error -= dxs;
  2021.         }
  2022.         y += s2;
  2023.         error += dys;
  2024.     }
  2025.     } else {
  2026.     dxs = dx << 1;        /* save the shifted values */
  2027.     dys = dy << 1;
  2028.     error = dys - dx;
  2029.  
  2030.     for (i = 0; i < dx; i++) {
  2031.         if (!xclear[y][x]) return 0;    /* plot point */
  2032.  
  2033.         while (error >= 0) {
  2034.         y += s2;
  2035.         error -= dxs;
  2036.         }
  2037.         x += s1;
  2038.         error += dys;
  2039.     }
  2040.     }
  2041.     return 1;
  2042. }
  2043. #endif /* VISION_TABLES */
  2044.  
  2045. /*makedefs.c*/
  2046.