Inside the world's least ambitious chess engine

The Technical Stuff

Shallow Red began with a simple question: what happens when a chess engine values its own checkmate above everything else?

01

What does “losing” mean?

Shallow Red succeeds when it gets checkmated.

Winning is a failure. Draws are also undesirable. Given two successful ways to lose, it prefers the faster one—but reliability always comes before speed.

The objective is reliability first and speed second. A system that loses 95% of its games slowly is better than one that loses 85% quickly and draws the rest. Several faster experimental versions were rejected for exactly that reason.

02

The policy is not the engine

Shallow Red has two layers. A neural policy ranks moves. A deterministic tactical evaluator makes the final decision.

The research policy is the larger 32-channel neural network. The research system combines that policy with the Python stalemate-aware reply evaluator.

The browser policy is the smaller quantized network downloaded by this page. The browser enginecombines it with a TypeScript version of the tactical evaluator. In both systems, the network proposes and the evaluator decides.

03

From a board to 4,672 actions

A position becomes 21 planes of 8 × 8 values. Twelve planes locate Shallow Red's six piece types and its opponent's six piece types. The remaining planes encode side to move, four castling rights, en passant, the halfmove clock, and repetition state.

Black positions are mirrored by rank, so the network always sees Shallow Red's home rank at the bottom. Policy actions are mirrored the same way.

The policy head emits 4,672 logits: 64 origin squares multiplied by 73 move planes. Those planes describe sliding moves, knight moves, and underpromotions. Castling, en passant, and queen promotions fit into the same geometry. Illegal actions are masked before ranking.

PolicyChannelsResidual blocksPolicy parameters
Research32482,473
Browser24337,633

Each residual block contains two 3 × 3 convolutions, ReLU activations, and a skip connection. A 1 × 1 policy head converts the final features into the 73 move planes.

04

Learning a ranking, not one move

Training did not label a position with one supposedly correct move. A teacher scored every legal move and assigned a complete ranking. The policy learned a soft distribution over those ranks, so near-best moves still contributed to the objective.

The selected v0.3 dataset contains 9,827 positions: 5,227 labeled by reverse-Stockfish analysis and 4,600 labeled by a random-reply evaluator. It was split into 7,937 training, 967 validation, and 923 test positions, keeping related game families together.

The 32 × 4 policy trained for 20 epochs on Apple MPS with a rank temperature of 2. Actions were aligned to Shallow Red's perspective. Although the architecture includes a value head, the selected run set its value-loss weight to zero: the final system uses the policy for move ordering, not as an outcome oracle.

05

The research system

On each turn, the policy keeps its twelve highest-ranked legal moves. For every retained move, the evaluator enumerates every legal immediate opponent reply.

Its leading term is exact under a uniform-reply assumption: what fraction of those replies checkmate Shallow Red immediately? It also measures draws, checks, captured material, attacks around the king, king escape squares, and Shallow Red's resulting mobility.

score(move) =
  1e9 × P(checkmated next)
− 1e8 × P(draw next)
+ 1e6 × P(checked next)
+ capture, king-pressure, and mobility terms
EventPrimary effect
Shallow Red checkmates its opponent−1 trillion
Opponent can checkmate Shallow Red+1 billion × probability
Opponent reply creates a draw−100 million × probability
Opponent reply gives check+1 million × probability

Two exact tactical layers take precedence over that score. If a move guarantees Shallow Red's checkmate after every legal opponent reply, it is played as a forced loss. A two-ply win shield then vetoes avoidable moves that either checkmate the opponent immediately or let the opponent force every Shallow Red response to checkmate them on the following turn.

When Shallow Red has at most 1,000 centipawns of non-king material, several smaller incentives reverse. Sacrificing the last pieces becomes dangerous, so the evaluator starts preserving material, king escapes, and legal mobility to reduce stalemates.

06

What runs on this website

The browser uses the same two-stage design with a smaller policy: 24 channels, three residual blocks, and 37,633 policy parameters. Per-tensor int8 quantization compresses it into a self-describing 39.7 KB artifact. The unused value head is not shipped.

  1. 01Encode the 21-plane position
  2. 02Run the neural policy
  3. 03Mask illegal actions and retain the top 12
  4. 04Enumerate every immediate opponent reply
  5. 05Apply the tactical score and play the winner

The neural logits determine which moves reach the tactical stage; they do not directly choose the move. If the policy cannot load or inference fails, the same tactical scorer evaluates every legal move instead.

Model loading, inference, legal-move generation, reply enumeration, and scoring all happen locally in your browser. No GPU or permanent chess server is required.

07

How bad is it?

Against a uniform-random opponent, the selected research system was checkmated in 281 of 300 frozen games:

93.7%Losses
5%Draws
1.3%Unfinished
0Wins

It also lost all 100 games against Stockfish at 1,000 nodes per move. Successful random-opponent losses took a median of 70 plies—about 35 full moves.

Before browser export, the smaller 24 × 3 policy was tested in the equivalent Python hybrid across random, Stockfish, weak, and stress opponents. It self-checkmated in 474 of 500 games, with 25 draws, one unresolved game, and zero wins.

After quantization, its held-out rank-one accuracy was 30.4% and its top-12 set agreed with the float policy 92.4% of the time. The dependency-free TypeScript forward pass measured 6.24 ms median in Node on the development Mac.

08

Why not just reverse Stockfish?

Stockfish is very helpful when the opponent wants to win. It eagerly accepts hanging pieces and finds mating attacks. Against that cooperative objective, Shallow Red can lose extremely well.

Random and weak opponents are harder. They overlook free material, ignore attacks, miss checkmates, and accidentally create stalemates. Shallow Red therefore needs an explicit model of unhelpful replies rather than simply negating a normal chess evaluation.

09

Limits and negative results

Shallow Red is not a general selfmate solver. Its tactical layer looks through one opponent reply, assumes a particular reply distribution, and can only inspect moves retained by the neural shortlist.

  • The bare v0.3 neural policy self-checkmated in only 33% of a 100-game random-opponent development suite and accidentally won 6%. Search is essential.
  • Models trained to lose faster became less reliable.
  • Rollout search looked faster only because it converted difficult losses into draws.
  • Repetition penalties reduced overall performance.
  • Two copies of Shallow Red produced 40 repetition draws in symmetric self-play.
  • Standard chess tablebases rarely affected actual games.
  • An exact 2.8-million-position bishop-versus-rook analysis found no nonterminal position where the losing side could force its own checkmate against perfect resistance.

The live challenge ignores repetition and the orthodox 50- and 75-move thresholds. Instead, each game has a player-configurable budget from 2 individual turns to unlimited, with unlimited selected by default. Reaching a finite budget records a draw. Checkmate, stalemate, and insufficient material remain terminal because play cannot meaningfully continue.

Every result is conditional on its opponents, openings, seeds, move limits, and rules. Zero observed wins is evidence, not a proof that Shallow Red can never win.

The guiding rule

First, lose consistently.
Then, and only then, lose faster.

Credit

Shallow Red was researched, trained, evaluated, built, and deployed in collaboration with Codex using gpt-5.6-sol-high.

Back to the game