Being able to deliver check is not the only threat, taking away squares from the king is another. So I would also count knight attacks for what you call zone 1.lucasart wrote: 2/ King Attacks
* zone 1 = "king ring" is all the squres adjacent to the king
* zone 2 = zone 1 + sqaures where a knight would give check (ie. squares the king go jump onto it the king was a knight)
* count pieces attacking the relevant zone (zone 1 for B/R/Q and zone 2 for N), where the square(s) attacked are neither occupied by a friendly pawn (blocking our own attack) or defended by an enemy pawn.
What I do in Sjaak (based on what I do in Jazz, which so far has a more direct translation of Ed's algorithm) is assign each piece a weight based on its attack strength on "small boards", which is a proxy for how dangerous such a piece is if it is part of a king attack. This is essentially the total of squares attacked on a 3x3 and a 5x5 board, with some penalty for colour-bound pieces. Every piece joining the attack increments a counter with a score proportional to its "attack strength", but with a cap. The idea is that at some point adding pieces to the attack is no longer enough to increase the threat and you need to do things like remove attackers.
The index is also icremented for defects in the pawn shield and otherwise missing defenders. Finally, there's a penalty for the king straying too far from the corner.
The counter is used to index a table, which is calculated at startup using a Fermi-function. There are three adjustable parameters: the asymptotic value (the normalisation, which is ~ 2/3 of a minor piece), the index where the value starts to rise steeply (this plays the role of the Fermi energy) and a parameter describing the slope (which plays the role of temperature).
The final result is then scaled with the total attack strength of the enemy army, normalised to the attack strength in the initial chess array.
This works reasonably ok, but I'm sure there's room for improvement.