Trouble Spotter

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
hgm
Posts: 27794
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Trouble Spotter

Post by hgm »

I am designing a proper evaluation, and one of the terms I want to include is mobility (global and per piece). As a side effect of counting the moves, I can detect soft-pins and hanging pieces comparatively cheaply. Which is good, as I want to include those features of the position too. A position where the stm has a hanging piece can recieve a small positional penalty, (or a reduction of the stm bonus) in anticipation of the fact that his more restricted move choice wil on the average not improve his score as much as when he has the initiative.

When scoring such features, you occasionally encounter positions where the stm has two hanging pieces (e.g. a fork) or a hanging pinned piece. Such motifs are more often than no insolvable threats, so it seems logically to assume here that material will be lost, and declare the node non-quiet.

The problem is what to do next. Should I give an extension to see what can be salvaged? Or should I use a null-move score to figure out how bad it is exactly, and return that score (which will likely mean a fail low, where a fail high was needed). Searching all moves is likely to come up with a delaying tactic to push the problem over the horizon. Two ply later the problem will then still exist, and I will still recognize it, but I will have the same problem again, unless I keep extending until I used up all delay moves.

Of course in some cases there might be an unexpected tactical solution to the problem. But in most cases extended searching will just confirm what I don't really want to know: that the node fails low. That means that the move two ply earlier will fail low, and that the search will have to find an alternative cut move. Actually this seems the most sensible recourse anyway: it is in general much easier to prevent, say, a fork, than it is to wrestle yourself out of one. So failing low without further ado might not be so crazy at all. Only if there is no solution there, it becomes attractive to re-examine the evasion possibilities from the fork in the end leave.

A similar argument could apply to null moves. If your initial evaluation of the node tells you there is a bad problem like a fork in a 'cut-node', not only will the null move fail low, but the very much more expensive search of the real moves will have a very high probability of failing low too. It might be cheaper to avoid this position altogether two ply earlier, by picking another move as cut-move there. If you originally played a null-move there, the alternative will also be more expensive. But it has a much higher probability for success to fight off the threat.

Has anyone any ideas on this matter?
yoshiharu
Posts: 56
Joined: Sat Nov 11, 2006 11:14 pm

Re: Trouble Spotter

Post by yoshiharu »

hgm wrote: The problem is what to do next. Should I give an extension to see what can be salvaged? Or should I use a null-move score to figure out how bad it is exactly, and return that score (which will likely mean a fail low, where a fail high was needed). Searching all moves is likely to come up with a delaying tactic to push the problem over the horizon. Two ply later the problem will then still exist, and I will still recognize it, but I will have the same problem again, unless I keep extending until I used up all delay moves.
Focusing on the problem of forks (or more generally double attacks), to escape one you have to threaten something. What is this 'something' depends on the "sensitivity" of the player (in this case, an engine).

Therefore, if your engine understands, say, threatening the King, it will presumably extend checks and mate threats; therefore if a code to statically detect if there is a double attack, after the move that triggered the extension, still detects a double, and there is no further extension possible, it means that the resolution, if any, lies beyond the horizon, and the threat is a killer (as far as your engine knows).
Otherwise, you evaded the threat.
What I think should be done, in summary, is showing no mercy with a position with a "static" threat, unless some extension evades the threat.
Since you cannot prove in advance that there is a double attack threatened in a few plies, you have to rely to your "extension policy".
This is what I try to do with my engine, indeed...the result are...ahem...:roll:

The part in which this mechanism doesn't work, I think, is the Qsearch, where you don't have many moves, besides captures (and checks, if you included them: I didn't). In that case I am still trying to convince myself that null move pruning in qsearch wouldn't be too heavy: one day I'll give it a try...when I have time...

Cheers, Mauro