Categorising Chess Tactics

A prerequisite to playing chess well is proficiency at tactics, the short sequences of moves which land a decisive blow - either winning the game outright with checkmate or attaining a material advantage. Unlike strategy - the softer skill of understanding long-term subtle dynamics in positions - tactics are a core skill which can be directly practised by solving puzzles. The positions have determinate answers and therefore provide a plentiful supply of discrete, tight feedback loop material for improving players to hone their skills. Indeed, countless books full of tactics puzzles have been published, and there are lots of websites offering up a never-ending stream of puzzles to solve.

Despite the huge supply of raw material, I have often thought there are considerable improvements which could be made to how we present and use tactics puzzles to improve our overall game.

The first problem is that the most popular tactics trainers like those on Lichess and Chess.com simply serve up a randomised infinite stream of puzzles. As you proceed through ever more puzzles, the sites continually update your tactics puzzle rating. This is typically structured as an elo rating, so that the puzzles themselves also have a rating and the hardest puzzles (by beating strong puzzle solvers) automatically get rated as hard. The site can then serve easier puzzles to beginners, and tougher puzzles to seasoned pros. Although all this is certainly helpful, a single tactics elo rating is far too coarse-grained to be really useful as a tool for improving.

Imagine a tennis player being given a single number summarising her overall proficiency at the game by her coach after each training session. Although that number will increase as time passes and she becomes ever stronger at the game, the number itself gives her very little information about which aspects of her game are weakest and should be focused on most in the next training session. Likewise, although tactics in chess form a high-level discipline within the game, we can be much more fine-grained about tactics in order to help us isolate weaknesses and improve more effectively.

Chess tactics are really composed from simpler ideas. At the root, there are some irreducible tactical motifs, like pins, skewers, forks, back-rank mates and probably a couple dozen more.

Here's an example of a skewer (also known as x-ray attack).

An example of a skewer tactic.
An example of a skewer tactic. White can play Re1, winning Black's queen and eventually the game.

In this position, white can play rook to e1, checking the black king, forcing it to move out of the way and expose its own queen. White can then capture the queen, gaining a decisive material advantage and winning the game.

Here's a more complex example which builds on this idea by combining the skewer concept with pawn promotion.

Another skewer tactic, combined with a pawn promotion motif.
In this position, white can create a threat of pawn promotion. Black's only defensive attempt isn't good enough because of a latent skewer.

Here, White's winning move is Rh8, threatening to promote the pawn on the next move (which would create a decisive material advantage). If Black captures the apparently undefended pawn by playing 1... Rxa7, White has the response 2. Rh7+. This once again skewers the Black king and allows the white rook to capture its opposite number for free. White will go on to win a simple endgame.

The commonly used online tactics trainers don't currently have any sophisticated methodology to categorise positions in a way which really identifies the similarities between two tactics puzzles. Lichess might tag (with user assistance) both of the above positions as skewers, and also tag the second one as a pawn promotion move.

My claim is that once a player is broadly familiar with the high level tactical motifs there is still significant further improvement to be made through the study of tactics; it's not the case that this improving player is unaware of skewers, or never sees them, but rather that they are not spotting deeper patterns composed from more basic motifs. A simple motif-tagging system seems very unlikely to give the kind of granularity this player needs to focus their learning.

In order to optimise our learning rate, we would like to make the feedback loop as tight as possible. When we're just learning to spot a new kind of pattern, we would like to be presented with a few dozen examples of that pattern back-to-back, helping it to bed in. Wading through hundreds of puzzles waiting for the next example of that pattern to show up is spreading our attention and learning capacity too thinly. We're trying to learn every pattern all at once - and we probably end up learning none of them!

So here's what I want:

  • A highly descriptive taxonomy of chess tactics. Not just 'removal of the defense' or 'pin' - full blown signatures which capture all of the ideas behind the solution to a specific puzzle.
  • An automated algorithm for analysing a tactics puzzle and producing a data structure recording its tactical signature.
  • A metric space over tactics signatures, so two puzzles can be deemed "close" if they share a lot of tactical features. For example, in the first diagrammed position above, if all four pieces move one square to the left, the signature of the resulting position should be extremely close to the original.
  • A system which can download all my games from Lichess, search through them to find all the tactics and dump them in a database. Then it works out the signature for each position and correlates whether or not I spotted it with the signature.
  • A spaced repetition training tool that tracks whether or not I'm improving at positions that have signatures close to the ones I'm frequently failing at in real games.
  • The trainer steadily adds new positions to the live repertoire that I'm learning, mixing positions I performed poorly in from my real games with positions that have very similar tactical signatures from a much larger database (like the Lichess puzzle database).

I believe that if a serious student had access to the above system, they would experience a very noticeable improvement in tactics training efficacy vs. the simpler Lichess and Chess.com versions, translating to overall improvement in competitive games.

There's quite a lot to build here but the only serious innovation is the tactics signature.

Tactic Signature

Consider this position. The correct move is of course Ne6, forking the King and Queen to cause a draw by insufficient material which is the best white can achieve.

A simple
    knight fork tactic.
White can fork black's king and queen, salvaging a draw despite the apparent material deficit.

How could we define the tactic signature for this position? I'll work with a JSON format because it's

  • self-describing
  • well-known
  • portable
  • can represent arbitrary tree structures.
{ "position": "8/2q3k1/8/8/5N2/8/8/6K1 w - - 0 1", "signature": { "best_move": "Ne6", "move_metadata": { "name": "fork", "attacker_sq": "e6", // the square the knight lands the fork on "is_check": true, "forked_pieces": [ { "piece": "King", "sq": "g7" }, { "piece": "Queen", "sq": "c7" } ] }, "responses": { "" } } }

This is a useful start. To develop things further, I'll switch to Typescript, whose type system is a convenient way to define the, possibly deeply nested structure of the signatures.

interface Fork { "name": "fork"; "attacker_sq": Square; "is_check": boolean; "forked_pieces": { "piece": PieceType; "sq": Square; }[]; } // We could set up the types to be even more granular, so that // `InterposePiece` can never be used as an escape to a knight check; // or `MoveAway` can never be used as an escape to a double check. enum CheckEscape { MoveAway, CaptureAttacker, InterposePiece, } // (probably very long) list of granular possibilities for a // single move tactic type MoveType = Fork | Pin | Skewer ... type ResponseType = CheckEscape | ... interface Response { "type": ResponseType; "move": SAN; "refutation": Tactic; } interface Tactic { "move": SAN; // Simple Algebraic Notation for the move "type": MoveType; "responses": Response[] } interface Puzzle { "position": Fen; "signature": Tactic; }

This is a rough draft of how a tactic signature schema could look. The important elements are:

  • it has a tree structure - this lets us represent arbitrarily complex tactics by composing smaller tactics
  • it is recursive; a tactic has a MoveType for each move we play, and that move has a list of possible responses our opponent could try
  • each response has a refutation, which is actually just another tactic
    • we probably need a response leaf node, which requires no further refutation - things like MaterialWin or Checkmate
  • it records granular information about squares and pieces involved - these are what will help us to define a metric over the space of tactics
    • for example, if the tree is identical except for the queen being located on c5 rather c7, we should be able to identify the two trees as being very closely related

This whole endeavour is really little more than formalising the usual solutions given to tactics puzzle in written material - combinations of plain English discussion and chess notation, systematically working through the pertinent variations.

Let's now try to give a full example of a tree. I'll try to do this for the (still relatively straightforward) example from earlier, of the pawn promotion + skewer puzzle.

{ "position": "R7/P3k3/8/8/8/8/7K/r7 w - - 0 1", "signature": { "move": "Rh8", "type": { "name": "threat", // we need a way to refer to moves which // have the tactical character of saying "if you do nothing // I will do this next"; perhaps 'null_move_threat' is a // good name "move": "a8=Q", "type": { "name": "promotion", "promotion_piece": "queen", "is_leaf": true, "leaf_result": "material_gain" } }, "responses": { "type": "capture_pawn_to_prevent_promotion", "move": "Rxa7", "refutation": { "move": "Rh7+", "type": { "name": "skewer", "attacker": "rook", "attacker_sq": "h7", "attacked_piece": "king", "attacked_piece_sq": "e7", "skewered_piece": "rook", "skewered_piece_sq": "a7", "is_leaf": true, "leaf_result": "material_gain" } } } } }

This is still somewhat pseudo-code and can probably be significantly refined, but hopefully it illustrates the idea.

Automated signature deduction

To generate a tactics signature from a given position is still going to be quite difficult. We can get the engine's game tree easily, but mapping this onto a signature is not completely straightforward. For example, in most tactics, it's important to show a selection of natural responses to the attacks. These responses form an important part of the tree structure, but clearly we can't just include all legal moves in this list or our tactic signatures will become massive. We want to only include plausible responses for the opponent in each position - but what counts as plausible? It isn't just the objectively best moves. A plausible move might have a terribly low score in a completely objective computer analysis - that's fine, we're trying to demonstrate that it's bad. There are probably some heuristics to develop here, but unfortunately it likely isn't going to be something we can do satisfactorily with a very simple approach.

Here's some Typescript pseudocode for recursively building the tactic signature (assuming all the hard work happens in other functions!):

function signature(position: Position): Tactic { const bestMove: SAN = position.bestMove(); const moveType: MoveType = position.matchMoveType(move); const responses: Response[] = position.plausibleResponses().map(resp => { "type": position.responseType(resp), "move": resp, "refutation": signature( position.makeMove(bestMove).makeMove(resp) ), }); return { "move": bestMove, "type": moveType, "responses": responses, } }

Definition of a distance metric

The power of this approach is supposed to be that it buys us the ability to cluster similar puzzles in a more fine-tuned way than the simple tagging systems in current use.

We want to write a function with the signature:

function dist(p1: Puzzle, p2: Puzzle): number;

so that we can present a user who has struggled with p1 with a bunch of other puzzles that have small distance to p1. The hope is that this would allow the student to improve at that pattern more quickly than simply discovering the answer to p1 and then hoping to put that learning to practice at some point in the next 1,000 puzzles they solve or games they play.

How close are two tactic signatures? Presumably differences deep in the branches of an otherwise similar pair of trees are less important than equivalent differences near the root. We'll need to quantify this in a way that is logical and matches our intuitions. A quick google suggests plenty of work has been done on the problem of comparing tree structures to produce distance metrics, so hopefully this aspect of the system is tractable.

Training

Once the basic signature and distance system is working, the ideal outcome would be to implement personalised learning for each user, effectively tracking their skill at identifying and solving patterns in different parts of the tactics 'state space'. By this point the system should have everything it needs to spot possibly nuanced weaknesses in a player's tactical vision, gleaned both from puzzles they have attempted and real games they have played. The player could then be presented with a dashboard displaying these findings, and a study plan built around spaced repetition of many puzzles with similar tactics signatures.

Conclusion

There's a lot of work to do to make this system for real, so instead of actually attempting to do it I've just written down the basic idea and conveniently omitted even attempting to solve some of the more complex challenges which will arise along the way. I really believe that this tool could be a massive boost for players striving to improve at chess, because tactical vision is an absolutely crucial element of the game. One can learn a lot about strategy, but tactical weakness places an insurmountable ceiling on improvements from positional understanding.

Hopefully one day, I (or you, dear reader) will have the time to attempt building it.