--- a/src/chess/rules.c Fri Aug 21 20:06:26 2026 +0200 +++ b/src/chess/rules.c Sat Aug 22 15:15:52 2026 +0200 @@ -195,33 +195,21 @@ } static void calc_movetime(GameState *gamestate, Move *move) { + /* only if move has no time info, compute it */ + if (move->movetime > 0) return; + struct timeval curtimestamp; gettimeofday(&curtimestamp, NULL); - move->timestamp.tv_sec = curtimestamp.tv_sec; - move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec; - move->movetime.tv_usec = 0; - move->movetime.tv_sec = 0; + move->timestamp.sec = curtimestamp.tv_sec; + move->timestamp.usec = (int32_t) curtimestamp.tv_usec; if (gamestate->movecount > 1) { struct movetimeval lasttstamp = gamestate->moves[gamestate->movecount - 1].timestamp; - uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; - suseconds_t micros; - if (curtimestamp.tv_usec < lasttstamp.tv_usec) { - micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec); - sec--; - } else { - micros = curtimestamp.tv_usec - lasttstamp.tv_usec; - } - - while (micros >= 1000000) { - micros -= 1000000; - sec++; - } - if (sec >= gamestate->info.delay) { - move->movetime.tv_sec = sec; - move->movetime.tv_usec = (int32_t) micros; - } + uint64_t cur = move->timestamp.sec * 1000000ull + move->timestamp.usec; + uint64_t last = lasttstamp.sec * 1000000ull + lasttstamp.usec; + + move->movetime = cur - last; } } @@ -469,11 +457,7 @@ /* copy the move data into the game's move array */ Move *melem = &gamestate->moves[gamestate->movecount]; *melem = *move; - - /* only if move has no time info, compute it */ - if (melem->movetime.tv_sec == 0 && melem->movetime.tv_usec == 0) { - calc_movetime(gamestate, melem); - } + calc_movetime(gamestate, melem); /* important: only "add" the move after calculating the time! */ gamestate->movecount++; @@ -1232,8 +1216,7 @@ } unsigned total_time = gamestate->info.time; - unsigned used_time = 0; - suseconds_t micros = 0; + uint64_t used_time_usec = 0; /* when this is a 0+X game, the clock starts with the increment */ if (gamestate->info.time == 0) { @@ -1245,18 +1228,11 @@ unsigned next_move = move_number; if (next_move > gamestate->movecount) next_move = gamestate->movecount; for (unsigned i = first_move ; i < next_move ; i += 2) { - used_time += gamestate->moves[i].movetime.tv_sec; - micros += gamestate->moves[i].movetime.tv_usec; + used_time_usec += gamestate->moves[i].movetime; /* add increments starting with move 2 */ if (i > 1) total_time += gamestate->info.addtime; } - /* apply microseconds */ - while (micros >= 1000000) { - micros -= 1000000; - used_time++; - } - /* when the player is currently playing, count down the clock */ if (is_game_running(gamestate) && move_number > 1 && move_number == gamestate->movecount) { @@ -1266,19 +1242,19 @@ gettimeofday(¤ttstamp, NULL); /* calculate current move time */ - unsigned cmsec = currenttstamp.tv_sec - lastmovetstamp.tv_sec; - suseconds_t cmusec = currenttstamp.tv_usec - lastmovetstamp.tv_usec; - - /* add microseconds carried over from last move and apply both */ - cmusec += micros; - cmsec += cmusec / 1000000; + uint64_t cusec = currenttstamp.tv_sec - lastmovetstamp.sec; + cusec *= 1000000ull; + cusec += currenttstamp.tv_usec - lastmovetstamp.usec; /* add the time and respect a possible dealy */ - if (cmsec >= gamestate->info.delay) { - used_time += cmsec - gamestate->info.delay; + uint64_t delay = gamestate->info.delay * 1000000ull; + if (cusec >= delay) { + used_time_usec += cusec - delay; } } + unsigned used_time = used_time_usec / 1000000ull; + return used_time >= total_time ? 0 : total_time - used_time; }