-
Notifications
You must be signed in to change notification settings - Fork 16
/
TimeControl.cpp
210 lines (191 loc) · 6.34 KB
/
TimeControl.cpp
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include <cassert>
#include "TimeControl.h"
#include "Utils.h"
#include "GTP.h"
using namespace Utils;
TimeControl::TimeControl(int boardsize, int maintime, int byotime,
int byostones, int byoperiods)
: m_maintime(maintime),
m_byotime(byotime),
m_byostones(byostones),
m_byoperiods(byoperiods) {
reset_clocks();
set_boardsize(boardsize);
}
void TimeControl::reset_clocks() {
m_remaining_time[0] = m_maintime;
m_remaining_time[1] = m_maintime;
m_stones_left[0] = m_byostones;
m_stones_left[1] = m_byostones;
m_periods_left[0] = m_byoperiods;
m_periods_left[1] = m_byoperiods;
m_inbyo[0] = m_maintime <= 0;
m_inbyo[1] = m_maintime <= 0;
// Now that byo-yomi status is set, add time
// back to our clocks
if (m_inbyo[0]) {
m_remaining_time[0] = m_byotime;
}
if (m_inbyo[1]) {
m_remaining_time[1] = m_byotime;
}
}
void TimeControl::start(int color) {
m_times[color] = Time();
}
void TimeControl::stop(int color) {
Time stop;
int elapsed = Time::timediff(m_times[color], stop);
assert(elapsed >= 0);
m_remaining_time[color] -= elapsed;
if (m_inbyo[color]) {
if (m_byostones) {
m_stones_left[color]--;
} else if (m_byoperiods) {
if (elapsed > m_byotime) {
m_periods_left[color]--;
}
}
}
/*
time up, entering byo yomi
*/
if (!m_inbyo[color] && m_remaining_time[color] <= 0) {
m_remaining_time[color] = m_byotime;
m_stones_left[color] = m_byostones;
m_periods_left[color] = m_byoperiods;
m_inbyo[color] = true;
} else if (m_inbyo[color] && m_byostones && m_stones_left[color] <= 0) {
// reset byoyomi time and stones
m_remaining_time[color] = m_byotime;
m_stones_left[color] = m_byostones;
} else if (m_inbyo[color] && m_byoperiods) {
m_remaining_time[color] = m_byotime;
}
}
void TimeControl::display_times() {
{
int rem = m_remaining_time[0] / 100; /* centiseconds to seconds */
int hours = rem / (60 * 60);
rem = rem % (60 * 60);
int minutes = rem / 60;
rem = rem % 60;
int seconds = rem;
myprintf("Black time: %02d:%02d:%02d", hours, minutes, seconds);
if (m_inbyo[0]) {
if (m_byostones) {
myprintf(", %d stones left", m_stones_left[0]);
} else if (m_byoperiods) {
myprintf(", %d period(s) of %d seconds left",
m_periods_left[0], m_byotime / 100);
}
}
myprintf("\n");
}
{
int rem = m_remaining_time[1] / 100; /* centiseconds to seconds */
int hours = rem / (60 * 60);
rem = rem % (60 * 60);
int minutes = rem / 60;
rem = rem % 60;
int seconds = rem;
myprintf("White time: %02d:%02d:%02d", hours, minutes, seconds);
if (m_inbyo[1]) {
if (m_byostones) {
myprintf(", %d stones left", m_stones_left[1]);
} else if (m_byoperiods) {
myprintf(", %d period(s) of %d seconds left",
m_periods_left[1], m_byotime / 100);
}
}
myprintf("\n");
}
myprintf("\n");
}
int TimeControl::max_time_for_move(int color) {
/*
always keep a 1 second margin for net hiccups
*/
const int BUFFER_CENTISECS = cfg_lagbuffer_cs;
int timealloc = 0;
/*
no byo yomi (absolute), easiest
*/
if (m_byotime == 0) {
timealloc = (m_remaining_time[color] - BUFFER_CENTISECS)
/ m_moves_expected;
} else if (m_byotime != 0) {
/*
no periods or stones set means
infinite time = 1 month
*/
if (m_byostones == 0 && m_byoperiods == 0) {
return 31 * 24 * 60 * 60 * 100;
}
/*
byo yomi and in byo yomi
*/
if (m_inbyo[color]) {
if (m_byostones) {
timealloc = (m_remaining_time[color] - BUFFER_CENTISECS)
/ std::max<int>(m_stones_left[color], 1);
} else {
assert(m_byoperiods);
// Just use the byo yomi period
timealloc = m_byotime - BUFFER_CENTISECS;
}
} else {
/*
byo yomi time but not in byo yomi yet
*/
if (m_byostones) {
int byo_extra = m_byotime / m_byostones;
int total_time = m_remaining_time[color] + byo_extra;
timealloc = (total_time - BUFFER_CENTISECS) / m_moves_expected;
// Add back the guaranteed extra seconds
timealloc += std::max<int>(byo_extra - BUFFER_CENTISECS, 0);
} else {
assert(m_byoperiods);
int byo_extra = m_byotime * (m_periods_left[color] - 1);
int total_time = m_remaining_time[color] + byo_extra;
timealloc = (total_time - BUFFER_CENTISECS) / m_moves_expected;
// Add back the guaranteed extra seconds
timealloc += std::max<int>(m_byotime - BUFFER_CENTISECS, 0);
}
}
}
timealloc = std::max<int>(timealloc, 0);
return timealloc;
}
void TimeControl::adjust_time(int color, int time, int stones) {
m_remaining_time[color] = time;
// From pachi: some GTP things send 0 0 at the end of main time
if (!time && !stones) {
m_inbyo[color] = true;
m_remaining_time[color] = m_byotime;
m_stones_left[color] = m_byostones;
m_periods_left[color] = m_byoperiods;
}
if (stones) {
// stones are only given in byo-yomi
m_inbyo[color] = true;
}
// we must be in byo-yomi before interpreting stones
// the previous condition guarantees we do this if != 0
if (m_inbyo[color]) {
if (m_byostones) {
m_stones_left[color] = stones;
} else if (m_byoperiods) {
// KGS extension
m_periods_left[color] = stones;
}
}
}
void TimeControl::set_boardsize(int boardsize) {
// Note this is constant as we play, so it's fair
// to underestimate quite a bit.
m_moves_expected = (boardsize * boardsize) / 5;
}
int TimeControl::get_remaining_time(int color) {
return m_remaining_time[color];
}