CHESS FORENSICS
Bayesian Engine-Correlation Analysis

Chess Forensics

Detect engine assistance in chess games through multi-signal statistical analysis. Honest uncertainty. No false certainty.

How It Works

Every game is analysed through multiple independent statistical lenses, then combined with proper correlation adjustment

♘ +0.0 −0.4

Engine Analysis

A chess engine finds the best move in every position. We compare the player's actual moves to what the engine recommends

Accuracy
Blunders
Timing
Complexity
IPR

Multiple Signals

No single stat tells the whole story. We measure move accuracy, blunder rates, complexity handling, timing patterns, and more

1200 2600 50% 0% 100%

Fair Comparison

Signals are compared against what's normal for the player's rating. A 1200 matching the engine 50% of the time is suspicious; for a GM, it's Tuesday

0% 50% 100% 3.2%

Honest Verdict

The result is a probability, not a yes/no. One game is rarely conclusive — scanning multiple games gives much stronger evidence

Documented Cases

The pipeline validated against confirmed professional cheating cases with known outcomes

The Project

The problems, the math, the validation, and the honest limitations behind detecting engine-assisted play.

The Problem

Detecting cheating in chess is genuinely hard

When a player uses a chess engine during a game, their moves will look more like what a computer would play. But here's the catch: strong players also match the engine often. A grandmaster's best game might look just like a cheater's average game.

Any detection system has to solve three problems at once:

?
False positives are catastrophic

Wrongly accusing a clean player can end a career. The system must be conservative.

♞
Skill varies enormously

What's suspicious for a 1200 is normal for a 2600. One size does not fit all.

One metric is never enough

Engine match rate alone is too noisy. You need multiple independent signals combined properly.

The Approach

Bayesian evidence combination

Instead of a binary "cheater or not" threshold, we use Bayes' theorem to compute the probability of engine assistance given the evidence. This is the same mathematical framework used in medical testing, courtroom forensics, and spam filtering.

Start with a prior
1%
Base rate of cheating
→
Collect evidence
+14.3 dB
Combined from all signals
→
Get a posterior
21.3%
Updated probability

Evidence is measured in decibans (dB) — a logarithmic scale where +10 dB means "10× more likely cheating" and −10 dB means "10× more likely clean." This lets evidence from different signals and different games simply add up.

The Signals

What we actually measure

Each game is run through Stockfish (one of the world's strongest engines), which evaluates every position and finds the best moves. From this analysis we extract:

Engine match rate

How often the player's move matches the engine's #1 choice. Expected range depends heavily on rating.

Centipawn loss (ACPL)

Average "points" lost per move compared to the best move. Lower means more accurate play.

Complexity slope

Do they play better in complex positions than in simple ones? Humans usually do worse; engines don't care.

Blunder distribution

The CPL tail test: cheaters have suspiciously few large mistakes compared to what's expected for their rating.

Timing patterns

Clock data reveals if thinking time correlates with move quality. Humans think longer on hard moves; bots don't.

Switchpoint detection

Did the player suddenly start playing much better mid-game? A statistical changepoint test finds where.

The Baseline

Knowing what "normal" looks like

The most critical piece: a reference model of how players at each rating level actually play. Without it, you can't tell if 55% engine match is suspicious or routine.

Expected top-1 match rate by rating
30% 40% 50% 1000 1600 2200 2800 A GM matching 49% is completely normal
3.4M
games in corpus
229M
positions analysed
12
rating bands fitted

The corpus spans the full rating spectrum from beginner (<800) through super-GM (2800+), split into 12 bands every 200 Elo. Each band gets its own fitted model so a 1200's "normal" isn't a 2400's "normal".

Evidence in Action

How a verdict builds up

Each signal contributes its own evidence (positive for suspicious, negative for normal). These combine with correlation adjustments to prevent double-counting:

Engine match
+8.2 dB
ACPL
+5.6 dB
Blunder rate
+3.8 dB
Complexity slope
−2.4 dB
Timing pattern
−1.2 dB
Total
+14.0 dB

When scanning multiple games, evidence from each game simply adds to the running total. 20 clean games at −8 dB each pile up to −160 dB of exonerating evidence — even one suspicious game at +20 dB can't overcome that aggregate. But the system will still flag that individual game for closer review.

The Pipeline

From PGN to verdict

1
Ingest

Parse PGN, fetch from Chess.com or Lichess API, detect book moves via the Lichess opening explorer

↓
2
Engine analysis

Multi-pass Stockfish: depth 4 shallow scan, depth 12 main pass, depth 22 on critical positions

↓
3
Feature extraction

Per-move frame with match rank, CP loss, complexity, timing, game phase. Book and forced moves excluded.

↓
4
Signal computation

13+ statistical tests: z-scores against the rating-specific baseline for each signal independently

↓
5
Bayesian combination

Correlation-adjusted log-likelihood ratios summed into a total. Credible intervals via Monte Carlo.

↓
6
Verdict

Posterior probability with uncertainty bounds. For scans: per-game flags, convergence curve, changepoint detection.

Validation

Does it actually work?

A model that hasn't been tested against reality is just a theory. We validated against known outcomes — games where we know the ground truth.

False positive control

0% false positive rate on 3,000 corpus games at 50% threshold
0% false positive rate on 20 out-of-sample GM games
1.70% Fischer–Spassky 1972 Game 6 — one of the greatest games ever played
0.28% Kasparov–Topalov 1999 — "Kasparov's Immortal"
1.07% Niemann at 2022 Sinquefield Cup — no evidence of assistance

Known cheater detection

99.4% Borislav Ivanov, Zadar 2012 — 9 games, beat 4 GMs rated 2227
+5.4 dB Sébastien Feller, 2010 Olympiad — SMS relay, 8 games
5.5% Igors Rausis, Czech Extraliga 2019 — caught with phone in toilet
+3.6 dB Gaioz Nigalidze, Dubai 2015 Round 6 — the game where he was caught

Detection power

2 games needed to reach 95% confidence at full engine assistance
~7 games needed at 50% assistance rate (every other move)
139 automated tests pass — covering calibration, detection, and false positives

The hardest case is partial cheating by strong players. Feller (GM, 2649) used intermittent SMS relay — individually each game is ambiguous, but the per-player mixture model correctly accumulates weak signals across 8 games into a positive detection. This is exactly what the system was designed for.

Open source — inspect everything

Every line of analysis code is public. The baseline corpus, the fitted model, the signal weights — nothing is hidden. Fork it, improve it, challenge it.

View on GitHub

Based on the research of Prof. Kenneth Regan (University at Buffalo), who pioneered statistical cheat detection in chess.
See the documented cases for validated examples.