-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathdate.c
150 lines (133 loc) · 3.54 KB
/
date.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
harris - a strategy game
Copyright (C) 2012-2015 Edward Cree
licensed under GPLv3+ - see top of harris.c for details
date: date & time handling functions
*/
#include "date.h"
#include <stdio.h>
#include <math.h>
#include "ui.h"
#include "bits.h"
#include "render.h"
date readdate(const char *t, date nulldate)
{
date d;
if(t&&*t&&(sscanf(t, "%u-%u-%d", &d.day, &d.month, &d.year)==3)) return(d);
return(nulldate);
}
size_t writedate(date when, char *buf)
{
if(!buf) return(0);
return(sprintf(buf, "%02u-%02u-%04d", when.day, when.month, when.year));
}
harris_time readtime(const char *text, harris_time nulltime)
{
harris_time t;
if(text&&*text&&(sscanf(text, "%u:%u", &t.hour, &t.minute)==2)) return(t);
return(nulltime);
}
size_t writetime(harris_time when, char *buf)
{
if(!buf) return(0);
return(sprintf(buf, "%02u:%02u", when.hour, when.minute));
}
bool datebefore(date date1, date date2) // returns true if date1 is strictly before date2
{
if(date1.year!=date2.year) return(date1.year<date2.year);
if(date1.month!=date2.month) return(date1.month<date2.month);
return(date1.day<date2.day);
}
int diffdate(date date1, date date2) // returns <0 if date1<date2, >0 if date1>date2, 0 if date1==date2. Value is difference in days
{
if(date1.month<3)
{
date1.month+=12;
date1.year--;
}
if(date2.month<3)
{
date2.month+=12;
date2.year--;
}
int days1=365*date1.year + floor(date1.year/4) - floor(date1.year/100) + floor(date1.year/400) + floor(date1.day) + floor((153*date1.month+8)/5);
int days2=365*date2.year + floor(date2.year/4) - floor(date2.year/100) + floor(date2.year/400) + floor(date2.day) + floor((153*date2.month+8)/5);
return(days1-days2);
}
static double season(date when)
{
// depth of winter at 04/02/1939
// tropical year 365.24217 (mean solar) days
return diffdate(when, (date){.day=4, .month=2, .year=1939})/365.24217;
}
double seasonal_temp(date when)
{
return 3.0-5.5*cos(season(when)*M_PI*2);
}
double pom(date when)
{
// new moon at 14/08/1939
// synodic month 29.530588853 days
return(fmod(diffdate(when, (date){.day=14, .month=8, .year=1939})/29.530588853, 1));
}
double foldpom(double pom)
{
return((1-cos(pom*M_PI*2))/2.0);
}
void drawmoon(SDL_Surface *s, double phase)
{
SDL_FillRect(s, &(SDL_Rect){.x=0, .y=0, .w=s->w, .h=s->h}, SDL_MapRGB(s->format, GAME_BG_COLOUR.r, GAME_BG_COLOUR.g, GAME_BG_COLOUR.b));
double left=(phase<0.5)?phase*2:1,
right=(phase>0.5)?phase*2-1:0;
double halfx=(s->w-1)/2.0,
halfy=(s->h-1)/2.0;
for(int y=1;y<s->h-1;y++)
{
double width=sqrt(((s->w/2)-1)*((s->w/2)-1)-(y-halfy)*(y-halfy));
double startx=halfx-width, endx=halfx+width;
double leftx=width*cos( left*M_PI)+halfx,
rightx=width*cos(right*M_PI)+halfx;
for(unsigned int x=floor(startx);x<=ceil(endx);x++)
{
double a;
if(x<startx)
a=x+1-startx;
else if(x>endx)
a=endx+1-x;
else
a=1;
unsigned int alpha=ceil(ATG_ALPHA_OPAQUE*a);
double lf=x+1-leftx,
rf=rightx-x;
clamp(lf, 0, 1);
clamp(rf, 0, 1);
unsigned int br=floor(lf*rf*224);
pset(s, x, y, (atg_colour){br, br, br, alpha});
}
}
}
inline harris_time maketime(int t)
{
return((harris_time){(12+(t/120))%24, (t/2)%60});
}
inline unsigned int rrtime(harris_time t)
{
int h=t.hour-12;
if(h<0) h+=24;
return(h*120+t.minute*2);
}
const unsigned int monthdays[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
date nextday(date when)
{
date d=when;
if(++d.day>monthdays[d.month-1]+(((d.month==2)&&!(d.year%4))?1:0))
{
d.day=1;
if(++d.month>12)
{
d.month=1;
d.year++;
}
}
return(d);
}