ChessEngineKiro is a two-layer chess project with:
- A C++ chess engine core (board state, move generation, evaluation, volatility metric, and alpha-beta search)
- A Python/Pygame desktop UI for interactive play
The project is structured to keep engine logic separate from rendering/input logic.
This codebase and its implemented feature set are AI-generated based on the design contract in Contract.md
The C++ engine is implemented and now connected to the Python UI through a C-compatible bridge plus ctypes.
That means:
make testexercises the C++ engine binary with per-ply minimax decision tracingmake runstarts the UI with move generation/search coming from the C++ engine
- 8x8 board representation using
Pieceenum - Full move generation framework:
- pseudo-legal move generation
- legal move filtering (king safety)
- castling and en-passant handling in board/move logic
- Search stack:
- minimax
- alpha-beta pruning
- move ordering (capture prioritization, MVV-LVA-style bias, center bonus)
- quiescence search on captures
- basic check extension
- Evaluation components:
- material
- king safety
- center control
- mobility (currently simplified)
- phase-interpolated heuristic weighting between opening and endgame weights
- Static Exchange Evaluation (SEE)
- Volatility-driven dynamic depth adjustment
- Pygame board rendering and piece display
- Mouse-based piece selection and moves
- Highlighting selected square and legal move targets
- Turn display and reset key (
R) - Live integration with C++ engine through
EngineInterface(ctypes)
- Dedicated C API bridge in
src/Engine/EngineCAPI.cpp(extern "C") - Shared library output:
src/bin/libchess_engine.so - Python wrapper in
src/UI/Modules/engine_interface.pyfor:- board state retrieval
- side-to-move
- legal moves for selected square
- legal move application
- best move search
- game-over detection
.
├── Makefile
├── requirements.txt
├── README
├── Contract.md
├── src
│ ├── Engine
│ │ ├── Include
│ │ │ ├── Board.h
│ │ │ ├── Engine.h
│ │ │ ├── Evaluation.h
│ │ │ ├── MoveGen.h
│ │ │ ├── Search.h
│ │ │ ├── SEE.h
│ │ │ ├── Types.h
│ │ │ └── Volatility.h
│ │ ├── Board.cpp
│ │ ├── Engine.cpp
│ │ ├── EngineCAPI.cpp
│ │ ├── Evaluation.cpp
│ │ ├── MoveGen.cpp
│ │ ├── Search.cpp
│ │ ├── SEE.cpp
│ │ ├── Volatility.cpp
│ │ └── main.cpp
│ └── UI
│ ├── chess_ui.py
│ └── Modules
│ └── engine_interface.py
g++with C++17 supportmake
- Python 3.8+
pygame>=2.5.0
make allOutput artifacts:
src/bin/chess_engine_testsrc/bin/libchess_engine.so
make testThis runs a self-playing loop from the starting position and prints one minimax decision line per ply until the game ends (or safety move cap is reached). Each line includes side/role, selected move, move-order weight, minimax score, phase, volatility, depth, and evaluation breakdown values.
make envCreates .venv and installs requirements.txt.
make runIf .venv exists, Makefile uses .venv/bin/python; otherwise it falls back to system Python.
make run depends on libchess_engine.so, so the bridge library is built automatically when needed.
make all: build C++ test executable and shared librarymake test: run CLI engine test appmake run: run Pygame UImake env: create virtualenv and install Python dependenciesmake check-deps: verifypygameimportmake clean: remove C++ objects, test executable, and shared librarymake clean-py: remove Python cache artifactsmake clean-all: clean C++ + Python caches +.venvmake rebuild: clean then rebuild
Piece,Side,CastlingRights, andMoveare defined inTypes.hBoardstores:Piece board[8][8]- side to move
- castling rights bitmask
- en-passant target square
Move selection follows this sequence:
- Compute phase (
Evaluation::computePhase) - Compute static evaluation (
Evaluation::evaluate) using phase-interpolated heuristic weights - Compute volatility (
Volatility::computeVolatility) - Derive depth (
Volatility::deriveDepth) - Search best move (
Search::findBestMove)
EngineCAPI.cpp exposes a stable C interface that wraps Engine methods so Python can call into the C++ core without pybind11.
Exposed operations include:
- create/destroy engine handle
- reset to starting position
- get board (flat 64-int buffer)
- get side to move
- make legal move
- get legal destinations for one square
- get best move for search depth
- check game-over state
- Root move search with alpha-beta minimax
- Quiescence at depth 0 for tactical stabilization
- Move ordering with capture/move heuristics
- Check extension (bounded by depth recursion path)
- Optional root decision debug logging (
Search::setDebugLogging, exposed viaEngine::setDebugLogging)
- Material in centipawns
- King safety model based on:
- pawn shield
- open/semi-open king-file pressure (king file and adjacent files)
- attacks in king zone
- local defenders
- phase scaling and opponent queen presence
- Center control via attacks/occupancy on d4/e4/d5/e5 with piece-type weighted attackers
- Mobility currently emphasizes knight reachability and is intentionally lightweight
- Top-level heuristic weights are phase-interpolated by contract:
weight = openingWeight * phase + endgameWeight * (1 - phase)
- Internal compute helpers in
Evaluation.cpp:centerAttackPieceWeight(Piece): maps attacking piece type to center-control weight.countWeightedAttackers(const Board&, int row, int col, Side): computes weighted attack score for a target square.
make testlogs evaluation details:heurW{...}= interpolated heuristic weightsheurV{...}= raw component valuesheurWV{...}= weighted component contributions
Volatility is a tactical complexity proxy used to adapt search depth:
- positive SEE captures
- safe checks / checking sacrifices
- king danger scaling
Depth adjustment is thresholded and capped.
src/UI/Modules/engine_interface.py is now a real bridge to the C++ engine via ctypes and libchess_engine.so.
If the shared library is missing, UI startup fails with a clear message instructing to run make all.
- No UCI protocol support yet
- No transposition tables, iterative deepening, opening book, or tablebases
- No multithreaded search
- No formal unit/integration test suite yet
- CLI
main.cppis a test harness, not a production protocol frontend - Shared-library naming is currently Linux-oriented (
.so)
The following functions/utilities are useful for UI/debugging but are outside the explicit contract scope:
Engine::setDebugLogging(bool): toggles root search trace output for test/debug runs.Search::setDebugLogging(bool): enables/disables internal per-ply search logging.Evaluation::evaluateBreakdown(const Board&): returns component-wise eval details, not just final score.EvaluationBreakdown: struct carrying eval components, interpolated weights, and weighted totals.Engine::getLegalMoves(): returns all legal moves for the current side to move.Engine::getLegalMovesForSquare(int row, int col): returns legal destinations from one source square.Engine::makeMoveIfLegal(const Move&): validates and applies a move only when legal.Engine::isGameOver(): reports whether the side to move has no legal moves.Engine::getSideToMove() const: exposes whose turn it is.Engine::getBoard() const: exposes current board state for UI/bridge reads.chess_engine_create: creates a C API engine handle.chess_engine_destroy: releases a C API engine handle.chess_engine_reset: resets engine state to the starting position.chess_engine_get_side_to_move: gets current side to move via C API.chess_engine_get_board: gets flat 64-square board snapshot via C API.chess_engine_make_move: attempts a legal move via C API and returns success/failure.chess_engine_get_legal_moves_for_square: gets legal destinations for one square via C API.chess_engine_get_best_move: returns engine-selected move via C API.chess_engine_is_game_over: reports no-legal-moves state via C API.
The current maximizer can be improved significantly with the following upgrades (roughly ordered by impact):
- Improve easy-capture detection first (current biggest weakness).
In
Search::orderMoves, rank captures with SEE buckets (winning,equal,losing) so clearly winning captures are searched first. - Add a "hanging piece" term in
Evaluation.cpp. Penalize own undefended attacked pieces and reward opponent undefended attacked pieces so free captures are consistently preferred. - Improve quiescence search. Ensure all immediate recaptures are searched and apply SEE pruning only to clearly losing/noisy captures.
- Expand evaluation terms. Add pawn structure, bishop pair, rook file activity, and piece-square tables.
The design contract targets deterministic move selection for identical position + depth. There is no randomness in current move choice pipeline.
No license file is currently present in the repository.
If you plan to publish or collaborate externally, add an explicit LICENSE file.