We value your privacy

We use essential cookies to keep you logged in securely. We also use functional cookies to remember your game preferences, sound volume, and local progress. You can read more in our Privacy Policy.

All articles

A brilliant sacrifice is invisible to the engine that proves it works

We spent weeks trying to make our analyser detect brilliant moves. It found nothing — not one famous sacrifice in chess history. The reason turned out to be the same reason the sacrifices are good.

August 2026 · 8 min read

Every analysis tool worth using grades your moves. Best, good, inaccuracy, mistake, blunder. And at the top, the one everybody actually wants: brilliant.

A brilliant move, in almost every case, is a sacrifice. You give up material — often a lot of it — for an attack the opponent cannot survive. Detecting that ought to be simple. Play the move, see how much material the player gave away, check that the position is still winning. Three conditions, all measurable.

Our first implementation did exactly that. Across ten complete games, including several of the most famous sacrificial masterpieces ever played, it fired zero times.

The trap

The measurement worked like this: play the candidate move, let the engine continue the game from there, and count the material that actually changed hands over the next few moves. If the player ended up materially down but still winning, that is a sacrifice.

Read that again with a chess player's eye and the problem becomes visible.

A sound sacrifice is sound precisely because accepting it loses. So the engine, playing well, declines it. No material changes hands. The measurement returns zero. And the better the sacrifice, the more certain the engine is to refuse — which makes the finest moves in chess the most reliably invisible.

The detector was not broken in the ordinary sense. Every line of it did what it was written to do. It was asking a question whose answer is guaranteed to be "no" in exactly the cases it was built to catch.

This is a nice example of a class of bug that is very hard to find by reading code, because the code is correct. You have to reason about what the measurement means, and the only reliable way we found to do that was to run it over real games with known answers and notice that the answers were all wrong.

Asking a different question

The fix was to stop asking "does the opponent take it?" and start asking "is material being offered?" — regardless of whether taking would be a good idea.

That second question has a standard answer in chess programming: static exchange evaluation, or SEE. For a given square, you play out every possible capture on it, both sides alternating, always capturing with the cheapest available piece, and you compute the net material result. It tells you what a square is worth to take, without any search at all.

Run SEE across every piece the player owns, after their move, and you learn whether anything is hanging by more than it should be. If a queen is sitting on a square where the opponent wins material by capturing it, material is being offered — whether or not the engine intends to accept.

Rebuilt on that basis, the detector immediately found what it was supposed to find. Rubinstein's Immortal Game from 1907, which ends in a cascade of rook and queen offers, now correctly flags 22...Rxc3, 23...Rd2 and 25...Rh3.

The detail that catches most implementations

There is a subtlety here that is easy to miss and, once seen, is obviously fundamental.

Bobby Fischer's 17...Be6 against Donald Byrne in 1956 — the move that made the "Game of the Century" famous, played when Fischer was thirteen — offers his queen. But the piece that moves is a bishop. The queen is not touched. It simply becomes capturable as a consequence of the bishop going somewhere else.

Any detector that examines the piece that moved will miss it completely. And this is not an exotic edge case: discovered offers, where moving one piece exposes another, are a large fraction of the most beautiful moves ever played. The geometry that makes them hard for humans to see is the same geometry that makes them easy for software to overlook.

The detector has to evaluate everything the player owns after the move, not the piece involved in it.

What this still cannot do

Chess software marketing usually stops at the point where things start working. It is more useful to say where the limits are.

Detecting an offer is now reliable. Judging whether the offer is sound still depends on the engine's evaluation of the resulting position, and that is where a browser-based engine runs out of room.

The clearest example we have is Kasparov's 24.Rxd4 against Topalov in 1999, frequently called the greatest move of the greatest game ever played. Our analyser evaluates it at roughly −38 — that is, distinctly bad for Kasparov. Throwing eight million additional positions at that single move moved the number to −33. Essentially nothing.

The compensation for that sacrifice is positional and does not resolve for about twenty more moves. No amount of search anyone will sit and wait for in a browser tab is going to find it. This is not a threshold that needs tuning; it is a real limit of how deep you can search on someone's laptop in a few seconds.

Forcing combinations are a different story. Rubinstein, Morphy, Anderssen — where the point of the sacrifice is a concrete mating net a handful of moves away — all evaluate correctly, because the tactics are inside the search horizon.

The general lesson

We got this wrong twice by reasoning about the code instead of measuring what it produced. Both times the code was doing exactly what it said. What was wrong was the belief that the quantity being measured was the quantity we cared about.

The thing that eventually worked was boring: take real games with known answers, run the analyser over them, and compare the output against what a strong player would say. Historic games are ideal for this because the correct answer has been agreed on by everyone for a century. If your brilliancy detector cannot find Rubinstein's rook sacrifices, the problem is not the threshold.

Every game mentioned in this article can be loaded into our analyser and checked move by move. That is, in the end, the only argument that counts.