Bishop and knight
Listen to this post7 min
Created by AI from the text of this post and read by a synthetic voice; not a word-for-word version, and it may contain errors.
Loading…
Created by AI from the text of this post and read by a synthetic voice; not a word-for-word version, and it may contain errors.Position and speed stay in this browser and are sent nowhere.
The recording could not be played. Open the audio file
A king with a bishop and a knight wins against a lone king in almost every position. The win can be forced, but it is not easy to find: the defending king has to be driven into a corner of the bishop's colour. A program that does not know this can chase the king around the board until a repetition or the fifty-move rule ends the game as a draw.
On 2026-09-29 the question came up whether Coherent can do it.
A first probe
A quick test that day let the engine play against itself from eight random positions with king, bishop and knight against king, at a tenth of a second per move. It delivered mate twice. Four games ended by threefold repetition and two by the fifty-move rule. Four of the six failed positions were played again with a full second per move: two more mates and two more repetitions, one after twenty half-moves and one after thirty-six. More time helped only in part, which pointed to missing knowledge rather than missing depth.
A battery instead of a probe
Eight games are a hint, not a measurement. The same day a small tool was written that tests endgames class by class. It was reviewed twice before its first report; four small changes made after the second review were not reviewed again.
- Positions: eleven endgame classes, twenty positions each, drawn at random but reproducibly from a fixed seed. Only quiet positions are used: the side to move is not in check and cannot capture or mate at once.
- Starting value: endgame tablebases label each starting position as won, drawn or lost. The tables only label the start; they never make a move.
- Play: the engine plays both sides with a fixed budget of one hundred thousand nodes per move. That makes every game repeatable move for move. A second run of sixty of the games was identical.
Results for version 0.1.120:
| Class | Result |
|---|---|
| bishop and knight against king | seven of twenty won positions converted; the other thirteen ended by the fifty-move rule |
| rook, queen, two bishops against king | twenty of twenty converted in each class |
| king and pawn against king | all fifteen wins converted, all five draws held |
| rook and pawn against rook | six of seven wins converted, all thirteen draws held |
| queen against rook | nineteen of twenty converted |
| queen and pawn against queen | all nine wins converted, all eleven draws held |
| rook against bishop, rook against knight (drawn positions) | nineteen and twenty of twenty draws held |
The eleventh class, rook and two pawns against rook and pawn, has more pieces than the tables cover. It has no starting value and is not scored.
One class stands apart: bishop and knight. The same battery at a tenth of a second and at one second per move has not run yet: the tool only starts timed runs on a mostly idle machine, and the machine was busy.
What had been tried before
- Mating guide: a table to steer the defending king in elementary won endings was rejected, because an existing king-endgame table was thought to cover it. For bishop and knight the battery suggests it does not.
- Tablebases: using endgame tablebases was ruled out by the project's rules at the time.
- King and pawn: a small exact table for king and pawn against king, derived by the project itself, showed no measurable gain in the first test matches and was rejected.
Tablebases, read by a decoder written from a description
The decision on 2026-09-29 was to use endgame tablebases after all, read by a decoder of the project's own, written under clean-room rules:
- One session wrote a description of the file format in prose, from public documentation and existing open implementations, together with fifty-four reference values.
- A separate session wrote the decoder from that description alone, without reading the code of any existing implementation. An existing implementation served only as a black box, to compare results against. The session's tool calls were checked afterwards for access to such code, and none was found.
The first version disagreed with the reference in more than seventy thousand positions, all of one kind. It concerned captures in lost positions, a case the description covered only in part. The implementer inferred the missing rule from the reference's behaviour, not from anyone's code. The description was amended afterwards; the amendment corrects part of the inferred rule and has not gone into the decoder yet.
With the inferred rule in place, a second session checked the decoder again:
- of the fifty-four reference values, fifty match exactly and four are one half-move off, each time the same value the reference gives;
- every position with three pieces, a sample of more than a million positions with four and five pieces, and all four-piece positions, about two hundred and fifty million, show no deviation from the reference;
- a sample of more than seventy-seven million five-piece positions, which finished later, shows none either.
At the time of writing, the full comparison of the five-piece tables that label positions as won, drawn or lost is still running. The full comparison of the five-piece tables that give the distance to the next capture or pawn move has not started yet.
In measured games the opponents will get the same tables, so that a test compares engines and not access to tables. That changes the measuring conditions and starts a new measuring epoch, which was approved on 2026-09-29. The tables are used in measured games only after the decoder has been accepted, and full comparisons of the five-piece tables are among the conditions for that.
What this does not say yet
This entry does not say whether the tables make Coherent play endgames better. That has not been measured. The battery will run again once the decoder is part of the engine, and that result, not this entry, will say whether it worked.