Allow defining total time not just time per move.
[pachi/derm.git] / timeinfo.c
blobffb0685fa530c5793535c7a57ecf0ce5e6ed1705
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <math.h>
6 #include <time.h>
8 #define DEBUG
10 #include "debug.h"
11 #include "timeinfo.h"
14 bool
15 time_parse(struct time_info *ti, char *s)
17 switch (s[0]) {
18 case '_': ti->period = TT_TOTAL; s++; break;
19 default: ti->period = TT_MOVE; break;
21 switch (s[0]) {
22 case '=':
23 ti->dim = TD_GAMES;
24 ti->len.games = atoi(++s);
25 break;
26 default:
27 if (!isdigit(s[0]))
28 return false;
29 ti->dim = TD_WALLTIME;
30 ti->len.t.recommended_time = atof(s);
31 break;
33 return true;
36 /* Set correct time information before making a move, and
37 * always make it time per move for the engine. */
38 void
39 time_prepare_move(struct time_info *ti, struct board *board)
41 int moves_left;
43 if (ti->period == TT_TOTAL) {
44 moves_left = board_estimated_moves_left(board);
45 assert(moves_left > 0);
46 if (ti->dim == TD_GAMES) {
47 ti->period = TT_MOVE;
48 ti->len.games /= moves_left;
51 if (ti->period == TT_NULL || ti->dim != TD_WALLTIME)
52 return;
54 double now = time_now();
55 if (!ti->len.t.timer_start) {
56 ti->len.t.timer_start = now; // we're playing the first game move
58 if (ti->period == TT_TOTAL) {
59 ti->period = TT_MOVE;
60 ti->len.t.recommended_time /= moves_left;
64 /* Start our timer. kgs does this (correctly) on "play" not "genmove"
65 * unless we are making the first move of the game. */
66 void
67 time_start_timer(struct time_info *ti)
69 if (ti->period != TT_NULL && ti->dim == TD_WALLTIME)
70 ti->len.t.timer_start = time_now();
73 /* Returns the current time. */
74 double
75 time_now(void)
77 struct timespec now;
78 clock_gettime(CLOCK_REALTIME, &now);
79 return now.tv_sec + now.tv_nsec/1000000000.0;
82 /* Sleep for a given interval (in seconds). Return immediately if interval < 0. */
83 void
84 time_sleep(double interval)
86 struct timespec ts;
87 double sec;
88 ts.tv_nsec = (int)(modf(interval, &sec)*1000000000.0);
89 ts.tv_sec = (int)sec;
90 nanosleep(&ts, NULL); /* ignore error if interval was < 0 */