Downloads · 30 days
0
RDTvlokip/RDTChess
RDTChess is a other model from RDTvlokip. Use it for the other task on the model card, and read the license before you ship it in a product. It is set up for pytorch. The card lists the license as apache-2.0.
<style / width et border-collapse sont AUSSI en inline sur chaque table, et ce n'est pas une redondance: la feuille du site cible ses tables avec une specificite superieure a une simple classe, donc une largeur declar…
Downloads · 30 days
0
Access
Public
Updated Sep 5, 2026
Repo size
99.2 MB
Likes
2
Public
Click a slice to open those files.
.pt88 MB · 98%
From the Hugging Face model README
A 11.05M-parameter residual network — recurrent depth ×2, gated memory, Squeeze-and-Excitation — that plays chess in one forward pass — no search, no MCTS, no opening book. Trained from scratch on a single GTX 1080 Ti by supervised imitation of ≈10.99M human games from Lichess. This is <code>RDTChess2.pt</code>, currently the model live on the <a href="https://lichess.org/@/RDTChessBot">Lichess bot</a>.
</div> <p> <a href="https://lichess.org/@/RDTChessBot"><img alt="play on lichess" src="https://img.shields.io/badge/play%20it%20on-Lichess-0CA678?style=flat-square&logo=lichess&logoColor=white" /></a> <img alt="license" src="https://img.shields.io/badge/license-Apache--2.0-4C6EF5?style=flat-square" /> <img alt="params" src="https://img.shields.io/badge/params-11.05M-4C6EF5?style=flat-square" /> <img alt="games" src="https://img.shields.io/badge/games-~11M-4C6EF5?style=flat-square" /> <img alt="positions" src="https://img.shields.io/badge/positions-801.3M-4C6EF5?style=flat-square" /> <img alt="search" src="https://img.shields.io/badge/search-none-495057?style=flat-square" /> <img alt="framework" src="https://img.shields.io/badge/PyTorch-ee4c2c?style=flat-square&logo=pytorch&logoColor=white" /> <img alt="hardware" src="https://img.shields.io/badge/1%C3%97%20GTX%201080%20Ti-76b900?style=flat-square&logo=nvidia&logoColor=white" /> </p> <div class="rdt-note">⚠️ <b>One seed, one run.</b> Every number in the Identity and Evaluation sections just below comes from a single training run on a single seed (123). Directions are consistent across three of the four instruments used there; magnitudes are not multi-seed validated. Read this as a lab notebook, not a benchmark.<br><br> This repository ships <b>two</b> checkpoints. <code>RDTChess2.pt</code> (this card's main subject, live on Lichess) is recurrent depth ×2 + gated + SE on top of a 128×8 tower, trained on ≈11M games — compared against the plain architecture just below. <code>RDTChess.pt</code> is that plain architecture on its own: the original, single-seed, 5.5M-game run, described with its own numbers in <a href="#rdtchess">📎 RDTChess (original)</a> near the end of this card. Smaller and differently-shaped siblings were trained alongside both — narrower, shallower, other variants — but none of them are released here, and none of the numbers on this card come from them.
</div>This is <code>RDTChess2.pt</code>. <code>RDTChess.pt</code> — the plain architecture on its own, no recurrence, no gate, no SE — has its own Identity/Evaluation/Data-scaling numbers in the <a href="#rdtchess">📎 RDTChess (original)</a> section near the end of this card.
</div>Everything lives in a canonical frame: the side to move is always "White, playing up the board". When Black is to move, every square is mirrored (square ^ 56) and the piece colours swap.
Two consequences, both deliberate:
The 19 planes: 12 for pieces (6 ours, 6 theirs), 4 castling rights, 1 en passant, 1 fifty-move counter, 1 repetition flag.
The policy head emits logits, not a softmax. That is what lets the caller mask illegal moves before normalising. Softmaxing over all 4096 actions and then zeroing ~99% of them spends most of the model's capacity learning that illegal moves are illegal — capacity this size cannot spare.
Architecture. Same 128×8 residual tower as RDTChess.pt, plus three additions applied together:
z = sigmoid(W[candidate; previous]), initialised at sigmoid(-2) ≈ 0.12 so ~88 % of the previous state survives each pass by default).Data. The Lichess July 2026 standard-game dump, split into 8 sequential slices of ≈1.37M games each (both players rated ≥ 1800). One seed (123) trained on the first slice, then carried through the other 7 with --resume, so the final checkpoint has seen all ≈10.99M games and 801,295,726 positions, one epoch each.
Objective. Plain behaviour cloning. The policy is cross-entropy against the move the human actually played, computed over the legal moves only. The value head regresses the final game result, expressed from the side to move.
Recipe. AdamW, learning rate 1e-3, weight decay 1e-4, betas (0.9, 0.999), batch size 512, gradient clipping 1.0, one epoch per slice, no learning-rate schedule.
That is the whole method. No self-play, no MCTS, no distillation from an engine, no opening book, no endgame tablebase.
Compared against the plain (non-recurrent, non-gated, non-SE) 128×8 architecture, same data, same seed, one run each time — puzzles, Maia and minimax across all 8 slices; the round-robin across the first 7, run before the 8th finished training:
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left">Yardstick</th> <th style="padding:10px;text-align:center">Result</th> </tr> </thead> <tbody> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Puzzles, first move (McNemar, 23,845 puzzles)</div> <div class="rdt-sub">single forward pass, no search</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">ahead 8 / 8</span> <span class="rdt-dim">— never inverted, always significant</span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Maia-1100 / 1500 / 1900, no search either side</div> <div class="rdt-sub">300 games per slice per level</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">ahead 23 / 24</span> <span class="rdt-dim">— one isolated reversal, recovered next slice</span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Full round-robin, 14 checkpoints, 91 pairs</div> <div class="rdt-sub">27,300 games, no search either side, aggregate score vs the other 13</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">ahead 7 / 7</span> <span class="rdt-dim">— never inverted, the most stable instrument of all four</span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Minimax depth 2 (n=300)</div> <div class="rdt-sub">an adversary that searches, unlike the three yardsticks above</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">ahead 4 / 8</span> <span class="rdt-dim">— no stable direction, each swing confirmed on a second independent draw</span></td> </tr> </tbody> </table> </div> <div class="rdt-note">🚫 <b>No absolute Elo is claimed.</b> This model has never been played against a rated pool. Every figure here is a <i>difference</i> measured inside one family of models, on one training seed.
</div>Actual scores against Maia (CSSLab's human-imitating engine, nodes=1, no search either side), on the final checkpoint — one training seed (123):
Read this precisely, not optimistically. Puzzles, Maia, and the round-robin all judge in one pass, no search — the same regime this model is actually deployed in — and all three are stable and one-sided across every slice tested. Minimax is a stress test against an opponent that searches for a refutation; the mechanism never collapses against it, but the signal is too noisy at n=300 to claim it wins there either. On the 5 hand-picked positions where the production model actually lost a real game, both architectures bounce between fixing and re-breaking the same handful of positions slice to slice — until, on the very last slice, both converged on choosing the exact identical move on all 6 tested, the first time that happened.
This was confirmed on one seed (123) only, extended sequentially across 8 slices of the same data with --resume. The 1.38M-game starting point was separately confirmed on three independent seeds (24, 123, 454) before this single-seed extension began; the extension itself has not been repeated on another seed. Full protocol, every intermediate number, and the honest instability of the minimax signal are in the project's own lab notebook, not reproduced here in full.
Measured on the same 23,845 Lichess puzzles as the comparison above, on the final checkpoint (all 8 slices). One move per position, no search.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <tbody> <tr> <td style="padding:9px 10px;width:58%"><span class="rdt-key">First move of the solution</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>61.5 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Entire line</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>42.5 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Random baseline</div> <div class="rdt-sub">28.0 legal moves on average</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-dim">3.6 %</span></td> </tr> </tbody> </table> </div>The network is asked at every move of the line — even after it has already erred, so that no step is measured on a pre-filtered sample.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left;width:22%">Length</th> <th style="padding:10px;text-align:left">Accuracy, first move → last</th> </tr> </thead> <tbody> <tr> <td style="padding:9px 10px"><span class="rdt-val">2 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">54.5</span> <span class="rdt-dim">→</span> <span class="rdt-good">78.3</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">3 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">56.9</span> <span class="rdt-dim">→ 71.1 →</span> <span class="rdt-good">87.0</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">4 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">64.1</span> <span class="rdt-dim">→ 72.7 → 77.7 →</span> <span class="rdt-good">89.6</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">5 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">68.7</span> <span class="rdt-dim">→ 75.5 → 77.6 → 83.0 →</span> <span class="rdt-good">91.7</span></td> </tr> </tbody> </table> </div>The entry is the hardest move of every line here too, by 10 to 22 points — a smaller gap than RDTChess.pt's 20 to 35, but not closed. The last move of the line sits around 90 %, same as the original architecture.
First move found, split by what kind of move it is.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left;width:20%">Entry move</th> <th style="padding:10px;text-align:center">< 1200</th> <th style="padding:10px;text-align:center">1200-1599</th> <th style="padding:10px;text-align:center">1600-1999</th> <th style="padding:10px;text-align:center">2000-2399</th> <th style="padding:10px;text-align:center">2400+</th> </tr> </thead> <tbody> <tr class="rdt-band"><td colspan="6" style="padding:7px 12px">Forcing — visible in the position</td></tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Check</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">79.7</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">65.2</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">52.6</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">42.0</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">55.3</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Capture</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">92.2</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">77.4</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">63.8</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">60.7</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">59.9</span></td> </tr> <tr class="rdt-band"><td colspan="6" style="padding:7px 12px">Non-forcing — justified only by what comes later</td></tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Quiet</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">95.1</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">80.3</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">59.1</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">42.0</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-bad">33.3</span></td> </tr> </tbody> </table> </div>The quiet move is still the hardest category at high rating — 33.3 % at 2400+, essentially unchanged from RDTChess.pt's 32.8 %. Every band improved a little (quiet at 1600-1999: 59.1 vs 54.7; at 2000-2399: 42.0 vs 39.3), but the shape — quiet collapsing from easiest to hardest as rating rises — is identical. Recurrent depth, gating and SE bought accuracy; they did not change what kind of move the network struggles to initiate.
The model runs live as a Lichess bot: lichess.org/@/RDTChessBot
Challenge it in bullet, blitz, rapid or classical, casual or rated. Correspondence is declined on purpose — the bot answers in about 7 ms, so a game played over days would tie up a slot for weeks and tell you nothing.
It plays exactly the weights in this repository, through uci.py, with FinishPlies: 1 and two CPU threads. No search, no opening book, no tablebase: every move you see is one forward pass. The bot currently runs RDTChess2.pt — swapping uci.py's default is the only thing that changes when the deployed checkpoint changes, so check this line if you're reproducing a game and the move doesn't match what you'd expect from RDTChess.pt.
pip install -r requirements.txt
python predict.py # initial position
python predict.py "6k1/5ppp/8/8/8/8/5PPP/R5K1 w - - 0 1" # any FEN
top 5 moves
Ra8# 64.3 %
Ra7 11.4 %
Re1 5.6 %
python play.py # you are White, opens http://localhost:8000
python play.py --black
python play.py --port 8080 --depth 3
Three modes in the page — play the model, play the minimax, or watch the two of them — plus a depth slider. Standard-library HTTP server, no build step, no CDN.
<details> <summary><b>Use it in your own code</b></summary> <br>import chess, numpy as np, torch
from encoding import board_to_planes, legal_move_indices
from network import ChessNetwork
model = ChessNetwork.from_checkpoint("RDTChess2.pt", device="cpu") # or "RDTChess.pt"
board = chess.Board()
moves, indices = legal_move_indices(board) # legal moves + their indices
planes = torch.from_numpy(board_to_planes(board)).unsqueeze(0)
with torch.no_grad():
logits, value = model(planes)
legal = logits[0, torch.as_tensor(indices.astype(np.int64))]
probs = torch.softmax(legal.float(), dim=0).numpy() # over legal moves ONLY
print(board.san(moves[int(probs.argmax())]), float(value))
⚠️ The one mistake to avoid: reading argmax over the full 4096 logits. About 99 % of them are illegal in any given position. Always gather at legal_move_indices first.
ChessNetwork.from_checkpoint returns the model already in eval() mode. Keep it there — the tower is BatchNorm, and train-mode batch statistics will corrupt single-position inference.
| file | role |
|---|---|
RDTChess2.pt | 128×8 + recurrence ×2 + gated + SE, weights + architecture config (44 MB) |
RDTChess.pt | plain 128×8, weights + architecture config (44 MB) |
network.py | the architecture — loads either checkpoint, config comes from the file |
encoding.py | board ↔ tensor, move ↔ index |
player.py | the network as a player, get_move(engine) |
engine.py | board wrapper, canonical encoding, hand-written evaluation |
algo_player.py | alpha-beta minimax, the opponent used in evaluation |
gui.py, play.py | the browser board |
predict.py | one-position example |
Inference only. The training code is not part of this release; the recipe above is complete enough to reproduce it. Both released checkpoints carry weights and architecture config, with the optimiser state stripped — 44 MB each instead of ~131 MB.
</details><a id="rdtchess"></a>
Everything in this section is about <code>RDTChess.pt</code> specifically: the plain 128×8 tower, no recurrence, no gate, no SE — the original single-seed, 5.5M-game run. None of the numbers below apply to <code>RDTChess2.pt</code> above; its own comparison against this architecture is in the Evaluation section near the top of this card.
</div> <div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <tbody> <tr> <td style="padding:9px 10px;width:30%"><span class="rdt-key">Architecture</span></td> <td style="padding:9px 10px"><span class="rdt-val">Residual tower, <b>128 channels × 8 blocks</b>, two heads</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Parameters</span></td> <td style="padding:9px 10px"><span class="rdt-val">10.92 M</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Input</span></td> <td style="padding:9px 10px"><span class="rdt-val">19 planes of 8×8, canonical frame</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Policy output</span></td> <td style="padding:9px 10px"><span class="rdt-val">4096 raw logits <span class="rdt-dim">(from-square × 64 + to-square)</span></span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Value output</span></td> <td style="padding:9px 10px"><span class="rdt-val">One scalar in [−1, 1], <code>tanh</code></span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Search</span></td> <td style="padding:9px 10px"><span class="rdt-val"><b>None</b> — one forward pass per move</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Training data</span></td> <td style="padding:9px 10px"><span class="rdt-val">5,497,103 Lichess games, both players ≥ 1800 Elo</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Positions seen</span></td> <td style="padding:9px 10px"><span class="rdt-val">400,581,531, one epoch</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Training time</span></td> <td style="padding:9px 10px"><span class="rdt-val">12 h 54 on a GTX 1080 Ti</span></td> </tr> </tbody> </table> </div>Data. The Lichess July 2026 standard-game dump. A game is kept when both players are rated ≥ 1800 (the filter takes min(WhiteElo, BlackElo)), which leaves 5,497,103 games in the 5 GB archive — all of them used. Every position of every kept game becomes one training sample, from the first ply: 400,581,531 positions, seen once.
Objective. Plain behaviour cloning. The policy is cross-entropy against the move the human actually played, computed over the legal moves only. The value head regresses the final game result, expressed from the side to move.
Recipe. AdamW, learning rate 1e-3, weight decay 1e-4, betas (0.9, 0.999), batch size 512, gradient clipping 1.0, one epoch, no learning-rate schedule.
That is the whole method. No self-play, no MCTS, no distillation from an engine, no opening book, no endgame tablebase.
Three independent yardsticks, because they disagree — and the disagreement is itself a finding.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left;width:58%">Yardstick</th> <th style="padding:10px;text-align:center">Result</th> </tr> </thead> <tbody> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Top-1 on held-out human moves</div> <div class="rdt-sub">agreement with what the human actually played</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>51.7 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">vs minimax depth 1</div> <div class="rdt-sub">300 games · +249 =34 −17</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">88.7 %</span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">vs minimax depth 2</div> <div class="rdt-sub">300 games · +144 =69 −87</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>59.5 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">vs the same net trained on 2M games</div> <div class="rdt-sub">600 games · +35 Elo · p = 0.0034</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>55.1 %</b></span></td> </tr> </tbody> </table> </div>A fixed opponent measures how well you exploit that opponent, not general strength: the depth-1 and depth-2 figures move by 29 points for the same model. The head-to-head duel is the most informative of the three.
<div class="rdt-note">🚫 <b>No absolute Elo is claimed.</b> This model has never been played against a rated pool. Every Elo figure here is a <i>difference</i> measured inside one family of models.
</div>The rate bends steadily — 25.7, 20.9, 18.2 — without collapsing. The +8.0 was predicted at +9 before the run from the two earlier points.
<div class="rdt-note">The last row is a wider net than the first two, so the three rates are <b>not</b> a single controlled curve: read the bend as a trend, not as a measurement. The architecture comparison was run separately, at fixed data, and found depth to be the lever that pays and width almost nothing on its own — until the two are combined.
</div>Measured on 23,845 Lichess puzzles, sampled by cell (solution length × rating band) so that puzzle difficulty is not confounded with solution length. One move per position, no search.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <tbody> <tr> <td style="padding:9px 10px;width:58%"><span class="rdt-key">First move of the solution</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>57.8 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Entire line</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val"><b>38.3 %</b></span></td> </tr> <tr> <td style="padding:9px 10px"> <div class="rdt-key">Random baseline</div> <div class="rdt-sub">28.0 legal moves on average</div> </td> <td style="padding:9px 10px;text-align:center"><span class="rdt-dim">3.6 %</span></td> </tr> </tbody> </table> </div>The network is asked at every move of the line — even after it has already erred, so that no step is measured on a pre-filtered sample.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left;width:22%">Length</th> <th style="padding:10px;text-align:left">Accuracy, first move → last</th> </tr> </thead> <tbody> <tr> <td style="padding:9px 10px"><span class="rdt-val">2 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">51.9</span> <span class="rdt-dim">→</span> <span class="rdt-good">76.1</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">3 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">53.6</span> <span class="rdt-dim">→ 67.5 →</span> <span class="rdt-good">85.1</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">4 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">60.4</span> <span class="rdt-dim">→ 69.6 → 75.2 →</span> <span class="rdt-good">88.0</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-val">5 moves</span></td> <td style="padding:9px 10px"><span class="rdt-bad">65.5</span> <span class="rdt-dim">→ 72.5 → 75.5 → 80.3 →</span> <span class="rdt-good">90.6</span></td> </tr> </tbody> </table> </div>The entry is the hardest move of every line, by 20 to 35 points. The last is around 90 %, whatever the depth. Once inside a forcing sequence — recaptures, checks, the mate — the network barely errs. Starting one is the problem.
First move found, split by what kind of move it is.
<div class="rdt-wrap"> <table class="rdt-table" style="width:100%;border-collapse:collapse"> <thead> <tr> <th style="padding:10px;text-align:left;width:20%">Entry move</th> <th style="padding:10px;text-align:center">< 1200</th> <th style="padding:10px;text-align:center">1200-1599</th> <th style="padding:10px;text-align:center">1600-1999</th> <th style="padding:10px;text-align:center">2000-2399</th> <th style="padding:10px;text-align:center">2400+</th> </tr> </thead> <tbody> <tr class="rdt-band"><td colspan="6" style="padding:7px 12px">Forcing — visible in the position</td></tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Check</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">74.4</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">59.5</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">47.5</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">39.5</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">51.4</span></td> </tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Capture</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">91.6</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">73.8</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">60.7</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">57.7</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">56.1</span></td> </tr> <tr class="rdt-band"><td colspan="6" style="padding:7px 12px">Non-forcing — justified only by what comes later</td></tr> <tr> <td style="padding:9px 10px"><span class="rdt-key">Quiet</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-good">94.6</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">75.6</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">54.7</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-val">39.3</span></td> <td style="padding:9px 10px;text-align:center"><span class="rdt-bad">32.8</span></td> </tr> </tbody> </table> </div>The quiet move goes from the easiest category to the hardest — 23 points below captures in the same band — as difficulty rises. Captures and checks are visible in the position; a quiet preparatory move is justified only by what comes three plies later.
<div class="rdt-punch">💡 In one sentence: this network <b>executes</b> tactics, it does not <b>initiate</b> them.
</div>Apache-2.0.
@misc{charlet2026rdtchess,
author = {Théo CHARLET},
title = {RDTChess: 128x8 chess policy and value networks trained on human Lichess games},
year = {2026},
publisher = {Hugging Face},
howpublished = {\url{https://huggingface.co/RDTvlokip/RDTChess}}
}
🚀 Seeking internship opportunities