Project
Kepler Chess Engine
Kepler is a from-scratch C++ chess engine I'm using to explore search algorithms, evaluation design, and engine architecture beyond basic minimax examples.
Goals
The point isn't beating top engines, it's having a codebase where every node, move, and score is transparent. The engine is structured so search, evaluation, and time management are all modular and swappable.
Architecture
- Bitboard representation for fast move generation.
- Clean separation between move generation, search, and evaluation.
- Alpha–beta search with iterative deepening and a transposition table.
- Evaluation module where terms (material, mobility, king safety, pawn structure) are easy to iterate on.
Core search loop
The heart of the engine is a negamax-style alpha–beta search with iterative deepening:
int search(Position& pos, int depth, int alpha, int beta) {
if (depth == 0 || pos.isTerminal())
return evaluate(pos);
int bestScore = -INF;
for (Move m : generate_moves(pos)) {
pos.make_move(m);
int score = -search(pos, depth - 1, -beta, -alpha);
pos.unmake_move(m);
if (score > bestScore) bestScore = score;
if (score > alpha) alpha = score;
if (alpha >= beta) break; // cutoff
}
return bestScore;
}The real implementation adds a transposition table, quiescence search, and better move ordering, but this sketch shows the core idea.
Testing & tooling
- Perft tests on known positions to validate move generation.
- Engine-vs-engine matches at low depth to sanity-check strength.
- Bench command to measure nodes/sec when testing new optimisations.
Next steps
Planned work: richer evaluation terms, experimenting with NNUE-style evaluation, and stronger time management so Kepler can plug into GUIs over UCI cleanly.
How to read this
The orb isn't literal engine state — it's a visual nod to Kepler's search graph: nodes pulsing as candidate positions, rings hinting at deepening search, and the central tile as the evaluation core.