]> granicus.if.org Git - nethack/commitdiff
Merge branch 'NetHack-3.6'
authornhmall <nhmall@nethack.org>
Fri, 6 Dec 2019 21:48:00 +0000 (16:48 -0500)
committernhmall <nhmall@nethack.org>
Fri, 6 Dec 2019 21:48:00 +0000 (16:48 -0500)
1  2 
include/global.h
src/mdlib.c
src/sys.c

Simple merge
diff --cc src/mdlib.c
index 54ad8f43707cab64f974e59a6742bf2b2eb581a7,0000000000000000000000000000000000000000..b749b18e002b4893d6872c2316ee6a227e766ab3
mode 100644,000000..100644
--- /dev/null
@@@ -1,803 -1,0 +1,807 @@@
-     char betabuf[64];
 +/* NetHack 3.7  mdlib.c  $NHDT-Date: 1575161954 2019/12/01 00:59:14 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.6 $ */
 +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 +/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 +/* Copyright (c) M. Stephenson, 1990, 1991.                       */
 +/* Copyright (c) Dean Luick, 1990.                                */
 +/* NetHack may be freely redistributed.  See license for details. */
 +
 +/*
 + * This can be linked into a binary to provide the functionality
 + * via the contained functions, or it can be #included directly
 + * into util/makedefs.c to provide it there.
 + */
 +
 +#ifndef MAKEDEFS_C
 +#define MDLIB_C
 +#include "config.h"
 +#ifdef MONITOR_HEAP
 +#undef free /* makedefs, mdlib don't use the alloc and free in src/alloc.c */
 +#endif
 +#include "permonst.h"
 +#include "objclass.h"
 +#include "monsym.h"
 +#include "artilist.h"
 +#include "dungeon.h"
 +#include "obj.h"
 +#include "monst.h"
 +#include "you.h"
 +#include "context.h"
 +#include "flag.h"
 +#include "dlb.h"
 +#include <ctype.h>
 +/* version information */
 +#ifdef SHORT_FILENAMES
 +#include "patchlev.h"
 +#else
 +#include "patchlevel.h"
 +#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  /* AMIGA || AZTEC_C */
 +#else
 +#ifndef GLOBAL_H
 +#include "global.h"
 +#endif
 +#endif  /* !MAKEDEFS_C */
 +
 +#if defined(MAKEDEFS_C) || defined(CROSSCOMPILE_TARGET)
 +/* REPRODUCIBLE_BUILD will change this to TRUE */
 +static boolean date_via_env = FALSE;
 +
 +static char *FDECL(version_string, (char *, const char *));
 +static char *FDECL(version_id_string, (char *, const char *));
 +static char *FDECL(bannerc_string, (char *, const char *));
 +
 +static int FDECL(case_insensitive_comp, (const char *, const char *));
 +static void NDECL(make_version);
 +static char *FDECL(eos, (char *));
 +#endif /* MAKEDEFS_C || CROSSCOMPILE_TARGET */
 +
 +void NDECL(build_options);
 +static void FDECL(opt_out_words, (char *, int *));
 +static void NDECL(build_savebones_compat_string);
 +static int idxopttext, done_runtime_opt_init_once = 0;
 +#define MAXOPT 40
 +static char rttimebuf[MAXOPT];
 +static char *opttext[120] = { 0 };
 +char optbuf[BUFSZ];
 +static struct version_info version;
 +static const char opt_indent[] = "    ";
 +
 +struct win_info {
 +    const char *id, /* DEFAULT_WINDOW_SYS string */
 +        *name;      /* description, often same as id */
 +};
 +
 +static struct win_info window_opts[] = {
 +#ifdef TTY_GRAPHICS
 +    { "tty",
 +      /* testing 'USE_TILES' here would bring confusion because it could
 +         apply to another interface such as X11, so check MSDOS explicitly
 +         instead; even checking TTY_TILES_ESCCODES would probably be
 +         confusing to most users (and it will already be listed separately
 +         in the compiled options section so users aware of it can find it) */
 +#ifdef MSDOS
 +      "traditional text with optional 'tiles' graphics"
 +#else
 +      /* assume that one or more of IBMgraphics, DECgraphics, or MACgraphics
 +         can be enabled; we can't tell from here whether that is accurate */
 +      "traditional text with optional line-drawing"
 +#endif
 +    },
 +#endif /*TTY_GRAPHICS */
 +#ifdef CURSES_GRAPHICS
 +    { "curses", "terminal-based graphics" },
 +#endif
 +#ifdef X11_GRAPHICS
 +    { "X11", "X11" },
 +#endif
 +#ifdef QT_GRAPHICS /* too vague; there are multiple incompatible versions */
 +    { "Qt", "Qt" },
 +#endif
 +#ifdef GNOME_GRAPHICS /* unmaintained/defunct */
 +    { "Gnome", "Gnome" },
 +#endif
 +#ifdef MAC /* defunct OS 9 interface */
 +    { "mac", "Mac" },
 +#endif
 +#ifdef AMIGA_INTUITION /* unmaintained/defunct */
 +    { "amii", "Amiga Intuition" },
 +#endif
 +#ifdef GEM_GRAPHICS /* defunct Atari interface */
 +    { "Gem", "Gem" },
 +#endif
 +#ifdef MSWIN_GRAPHICS /* win32 */
 +    { "mswin", "mswin" },
 +#endif
 +#ifdef BEOS_GRAPHICS /* unmaintained/defunct */
 +    { "BeOS", "BeOS InterfaceKit" },
 +#endif
 +    { 0, 0 }
 +};
 +
 +/*
 + * Use this to explicitly mask out features during version checks.
 + *
 + * ZEROCOMP, RLECOMP, and ZLIB_COMP describe compression features
 + * that the port/plaform which wrote the savefile was capable of
 + * dealing with. Don't reject a savefile just because the port
 + * reading the savefile doesn't match on all/some of them.
 + * The actual compression features used to produce the savefile are
 + * recorded in the savefile_info structure immediately following the
 + * version_info, and that is what needs to be checked against the
 + * feature set of the port that is reading the savefile back in.
 + * That check is done in src/restore.c now.
 + *
 + */
 +#ifndef MD_IGNORED_FEATURES
 +#define MD_IGNORED_FEATURES              \
 +    (0L | (1L << 19) /* SCORE_ON_BOTL */ \
 +     | (1L << 27)    /* ZEROCOMP */      \
 +     | (1L << 28)    /* RLECOMP */       \
 +     )
 +#endif /* MD_IGNORED_FEATUES */
 +
 +static void
 +make_version()
 +{
 +    register int i;
 +
 +    /*
 +     * integer version number
 +     */
 +    version.incarnation = ((unsigned long) VERSION_MAJOR << 24)
 +                          | ((unsigned long) VERSION_MINOR << 16)
 +                          | ((unsigned long) PATCHLEVEL << 8)
 +                          | ((unsigned long) EDITLEVEL);
 +    /*
 +     * encoded feature list
 +     * Note:  if any of these magic numbers are changed or reassigned,
 +     * EDITLEVEL in patchlevel.h should be incremented at the same time.
 +     * The actual values have no special meaning, and the category
 +     * groupings are just for convenience.
 +     */
 +    version.feature_set = (unsigned long) (0L
 +/* levels and/or topology (0..4) */
 +/* monsters (5..9) */
 +#ifdef MAIL_STRUCTURES
 +                                           | (1L << 6)
 +#endif
 +/* objects (10..14) */
 +/* flag bits and/or other global variables (15..26) */
 +#ifdef TEXTCOLOR
 +                                           | (1L << 17)
 +#endif
 +#ifdef INSURANCE
 +                                           | (1L << 18)
 +#endif
 +#ifdef SCORE_ON_BOTL
 +                                           | (1L << 19)
 +#endif
 +/* data format (27..31)
 + * External compression methods such as COMPRESS and ZLIB_COMP
 + * do not affect the contents and are thus excluded from here */
 +#ifdef ZEROCOMP
 +                                           | (1L << 27)
 +#endif
 +#ifdef RLECOMP
 +                                           | (1L << 28)
 +#endif
 +                                               );
 +    /*
 +     * Value used for object & monster sanity check.
 +     *    (NROFARTIFACTS<<24) | (NUM_OBJECTS<<12) | (NUMMONS<<0)
 +     */
 +    for (i = 1; artifact_names[i]; i++)
 +        continue;
 +    version.entity_count = (unsigned long) (i - 1);
 +    for (i = 1; objects[i].oc_class != ILLOBJ_CLASS; i++)
 +        continue;
 +    version.entity_count = (version.entity_count << 12) | (unsigned long) i;
 +    for (i = 0; mons[i].mlet; i++)
 +        continue;
 +    version.entity_count = (version.entity_count << 12) | (unsigned long) i;
 +    /*
 +     * Value used for compiler (word size/field alignment/padding) check.
 +     */
 +    version.struct_sizes1 =
 +        (((unsigned long) sizeof(struct context_info) << 24)
 +         | ((unsigned long) sizeof(struct obj) << 17)
 +         | ((unsigned long) sizeof(struct monst) << 10)
 +         | ((unsigned long) sizeof(struct you)));
 +    version.struct_sizes2 = (((unsigned long) sizeof(struct flag) << 10) |
 +/* free bits in here */
 +#ifdef SYSFLAGS
 +                             ((unsigned long) sizeof(struct sysflag)));
 +#else
 +                             ((unsigned long) 0L));
 +#endif
 +    return;
 +}
 +
 +#if defined(MAKEDEFS_C) || defined(CROSSCOMPILE_TARGET)
 +
 +static char *
 +version_string(outbuf, delim)
 +char *outbuf;
 +const char *delim;
 +{
 +    Sprintf(outbuf, "%d%s%d%s%d", VERSION_MAJOR, delim, VERSION_MINOR, delim,
 +            PATCHLEVEL);
 +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
 +    Sprintf(eos(outbuf), "-%d", EDITLEVEL);
 +#endif
 +    return outbuf;
 +}
 +
 +static char *
 +version_id_string(outbuf, build_date)
 +char *outbuf;
 +const char *build_date;
 +{
 +    char subbuf[64], versbuf[64];
-     Strcpy(betabuf, " Beta");
++    char statusbuf[64];
 +
 +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
 +#if (NH_DEVEL_STATUS == NH_STATUS_BETA)
-     Strcpy(betabuf, " Work-in-progress");
++    Strcpy(statusbuf, " Beta");
 +#else
-     betabuf[0] = '\0';
++#if (NH_DEVEL_STATUS == NH_STATUS_WIP)
++    Strcpy(statusbuf, " Work-in-progress");
++#else
++    Strcpy(statusbuf, " post-release");
++#endif
 +#endif
 +#else
-             subbuf, version_string(versbuf, "."), betabuf,
++    statusbuf[0] = '\0';
 +#endif
 +    subbuf[0] = '\0';
 +#ifdef PORT_SUB_ID
 +    subbuf[0] = ' ';
 +    Strcpy(&subbuf[1], PORT_SUB_ID);
 +#endif
 +
 +    Sprintf(outbuf, "%s NetHack%s Version %s%s - last %s %s.", PORT_ID,
++            subbuf, version_string(versbuf, "."), statusbuf,
 +            date_via_env ? "revision" : "build", build_date);
 +    return outbuf;
 +}
 +
 +/* still within #if MAKDEFS_C || CROSSCOMPILE_TARGET */
 +
 +static char *
 +bannerc_string(outbuf, build_date)
 +char *outbuf;
 +const char *build_date;
 +{
 +    char subbuf[64], versbuf[64];
 +
 +    subbuf[0] = '\0';
 +#ifdef PORT_SUB_ID
 +    subbuf[0] = ' ';
 +    Strcpy(&subbuf[1], PORT_SUB_ID);
 +#endif
 +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
 +#if (NH_DEVEL_STATUS == NH_STATUS_BETA)
 +    Strcat(subbuf, " Beta");
 +#else
 +    Strcat(subbuf, " Work-in-progress");
 +#endif
 +#endif
 +
 +    Sprintf(outbuf, "         Version %s %s%s, %s %s.",
 +            version_string(versbuf, "."), PORT_ID, subbuf,
 +            date_via_env ? "revised" : "built", &build_date[4]);
 +#if 0
 +    Sprintf(outbuf, "%s NetHack%s %s Copyright 1985-%s (built %s)",
 +            PORT_ID, subbuf, version_string(versbuf,"."), RELEASE_YEAR,
 +            &build_date[4]);
 +#endif
 +    return outbuf;
 +}
 +
 +#endif /* MAKEDEFS_C || CROSSCOMPILE_TARGET */
 +
 +static int
 +case_insensitive_comp(s1, s2)
 +const char *s1;
 +const char *s2;
 +{
 +    uchar u1, u2;
 +
 +    for (;; s1++, s2++) {
 +        u1 = (uchar) *s1;
 +        if (isupper(u1))
 +            u1 = tolower(u1);
 +        u2 = (uchar) *s2;
 +        if (isupper(u2))
 +            u2 = tolower(u2);
 +        if (u1 == '\0' || u1 != u2)
 +            break;
 +    }
 +    return u1 - u2;
 +}
 +
 +static char *
 +eos(str)
 +char *str;
 +{
 +    while (*str)
 +        str++;
 +    return str;
 +}
 +
 +static char save_bones_compat_buf[BUFSZ];
 +
 +static void
 +build_savebones_compat_string()
 +{
 +#ifdef VERSION_COMPATIBILITY
 +    unsigned long uver = VERSION_COMPATIBILITY,
 +                  cver  = (((unsigned long) VERSION_MAJOR << 24)
 +                         | ((unsigned long) VERSION_MINOR << 16)
 +                         | ((unsigned long) PATCHLEVEL    <<  8));
 +#endif
 +
 +    Strcpy(save_bones_compat_buf,
 +           "save and bones files accepted from version");
 +#ifdef VERSION_COMPATIBILITY
 +    if (uver != cver)
 +        Sprintf(eos(save_bones_compat_buf), "s %lu.%lu.%lu through %d.%d.%d",
 +                ((uver >> 24) & 0x0ffUL),
 +                ((uver >> 16) & 0x0ffUL),
 +                ((uver >>  8) & 0x0ffUL),
 +                VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
 +    else
 +#endif
 +        Sprintf(eos(save_bones_compat_buf), " %d.%d.%d only",
 +                VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
 +}
 +
 +static const char *build_opts[] = {
 +#ifdef AMIGA_WBENCH
 +    "Amiga WorkBench support",
 +#endif
 +#ifdef ANSI_DEFAULT
 +    "ANSI default terminal",
 +#endif
 +#ifdef TEXTCOLOR
 +    "color",
 +#endif
 +#ifdef TTY_GRAPHICS
 +#ifdef TTY_TILES_ESCCODES
 +    "console escape codes for tile hinting",
 +#endif
 +#endif
 +#ifdef COM_COMPL
 +    "command line completion",
 +#endif
 +#ifdef LIFE
 +    "Conway's Game of Life",
 +#endif
 +#ifdef COMPRESS
 +    "data file compression",
 +#endif
 +#ifdef ZLIB_COMP
 +    "ZLIB data file compression",
 +#endif
 +#ifdef DLB
 +#ifndef VERSION_IN_DLB_FILENAME
 +    "data librarian",
 +#else
 +    "data librarian with a version-dependent name",
 +#endif
 +#endif
 +#ifdef DUMPLOG
 +    "end-of-game dumplogs",
 +#endif
 +#ifdef HOLD_LOCKFILE_OPEN
 +    "exclusive lock on level 0 file",
 +#endif
 +#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
 +    "external program as a message handler",
 +#endif
 +#ifdef MFLOPPY
 +    "floppy drive support",
 +#endif
 +#ifdef INSURANCE
 +    "insurance files for recovering from crashes",
 +#endif
 +#ifdef LOGFILE
 +    "log file",
 +#endif
 +#ifdef XLOGFILE
 +    "extended log file",
 +#endif
 +#ifdef PANICLOG
 +    "errors and warnings log file",
 +#endif
 +#ifdef MAIL_STRUCTURES
 +    "mail daemon",
 +#endif
 +#if defined(GNUDOS) || defined(__DJGPP__)
 +    "MSDOS protected mode",
 +#endif
 +#ifdef NEWS
 +    "news file",
 +#endif
 +#ifdef OVERLAY
 +#ifdef MOVERLAY
 +    "MOVE overlays",
 +#else
 +#ifdef VROOMM
 +    "VROOMM overlays",
 +#else
 +    "overlays",
 +#endif
 +#endif
 +#endif
 +    /* pattern matching method will be substituted by nethack at run time */
 +    "pattern matching via :PATMATCH:",
 +#ifdef USE_ISAAC64
 +    "pseudo random numbers generated by ISAAC64",
 +#ifdef DEV_RANDOM
 +#ifdef NHSTDC
 +    /* include which specific one */
 +    "strong PRNG seed available from " DEV_RANDOM,
 +#else
 +    "strong PRNG seed available from DEV_RANDOM",
 +#endif
 +#else
 +#ifdef WIN32
 +    "strong PRNG seed available from CNG BCryptGenRandom()",
 +#endif
 +#endif  /* DEV_RANDOM */    
 +#else   /* ISAAC64 */
 +#ifdef RANDOM
 +    "pseudo random numbers generated by random()",
 +#else
 +    "pseudo random numbers generated by C rand()",
 +#endif
 +#endif /* ISAAC64 */
 +#ifdef SELECTSAVED
 +    "restore saved games via menu",
 +#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 SCREEN_VGA
 +    "screen control via VGA graphics",
 +#endif
 +#ifdef WIN32CON
 +    "screen control via WIN32 console I/O",
 +#endif
 +#endif /* NO_TERMS */
 +#ifdef SHELL
 +    "shell command",
 +#endif
 +    "traditional status display",
 +#ifdef STATUS_HILITES
 +    "status via windowport with highlighting",
 +#else
 +    "status via windowport without highlighting",
 +#endif
 +#ifdef SUSPEND
 +    "suspend command",
 +#endif
 +#ifdef TTY_GRAPHICS
 +#ifdef TERMINFO
 +    "terminal info library",
 +#else
 +#if defined(TERMLIB) || (!defined(MICRO) && !defined(WIN32))
 +    "terminal capability library",
 +#endif
 +#endif
 +#endif /*TTY_GRAPHICS*/
 +#ifdef USE_XPM
 +    "tiles file in XPM format",
 +#endif
 +#ifdef GRAPHIC_TOMBSTONE
 +    "graphical RIP screen",
 +#endif
 +#ifdef TIMED_DELAY
 +    "timed wait for display effects",
 +#endif
 +#ifdef USER_SOUNDS
 +    "user sounds",
 +#endif
 +#ifdef PREFIXES_IN_USE
 +    "variable playground",
 +#endif
 +#ifdef VISION_TABLES
 +    "vision tables",
 +#endif
 +#ifdef ZEROCOMP
 +    "zero-compressed save files",
 +#endif
 +#ifdef RLECOMP
 +    "run-length compression of map in save files",
 +#endif
 +#ifdef SYSCF
 +    "system configuration at run-time",
 +#endif
 +    save_bones_compat_buf,
 +    "and basic NetHack features"
 +};
 +
 +static void
 +opt_out_words(str, length_p)
 +char *str; /* input, but modified during processing */
 +int *length_p; /* in/out */
 +{
 +    char *word;
 +
 +    while (*str) {
 +        word = index(str, ' ');
 +#if 0
 +        /* treat " (" as unbreakable space */
 +        if (word && *(word + 1) == '(')
 +            word = index(word + 1,  ' ');
 +#endif
 +        if (word)
 +            *word = '\0';
 +        if (*length_p + (int) strlen(str) > COLNO - 5) {
 +            opttext[idxopttext] = strdup(optbuf);
 +            if (idxopttext < (MAXOPT - 1))
 +                idxopttext++;
 +            Sprintf(optbuf, "%s", opt_indent),
 +                    *length_p = (int) strlen(opt_indent);
 +        } else {
 +            Sprintf(eos(optbuf), " "), (*length_p)++;
 +        }
 +        Sprintf(eos(optbuf),
 +                "%s", str), *length_p += (int) strlen(str);
 +        str += strlen(str) + (word ? 1 : 0);
 +    }
 +}
 +
 +void
 +build_options()
 +{
 +    char buf[BUFSZ];
 +    int i, length, winsyscnt;
 +
 +    build_savebones_compat_string();
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
 +#if (NH_DEVEL_STATUS == NH_STATUS_BETA)
 +#define STATUS_ARG " [beta]"
 +#else
 +#define STATUS_ARG " [work-in-progress]"
 +#endif
 +#else
 +#define STATUS_ARG ""
 +#endif /* NH_DEVEL_STATUS == NH_STATUS_RELEASED */
 +    Sprintf(optbuf, "%sNetHack version %d.%d.%d%s\n",
 +            opt_indent, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, STATUS_ARG);
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    Sprintf(optbuf, "Options compiled into this edition:");
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    optbuf[0] = '\0';
 +    length = COLNO + 1; /* force 1st item onto new line */
 +    for (i = 0; i < SIZE(build_opts); i++) {
 +        opt_out_words(strcat(strcpy(buf, build_opts[i]),
 +                             (i < SIZE(build_opts) - 1) ? "," : "."),
 +                      &length);
 +    }
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    optbuf[0] = '\0';
 +    winsyscnt = SIZE(window_opts) - 1;
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    Sprintf(optbuf, "Supported windowing system%s:",
 +            (winsyscnt > 1) ? "s" : "");
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    optbuf[0] = '\0';
 +    length = COLNO + 1; /* force 1st item onto new line */
 +    for (i = 0; i < winsyscnt; i++) {
 +        Sprintf(buf, "\"%s\"", window_opts[i].id);
 +        if (strcmp(window_opts[i].name, window_opts[i].id))
 +            Sprintf(eos(buf), " (%s)", window_opts[i].name);
 +        /*
 +         * 1 : foo.
 +         * 2 : foo and bar  (note no period; comes from 'with default' below)
 +         * 3+: for, bar, and quux
 +         */
 +        opt_out_words(strcat(buf, (winsyscnt == 1) ? "." /* no 'default' */
 +                                  : (winsyscnt == 2 && i == 0) ? " and"
 +                                    : (i == winsyscnt - 2) ? ", and"
 +                                      : ","),
 +                      &length);
 +    }
 +    if (winsyscnt > 1) {
 +        Sprintf(buf, "with a default of \"%s\".", DEFAULT_WINDOW_SYS);
 +        opt_out_words(buf, &length);
 +    }
 +    opttext[idxopttext] = strdup(optbuf);
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    optbuf[0] = '\0';
 +
 +#if defined(MAKEDEFS_C) || (defined(CROSSCOMPILE) && defined(CROSSCOMPILE_TARGET))
 +    {
 +        static const char *lua_info[] = {
 + "", "NetHack 3.7.* uses the 'Lua' interpreter to process some data:", "",
 + "    :LUACOPYRIGHT:", "",
 + /*        1         2         3         4         5         6         7
 +  1234567890123456789012345678901234567890123456789012345678901234567890123456
 +  */
 + "    \"Permission is hereby granted, free of charge, to any person obtaining",
 + "     a copy of this software and associated documentation files (the ",
 + "     \"Software\"), to deal in the Software without restriction including",
 + "     without limitation the rights to use, copy, modify, merge, publish,",
 + "     distribute, sublicense, and/or sell copies of the Software, and to ",
 + "     permit persons to whom the Software is furnished to do so, subject to",
 + "     the following conditions:",
 + "     The above copyright notice and this permission notice shall be",
 + "     included in all copies or substantial portions of the Software.\"",
 +            (const char *) 0
 +        };
 +
 +        /* add lua copyright notice;
 +           ":TAG:" substitutions are deferred to caller */
 +        for (i = 0; lua_info[i]; ++i) {
 +            opttext[idxopttext] = strdup(lua_info[i]);
 +            if (idxopttext < (MAXOPT - 1))
 +                idxopttext++;
 +        }
 +    }
 +#endif /* MAKEDEFS_C || (CROSSCOMPILE && CROSSCOMPILE_TARGET) */
 +
 +    /* end with a blank line */
 +    opttext[idxopttext] = strdup("");
 +    if (idxopttext < (MAXOPT - 1))
 +        idxopttext++;
 +    return;
 +}
 +
 +#if defined(__DATE__) && defined(__TIME__)
 +#define extract_field(t,s,n,z)    \
 +    do {                          \
 +        for (i = 0; i < n; ++i)   \
 +            t[i] = s[i + z];      \
 +        t[i] = '\0';              \
 +    } while (0)
 +#endif
 +
 +void
 +runtime_info_init()
 +{
 +    int i;
 +    char tmpbuf[BUFSZ], *strp;
 +    const char *mth[] = {
 +        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 +        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 +    struct tm t = {0};
 +    time_t timeresult;
 +
 +    if (!done_runtime_opt_init_once) {
 +        done_runtime_opt_init_once = 1;
 +        build_savebones_compat_string();
 +        /* construct the current version number */
 +        make_version();
 +        /*
 +         * In a cross-compiled environment, you can't execute
 +         * the target binaries during the build, so we can't
 +         * use makedefs to write the values of the build
 +         * date and time to a file for retrieval. Not for
 +         * information meaningful to the target execution
 +         * environment.
 +         *
 +         * How can we capture the build date/time of the target
 +         * binaries in such a situation?  We need to rely on the
 +         * cross-compiler itself to do it for us during the
 +         * cross-compile.
 +         *
 +         * To that end, we are going to make use of the
 +         * following pre-defined preprocessor macros for this:
 +         *    gcc, msvc, clang   __DATE__  "Feb 12 1996"
 +         *    gcc, msvc, clang   __TIME__  "23:59:01"
 +         *
 +         */
 +
 +#if defined(__DATE__) && defined(__TIME__)
 +        if (sizeof __DATE__ + sizeof __TIME__  + sizeof "123" <
 +            sizeof rttimebuf)
 +            Sprintf(rttimebuf, "%s %s", __DATE__, __TIME__);
 +        /* "Feb 12 1996 23:59:01"
 +            01234567890123456789  */
 +        if ((int) strlen(rttimebuf) == 20) {
 +            extract_field(tmpbuf, rttimebuf, 4, 7);   /* year */
 +            t.tm_year = atoi(tmpbuf) - 1900;
 +            extract_field(tmpbuf, rttimebuf, 3, 0);   /* mon */
 +            for (i = 0; i < SIZE(mth); ++i)
 +                if (!case_insensitive_comp(tmpbuf, mth[i])) {
 +                    t.tm_mon = i;
 +                    break;
 +                }
 +            extract_field(tmpbuf, rttimebuf, 2, 4);   /* mday */
 +            strp = tmpbuf;
 +            if (*strp == ' ')
 +                strp++;
 +            t.tm_mday = atoi(strp);
 +            extract_field(tmpbuf, rttimebuf, 2, 12);  /* hour */
 +            t.tm_hour = atoi(tmpbuf);
 +            extract_field(tmpbuf, rttimebuf, 2, 15);  /* min  */
 +            t.tm_min = atoi(tmpbuf);
 +            extract_field(tmpbuf, rttimebuf, 2, 18);  /* sec  */
 +            t.tm_sec = atoi(tmpbuf);
 +            timeresult = mktime(&t);
 +#if defined(CROSSCOMPILE_TARGET) && !defined(MAKEDEFS_C)
 +            BUILD_TIME = (unsigned long) timeresult;
 +            BUILD_DATE = rttimebuf;
 +#endif
 +#else  /* __DATE__ && __TIME__ */
 +            nhUse(strp);
 +#endif /* __DATE__ && __TIME__ */
 +
 +#if defined(CROSSCOMPILE_TARGET) && !defined(MAKEDEFS_C)
 +            VERSION_NUMBER = version.incarnation;
 +            VERSION_FEATURES = version.feature_set;
 +#ifdef MD_IGNORED_FEATURES
 +            IGNORED_FEATURES = MD_IGNORED_FEATURES;
 +#endif
 +            VERSION_SANITY1 = version.entity_count;
 +            VERSION_SANITY2 = version.struct_sizes1;
 +            VERSION_SANITY3 = version.struct_sizes2;
 +
 +            VERSION_STRING = strdup(version_string(tmpbuf, "."));
 +            VERSION_ID = strdup(version_id_string(tmpbuf, BUILD_DATE));
 +            COPYRIGHT_BANNER_C = strdup(bannerc_string(tmpbuf, BUILD_DATE));
 +#ifdef NETHACK_HOST_GIT_SHA
 +            NETHACK_GIT_SHA = strdup(NETHACK_HOST_GIT_SHA);
 +#endif
 +#ifdef NETHACK_HOST_GIT_BRANCH
 +            NETHACK_GIT_BRANCH = strdup(NETHACK_HOST_GIT_BRANCH);
 +#endif
 +#endif /* CROSSCOMPILE_TARGET && !MAKEDEFS_C */
 +      }
 +        idxopttext = 0;
 +        build_options();
 +    }
 +}
 +
 +const char *
 +do_runtime_info(rtcontext)
 +int *rtcontext;
 +{
 +    const char *retval = (const char *) 0;
 +
 +    if (!done_runtime_opt_init_once)
 +        runtime_info_init();
 +    if (idxopttext && rtcontext)
 +        if (*rtcontext >= 0 && *rtcontext < (MAXOPT - 1)) {
 +            retval = opttext[*rtcontext];
 +            *rtcontext += 1;
 +      }
 +    return retval;
 +}
 +
 +/*mdlib.c*/
diff --cc src/sys.c
Simple merge