| 193 string[idx++] = '+'; |
193 string[idx++] = '+'; |
| 194 } |
194 } |
| 195 } |
195 } |
| 196 |
196 |
| 197 static void calc_movetime(GameState *gamestate, Move *move) { |
197 static void calc_movetime(GameState *gamestate, Move *move) { |
| |
198 /* only if move has no time info, compute it */ |
| |
199 if (move->movetime > 0) return; |
| |
200 |
| 198 struct timeval curtimestamp; |
201 struct timeval curtimestamp; |
| 199 gettimeofday(&curtimestamp, NULL); |
202 gettimeofday(&curtimestamp, NULL); |
| 200 move->timestamp.tv_sec = curtimestamp.tv_sec; |
203 move->timestamp.sec = curtimestamp.tv_sec; |
| 201 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec; |
204 move->timestamp.usec = (int32_t) curtimestamp.tv_usec; |
| 202 move->movetime.tv_usec = 0; |
|
| 203 move->movetime.tv_sec = 0; |
|
| 204 if (gamestate->movecount > 1) { |
205 if (gamestate->movecount > 1) { |
| 205 struct movetimeval lasttstamp = |
206 struct movetimeval lasttstamp = |
| 206 gamestate->moves[gamestate->movecount - 1].timestamp; |
207 gamestate->moves[gamestate->movecount - 1].timestamp; |
| 207 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; |
208 |
| 208 suseconds_t micros; |
209 uint64_t cur = move->timestamp.sec * 1000000ull + move->timestamp.usec; |
| 209 if (curtimestamp.tv_usec < lasttstamp.tv_usec) { |
210 uint64_t last = lasttstamp.sec * 1000000ull + lasttstamp.usec; |
| 210 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec); |
211 |
| 211 sec--; |
212 move->movetime = cur - last; |
| 212 } else { |
|
| 213 micros = curtimestamp.tv_usec - lasttstamp.tv_usec; |
|
| 214 } |
|
| 215 |
|
| 216 while (micros >= 1000000) { |
|
| 217 micros -= 1000000; |
|
| 218 sec++; |
|
| 219 } |
|
| 220 |
|
| 221 if (sec >= gamestate->info.delay) { |
|
| 222 move->movetime.tv_sec = sec; |
|
| 223 move->movetime.tv_usec = (int32_t) micros; |
|
| 224 } |
|
| 225 } |
213 } |
| 226 } |
214 } |
| 227 |
215 |
| 228 size_t piece_moves_allowed(const GameState *gamestate, |
216 size_t piece_moves_allowed(const GameState *gamestate, |
| 229 Row r, File f, Move *moves) { |
217 Row r, File f, Move *moves) { |
| 467 } |
455 } |
| 468 |
456 |
| 469 /* copy the move data into the game's move array */ |
457 /* copy the move data into the game's move array */ |
| 470 Move *melem = &gamestate->moves[gamestate->movecount]; |
458 Move *melem = &gamestate->moves[gamestate->movecount]; |
| 471 *melem = *move; |
459 *melem = *move; |
| 472 |
460 calc_movetime(gamestate, melem); |
| 473 /* only if move has no time info, compute it */ |
|
| 474 if (melem->movetime.tv_sec == 0 && melem->movetime.tv_usec == 0) { |
|
| 475 calc_movetime(gamestate, melem); |
|
| 476 } |
|
| 477 |
461 |
| 478 /* important: only "add" the move after calculating the time! */ |
462 /* important: only "add" the move after calculating the time! */ |
| 479 gamestate->movecount++; |
463 gamestate->movecount++; |
| 480 |
464 |
| 481 /* calculate the FEN of the new position and store it in the FEN array */ |
465 /* calculate the FEN of the new position and store it in the FEN array */ |
| 1230 if (!gamestate->info.timecontrol) { |
1214 if (!gamestate->info.timecontrol) { |
| 1231 return 0; |
1215 return 0; |
| 1232 } |
1216 } |
| 1233 |
1217 |
| 1234 unsigned total_time = gamestate->info.time; |
1218 unsigned total_time = gamestate->info.time; |
| 1235 unsigned used_time = 0; |
1219 uint64_t used_time_usec = 0; |
| 1236 suseconds_t micros = 0; |
|
| 1237 |
1220 |
| 1238 /* when this is a 0+X game, the clock starts with the increment */ |
1221 /* when this is a 0+X game, the clock starts with the increment */ |
| 1239 if (gamestate->info.time == 0) { |
1222 if (gamestate->info.time == 0) { |
| 1240 total_time += gamestate->info.addtime; |
1223 total_time += gamestate->info.addtime; |
| 1241 } |
1224 } |
| 1243 /* go through all already played moves */ |
1226 /* go through all already played moves */ |
| 1244 unsigned first_move = move_number % 2; |
1227 unsigned first_move = move_number % 2; |
| 1245 unsigned next_move = move_number; |
1228 unsigned next_move = move_number; |
| 1246 if (next_move > gamestate->movecount) next_move = gamestate->movecount; |
1229 if (next_move > gamestate->movecount) next_move = gamestate->movecount; |
| 1247 for (unsigned i = first_move ; i < next_move ; i += 2) { |
1230 for (unsigned i = first_move ; i < next_move ; i += 2) { |
| 1248 used_time += gamestate->moves[i].movetime.tv_sec; |
1231 used_time_usec += gamestate->moves[i].movetime; |
| 1249 micros += gamestate->moves[i].movetime.tv_usec; |
|
| 1250 /* add increments starting with move 2 */ |
1232 /* add increments starting with move 2 */ |
| 1251 if (i > 1) total_time += gamestate->info.addtime; |
1233 if (i > 1) total_time += gamestate->info.addtime; |
| 1252 } |
|
| 1253 |
|
| 1254 /* apply microseconds */ |
|
| 1255 while (micros >= 1000000) { |
|
| 1256 micros -= 1000000; |
|
| 1257 used_time++; |
|
| 1258 } |
1234 } |
| 1259 |
1235 |
| 1260 /* when the player is currently playing, count down the clock */ |
1236 /* when the player is currently playing, count down the clock */ |
| 1261 if (is_game_running(gamestate) && move_number > 1 && |
1237 if (is_game_running(gamestate) && move_number > 1 && |
| 1262 move_number == gamestate->movecount) { |
1238 move_number == gamestate->movecount) { |
| 1264 gamestate->moves[move_number - 1].timestamp; |
1240 gamestate->moves[move_number - 1].timestamp; |
| 1265 struct timeval currenttstamp; |
1241 struct timeval currenttstamp; |
| 1266 gettimeofday(¤ttstamp, NULL); |
1242 gettimeofday(¤ttstamp, NULL); |
| 1267 |
1243 |
| 1268 /* calculate current move time */ |
1244 /* calculate current move time */ |
| 1269 unsigned cmsec = currenttstamp.tv_sec - lastmovetstamp.tv_sec; |
1245 uint64_t cusec = currenttstamp.tv_sec - lastmovetstamp.sec; |
| 1270 suseconds_t cmusec = currenttstamp.tv_usec - lastmovetstamp.tv_usec; |
1246 cusec *= 1000000ull; |
| 1271 |
1247 cusec += currenttstamp.tv_usec - lastmovetstamp.usec; |
| 1272 /* add microseconds carried over from last move and apply both */ |
|
| 1273 cmusec += micros; |
|
| 1274 cmsec += cmusec / 1000000; |
|
| 1275 |
1248 |
| 1276 /* add the time and respect a possible dealy */ |
1249 /* add the time and respect a possible dealy */ |
| 1277 if (cmsec >= gamestate->info.delay) { |
1250 uint64_t delay = gamestate->info.delay * 1000000ull; |
| 1278 used_time += cmsec - gamestate->info.delay; |
1251 if (cusec >= delay) { |
| 1279 } |
1252 used_time_usec += cusec - delay; |
| 1280 } |
1253 } |
| |
1254 } |
| |
1255 |
| |
1256 unsigned used_time = used_time_usec / 1000000ull; |
| 1281 |
1257 |
| 1282 return used_time >= total_time ? 0 : total_time - used_time; |
1258 return used_time >= total_time ? 0 : total_time - used_time; |
| 1283 } |
1259 } |
| 1284 |
1260 |
| 1285 int print_clk(uint16_t time, char *str, bool always_hours) { |
1261 int print_clk(uint16_t time, char *str, bool always_hours) { |