hacklib.c formatting

hacklib.c took a beating in the reformatting, so clean it up.
A tweak to the anti-predictability hack in setrandom() is the only
change in the actual code.
This commit is contained in:
PatR
2015-05-27 03:49:09 -07:00
parent eeb69bfe09
commit ad3af4efb2

View File

@@ -1,96 +1,106 @@
/* NetHack 3.6 hacklib.c $NHDT-Date: 1432512764 2015/05/25 00:12:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */ /* NetHack 3.6 hacklib.c $NHDT-Date: 1432723746 2015/05/27 10:49:06 $ $NHDT-Branch: master $:$NHDT-Revision: 1.43 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) Robert Patrick Rankin, 1991 */ /* Copyright (c) Robert Patrick Rankin, 1991 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
#include "hack.h" /* for config.h+extern.h */ #include "hack.h" /* for config.h+extern.h */
/*= /*=
Assorted 'small' utility routines. They're virtually independent of Assorted 'small' utility routines. They're virtually independent of
NetHack, except that rounddiv may call panic(). setrandom calls one of NetHack, except that rounddiv may call panic(). setrandom calls one
srandom(), srand48(), or srand() depending upon configuration. of srandom(), srand48(), or srand() depending upon configuration.
return type routine name argument type(s) return type routine name argument type(s)
boolean digit (char) boolean digit (char)
boolean letter (char) boolean letter (char)
char highc (char) char highc (char)
char lowc (char) char lowc (char)
char * lcase (char *) char * lcase (char *)
char * ucase (char *) char * ucase (char *)
char * upstart (char *) char * upstart (char *)
char * mungspaces (char *) char * mungspaces (char *)
char * eos (char *) char * eos (char *)
char * strkitten (char *,char) char * strkitten (char *,char)
void copynchars (char *,const char *,int) void copynchars (char *,const char *,int)
char chrcasecpy (int,int) char chrcasecpy (int,int)
char * strcasecpy (char *,const char *) char * strcasecpy (char *,const char *)
char * s_suffix (const char *) char * s_suffix (const char *)
char * ing_suffix (const char *) char * ing_suffix (const char *)
char * xcrypt (const char *, char *) char * xcrypt (const char *, char *)
boolean onlyspace (const char *) boolean onlyspace (const char *)
char * tabexpand (char *) char * tabexpand (char *)
char * visctrl (char) char * visctrl (char)
char * strsubst (char *, const char *, const char *) char * strsubst (char *, const char *, const char *)
const char * ordin (int) const char * ordin (int)
char * sitoa (int) char * sitoa (int)
int sgn (int) int sgn (int)
int rounddiv (long, int) int rounddiv (long, int)
int distmin (int, int, int, int) int distmin (int, int, int, int)
int dist2 (int, int, int, int) int dist2 (int, int, int, int)
boolean online2 (int, int) boolean online2 (int, int)
boolean pmatch (const char *, const char *) boolean pmatch (const char *, const char *)
boolean pmatchi (const char *, const char *) boolean pmatchi (const char *, const char *)
boolean pmatchz (const char *, const char *) boolean pmatchz (const char *, const char *)
int strncmpi (const char *, const char *, int) int strncmpi (const char *, const char *, int)
char * strstri (const char *, const char *) char * strstri (const char *, const char *)
boolean fuzzymatch (const char *,const char *, boolean fuzzymatch (const char *,const char *,
const char *,boolean) const char *, boolean)
void setrandom (void) void setrandom (void)
time_t getnow (void) time_t getnow (void)
int getyear (void) int getyear (void)
char * yymmdd (time_t) char * yymmdd (time_t)
long yyyymmdd (time_t) long yyyymmdd (time_t)
long hhmmss (time_t) long hhmmss (time_t)
char * yyyymmddhhmmss (time_t) char * yyyymmddhhmmss (time_t)
time_t time_from_yyyymmddhhmmss (char *) time_t time_from_yyyymmddhhmmss (char *)
int phase_of_the_moon (void) int phase_of_the_moon (void)
boolean friday_13th (void) boolean friday_13th (void)
int night (void) int night (void)
int midnight (void) int midnight (void)
=*/ =*/
#ifdef LINT #ifdef LINT
#define Static /* pacify lint */ #define Static /* pacify lint */
#else #else
#define Static static #define Static static
#endif #endif
static boolean FDECL(pmatch_internal, static boolean FDECL(pmatch_internal, (const char *, const char *,
(const char *, const char *, BOOLEAN_P, const char *)); BOOLEAN_P, const char *));
boolean digit(c) /* is 'c' a digit? */ /* is 'c' a digit? */
boolean
digit(c)
char c; char c;
{ {
return ((boolean)('0' <= c && c <= '9')); return (boolean) ('0' <= c && c <= '9');
} }
boolean letter(c) /* is 'c' a letter? note: '@' classed as letter */ /* is 'c' a letter? note: '@' classed as letter */
boolean
letter(c)
char c; char c;
{ {
return ((boolean)(('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))); return (boolean) ('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
} }
char highc(c) /* force 'c' into uppercase */ /* force 'c' into uppercase */
char
highc(c)
char c; char c;
{ {
return ((char) (('a' <= c && c <= 'z') ? (c & ~040) : c)); return (char) (('a' <= c && c <= 'z') ? (c & ~040) : c);
} }
char lowc(c) /* force 'c' into lowercase */ /* force 'c' into lowercase */
char
lowc(c)
char c; char c;
{ {
return ((char) (('A' <= c && c <= 'Z') ? (c | 040) : c)); return (char) (('A' <= c && c <= 'Z') ? (c | 040) : c);
} }
char *lcase(s) /* convert a string into all lowercase */ /* convert a string into all lowercase */
char *
lcase(s)
char *s; char *s;
{ {
register char *p; register char *p;
@@ -101,7 +111,9 @@ char *s;
return s; return s;
} }
char *ucase(s) /* convert a string into all uppercase */ /* convert a string into all uppercase */
char *
ucase(s)
char *s; char *s;
{ {
register char *p; register char *p;
@@ -112,7 +124,9 @@ char *s;
return s; return s;
} }
char *upstart(s) /* convert first character of a string to uppercase */ /* convert first character of a string to uppercase */
char *
upstart(s)
char *s; char *s;
{ {
if (s) if (s)
@@ -143,7 +157,9 @@ char *bp;
return bp; return bp;
} }
char *eos(s) /* return the end of a string (pointing at '\0') */ /* return the end of a string (pointing at '\0') */
char *
eos(s)
register char *s; register char *s;
{ {
while (*s) while (*s)
@@ -151,8 +167,9 @@ register char *s;
return s; return s;
} }
/* strcat(s, {c,'\0'}); */ /* append a character to a string (in place): strcat(s, {c,'\0'}); */
char *strkitten(s, c) /* append a character to a string (in place) */ char *
strkitten(s, c)
char *s; char *s;
char c; char c;
{ {
@@ -163,7 +180,9 @@ char c;
return s; return s;
} }
void copynchars(dst, src, n) /* truncating string copy */ /* truncating string copy */
void
copynchars(dst, src, n)
char *dst; char *dst;
const char *src; const char *src;
int n; int n;
@@ -178,8 +197,9 @@ int n;
*dst = '\0'; *dst = '\0';
} }
/* mostly used by strcasecpy */ /* convert char nc into oc's case; mostly used by strcasecpy */
char chrcasecpy(oc, nc) /* convert char nc into oc's case */ char
chrcasecpy(oc, nc)
int oc, nc; int oc, nc;
{ {
#if 0 /* this will be necessary if we switch to <ctype.h> */ #if 0 /* this will be necessary if we switch to <ctype.h> */
@@ -198,9 +218,11 @@ int oc, nc;
return (char) nc; return (char) nc;
} }
/* for case-insensitive editions of makeplural() and makesingular(); /* overwrite string, preserving old chars' case;
for case-insensitive editions of makeplural() and makesingular();
src might be shorter, same length, or longer than dst */ src might be shorter, same length, or longer than dst */
char *strcasecpy(dst, src) /* overwrite string, preserving old chars' case */ char *
strcasecpy(dst, src)
char *dst; char *dst;
const char *src; const char *src;
{ {
@@ -222,7 +244,9 @@ const char *src;
return result; return result;
} }
char *s_suffix(s) /* return a name converted to possessive */ /* return a name converted to possessive */
char *
s_suffix(s)
const char *s; const char *s;
{ {
Static char buf[BUFSZ]; Static char buf[BUFSZ];
@@ -239,6 +263,7 @@ const char *s;
return buf; return buf;
} }
/* construct a gerund (a verb formed by appending "ing" to a noun) */
char * char *
ing_suffix(s) ing_suffix(s)
const char *s; const char *s;
@@ -247,6 +272,7 @@ const char *s;
static char buf[BUFSZ]; static char buf[BUFSZ];
char onoff[10]; char onoff[10];
char *p; char *p;
Strcpy(buf, s); Strcpy(buf, s);
p = eos(buf); p = eos(buf);
onoff[0] = *p = *(p + 1) = '\0'; onoff[0] = *p = *(p + 1) = '\0';
@@ -272,7 +298,9 @@ const char *s;
return buf; return buf;
} }
char *xcrypt(str, buf) /* trivial text encryption routine (see makedefs) */ /* trivial text encryption routine (see makedefs) */
char *
xcrypt(str, buf)
const char *str; const char *str;
char *buf; char *buf;
{ {
@@ -309,7 +337,6 @@ char *sbuf;
if (!*s) if (!*s)
return sbuf; return sbuf;
/* warning: no bounds checking performed */ /* warning: no bounds checking performed */
for (bp = buf, idx = 0; *s; s++) for (bp = buf, idx = 0; *s; s++)
if (*s == '\t') { if (*s == '\t') {
@@ -330,7 +357,6 @@ char c;
Static char ccc[3]; Static char ccc[3];
c &= 0177; c &= 0177;
ccc[2] = '\0'; ccc[2] = '\0';
if (c < 040) { if (c < 040) {
ccc[0] = '^'; ccc[0] = '^';
@@ -365,17 +391,20 @@ const char *orig, *replacement;
return bp; return bp;
} }
const char *ordin(n) /* return the ordinal suffix of a number */ /* return the ordinal suffix of a number */
const char *
ordin(n)
int n; /* note: should be non-negative */ int n; /* note: should be non-negative */
{ {
register int dd = n % 10; register int dd = n % 10;
return (dd == 0 || dd > 3 || (n % 100) / 10 == 1) return (dd == 0 || dd > 3 || (n % 100) / 10 == 1) ? "th"
? "th"
: (dd == 1) ? "st" : (dd == 2) ? "nd" : "rd"; : (dd == 1) ? "st" : (dd == 2) ? "nd" : "rd";
} }
char *sitoa(n) /* make a signed digit string from a number */ /* make a signed digit string from a number */
char *
sitoa(n)
int n; int n;
{ {
Static char buf[13]; Static char buf[13];
@@ -384,13 +413,17 @@ int n;
return buf; return buf;
} }
int sgn(n) /* return the sign of a number: -1, 0, or 1 */ /* return the sign of a number: -1, 0, or 1 */
int
sgn(n)
int n; int n;
{ {
return (n < 0) ? -1 : (n != 0); return (n < 0) ? -1 : (n != 0);
} }
int rounddiv(x, y) /* calculate x/y, rounding as appropriate */ /* calculate x/y, rounding as appropriate */
int
rounddiv(x, y)
long x; long x;
int y; int y;
{ {
@@ -415,42 +448,48 @@ int y;
return divsgn * r; return divsgn * r;
} }
int distmin(x0, y0, x1, y1) /* distance between two points, in moves */ /* distance between two points, in moves */
int
distmin(x0, y0, x1, y1)
int x0, y0, x1, y1; int x0, y0, x1, y1;
{ {
register int dx = x0 - x1, dy = y0 - y1; register int dx = x0 - x1, dy = y0 - y1;
if (dx < 0) if (dx < 0)
dx = -dx; dx = -dx;
if (dy < 0) if (dy < 0)
dy = -dy; dy = -dy;
/* The minimum number of moves to get from (x0,y0) to (x1,y1) is the /* The minimum number of moves to get from (x0,y0) to (x1,y1) is the
: larger of the [absolute value of the] two deltas. * larger of the [absolute value of the] two deltas.
*/ */
return (dx < dy) ? dy : dx; return (dx < dy) ? dy : dx;
} }
int dist2(x0, y0, x1, /* square of euclidean distance between pair of pts */
y1) /* square of euclidean distance between pair of pts */ int
dist2(x0, y0, x1, y1)
int x0, y0, x1, y1; int x0, y0, x1, y1;
{ {
register int dx = x0 - x1, dy = y0 - y1; register int dx = x0 - x1, dy = y0 - y1;
return dx * dx + dy * dy; return dx * dx + dy * dy;
} }
/* Integer square root function without using floating point. /* integer square root function without using floating point */
* This could be replaced by a faster algorithm, but has not been because:
* + the simple algorithm is easy to read
* + this algorithm does not require 64-bit support
* + in current usage, the values passed to isqrt() are not really that
* large, so the performance difference is negligible
* + isqrt() is used in only few places, which are not bottle-necks
*/
int int
isqrt(val) isqrt(val)
int val; int val;
{ {
int rt = 0; int rt = 0;
int odd = 1; int odd = 1;
/*
* This could be replaced by a faster algorithm, but has not been because:
* + the simple algorithm is easy to read;
* + this algorithm does not require 64-bit support;
* + in current usage, the values passed to isqrt() are not really that
* large, so the performance difference is negligible;
* + isqrt() is used in only few places, which are not bottle-necks.
*/
while (val >= odd) { while (val >= odd) {
val = val - odd; val = val - odd;
odd = odd + 2; odd = odd + 2;
@@ -459,30 +498,30 @@ int val;
return rt; return rt;
} }
boolean online2(x0, y0, x1, /* are two points lined up (on a straight line)? */
y1) /* are two points lined up (on a straight line)? */ boolean
online2(x0, y0, x1, y1)
int x0, y0, x1, y1; int x0, y0, x1, y1;
{ {
int dx = x0 - x1, dy = y0 - y1; int dx = x0 - x1, dy = y0 - y1;
/* If either delta is zero then they're on an orthogonal line, /* If either delta is zero then they're on an orthogonal line,
* else if the deltas are equal (signs ignored) they're on a diagonal. * else if the deltas are equal (signs ignored) they're on a diagonal.
*/ */
return ((boolean)(!dy || !dx || (dy == dx) return (boolean) (!dy || !dx || dy == dx || dy == -dx);
|| (dy + dx == 0))); /* (dy == -dx) */
} }
/* guts of pmatch(), pmatchi(), and pmatchz() */ /* guts of pmatch(), pmatchi(), and pmatchz() */
static boolean pmatch_internal(patrn, strng, ci, static boolean
sk) /* match a string against a pattern */ pmatch_internal(patrn, strng, ci, sk) /* match a string against a pattern */
const char *patrn, *strng; const char *patrn, *strng;
boolean ci; /* True => case-insensitive, False => case-sensitive */ boolean ci; /* True => case-insensitive, False => case-sensitive */
const char *sk; /* set of characters to skip */ const char *sk; /* set of characters to skip */
{ {
char s, p; char s, p;
/* /*
: Simple pattern matcher: '*' matches 0 or more characters, '?' matches * Simple pattern matcher: '*' matches 0 or more characters, '?' matches
: any single character. Returns TRUE if 'strng' matches 'patrn'. * any single character. Returns TRUE if 'strng' matches 'patrn'.
*/ */
pmatch_top: pmatch_top:
if (!sk) { if (!sk) {
s = *strng++; s = *strng++;
@@ -496,13 +535,14 @@ pmatch_top:
p = *patrn++; p = *patrn++;
} while (index(sk, p)); } while (index(sk, p));
} }
if (!p) /* end of pattern */ if (!p) /* end of pattern */
return (boolean)(s == '\0'); /* matches iff end of string too */ return (boolean) (s == '\0'); /* matches iff end of string too */
else if (p == '*') /* wildcard reached */ else if (p == '*') /* wildcard reached */
return (boolean)( return (boolean) ((!*patrn
(!*patrn || pmatch_internal(patrn, strng - 1, ci, sk)) || pmatch_internal(patrn, strng - 1, ci, sk))
? TRUE ? TRUE
: s ? pmatch_internal(patrn - 1, strng, ci, sk) : FALSE); : s ? pmatch_internal(patrn - 1, strng, ci, sk)
: FALSE);
else if ((ci ? lowc(p) != lowc(s) : p != s) /* check single character */ else if ((ci ? lowc(p) != lowc(s) : p != s) /* check single character */
&& (p != '?' || !s)) /* & single-char wildcard */ && (p != '?' || !s)) /* & single-char wildcard */
return FALSE; /* doesn't match */ return FALSE; /* doesn't match */
@@ -538,10 +578,12 @@ const char *patrn, *strng;
} }
#ifndef STRNCMPI #ifndef STRNCMPI
int strncmpi(s1, s2, n) /* case insensitive counted string comparison */ /* case insensitive counted string comparison */
int
strncmpi(s1, s2, n) /*{ aka strncasecmp }*/
register const char *s1, *s2; register const char *s1, *s2;
register int n; /*(should probably be size_t, which is usually unsigned)*/ register int n; /*(should probably be size_t, which is unsigned)*/
{ /*{ aka strncasecmp }*/ {
register char t1, t2; register char t1, t2;
while (n--) { while (n--) {
@@ -559,8 +601,9 @@ register int n; /*(should probably be size_t, which is usually unsigned)*/
#endif /* STRNCMPI */ #endif /* STRNCMPI */
#ifndef STRSTRI #ifndef STRSTRI
/* case insensitive substring search */
char *strstri(str, sub) /* case insensitive substring search */ char *
strstri(str, sub)
const char *str; const char *str;
const char *sub; const char *sub;
{ {
@@ -570,7 +613,7 @@ const char *sub;
char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */ char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */
#if 0 #if 0
assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */ assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */
assert( &lowc != 0 ); /* can't be unsafe macro */ assert( &lowc != 0 ); /* can't be unsafe macro */
#endif #endif
/* special case: empty substring */ /* special case: empty substring */
@@ -629,18 +672,18 @@ boolean caseblind;
} while (c1 == c2); } while (c1 == c2);
/* match occurs only when the end of both strings has been reached */ /* match occurs only when the end of both strings has been reached */
return (boolean)(!c1 && !c2); return (boolean) (!c1 && !c2);
} }
/* /*
* Time routines * Time routines
* *
* The time is used for: * The time is used for:
* - seed for rand() * - seed for rand()
* - year on tombstone and yyyymmdd in record file * - year on tombstone and yyyymmdd in record file
* - phase of the moon (various monsters react to NEW_MOON or FULL_MOON) * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
* - night and midnight (the undead are dangerous at midnight) * - night and midnight (the undead are dangerous at midnight)
* - determination of what files are "very old" * - determination of what files are "very old"
*/ */
/* TIME_type: type of the argument to time(); we actually use &(time_t) */ /* TIME_type: type of the argument to time(); we actually use &(time_t) */
@@ -667,14 +710,23 @@ void
setrandom() setrandom()
{ {
unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */ unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
#ifdef UNIX
/* Quick dirty band-aid to prevent PRNG prediction */ #if defined(UNIX) || defined(VMS)
seed *= getpid(); {
unsigned long pid = (unsigned long) getpid();
/* Quick dirty band-aid to prevent PRNG prediction */
if (pid) {
if (!(pid & 3L))
pid -= 1L;
seed *= pid;
}
}
#endif #endif
/* the types are different enough here that sweeping the different /* the types are different enough here that sweeping the different
* routine names into one via #defines is even more confusing * routine names into one via #defines is even more confusing
*/ */
#ifdef RANDOM /* srandom() from sys/share/random.c */ #ifdef RANDOM /* srandom() from sys/share/random.c */
srandom((unsigned int) seed); srandom((unsigned int) seed);
#else #else
@@ -723,17 +775,17 @@ char *
yymmdd(date) yymmdd(date)
time_t date; time_t date;
{ {
Static char datestr[10]; Static char datestr[10];
struct tm *lt; struct tm *lt;
if (date == 0) if (date == 0)
lt = getlt(); lt = getlt();
else else
lt = localtime((LOCALTIME_type) &date); lt = localtime((LOCALTIME_type) &date);
Sprintf(datestr, "%02d%02d%02d", Sprintf(datestr, "%02d%02d%02d",
lt->tm_year, lt->tm_mon + 1, lt->tm_mday); lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
return(datestr); return datestr;
} }
#endif #endif
@@ -804,7 +856,7 @@ time_t date;
Sprintf(datestr, "%04ld%02d%02d%02d%02d%02d", datenum, lt->tm_mon + 1, Sprintf(datestr, "%04ld%02d%02d%02d%02d%02d", datenum, lt->tm_mon + 1,
lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
debugpline1("yyyymmddhhmmss() produced date string %s", datestr); debugpline1("yyyymmddhhmmss() produced date string %s", datestr);
return (datestr); return datestr;
} }
time_t time_t
@@ -815,6 +867,7 @@ char *buf;
time_t timeresult = (time_t) 0; time_t timeresult = (time_t) 0;
struct tm t, *lt; struct tm t, *lt;
char *g, *p, y[5], mo[3], md[3], h[3], mi[3], s[3]; char *g, *p, y[5], mo[3], md[3], h[3], mi[3], s[3];
if (buf && strlen(buf) == 14) { if (buf && strlen(buf) == 14) {
g = buf; g = buf;
p = y; /* year */ p = y; /* year */
@@ -864,17 +917,18 @@ char *buf;
/* /*
* moon period = 29.53058 days ~= 30, year = 365.2422 days * moon period = 29.53058 days ~= 30, year = 365.2422 days
* days moon phase advances on first day of year compared to preceding year * days moon phase advances on first day of year compared to preceding year
* = 365.2422 - 12*29.53058 ~= 11 * = 365.2422 - 12*29.53058 ~= 11
* years in Metonic cycle (time until same phases fall on the same days of * years in Metonic cycle (time until same phases fall on the same days of
* the month) = 18.6 ~= 19 * the month) = 18.6 ~= 19
* moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30 * moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30
* (29 as initial condition) * (29 as initial condition)
* current phase in days = first day phase + days elapsed in year * current phase in days = first day phase + days elapsed in year
* 6 moons ~= 177 days * 6 moons ~= 177 days
* 177 ~= 8 reported phases * 22 * 177 ~= 8 reported phases * 22
* + 11/22 for rounding * + 11/22 for rounding
*/ */
int phase_of_the_moon() /* 0-7, with 0: new, 4: full */ int
phase_of_the_moon() /* 0-7, with 0: new, 4: full */
{ {
register struct tm *lt = getlt(); register struct tm *lt = getlt();
register int epact, diy, goldn; register int epact, diy, goldn;
@@ -893,7 +947,8 @@ friday_13th()
{ {
register struct tm *lt = getlt(); register struct tm *lt = getlt();
return ((boolean)(lt->tm_wday == 5 /* friday */ && lt->tm_mday == 13)); /* tm_wday (day of week; 0==Sunday) == 5 => Friday */
return (boolean) (lt->tm_wday == 5 && lt->tm_mday == 13);
} }
int int