1 /* NetHack 3.6 hacklib.c $NHDT-Date: 1446336792 2015/11/01 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* Copyright (c) Robert Patrick Rankin, 1991 */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
9 /* JNetHack may be freely redistributed. See license for details. */
11 #include "hack.h" /* for config.h+extern.h */
13 Assorted 'small' utility routines. They're virtually independent of
14 NetHack, except that rounddiv may call panic(). setrandom calls one
15 of srandom(), srand48(), or srand() depending upon configuration.
17 return type routine name argument type(s)
24 char * upstart (char *)
25 char * mungspaces (char *)
27 boolean str_end_is (const char *, const char *)
28 char * strkitten (char *,char)
29 void copynchars (char *,const char *,int)
30 char chrcasecpy (int,int)
31 char * strcasecpy (char *,const char *)
32 char * s_suffix (const char *)
33 char * ing_suffix (const char *)
34 char * xcrypt (const char *, char *)
35 boolean onlyspace (const char *)
36 char * tabexpand (char *)
38 char * strsubst (char *, const char *, const char *)
39 const char * ordin (int)
42 int rounddiv (long, int)
43 int distmin (int, int, int, int)
44 int dist2 (int, int, int, int)
45 boolean online2 (int, int)
46 boolean pmatch (const char *, const char *)
47 boolean pmatchi (const char *, const char *)
48 boolean pmatchz (const char *, const char *)
49 int strncmpi (const char *, const char *, int)
50 char * strstri (const char *, const char *)
51 boolean fuzzymatch (const char *,const char *,
52 const char *, boolean)
56 char * yymmdd (time_t)
57 long yyyymmdd (time_t)
59 char * yyyymmddhhmmss (time_t)
60 time_t time_from_yyyymmddhhmmss (char *)
61 int phase_of_the_moon (void)
62 boolean friday_13th (void)
67 #define Static /* pacify lint */
72 static boolean FDECL(pmatch_internal, (const char *, const char *,
73 BOOLEAN_P, const char *));
80 return (boolean) ('0' <= c && c <= '9');
83 /* is 'c' a letter? note: '@' classed as letter */
88 return (boolean) ('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
91 /* force 'c' into uppercase */
96 return (char) (('a' <= c && c <= 'z') ? (c & ~040) : c);
99 /* force 'c' into lowercase */
104 return (char) (('A' <= c && c <= 'Z') ? (c | 040) : c);
107 /* convert a string into all lowercase */
115 #if 1 /*JP*//*
\8a¿
\8e\9a\82Í
\8f¬
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
116 if (is_kanji(*(unsigned char *)p)) p++; else
118 if ('A' <= *p && *p <= 'Z')
123 /* convert a string into all uppercase */
131 #if 1 /*JP*//*
\8a¿
\8e\9a\82Í
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
132 if (is_kanji(*(unsigned char *)p)) p++; else
134 if ('a' <= *p && *p <= 'z')
139 /* convert first character of a string to uppercase */
149 /* remove excess whitespace from a string buffer (in place) */
154 register char c, *p, *p2;
155 boolean was_space = TRUE;
157 for (p = p2 = bp; (c = *p) != '\0'; p++) {
159 break; /* treat newline the same as end-of-string */
162 if (c != ' ' || !was_space)
164 was_space = (c == ' ');
166 if (was_space && p2 > bp)
172 /* return the end of a string (pointing at '\0') */
178 s++; /* s += strlen(s); */
182 /* determine whether 'str' ends in 'chkstr' */
184 str_end_is(str, chkstr)
185 const char *str, *chkstr;
187 int clen = (int) strlen(chkstr);
189 if ((int) strlen(str) >= clen)
190 return (boolean) (!strncmp(eos((char *) str) - clen, chkstr, clen));
194 /* append a character to a string (in place): strcat(s, {c,'\0'}); */
207 /* truncating string copy */
209 copynchars(dst, src, n)
214 /* copies at most n characters, stopping sooner if terminator reached;
215 treats newline as input terminator; unlike strncpy, always supplies
216 '\0' terminator so dst must be able to hold at least n+1 characters */
217 while (n > 0 && *src != '\0' && *src != '\n') {
224 /* convert char nc into oc's case; mostly used by strcasecpy */
229 #if 0 /* this will be necessary if we switch to <ctype.h> */
230 oc = (int) (unsigned char) oc;
231 nc = (int) (unsigned char) nc;
233 if ('a' <= oc && oc <= 'z') {
234 /* old char is lower case; if new char is upper case, downcase it */
235 if ('A' <= nc && nc <= 'Z')
236 nc += 'a' - 'A'; /* lowc(nc) */
237 } else if ('A' <= oc && oc <= 'Z') {
238 /* old char is upper case; if new char is lower case, upcase it */
239 if ('a' <= nc && nc <= 'z')
240 nc += 'A' - 'a'; /* highc(nc) */
245 /* overwrite string, preserving old chars' case;
246 for case-insensitive editions of makeplural() and makesingular();
247 src might be shorter, same length, or longer than dst */
254 int ic, oc, dst_exhausted = 0;
256 /* while dst has characters, replace each one with corresponding
257 character from src, converting case in the process if they differ;
258 once dst runs out, propagate the case of its last character to any
259 remaining src; if dst starts empty, it must be a pointer to the
260 tail of some other string because we examine the char at dst[-1] */
261 while ((ic = (int) *src++) != '\0') {
262 if (!dst_exhausted && !*dst)
264 oc = (int) *(dst - dst_exhausted);
265 *dst++ = chrcasecpy(oc, ic);
271 /* return a name converted to possessive */
276 Static char buf[BUFSZ];
279 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\8a\97L
\8ai
\82Ìs
\82ð
\95t
\82¯
\82È
\82¢*/
280 if (!strcmpi(buf, "it")) /* it -> its */
282 else if (!strcmpi(buf, "you")) /* you -> your */
284 else if (*(eos(buf) - 1) == 's') /* Xs -> Xs' */
292 /* construct a gerund (a verb formed by appending "ing" to a noun) */
297 const char *vowel = "aeiouy";
298 static char buf[BUFSZ];
304 onoff[0] = *p = *(p + 1) = '\0';
305 if ((strlen(buf) > 4)
306 && (!strcmpi(p - 3, " on") || !strcmpi(p - 4, " off")
307 || !strcmpi(p - 5, " with"))) {
308 p = strrchr(buf, ' ');
311 if (!index(vowel, *(p - 1)) && index(vowel, *(p - 2))
312 && !index(vowel, *(p - 3))) {
313 /* tip -> tipp + ing */
316 } else if (!strcmpi(p - 2, "ie")) { /* vie -> vy + ing */
319 } else if (*(p - 1) == 'e') /* grease -> greas + ing */
327 /* trivial text encryption routine (see makedefs) */
333 register const char *p;
335 register int bitmask;
337 for (bitmask = 1, p = str, q = buf; *p; q++) {
341 if ((bitmask <<= 1) >= 32)
348 /* is a string entirely whitespace? */
354 if (*s != ' ' && *s != '\t')
359 /* expand tabs into proper number of spaces */
365 register char *bp, *s = sbuf;
370 /* warning: no bounds checking performed */
371 for (bp = buf, idx = 0; *s; s++)
381 return strcpy(sbuf, buf);
384 /* make a displayable string from a character */
395 ccc[1] = c | 0100; /* letter */
396 } else if (c == 0177) {
398 ccc[1] = c & ~0100; /* '?' */
400 ccc[0] = c; /* printable character */
406 /* substitute a word or phrase in a string (in place) */
407 /* caller is responsible for ensuring that bp points to big enough buffer */
409 strsubst(bp, orig, replacement)
411 const char *orig, *replacement;
413 char *found, buf[BUFSZ];
416 found = strstr(bp, orig);
418 Strcpy(buf, found + strlen(orig));
419 Strcpy(found, replacement);
426 /* return the ordinal suffix of a number */
429 int n; /* note: should be non-negative */
431 register int dd = n % 10;
433 return (dd == 0 || dd > 3 || (n % 100) / 10 == 1) ? "th"
434 : (dd == 1) ? "st" : (dd == 2) ? "nd" : "rd";
437 /* make a signed digit string from a number */
444 Sprintf(buf, (n < 0) ? "%d" : "+%d", n);
448 /* return the sign of a number: -1, 0, or 1 */
453 return (n < 0) ? -1 : (n != 0);
456 /* calculate x/y, rounding as appropriate */
466 panic("division by zero in rounddiv");
483 /* distance between two points, in moves */
485 distmin(x0, y0, x1, y1)
488 register int dx = x0 - x1, dy = y0 - y1;
494 /* The minimum number of moves to get from (x0,y0) to (x1,y1) is the
495 * larger of the [absolute value of the] two deltas.
497 return (dx < dy) ? dy : dx;
500 /* square of euclidean distance between pair of pts */
502 dist2(x0, y0, x1, y1)
505 register int dx = x0 - x1, dy = y0 - y1;
507 return dx * dx + dy * dy;
510 /* integer square root function without using floating point */
518 * This could be replaced by a faster algorithm, but has not been because:
519 * + the simple algorithm is easy to read;
520 * + this algorithm does not require 64-bit support;
521 * + in current usage, the values passed to isqrt() are not really that
522 * large, so the performance difference is negligible;
523 * + isqrt() is used in only few places, which are not bottle-necks.
533 /* are two points lined up (on a straight line)? */
535 online2(x0, y0, x1, y1)
538 int dx = x0 - x1, dy = y0 - y1;
539 /* If either delta is zero then they're on an orthogonal line,
540 * else if the deltas are equal (signs ignored) they're on a diagonal.
542 return (boolean) (!dy || !dx || dy == dx || dy == -dx);
545 /* guts of pmatch(), pmatchi(), and pmatchz();
546 match a string against a pattern */
548 pmatch_internal(patrn, strng, ci, sk)
549 const char *patrn, *strng;
550 boolean ci; /* True => case-insensitive, False => case-sensitive */
551 const char *sk; /* set of characters to skip */
555 * Simple pattern matcher: '*' matches 0 or more characters, '?' matches
556 * any single character. Returns TRUE if 'strng' matches 'patrn'.
561 p = *patrn++; /* get next chars and pre-advance */
563 /* fuzzy match variant of pmatch; particular characters are ignored */
566 } while (index(sk, s));
569 } while (index(sk, p));
571 if (!p) /* end of pattern */
572 return (boolean) (s == '\0'); /* matches iff end of string too */
573 else if (p == '*') /* wildcard reached */
574 return (boolean) ((!*patrn
575 || pmatch_internal(patrn, strng - 1, ci, sk))
577 : s ? pmatch_internal(patrn - 1, strng, ci, sk)
579 else if ((ci ? lowc(p) != lowc(s) : p != s) /* check single character */
580 && (p != '?' || !s)) /* & single-char wildcard */
581 return FALSE; /* doesn't match */
582 else /* return pmatch_internal(patrn, strng, ci, sk); */
583 goto pmatch_top; /* optimize tail recursion */
586 /* case-sensitive wildcard match */
589 const char *patrn, *strng;
591 return pmatch_internal(patrn, strng, FALSE, (const char *) 0);
594 /* case-insensitive wildcard match */
596 pmatchi(patrn, strng)
597 const char *patrn, *strng;
599 return pmatch_internal(patrn, strng, TRUE, (const char *) 0);
602 /* case-insensitive wildcard fuzzymatch */
604 pmatchz(patrn, strng)
605 const char *patrn, *strng;
607 /* ignore spaces, tabs (just in case), dashes, and underscores */
608 static const char fuzzychars[] = " \t-_";
610 return pmatch_internal(patrn, strng, TRUE, fuzzychars);
614 /* case insensitive counted string comparison */
616 strncmpi(s1, s2, n) /*{ aka strncasecmp }*/
617 register const char *s1, *s2;
618 register int n; /*(should probably be size_t, which is unsigned)*/
620 register char t1, t2;
624 return (*s1 != 0); /* s1 >= s2 */
626 return -1; /* s1 < s2 */
630 return (t1 > t2) ? 1 : -1;
632 return 0; /* s1 == s2 */
634 #endif /* STRNCMPI */
637 /* case insensitive substring search */
643 register const char *s1, *s2;
645 #define TABSIZ 0x20 /* 0x40 would be case-sensitive */
646 char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */
648 assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */
649 assert( &lowc != 0 ); /* can't be unsafe macro */
652 /* special case: empty substring */
656 /* do some useful work while determining relative lengths */
657 for (i = 0; i < TABSIZ; i++)
658 tstr[i] = tsub[i] = 0; /* init */
659 for (k = 0, s1 = str; *s1; k++)
660 tstr[*s1++ & (TABSIZ - 1)]++;
661 for (s2 = sub; *s2; --k)
662 tsub[*s2++ & (TABSIZ - 1)]++;
664 /* evaluate the info we've collected */
666 return (char *) 0; /* sub longer than str, so can't match */
667 for (i = 0; i < TABSIZ; i++) /* does sub have more 'x's than str? */
668 if (tsub[i] > tstr[i])
669 return (char *) 0; /* match not possible */
671 /* now actually compare the substring repeatedly to parts of the string */
672 for (i = 0; i <= k; i++) {
675 while (lowc(*s1++) == lowc(*s2++))
677 return (char *) &str[i]; /* full match */
679 return (char *) 0; /* not found */
683 /* compare two strings for equality, ignoring the presence of specified
684 characters (typically whitespace) and possibly ignoring case */
686 fuzzymatch(s1, s2, ignore_chars, caseblind)
688 const char *ignore_chars;
691 register char c1, c2;
694 while ((c1 = *s1++) != '\0' && index(ignore_chars, c1) != 0)
696 while ((c2 = *s2++) != '\0' && index(ignore_chars, c2) != 0)
699 break; /* stop when end of either string is reached */
707 /* match occurs only when the end of both strings has been reached */
708 return (boolean) (!c1 && !c2);
714 * The time is used for:
716 * - year on tombstone and yyyymmdd in record file
717 * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
718 * - night and midnight (the undead are dangerous at midnight)
719 * - determination of what files are "very old"
722 /* TIME_type: type of the argument to time(); we actually use &(time_t) */
723 #if defined(BSD) && !defined(POSIX_TYPES)
724 #define TIME_type long *
726 #define TIME_type time_t *
728 /* LOCALTIME_type: type of the argument to localtime() */
729 #if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) \
730 || (defined(BSD) && !defined(POSIX_TYPES))
731 #define LOCALTIME_type long *
733 #define LOCALTIME_type time_t *
736 #if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60) \
737 && !defined(_DCC) && !defined(__GNUC__)
738 extern struct tm *FDECL(localtime, (time_t *));
740 STATIC_DCL struct tm *NDECL(getlt);
745 unsigned long seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
747 #if defined(UNIX) || defined(VMS)
749 unsigned long pid = (unsigned long) getpid();
751 /* Quick dirty band-aid to prevent PRNG prediction */
760 /* the types are different enough here that sweeping the different
761 * routine names into one via #defines is even more confusing
763 #ifdef RANDOM /* srandom() from sys/share/random.c */
764 srandom((unsigned int) seed);
766 #if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \
767 || defined(CYGWIN32) /* system srandom() */
768 #if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4)
773 #ifdef UNIX /* system srand48() */
774 srand48((long) seed);
775 #else /* poor quality system routine */
787 (void) time((TIME_type) &datetime);
791 STATIC_OVL struct tm *
794 time_t date = getnow();
796 return localtime((LOCALTIME_type) &date);
802 return (1900 + getlt()->tm_year);
806 /* This routine is no longer used since in 20YY it yields "1YYmmdd". */
811 Static char datestr[10];
817 lt = localtime((LOCALTIME_type) &date);
819 Sprintf(datestr, "%02d%02d%02d",
820 lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
835 lt = localtime((LOCALTIME_type) &date);
837 /* just in case somebody's localtime supplies (year % 100)
838 rather than the expected (year - 1900) */
839 if (lt->tm_year < 70)
840 datenum = (long) lt->tm_year + 2000L;
842 datenum = (long) lt->tm_year + 1900L;
843 /* yyyy --> yyyymm */
844 datenum = datenum * 100L + (long) (lt->tm_mon + 1);
845 /* yyyymm --> yyyymmdd */
846 datenum = datenum * 100L + (long) lt->tm_mday;
860 lt = localtime((LOCALTIME_type) &date);
862 timenum = lt->tm_hour * 10000L + lt->tm_min * 100L + lt->tm_sec;
871 static char datestr[15];
877 #if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) \
879 lt = localtime((long *) (&date));
881 lt = localtime(&date);
883 /* just in case somebody's localtime supplies (year % 100)
884 rather than the expected (year - 1900) */
885 if (lt->tm_year < 70)
886 datenum = (long) lt->tm_year + 2000L;
888 datenum = (long) lt->tm_year + 1900L;
889 Sprintf(datestr, "%04ld%02d%02d%02d%02d%02d", datenum, lt->tm_mon + 1,
890 lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
891 debugpline1("yyyymmddhhmmss() produced date string %s", datestr);
896 time_from_yyyymmddhhmmss(buf)
900 time_t timeresult = (time_t) 0;
902 char *g, *p, y[5], mo[3], md[3], h[3], mi[3], s[3];
904 if (buf && strlen(buf) == 14) {
907 for (k = 0; k < 4; ++k)
911 for (k = 0; k < 2; ++k)
915 for (k = 0; k < 2; ++k)
919 for (k = 0; k < 2; ++k)
922 p = mi; /* minutes */
923 for (k = 0; k < 2; ++k)
927 for (k = 0; k < 2; ++k)
933 t.tm_year = atoi(y) - 1900;
934 t.tm_mon = atoi(mo) - 1;
935 t.tm_mday = atoi(md);
939 timeresult = mktime(&t);
941 if ((int) timeresult == -1)
942 debugpline1("time_from_yyyymmddhhmmss(%s) would have returned -1",
951 * moon period = 29.53058 days ~= 30, year = 365.2422 days
952 * days moon phase advances on first day of year compared to preceding year
953 * = 365.2422 - 12*29.53058 ~= 11
954 * years in Metonic cycle (time until same phases fall on the same days of
955 * the month) = 18.6 ~= 19
956 * moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30
957 * (29 as initial condition)
958 * current phase in days = first day phase + days elapsed in year
959 * 6 moons ~= 177 days
960 * 177 ~= 8 reported phases * 22
961 * + 11/22 for rounding
964 phase_of_the_moon() /* 0-7, with 0: new, 4: full */
966 register struct tm *lt = getlt();
967 register int epact, diy, goldn;
970 goldn = (lt->tm_year % 19) + 1;
971 epact = (11 * goldn + 18) % 30;
972 if ((epact == 25 && goldn > 11) || epact == 24)
975 return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
981 register struct tm *lt = getlt();
983 /* tm_wday (day of week; 0==Sunday) == 5 => Friday */
984 return (boolean) (lt->tm_wday == 5 && lt->tm_mday == 13);
990 register int hour = getlt()->tm_hour;
992 return (hour < 6 || hour > 21);
998 return (getlt()->tm_hour == 0);