app/game_clock.h

a two-sided chess clock with Fischer increment.

WHAT THE CLOCK DOES NOT CHARGE FOR. This is the one rule that makes a physical board different from a screen. The gantry takes real seconds to carry a piece across the board, and that time belongs to NEITHER player:

human lifts/places  -> human's clock stops (the move is decided)
engine thinks       -> engine's clock runs
gantry executes     -> nothing runs          <-- free
human's turn begins -> human's clock starts
So a turn is charged from when a side is put on move to when its move is DECIDED — not to when the machine finishes acting on it. Wall-clock time for a game therefore exceeds the time drawn from the two clocks, by design. Charging the engine for its own gantry travel was the alternative; it would make the engine’s strength a function of how well-tuned the gantry is, which is a coupling worth refusing.

Pure and time-source-injectable: the game loop ticks it with a monotonic now(), and tests supply a fake one, so nothing here has to sleep to be tested.

namespace kirin

Typedefs

using SteadyNow = std::function<std::chrono::steady_clock::time_point()>

Enums

enum class TimeCategory

Values:

enumerator Untimed
enumerator Bullet
enumerator Blitz
enumerator Rapid
enumerator Classical
class GameClock
#include <game_clock.h>

Public Functions

explicit GameClock(TimeControl tc = TimeControl::untimed(), SteadyNow now = {})
void reset()
void setTimeControl(const TimeControl &tc)
inline const TimeControl &timeControl() const
inline bool enabled() const
void startTurn(char side)
void completeTurn()
void pause()
int remainingMs(char side) const
bool flagged(char side) const
inline char runningSide() const
int msUntilFlag() const
void setRemaining(int whiteMs, int blackMs)

Private Functions

int elapsedRunningMs() const

Private Members

TimeControl tc_
SteadyNow now_
int remainingMs_[2] = {0, 0}
char running_ = 0
std::chrono::steady_clock::time_point turnStartedAt_

Private Static Functions

static inline int idx(char side)
struct TimeControl
#include <game_clock.h>

Public Functions

TimeCategory category() const

Public Members

bool enabled = false
int baseMs = 0
int incrementMs = 0

Public Static Functions

static inline TimeControl untimed()
static inline TimeControl of(int baseMs, int incrementMs)