Crossfire Server, Trunk
time.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <math.h>
23 
24 #include "tod.h"
25 
26 #ifndef WIN32 /* ---win32 exclude header */
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #endif /* win32 */
31 
35 uint32_t max_time = MAX_TIME;
36 static struct timespec game_time;
37 
39 #define PBUFLEN 100
40 static uint32_t process_utime_save[PBUFLEN];
41 static uint32_t psaveind;
42 static uint32_t process_max_utime = 0;
43 static uint32_t process_min_utime = 999999999;
44 static uint32_t process_tot_mtime;
45 uint32_t pticks;
46 static uint32_t process_utime_long_count;
49 static const char *const season_name[SEASONS_PER_YEAR+1] = {
50  "The Season of New Year",
51  "The Season of Growth",
52  "The Season of Harvest",
53  "The Season of Decay",
54  "The Season of the Blizzard",
55  "\n"
56 };
57 
59 static const char *const weekdays[DAYS_PER_WEEK] = {
60  "the Day of the Moon",
61  "the Day of the Bull",
62  "the Day of the Deception",
63  "the Day of Thunder",
64  "the Day of Freedom",
65  "the Day of the Great Gods",
66  "the Day of the Sun"
67 };
68 
70 static const char *const month_name[MONTHS_PER_YEAR] = {
71  "Month of Winter", /* 0 */
72  "Month of the Ice Dragon",
73  "Month of the Frost Giant",
74  "Month of Valriel",
75  "Month of Lythander",
76  "Month of the Harvest",
77  "Month of Gaea",
78  "Month of Futility",
79  "Month of the Dragon",
80  "Month of the Sun",
81  "Month of the Great Infernus",
82  "Month of Ruggilli",
83  "Month of the Dark Shades",
84  "Month of the Devourers",
85  "Month of Sorig",
86  "Month of the Ancient Darkness",
87  "Month of Gorokh"
88 };
89 
90 static const char *const periodsofday[PERIODS_PER_DAY] = {
91  "Night",
92  "Dawn",
93  "Morning",
94  "Noon",
95  "Evening",
96  "Dusk"
97 };
98 
102 const char *get_periodofday(const int index) {
103  return ((index >= 0) && (index < PERIODS_PER_DAY)) ? periodsofday[index] : NULL;
104 }
105 
109 const char *get_month_name(const int index) {
110  return ((index >= 0) && (index < MONTHS_PER_YEAR)) ? month_name[index] : NULL;
111 }
112 
116 const char *get_weekday(const int index) {
117  return ((index >= 0) && (index < DAYS_PER_WEEK)) ? weekdays[index] : NULL;
118 }
119 
123 const char *get_season_name(const int index) {
124  return ((index >= 0) && (index < (SEASONS_PER_YEAR+1))) ? season_name[index] : NULL;
125 }
126 
130 void reset_sleep(void) {
131  int i;
132 
133  for (i = 0; i < PBUFLEN; i++)
134  process_utime_save[i] = 0;
135  psaveind = 0;
136  process_max_utime = 0;
137  process_min_utime = 999999999;
138  process_tot_mtime = 0;
139  pticks = 0;
140 
141  clock_gettime(CLOCK_MONOTONIC, &game_time);
142 }
143 
147 static void log_time(uint32_t process_utime) {
148  pticks++;
149  if (++psaveind >= PBUFLEN)
150  psaveind = 0;
151  process_utime_save[psaveind] = process_utime;
152  if (process_utime > process_max_utime)
153  process_max_utime = process_utime;
154  if (process_utime < process_min_utime)
155  process_min_utime = process_utime;
156  process_tot_mtime += process_utime/1000;
157 }
158 
162 long timespec_diff(struct timespec *end, struct timespec *start) {
163  long long sec = (long long)end->tv_sec - (long long)start->tv_sec;
164  long nsec = end->tv_nsec - start->tv_nsec;
165  return sec * 1e6 + nsec / 1e3;
166 }
167 
171 static void timespec_add(struct timespec *time, long usec) {
172  long nsec_sum = time->tv_nsec + usec * 1e3;
173  time->tv_sec += nsec_sum / 1e9;
174  time->tv_nsec = nsec_sum % (long)1e9;
175 }
176 
177 /*
178  * Add one tick length to the last tick time.
179  */
182 }
183 
185  struct timespec now;
186  clock_gettime(CLOCK_MONOTONIC, &now);
187  long time_since_last_sleep = timespec_diff(&now, &game_time);
188  log_time(time_since_last_sleep);
189  return max_time - time_since_last_sleep;
190 }
191 
192 void jump_time() {
194  clock_gettime(CLOCK_MONOTONIC, &game_time);
195 }
196 
203 void set_max_time(long t) {
204  max_time = t;
205 }
206 
207 extern unsigned long todtick;
208 
215 void get_tod(timeofday_t *tod) {
216  tod->year = todtick/HOURS_PER_YEAR;
219  tod->dayofweek = tod->day%DAYS_PER_WEEK;
220  tod->hour = todtick%HOURS_PER_DAY;
222  if (tod->minute > 58)
223  tod->minute = 58; /* it's imprecise at best anyhow */
224  tod->weekofmonth = tod->day/WEEKS_PER_MONTH;
225  if (tod->month < 3)
226  tod->season = 0;
227  else if (tod->month < 6)
228  tod->season = 1;
229  else if (tod->month < 9)
230  tod->season = 2;
231  else if (tod->month < 12)
232  tod->season = 3;
233  else
234  tod->season = 4;
235 
236  if (tod->hour < 5) /*until 4:59*/
237  tod->periodofday = 0;
238  else if (tod->hour < 8)
239  tod->periodofday = 1;
240  else if (tod->hour < 13)
241  tod->periodofday = 2;
242  else if (tod->hour < 15)
243  tod->periodofday = 3;
244  else if (tod->hour < 20)
245  tod->periodofday = 4;
246  else if (tod->hour < 23)
247  tod->periodofday = 5;
248  else /*back to night*/
249  tod->periodofday = 0;
250 }
251 
258 static void print_tod(object *op) {
259  timeofday_t tod;
260  const char *suf;
261  int day;
262  char buf1[128];
263 
264  get_tod(&tod);
265 
267  "It is %s, on %s", time_format_time(&tod, buf1, sizeof(buf1)), weekdays[tod.dayofweek]);
268 
269  day = tod.day+1;
270  if (day == 1 || ((day%10) == 1 && day > 20))
271  suf = "st";
272  else if (day == 2 || ((day%10) == 2 && day > 20))
273  suf = "nd";
274  else if (day == 3 || ((day%10) == 3 && day > 20))
275  suf = "rd";
276  else
277  suf = "th";
278 
280  "The %d%s Day of the %s, Year %d",
281  day, suf, month_name[tod.month], tod.year+1);
282 
284  "Time of Year: %s",
285  season_name[tod.season]);
286 }
287 
294 void time_info(object *op) {
295  int tot = 0, long_count = 0;
296  uint32_t maxt = 0, mint = 99999999, i;
297 
298  print_tod(op);
299 
300  if (!QUERY_FLAG(op, FLAG_WIZ))
301  return;
302 
305  "Statistics for last %d ticks:\n\tmin/avg/max = %d/%d/%d ms per tick",
307  process_max_utime / 1000);
308 
311  "\tticks longer than %d ms = %d (%d%%)", max_time / 1000,
313 
315  "Time last %d ticks:",
316  MIN(pticks, PBUFLEN));
317 
318  for (i = 0; i < MIN(pticks, PBUFLEN); i++) {
319  tot += process_utime_save[i];
320  if (process_utime_save[i] > maxt)
321  maxt = process_utime_save[i];
322  if (process_utime_save[i] < mint)
323  mint = process_utime_save[i];
324  if (process_utime_save[i] > max_time)
325  long_count++;
326  }
327 
328  assert(pticks > 0);
329 
331  "avg time=%dms max time=%dms min time=%dms",
332  tot/MIN(pticks, PBUFLEN)/1000, maxt/1000,
333  mint/1000);
334 
336  "ticks longer than max time (%dms) = %d (%d%%)",
337  max_time/1000, long_count,
338  100*long_count/MIN(pticks, PBUFLEN));
339 }
340 
344 long seconds(void) {
345  struct timespec now;
346  clock_gettime(CLOCK_REALTIME, &now);
347  return now.tv_sec;
348 }
349 
365 const char *time_format_time(const timeofday_t *tod, char *buf, size_t bufsize)
366 {
367  snprintf(buf, bufsize, "%d minute%s past %d o'clock %s",
368  tod->minute+1,
369  tod->minute+1 < 2 ? "" : "s",
370  tod->hour%14 == 0 ? 14 : tod->hour%14,
371  tod->hour >= 14 ? "pm" : "am");
372  return buf;
373 }
374 
378 unsigned int tick_length(float seconds) {
379  return (int)ceil(seconds * 1000000 / max_time);
380 }
get_month_name
const char * get_month_name(const int index)
Definition: time.c:109
_timeofday::month
int month
Definition: tod.h:36
global.h
DAYS_PER_WEEK
#define DAYS_PER_WEEK
Definition: tod.h:15
time_info
void time_info(object *op)
Definition: time.c:294
psaveind
static uint32_t psaveind
Definition: time.c:41
PTICKS_PER_CLOCK
#define PTICKS_PER_CLOCK
Definition: tod.h:11
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
game_time
static struct timespec game_time
Definition: time.c:36
tick_game_time
void tick_game_time()
Definition: time.c:180
_timeofday::day
int day
Definition: tod.h:37
get_sleep_remaining
long get_sleep_remaining()
Definition: time.c:184
set_max_time
void set_max_time(long t)
Definition: time.c:203
MAX_TIME
#define MAX_TIME
Definition: config.h:246
HOURS_PER_DAY
#define HOURS_PER_DAY
Definition: tod.h:14
get_periodofday
const char * get_periodofday(const int index)
Definition: time.c:102
weekdays
static const char *const weekdays[DAYS_PER_WEEK]
Definition: time.c:59
month_name
static const char *const month_name[MONTHS_PER_YEAR]
Definition: time.c:70
_timeofday::year
int year
Definition: tod.h:35
MIN
#define MIN(x, y)
Definition: compat.h:21
max_time
uint32_t max_time
Definition: time.c:35
tick_length
unsigned int tick_length(float seconds)
Definition: time.c:378
_timeofday::periodofday
int periodofday
Definition: tod.h:43
HOURS_PER_YEAR
#define HOURS_PER_YEAR
Definition: tod.h:27
season_name
static const char *const season_name[SEASONS_PER_YEAR+1]
Definition: time.c:49
_timeofday::dayofweek
int dayofweek
Definition: tod.h:38
WEEKS_PER_MONTH
#define WEEKS_PER_MONTH
Definition: tod.h:16
print_tod
static void print_tod(object *op)
Definition: time.c:258
_timeofday
Definition: tod.h:34
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
periodsofday
static const char *const periodsofday[PERIODS_PER_DAY]
Definition: time.c:90
reset_sleep
void reset_sleep(void)
Definition: time.c:130
MSG_TYPE_COMMAND_DEBUG
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:528
_timeofday::season
int season
Definition: tod.h:42
get_tod
void get_tod(timeofday_t *tod)
Definition: time.c:215
SEASONS_PER_YEAR
#define SEASONS_PER_YEAR
Definition: tod.h:18
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:526
_timeofday::weekofmonth
int weekofmonth
Definition: tod.h:41
todtick
unsigned long todtick
Definition: init.c:398
DAYS_PER_MONTH
#define DAYS_PER_MONTH
Definition: tod.h:23
process_max_utime
static uint32_t process_max_utime
Definition: time.c:42
PBUFLEN
#define PBUFLEN
Definition: time.c:39
timespec_diff
long timespec_diff(struct timespec *end, struct timespec *start)
Definition: time.c:162
MONTHS_PER_YEAR
#define MONTHS_PER_YEAR
Definition: tod.h:17
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
HOURS_PER_MONTH
#define HOURS_PER_MONTH
Definition: tod.h:26
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
Floor.t
t
Definition: Floor.py:62
pticks
uint32_t pticks
Definition: time.c:45
process_utime_long_count
static uint32_t process_utime_long_count
Definition: time.c:46
timespec_add
static void timespec_add(struct timespec *time, long usec)
Definition: time.c:171
log_time
static void log_time(uint32_t process_utime)
Definition: time.c:147
process_min_utime
static uint32_t process_min_utime
Definition: time.c:43
PERIODS_PER_DAY
#define PERIODS_PER_DAY
Definition: tod.h:19
give.op
op
Definition: give.py:33
get_season_name
const char * get_season_name(const int index)
Definition: time.c:123
npc_dialog.index
int index
Definition: npc_dialog.py:102
buf
StringBuffer * buf
Definition: readable.c:1606
process_utime_save
static uint32_t process_utime_save[PBUFLEN]
Definition: time.c:40
process_tot_mtime
static uint32_t process_tot_mtime
Definition: time.c:44
seconds
long seconds(void)
Definition: time.c:344
get_weekday
const char * get_weekday(const int index)
Definition: time.c:116
jump_time
void jump_time()
Definition: time.c:192
_timeofday::minute
int minute
Definition: tod.h:40
tod.h
time_format_time
const char * time_format_time(const timeofday_t *tod, char *buf, size_t bufsize)
Definition: time.c:365
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
_timeofday::hour
int hour
Definition: tod.h:39