home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)hacklib.c 3.1 91/11/25 */
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* Copyright (c) Robert Patrick Rankin, 1991 */
- /* NetHack may be freely redistributed. See license for details. */
-
- /* We could only include config.h, except for the overlay definitions... */
- #include "hack.h"
- /*=
- Assorted 'small' utility routines. They're virtually independent of
- NetHack, except that rounddiv may call panic().
-
- return type routine name argument type(s)
- boolean digit (char)
- boolean letter (char)
- char highc (char)
- char lowc (char)
- char * lcase (char *)
- char * eos (char *)
- char * s_suffix (const char *)
- char * xcrypt (const char *)
- boolean onlyspace (const char *)
- char * tabexpand (char *)
- char * visctrl (char)
- const char * ordin (int)
- char * sitoa (int)
- int sgn (int)
- int rounddiv (long, int)
- int distmin (int, int, int, int)
- int dist2 (int, int, int, int)
- boolean online2 (int, int)
- boolean pmatch (const char *, const char *)
- int strncmpi (const char *, const char *, int)
- char * strstri (const char *, const char *)
- void setrandom (void)
- int getyear (void)
- char * get_date (void)
- int phase_of_the_moon (void)
- boolean friday_13th (void)
- int night (void)
- int midnight (void)
- =*/
- #ifdef LINT
- # define Static /* pacify lint */
- #else
- # define Static static
- #endif
-
- #ifdef OVLB
- boolean
- digit(c) /* is 'c' a digit? */
- char c;
- {
- return '0' <= c && c <= '9';
- }
-
- boolean
- letter(c) /* is 'c' a letter? note: '@' classed as letter */
- char c;
- {
- return ('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
- }
- #endif /* OVLB */
-
- #ifdef OVL1
- char
- highc(c) /* force 'c' into uppercase */
- char c;
- {
- return ('a' <= c && c <= 'z') ? (c & ~040) : c;
- }
-
- char
- lowc(c) /* force 'c' into lowercase */
- char c;
- {
- return ('A' <= c && c <= 'Z') ? (c | 040) : c;
- }
- #endif /* OVL1 */
-
- #ifdef OVLB
- char *
- lcase(s) /* convert a string into all lowercase */
- char *s;
- {
- register char *p;
-
- for (p = s; *p; p++)
- if ('A' <= *p && *p <= 'Z') *p |= 040;
- return s;
- }
- #endif /* OVLB */
-
- #ifdef OVL0
- char *
- eos(s) /* return the end of a string (pointing at '\0') */
- register char *s;
- {
- while (*s) s++; /* s += strlen(s); */
- return s;
- }
-
- char *
- s_suffix(s) /* return a name converted to possessive */
- const char *s;
- {
- Static char buf[BUFSZ];
-
- Strcpy(buf, s);
- if(!strcmpi(buf, "it"))
- Strcat(buf, "s");
- else if(*(eos(buf)-1) == 's')
- Strcat(buf, "'");
- else
- Strcat(buf, "'s");
- return buf;
- }
-
- char *
- xcrypt(str) /* trivial text encryption routine (see makedefs) */
- const char *str;
- {
- Static char buf[BUFSZ];
- register const char *p;
- register char *q;
- register int bitmask;
-
- for (bitmask = 1, p = str, q = buf; *p; q++) {
- *q = *p++;
- if (*q & (32|64)) *q ^= bitmask;
- if ((bitmask <<= 1) >= 32) bitmask = 1;
- }
- *q = '\0';
- return buf;
- }
- #endif /* OVL0 */
-
- #ifdef OVL2
- boolean
- onlyspace(s) /* is a string entirely whitespace? */
- const char *s;
- {
- for (; *s; s++)
- if (*s != ' ' && *s != '\t') return FALSE;
- return TRUE;
- }
- #endif /* OVL2 */
-
- #ifdef OVLB
- char *
- tabexpand(sbuf) /* expand tabs into proper number of spaces */
- char *sbuf;
- {
- char buf[BUFSZ];
- register char *bp, *s = sbuf;
- register int idx;
-
- if (!*s) return sbuf;
-
- /* warning: no bounds checking performed */
- for (bp = buf, idx = 0; *s; s++)
- if (*s == '\t') {
- do *bp++ = ' '; while (++idx % 8);
- } else {
- *bp++ = *s;
- idx++;
- }
- *bp = 0;
- return strcpy(sbuf, buf);
- }
-
- char *
- visctrl(c) /* make a displayable string from a character */
- char c;
- {
- Static char ccc[3];
-
- c &= 0177;
-
- ccc[2] = '\0';
- if (c < 040) {
- ccc[0] = '^';
- ccc[1] = c | 0100; /* letter */
- } else if (c == 0177) {
- ccc[0] = '^';
- ccc[1] = c & ~0100; /* '?' */
- } else {
- ccc[0] = c; /* printable character */
- ccc[1] = '\0';
- }
- return ccc;
- }
- #endif /* OVLB */
-
- #ifdef OVL2
- const char *
- ordin(n) /* return the ordinal suffix of a number */
- int n; /* note: should be non-negative */
- {
- register int dd = n % 10;
-
- return (dd == 0 || dd > 3 || (n % 100) / 10 == 1) ? "th" :
- (dd == 1) ? "st" : (dd == 2) ? "nd" : "rd";
- }
- #endif /* OVL2 */
-
- #ifdef OVL1
- char *
- sitoa(n) /* make a signed digit string from a number */
- int n;
- {
- Static char buf[13];
-
- (void) sprintf(buf, (n < 0) ? "%d" : "+%d", n);
- return buf;
- }
-
- int
- sgn(n) /* return the sign of a number: -1, 0, or 1 */
- int n;
- {
- return (n < 0) ? -1 : (n != 0);
- }
- #endif /* OVL1 */
-
- #ifdef OVLB
- int
- rounddiv(x, y) /* calculate x/y, rounding as appropriate */
- long x;
- int y;
- {
- int r, m;
- int divsgn = 1;
-
- if (y == 0)
- panic("division by zero in rounddiv");
- else if (y < 0) {
- divsgn = -divsgn; y = -y;
- }
- if (x < 0) {
- divsgn = -divsgn; x = -x;
- }
- r = x / y;
- m = x % y;
- if (2*m >= y) r++;
-
- return divsgn * r;
- }
- #endif /* OVLB */
-
- #ifdef OVL0
- int
- distmin(x0, y0, x1, y1) /* distance between two points, in moves */
- int x0, y0, x1, y1;
- {
- register int dx = x0 - x1, dy = y0 - y1;
- if (dx < 0) dx = -dx;
- if (dy < 0) dy = -dy;
- /* The minimum number of moves to get from (x0,y0) to (x1,y1) is the
- : larger of the [absolute value of the] two deltas.
- */
- return (dx < dy) ? dy : dx;
- }
-
- int
- dist2(x0, y0, x1, y1) /* square of euclidean distance between pair of pts */
- int x0, y0, x1, y1;
- {
- register int dx = x0 - x1, dy = y0 - y1;
- return dx * dx + dy * dy;
- }
-
- boolean
- online2(x0, y0, x1, y1) /* are two points lined up (on a straight line)? */
- int x0, y0, x1, y1;
- {
- register dx = x0 - x1, dy = y0 - y1;
- /* 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.
- */
- return !dy || !dx || (dy == dx) || (dy + dx == 0); /* (dy == -dx) */
- }
-
- #endif /* OVL0 */
- #ifdef OVLB
-
- boolean
- pmatch(patrn, strng) /* match a string against a pattern */
- const char *patrn, *strng;
- {
- char s, p;
- /*
- : Simple pattern matcher: '*' matches 0 or more characters, '?' matches
- : any single character. Returns TRUE if 'strng' matches 'patrn'.
- */
- pmatch_top:
- s = *strng++; p = *patrn++; /* get next chars and pre-advance */
- if (!p) /* end of pattern */
- return (s == '\0'); /* matches iff end of string too */
- else if (p == '*') /* wildcard reached */
- return (!*patrn || pmatch(patrn, strng-1)) ? TRUE :
- s ? pmatch(patrn-1, strng) : FALSE;
- else if (p != s && (p != '?' || !s)) /* check single character */
- return FALSE; /* doesn't match */
- else /* return pmatch(patrn, strng); */
- goto pmatch_top; /* optimize tail recursion */
- }
- #endif /* OVLB */
-
- #ifdef OVL2
- #ifndef STRNCMPI
- int
- strncmpi(s1, s2, n) /* case insensitive counted string comparison */
- register const char *s1, *s2;
- register int n; /*(should probably be size_t, which is usually unsigned)*/
- { /*{ aka strncasecmp }*/
- register char t1, t2;
-
- while (n--) {
- if (!*s2) return (*s1 != 0); /* s1 >= s2 */
- else if (!*s1) return -1; /* s1 < s2 */
- t1 = lowc(*s1++);
- t2 = lowc(*s2++);
- if (t1 != t2) return (t1 > t2) ? 1 : -1;
- }
- return 0; /* s1 == s2 */
- }
- #endif /* STRNCMPI */
- #endif /* OVL2 */
-
- #ifdef OVLB
- #ifndef STRSTRI
-
- /* A note on the #ifndef GCC_WARN: "const" unfortunately has two different
- * meanings. One meaning for "const char *str" is that the data pointed
- * to by "str" happens not to be modified by this function. That is true
- * for strstri. Another meaning is that "str" is (or may be) a pointer
- * to a constant string that must never be modified. gcc takes the latter
- * interpretation, and warns us about possible subversion of the const
- * modifier. Actually, that warning can be useful (we could accidentally
- * turn a constant string into a non-constant one with this function)
- * and so we note the fact that we're returning "str" as a non-const
- * by declaring it as non-const if GCC_WARN is defined.
- */
-
- char *
- strstri(str, sub) /* case insensitive substring search */
- #ifndef GCC_WARN
- const
- #endif
- char *str;
- const char *sub;
- {
- register const char *s1, *s2;
- register int i, k;
- # define TABSIZ 0x20 /* 0x40 would be case-sensitive */
- char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */
- # if 0
- assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */
- assert( &lowc != 0 ); /* can't be unsafe macro */
- # endif
-
- /* special case: empty substring */
- if (!*sub) return (char *) str;
-
- /* do some useful work while determining relative lengths */
- for (i = 0; i < TABSIZ; i++) tstr[i] = tsub[i] = 0; /* init */
- for (k = 0, s1 = str; *s1; k++) tstr[*s1++ & (TABSIZ-1)]++;
- for ( s2 = sub; *s2; --k) tsub[*s2++ & (TABSIZ-1)]++;
-
- /* evaluate the info we've collected */
- if (k < 0) return (char *) 0; /* sub longer than str, so can't match */
- for (i = 0; i < TABSIZ; i++) /* does sub have more 'x's than str? */
- if (tsub[i] > tstr[i]) return (char *) 0; /* match not possible */
-
- /* now actually compare the substring repeatedly to parts of the string */
- for (i = 0; i <= k; i++) {
- s1 = &str[i];
- s2 = sub;
- while (lowc(*s1++) == lowc(*s2++))
- if (!*s2) return (char *) &str[i]; /* full match */
- }
- return (char *) 0; /* not found */
- }
- #endif /* STRSTRI */
- #endif /* OVLB */
-
- #ifdef OVL2
- /*
- * Time routines
- *
- * The time is used for:
- * - seed for rand()
- * - year on tombstone and yymmdd in record file
- * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
- * - night and midnight (the undead are dangerous at midnight)
- * - determination of what files are "very old"
- */
-
- #if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60)
- extern struct tm *FDECL(localtime,(time_t *));
- #endif
- static struct tm *NDECL(getlt);
-
- void
- setrandom()
- {
- /* the types are different enough here that sweeping the different
- * routine names into one via #defines is even more confusing
- */
- #ifdef RANDOM /* srandom() from sys/share/random.c */
- srandom((unsigned int) time((time_t *)0));
- #else
- # if defined(BSD) || defined(ULTRIX) /* system srandom() */
- # ifdef BSD
- # if defined(SUNOS4)
- (void)
- # endif
- srandom((int) time((long *)0));
- # else
- srandom((int) time((time_t *)0));
- # endif
- # else
- # ifdef UNIX /* system srand48() */
- srand48((long) time((time_t *)0));
- # else /* poor quality system routine */
- srand((int) time((time_t *)0));
- # endif
- # endif
- #endif
- }
-
- static struct tm *
- getlt()
- {
- time_t date;
-
- #ifdef BSD
- (void) time((long *)(&date));
- #else
- (void) time(&date);
- #endif
- #if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD)
- return(localtime((long *)(&date)));
- #else
- return(localtime(&date));
- #endif
- }
-
- int
- getyear()
- {
- return(1900 + getlt()->tm_year);
- }
-
- char *
- get_date()
- {
- Static char datestr[7];
- register struct tm *lt = getlt();
-
- Sprintf(datestr, "%2d%2d%2d",
- lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
- if(datestr[2] == ' ') datestr[2] = '0';
- if(datestr[4] == ' ') datestr[4] = '0';
- return(datestr);
- }
-
- int
- phase_of_the_moon() /* 0-7, with 0: new, 4: full */
- /* moon period: 2551442 seconds == 29.53058 days */
- /* 722578680: date when there was a new moon (Tue Nov 24 04:18 1992) */
- /* *8/2551442: divide into 8 phases */
- /* *8 +2551442/2 /2551442: let the division round to nearest instead of down */
- {
- #ifdef BSD
- long now = time((long *)0);
- #else
- long now = time((time_t *)0);
- #endif
-
- return (int) (((((now - 722578680L) % 2551442L) * 8L) + 2551442L/2L)
- / 2551442L);
- }
-
- boolean
- friday_13th()
- {
- register struct tm *lt = getlt();
-
- return (lt->tm_wday == 5 /* friday */ && lt->tm_mday == 13);
- }
-
- int
- night()
- {
- register int hour = getlt()->tm_hour;
-
- return(hour < 6 || hour > 21);
- }
-
- int
- midnight()
- {
- return(getlt()->tm_hour == 0);
- }
- #endif /* OVL2 */
-
- /*hacklib.c*/
-