Automatic detection of chess tactical themes in PGN games
Project description
chess_detect
Automatic detection of chess tactical and strategic themes in PGN games using python-chess.
Analyzes PGN files and annotates moves with tactical motifs (forks, pins, skewers, discovered checks) and strategic patterns (open files, doubled/isolated pawns). Supports Russian and English output with visual PGN arrow annotations.
Installation
pip install chess-detect
For development:
git clone https://github.com/aslyamov/chess_detect.git
cd chess_detect
pip install -e ".[dev]"
Quick Start
from chess_detect import ChessDetector
detector = ChessDetector(lang="en") # or lang="ru"
pgn = """[FEN "q3k3/8/8/1N6/8/8/8/4K3 w - - 0 1"]
1. Nc7+"""
result = detector.analyze(pgn)
print(result)
# 1. Nc7+ {Fork (Nc7 -> Qa8, Ke8)} *
Configuration
ChessDetector(
lang="en", # "ru" or "en" (default: "ru")
tactics=True, # tactical themes (forks, pins, skewers...)
strategy=True, # strategic motifs (open files, doubled pawns...)
arrows=True, # arrows and square highlights in PGN
)
| Parameter | Type | Default | Description |
|---|---|---|---|
lang |
str |
"ru" |
Output language |
tactics |
bool |
True |
Enable tactical themes |
strategy |
bool |
True |
Enable strategic motifs |
arrows |
bool |
True |
Enable PGN arrows ([%cal]) and highlights ([%csl]) |
Examples:
# Tactics only, no arrows
detector = ChessDetector(lang="en", strategy=False, arrows=False)
# Strategy only
detector = ChessDetector(lang="ru", tactics=False)
Tactical Themes
1. Double Check
Two pieces check the king simultaneously. The king must move.
FEN: 3k4/8/8/8/3N4/8/8/3RK3 w - - 0 1
Move: Nc6+ — knight gives check and discovers check from rook d1.
2. Fork
One piece attacks two or more valuable enemy pieces.
FEN: q3k3/8/8/1N6/8/8/8/4K3 w - - 0 1
Move: Nc7+ — knight attacks both king e8 and queen a8.
3. Discovered Check
A piece moves away, uncovering check from another piece, while making a useful attack.
FEN: 3k4/8/4p3/8/3N4/8/8/3RK3 w - - 0 1
Move: Nxe6 — knight captures pawn and discovers check from rook d1.
4. Pin
A ray piece attacks through an enemy piece to a more valuable one behind it. The front piece cannot move.
FEN: 6k1/8/4n3/8/8/1B6/8/4K3 w - - 0 1
Move: Bc4 — bishop pins knight e6 to king g8 along the diagonal.
5. Skewer
Reverse pin: the more valuable piece is in front and must move, exposing the piece behind.
FEN: 4q3/8/8/4k3/8/8/8/R5K1 w - - 0 1
Move: Re1+ — rook checks king e5, queen e8 is behind.
6. Trapped Piece
After a move, an enemy piece has no safe squares.
FEN: 4k2n/4P3/5R2/5BP1/8/8/8/4K2Q w - - 0 1
Move: g6 — knight h8 is trapped, all escape squares are under attack.
7. Hanging Capture
Capturing a piece that is undefended or can be taken by a cheaper piece.
FEN: 4k3/8/8/R3n3/8/8/8/4K3 w - - 0 1
Move: Rxe5 — rook captures undefended knight.
8. Removing Defender (material)
Capturing a piece that defended another. The defended piece is now hanging.
FEN: 4k3/8/8/8/4b3/Q1n5/8/1B2K3 w - - 0 1
Move: Qxc3 — queen takes knight that defended bishop e4.
9. Removing Defender (mate)
Capturing a piece that defended a key square. A mate threat appears.
FEN: 7k/6p1/6r1/8/4B3/2Q5/8/4K3 w - - 0 1
Move: Bxg6 — bishop takes rook, creating mate threat Qc8#.
10. Exploiting Pin
Attacking a pinned piece (it cannot escape) or capturing through a pinned defender.
FEN: 4k3/8/8/5p2/4n3/8/3P4/4R1K1 w - - 0 1
Move: d3 — pawn attacks knight e4 pinned to king by rook e1.
Strategic Motifs
Strategic themes are annotated with blue arrows/highlights (tactical themes use green). Each motif is detected once when it first appears, then ignored.
11. Open File
A file with no pawns of either color.
FEN: 4k3/8/8/3p4/8/8/8/3RK3 w - - 0 1
Move: Rxd5 — last pawn removed from d-file, the file is now open.
12. Doubled Pawns
Two or more pawns of the same color on the same file.
FEN: 4k3/8/8/8/8/3n4/2PP4/4K3 w - - 0 1
Move: cxd3 — pawn captures, creating doubled pawns on d2 and d3.
13. Isolated Pawn
A pawn with no friendly pawns on adjacent files.
FEN: 4k3/8/8/8/r1PP4/8/8/4K3 b - - 0 1
Move: Rxc4 — rook captures c4 pawn, leaving d4 pawn isolated.
Status
| Theme | Russian | English | Status |
|---|---|---|---|
| Double Check | Двойной шах | Double Check | :white_check_mark: |
| Fork | Вилка | Fork | :white_check_mark: |
| Discovered Check | Вскрытый шах | Discovered Check | :white_check_mark: |
| Pin | Связка | Pin | :white_check_mark: |
| Skewer | Копьё | Skewer | :white_check_mark: |
| Trapped Piece | Пойманная фигура | Trapped Piece | :white_check_mark: |
| Hanging Capture | Взятие висящей фигуры | Hanging Capture | :white_check_mark: |
| Removing Defender (material) | Уничтожение защитника (выигрыш фигуры) | Removing Defender (winning material) | :white_check_mark: |
| Removing Defender (mate) | Уничтожение защитника (угроза мата) | Removing Defender (mate threat) | :white_check_mark: |
| Exploiting Pin | Использование связки | Exploiting Pin | :white_check_mark: |
| Open File | Открытая линия | Open File | :white_check_mark: |
| Doubled Pawns | Сдвоенные пешки | Doubled Pawns | :white_check_mark: |
| Isolated Pawn | Изолированная пешка | Isolated Pawn | :white_check_mark: |
Planned
- Deflection
- Decoy
- Zwischenzug
- Discovered Attack
- Back Rank Mate
- Smothered Mate
PGN Annotations
Detected themes are visualized with arrows ([%cal]) and square highlights ([%csl]) in the PGN output. These annotations are displayed by Lichess, chess.com, and other viewers.
- Green arrows/highlights — tactical themes
- Blue arrows/highlights — strategic motifs
1. Nc7+ { [%csl Ga8,Ge8][%cal Gc7a8,Gc7e8] Fork (Nc7 -> Qa8, Ke8) }
1. Rxd5 { [%cal Bd1d8] Open File (d) }
Architecture
chess_detect/
├── __init__.py # Exports ChessDetector
├── detector.py # Main class
├── context.py # MoveContext — lazy evaluation
├── utils.py # Utilities (piece values, ray casting)
├── i18n/ # Translations
│ ├── ru.py
│ └── en.py
└── detectors/
├── base.py # BaseDetector (arrow_color, reset)
├── tactics/ # 10 tactical detectors
│ ├── double_check.py
│ ├── fork.py
│ ├── discovered_check.py
│ ├── pin.py
│ ├── skewer.py
│ ├── trapped.py
│ ├── hanging_capture.py
│ ├── removing_defender.py
│ └── exploiting_pin.py
└── strategic/ # 3 strategic detectors
├── open_file.py
├── doubled_pawns.py
└── isolated_pawn.py
Adding a New Detector
from ..base import BaseDetector
from ...context import MoveContext
class MyDetector(BaseDetector):
key = "my_theme" # i18n key
arrow_color = "green" # "green" for tactics, "blue" for strategy
def detect(self, ctx: MoveContext) -> bool:
# ctx.board_before, ctx.board_after, ctx.move
# ctx.is_check, ctx.is_capture, ctx.captured_piece
return False
def format_details(self, ctx: MoveContext, lang: str) -> str:
return "" # e.g. "Nc7 -> Qa8, Ke8"
def get_arrows(self, ctx: MoveContext) -> list[tuple[int, int]]:
return [] # (from_sq, to_sq) or (sq, sq) for highlights
- Create a file in
detectors/tactics/ordetectors/strategic/ - Add translations to
i18n/ru.pyandi18n/en.py - Register in
detector.py
Tests
python -m pytest tests/ -v
110 tests — all passing.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chess_detect-0.2.1.tar.gz.
File metadata
- Download URL: chess_detect-0.2.1.tar.gz
- Upload date:
- Size: 39.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f903092630018c321b82d2a5486e73981939b140208913c32530884952ce95ce
|
|
| MD5 |
901ede2b58edbe7856ab6e17c0ec1cac
|
|
| BLAKE2b-256 |
a781d9fea10eea373d8ec6e0c646e05af985b2bdaae54573b6c6bc3549291ba1
|
Provenance
The following attestation bundles were made for chess_detect-0.2.1.tar.gz:
Publisher:
publish.yml on aslyamov/chess_detect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chess_detect-0.2.1.tar.gz -
Subject digest:
f903092630018c321b82d2a5486e73981939b140208913c32530884952ce95ce - Sigstore transparency entry: 928324603
- Sigstore integration time:
-
Permalink:
aslyamov/chess_detect@662ad8d64f59a4bbc83cc003585f9bf10f4b7a70 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/aslyamov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@662ad8d64f59a4bbc83cc003585f9bf10f4b7a70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file chess_detect-0.2.1-py3-none-any.whl.
File metadata
- Download URL: chess_detect-0.2.1-py3-none-any.whl
- Upload date:
- Size: 34.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
487c154ac4139a93b27e2325a4ce0685d29c5788f63a23d3c0d446aca27e0667
|
|
| MD5 |
8cd7b19beb911eccede104e0a77b1c61
|
|
| BLAKE2b-256 |
837b7491db66f231d913408f0c4e4e18a114199f8ae9979b926c5e5e12964f13
|
Provenance
The following attestation bundles were made for chess_detect-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on aslyamov/chess_detect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chess_detect-0.2.1-py3-none-any.whl -
Subject digest:
487c154ac4139a93b27e2325a4ce0685d29c5788f63a23d3c0d446aca27e0667 - Sigstore transparency entry: 928324604
- Sigstore integration time:
-
Permalink:
aslyamov/chess_detect@662ad8d64f59a4bbc83cc003585f9bf10f4b7a70 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/aslyamov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@662ad8d64f59a4bbc83cc003585f9bf10f4b7a70 -
Trigger Event:
push
-
Statement type: