diff -r 189c7c77aaab -r 3fc6b1d6cbe9 src/chess/rules.c --- a/src/chess/rules.c Thu May 28 12:15:26 2026 +0200 +++ b/src/chess/rules.c Thu May 28 13:58:24 2026 +0200 @@ -170,7 +170,8 @@ 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; if (gamestate->movecount > 1) { struct movetimeval lasttstamp = last_move(gamestate).timestamp; uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; @@ -181,13 +182,16 @@ } else { micros = curtimestamp.tv_usec - lasttstamp.tv_usec; } + + while (micros >= 1000000) { + micros -= 1000000; + sec++; + } - move->movetime.tv_sec = sec; - move->movetime.tv_usec = (int32_t) micros; - } else { - /* no move time for the first move of both white and black */ - move->movetime.tv_usec = 0; - move->movetime.tv_sec = 0; + if (sec >= gamestate->info.delay) { + move->movetime.tv_sec = sec; + move->movetime.tv_usec = (int32_t) micros; + } } } @@ -316,6 +320,7 @@ void gamestate_at_move(GameState *gamestate, unsigned move_number, GameState *replay) { gamestate_init(replay); + memcpy(&replay->info, &gamestate->info, sizeof(GameInfo)); replay->review = true; if (move_number > gamestate->movecount) { move_number = gamestate->movecount; @@ -841,30 +846,28 @@ } } -uint16_t remaining_movetime(GameInfo *gameinfo, GameState *gamestate, - uint8_t color) { +uint16_t remaining_movetime(GameState *gamestate, uint8_t color) { unsigned move_number = gamestate->movecount; if (color == BLACK) { move_number |= 1; } else { move_number = (move_number + 1) & ~1; } - return remaining_movetime2(gameinfo, gamestate, move_number); + return remaining_movetime2(gamestate, move_number); } -uint16_t remaining_movetime2(GameInfo *gameinfo, GameState *gamestate, - unsigned move_number) { - if (!gameinfo->timecontrol) { +uint16_t remaining_movetime2(GameState *gamestate, unsigned move_number) { + if (!gamestate->info.timecontrol) { return 0; } - unsigned total_time = gameinfo->time; + unsigned total_time = gamestate->info.time; unsigned used_time = 0; suseconds_t micros = 0; /* when this is a 0+X game, the clock starts with the increment */ - if (gameinfo->time == 0) { - total_time += gameinfo->addtime; + if (gamestate->info.time == 0) { + total_time += gamestate->info.addtime; } /* go through all already played moves */ @@ -875,7 +878,13 @@ used_time += gamestate->moves[i].movetime.tv_sec; micros += gamestate->moves[i].movetime.tv_usec; /* add increments starting with move 2 */ - if (i > 1) total_time += gameinfo->addtime; + 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 */ @@ -885,13 +894,21 @@ gamestate->moves[move_number - 1].timestamp; struct timeval currenttstamp; gettimeofday(¤ttstamp, NULL); - used_time += currenttstamp.tv_sec - lastmovetstamp.tv_sec; - micros += currenttstamp.tv_usec - lastmovetstamp.tv_usec; + + /* 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; + + /* add the time and respect a possible dealy */ + if (cmsec >= gamestate->info.delay) { + used_time += cmsec - gamestate->info.delay; + } } - /* apply the microseconds */ - used_time += micros / 1000000; - return used_time >= total_time ? 0 : total_time - used_time; }