230 lines
5.4 KiB
C
230 lines
5.4 KiB
C
/* NetHack 3.7 calendar.c $NHDT-Date: 1706213796 2024/01/25 20:16:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.116 $ */
|
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
|
/*-Copyright (c) Michael Allison, 2007. */
|
|
/* Copyright (c) Robert Patrick Rankin, 1991 */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
|
|
/*
|
|
* Time routines
|
|
*
|
|
* The time is used for:
|
|
* - seed for rand()
|
|
* - year on tombstone and yyyymmdd 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"
|
|
*/
|
|
|
|
/* TIME_type: type of the argument to time(); we actually use &(time_t);
|
|
you might need to define either or both of these to 'long *' in *conf.h */
|
|
#ifndef TIME_type
|
|
#define TIME_type time_t *
|
|
#endif
|
|
#ifndef LOCALTIME_type
|
|
#define LOCALTIME_type time_t *
|
|
#endif
|
|
|
|
staticfn struct tm *getlt(void);
|
|
|
|
time_t
|
|
getnow(void)
|
|
{
|
|
time_t datetime = 0;
|
|
|
|
(void) time((TIME_type) &datetime);
|
|
return datetime;
|
|
}
|
|
|
|
staticfn struct tm *
|
|
getlt(void)
|
|
{
|
|
time_t date = getnow();
|
|
|
|
return localtime((LOCALTIME_type) &date);
|
|
}
|
|
|
|
int
|
|
getyear(void)
|
|
{
|
|
return (1900 + getlt()->tm_year);
|
|
}
|
|
|
|
|
|
long
|
|
yyyymmdd(time_t date)
|
|
{
|
|
long datenum;
|
|
struct tm *lt;
|
|
|
|
if (date == 0)
|
|
lt = getlt();
|
|
else
|
|
lt = localtime((LOCALTIME_type) &date);
|
|
|
|
/* just in case somebody's localtime supplies (year % 100)
|
|
rather than the expected (year - 1900) */
|
|
if (lt->tm_year < 70)
|
|
datenum = (long) lt->tm_year + 2000L;
|
|
else
|
|
datenum = (long) lt->tm_year + 1900L;
|
|
/* yyyy --> yyyymm */
|
|
datenum = datenum * 100L + (long) (lt->tm_mon + 1);
|
|
/* yyyymm --> yyyymmdd */
|
|
datenum = datenum * 100L + (long) lt->tm_mday;
|
|
return datenum;
|
|
}
|
|
|
|
long
|
|
hhmmss(time_t date)
|
|
{
|
|
long timenum;
|
|
struct tm *lt;
|
|
|
|
if (date == 0)
|
|
lt = getlt();
|
|
else
|
|
lt = localtime((LOCALTIME_type) &date);
|
|
|
|
timenum = lt->tm_hour * 10000L + lt->tm_min * 100L + lt->tm_sec;
|
|
return timenum;
|
|
}
|
|
|
|
char *
|
|
yyyymmddhhmmss(time_t date)
|
|
{
|
|
long datenum;
|
|
static char datestr[15];
|
|
struct tm *lt;
|
|
|
|
if (date == 0)
|
|
lt = getlt();
|
|
else
|
|
lt = localtime((LOCALTIME_type) &date);
|
|
|
|
/* just in case somebody's localtime supplies (year % 100)
|
|
rather than the expected (year - 1900) */
|
|
if (lt->tm_year < 70)
|
|
datenum = (long) lt->tm_year + 2000L;
|
|
else
|
|
datenum = (long) lt->tm_year + 1900L;
|
|
Snprintf(datestr, sizeof datestr, "%04ld%02d%02d%02d%02d%02d",
|
|
datenum, lt->tm_mon + 1,
|
|
lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
|
|
//debugpline1("yyyymmddhhmmss() produced date string %s", datestr);
|
|
return datestr;
|
|
}
|
|
|
|
time_t
|
|
time_from_yyyymmddhhmmss(char *buf)
|
|
{
|
|
int k;
|
|
time_t timeresult = (time_t) 0;
|
|
struct tm t, *lt;
|
|
char *d, *p, y[5], mo[3], md[3], h[3], mi[3], s[3];
|
|
|
|
if (buf && strlen(buf) == 14) {
|
|
d = buf;
|
|
p = y; /* year */
|
|
for (k = 0; k < 4; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
p = mo; /* month */
|
|
for (k = 0; k < 2; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
p = md; /* day */
|
|
for (k = 0; k < 2; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
p = h; /* hour */
|
|
for (k = 0; k < 2; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
p = mi; /* minutes */
|
|
for (k = 0; k < 2; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
p = s; /* seconds */
|
|
for (k = 0; k < 2; ++k)
|
|
*p++ = *d++;
|
|
*p = '\0';
|
|
lt = getlt();
|
|
if (lt) {
|
|
t = *lt;
|
|
t.tm_year = atoi(y) - 1900;
|
|
t.tm_mon = atoi(mo) - 1;
|
|
t.tm_mday = atoi(md);
|
|
t.tm_hour = atoi(h);
|
|
t.tm_min = atoi(mi);
|
|
t.tm_sec = atoi(s);
|
|
timeresult = mktime(&t);
|
|
}
|
|
if (timeresult == (time_t) -1)
|
|
;
|
|
#if 0
|
|
TODO: set_debugpline1, debugpline1 -> function pointer
|
|
debugpline1("time_from_yyyymmddhhmmss(%s) would have returned -1",
|
|
buf ? buf : "");
|
|
#endif
|
|
else
|
|
return timeresult;
|
|
}
|
|
return (time_t) 0;
|
|
}
|
|
|
|
/*
|
|
* moon period = 29.53058 days ~= 30, year = 365.2422 days
|
|
* days moon phase advances on first day of year compared to preceding year
|
|
* = 365.2422 - 12*29.53058 ~= 11
|
|
* years in Metonic cycle (time until same phases fall on the same days of
|
|
* the month) = 18.6 ~= 19
|
|
* moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30
|
|
* (29 as initial condition)
|
|
* current phase in days = first day phase + days elapsed in year
|
|
* 6 moons ~= 177 days
|
|
* 177 ~= 8 reported phases * 22
|
|
* + 11/22 for rounding
|
|
*/
|
|
int
|
|
phase_of_the_moon(void) /* 0-7, with 0: new, 4: full */
|
|
{
|
|
struct tm *lt = getlt();
|
|
int epact, diy, goldn;
|
|
|
|
diy = lt->tm_yday;
|
|
goldn = (lt->tm_year % 19) + 1;
|
|
epact = (11 * goldn + 18) % 30;
|
|
if ((epact == 25 && goldn > 11) || epact == 24)
|
|
epact++;
|
|
|
|
return ((((((diy + epact) * 6) + 11) % 177) / 22) & 7);
|
|
}
|
|
|
|
boolean
|
|
friday_13th(void)
|
|
{
|
|
struct tm *lt = getlt();
|
|
|
|
/* tm_wday (day of week; 0==Sunday) == 5 => Friday */
|
|
return (boolean) (lt->tm_wday == 5 && lt->tm_mday == 13);
|
|
}
|
|
|
|
int
|
|
night(void)
|
|
{
|
|
int hour = getlt()->tm_hour;
|
|
|
|
return (hour < 6 || hour > 21);
|
|
}
|
|
|
|
int
|
|
midnight(void)
|
|
{
|
|
return (getlt()->tm_hour == 0);
|
|
}
|
|
|
|
/* calendar.c */
|
|
|