Files
nethack/src/calendar.c
2024-06-10 10:57:59 -04:00

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 */