Atrinik Server  4.0
time.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 
32 long max_time = MAX_TIME;
33 int max_time_multiplier = MAX_TIME_MULTIPLIER;
34 
36 #define PBUFLEN 100
37 
41 static long psaveind;
43 static long process_max_utime = 0;
45 static long process_min_utime = 999999999;
46 static long process_tot_mtime;
47 long pticks;
48 static long process_utime_long_count;
50 struct timeval last_time;
51 
53 const char *season_name[SEASONS_PER_YEAR] = {
54  "Season of the Blizzard",
55  "Season of Growth",
56  "Season of Harvest",
57  "Season of Decay",
58 };
59 
61 const char *weekdays[DAYS_PER_WEEK] = {
62  "Day of the Moon",
63  "Day of the Bull",
64  "Day of the Deception",
65  "Day of Thunder",
66  "Day of Freedom",
67  "Day of the Great Gods",
68  "Day of the Sun"
69 };
70 
72 const char *month_name[MONTHS_PER_YEAR] = {
73  "Month of the Winter",
74  "Month of the Ice Dragon",
75  "Month of the Frost Giant",
76  "Month of Terria",
77  "Month of the Harvest",
78  "Month of Futility",
79  "Month of the Dragon",
80  "Month of the Sun",
81  "Month of the Falling",
82  "Month of the Dark Shades",
83  "Month of the Great Infernus",
84  "Month of the Ancient Darkness",
85 };
86 
88 const char *periodsofday[PERIODS_PER_DAY] = {
89  "midnight",
90  "late night",
91  "dawn",
92  "morning",
93  "late morning",
94  "noon",
95  "afternoon",
96  "dusk",
97  "evening",
98  "night"
99 };
100 
105  /* 24: Midnight */
106  0,
107  /* 1 - 4: Late night */
108  1, 1, 1, 1,
109  /* 5: Dawn */
110  2,
111  /* 6 - 9: Morning */
112  3, 3, 3, 3,
113  /* 10 - 11: Late morning */
114  4, 4,
115  /* 12: Noon */
116  5,
117  /* 13 - 17: Afternoon */
118  6, 6, 6, 6, 6,
119  /* 18: Dusk */
120  7,
121  /* 19 - 21: Evening */
122  8, 8, 8,
123  /* 22 - 23: Night */
124  9, 9
125 };
126 
130 void reset_sleep(void)
131 {
132  int i;
133 
134  for (i = 0; i < PBUFLEN; i++) {
135  process_utime_save[i] = 0;
136  }
137 
138  psaveind = 0;
139  process_max_utime = 0;
140  process_min_utime = 999999999;
141  process_tot_mtime = 0;
142  pticks = 1;
143 
144  (void) GETTIMEOFDAY(&last_time);
145 }
146 
150 static void log_time(long process_utime)
151 {
152  if (++psaveind >= PBUFLEN) {
153  psaveind = 0;
154  }
155 
156  process_utime_save[psaveind] = process_utime;
157 
158  if (process_utime > process_max_utime) {
159  process_max_utime = process_utime;
160  }
161 
162  if (process_utime < process_min_utime) {
163  process_min_utime = process_utime;
164  }
165 
166  process_tot_mtime += process_utime / 1000;
167 }
168 
174 void sleep_delta(void)
175 {
176  static struct timeval new_time;
177  long sleep_sec, sleep_usec;
178 
179  GETTIMEOFDAY(&new_time);
180 
181  sleep_sec = last_time.tv_sec - new_time.tv_sec;
182  sleep_usec = max_time / max_time_multiplier - (new_time.tv_usec - last_time.tv_usec);
183 
184  /* This is very ugly, but probably the fastest for our use: */
185  while (sleep_usec < 0) {
186  sleep_usec += 1000000;
187  sleep_sec -= 1;
188  }
189 
190  while (sleep_usec > 1000000) {
191  sleep_usec -= 1000000;
192  sleep_sec += 1;
193  }
194 
195  log_time((new_time.tv_sec - last_time.tv_sec) * 1000000 + new_time.tv_usec - last_time.tv_usec);
196 
197  if (sleep_sec >= 0 && sleep_usec > 0) {
198  static struct timeval sleep_time;
199 
200  sleep_time.tv_sec = sleep_sec;
201  sleep_time.tv_usec = sleep_usec;
202 
203 #ifndef WIN32
204  select(0, NULL, NULL, NULL, &sleep_time);
205 #else
206 
207  if (sleep_time.tv_sec) {
208  Sleep(sleep_time.tv_sec * 1000);
209  }
210 
211  Sleep((int) (sleep_time.tv_usec / 1000.0));
212 #endif
213  } else {
214  process_utime_long_count++;
215  }
216 
217  /* Set last_time to when we're expected to wake up: */
218  last_time.tv_usec += max_time / max_time_multiplier;
219 
220  while (last_time.tv_usec > 1000000) {
221  last_time.tv_usec -= 1000000;
222  last_time.tv_sec++;
223  }
224 
225  /* Don't do too much catching up:
226  * (Things can still get jerky on a slow/loaded computer) */
227  if ((last_time.tv_sec - new_time.tv_sec) * 1000000 + (last_time.tv_usec - new_time.tv_usec) < 0) {
228  last_time.tv_sec = new_time.tv_sec;
229  last_time.tv_usec = new_time.tv_usec;
230  }
231 }
232 
239 void set_max_time(long t)
240 {
241  if (max_time == t) {
242  return;
243  }
244 
245  LOG(INFO,
246  "The speed has been changed from %ld to %ld.",
247  max_time, t);
248  draw_info(COLOR_GRAY, NULL,
249  "You feel a sudden and inexplicable change in the fabric of "
250  "time and space...");
251  max_time = t;
252 }
253 
260 {
261  if (max_time_multiplier == t) {
262  return;
263  }
264 
265  LOG(INFO,
266  "The speed multiplier has been changed from %d to %d.",
267  max_time_multiplier, t);
268  draw_info(COLOR_GRAY, NULL,
269  "You feel a sudden and inexplicable change in the fabric of "
270  "time and space...");
271  max_time_multiplier = t;
272 }
273 
280 {
281  tod->year = todtick / HOURS_PER_YEAR;
283  tod->season = tod->month / MONTHS_PER_SEASON;
285  tod->dayofweek = tod->day % DAYS_PER_WEEK;
286  tod->weekofmonth = tod->day / WEEKS_PER_MONTH;
287  tod->hour = todtick % HOURS_PER_DAY;
288  tod->periodofday = periodsofday_hours[tod->hour];
289  tod->minute = (pticks % PTICKS_PER_CLOCK) / (PTICKS_PER_CLOCK / 58);
290 
291  if (tod->minute > 59) {
292  tod->minute = 59;
293  }
294 }
295 
301 void print_tod(object *op)
302 {
303  timeofday_t tod;
304  get_tod(&tod);
305  draw_info_format(COLOR_WHITE, op, "It is %s, %d minute%s past %d o'clock %s, on the %s.", periodsofday[tod.periodofday], tod.minute, ((tod.minute == 1) ? "" : "s"), ((tod.hour % (HOURS_PER_DAY / 2) == 0) ? (HOURS_PER_DAY / 2) : ((tod.hour) % (HOURS_PER_DAY / 2))), ((tod.hour >= (HOURS_PER_DAY / 2)) ? "pm" : "am"), weekdays[tod.dayofweek]);
306 
307  int day = tod.day + 1;
308 
309  const char *suf;
310  if (day == 1 || ((day % 10) == 1 && day > 20)) {
311  suf = "st";
312  } else if (day == 2 || ((day % 10) == 2 && day > 20)) {
313  suf = "nd";
314  } else if (day == 3 || ((day % 10) == 3 && day > 20)) {
315  suf = "rd";
316  } else {
317  suf = "th";
318  }
319 
320  draw_info_format(COLOR_WHITE, op, "The %d%s Day of the %s, Year %d, in the %s.", day, suf, month_name[tod.month], tod.year + 1, season_name[tod.season]);
321 }
322 
328 void time_info(object *op)
329 {
330  print_tod(op);
331 }
332 
338 long seconds(void)
339 {
340  struct timeval now;
341 
342  (void) GETTIMEOFDAY(&now);
343  return now.tv_sec;
344 }
#define DAYS_PER_WEEK
Definition: tod.h:39
const char * periodsofday[PERIODS_PER_DAY]
Definition: time.c:88
long seconds(void)
Definition: time.c:338
#define HOURS_PER_YEAR
Definition: tod.h:60
int minute
Definition: tod.h:82
static long psaveind
Definition: time.c:41
static long process_utime_save[PBUFLEN]
Definition: time.c:39
#define MAX_TIME_MULTIPLIER
Definition: config.h:82
#define PERIODS_PER_DAY
Definition: tod.h:47
int periodofday
Definition: tod.h:91
int year
Definition: tod.h:67
const int periodsofday_hours[HOURS_PER_DAY]
Definition: time.c:104
struct timeval last_time
Definition: time.c:50
void get_tod(timeofday_t *tod)
Definition: time.c:279
#define HOURS_PER_MONTH
Definition: tod.h:58
const char * season_name[SEASONS_PER_YEAR]
Definition: time.c:53
#define DAYS_PER_MONTH
Definition: tod.h:52
int month
Definition: tod.h:70
#define MAX_TIME
Definition: config.h:72
int weekofmonth
Definition: tod.h:85
int day
Definition: tod.h:73
int dayofweek
Definition: tod.h:76
#define MONTHS_PER_SEASON
Definition: tod.h:62
const char * weekdays[DAYS_PER_WEEK]
Definition: time.c:61
unsigned long todtick
Definition: init.c:64
void sleep_delta(void)
Definition: time.c:174
void reset_sleep(void)
Definition: time.c:130
#define HOURS_PER_DAY
Definition: tod.h:37
const char * month_name[MONTHS_PER_YEAR]
Definition: time.c:72
void set_max_time(long t)
Definition: time.c:239
Definition: tod.h:65
static void log_time(long process_utime)
Definition: time.c:150
void print_tod(object *op)
Definition: time.c:301
#define WEEKS_PER_MONTH
Definition: tod.h:41
int hour
Definition: tod.h:79
static long process_min_utime
Definition: time.c:45
void set_max_time_multiplier(int t)
Definition: time.c:259
void time_info(object *op)
Definition: time.c:328
#define MONTHS_PER_YEAR
Definition: tod.h:43
#define PBUFLEN
Definition: time.c:36
#define PTICKS_PER_CLOCK
Definition: tod.h:34
#define SEASONS_PER_YEAR
Definition: tod.h:45
static long process_max_utime
Definition: time.c:43
int season
Definition: tod.h:88