Non-quiet position after quiescence...

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Nomis
Posts: 18
Joined: Sun Jan 03, 2021 1:19 pm
Full name: Simon Reed

Non-quiet position after quiescence...

Post by Nomis »

Hello,

I'm investigating a bullet game played (and lost) by my engine this morning, in which it played a rather stupid move.

In this position:
[d]r2qkbnr/1b2p2p/n1p2pp1/pp1p4/8/BPNBPN2/P1PP1PPP/R2QK2R w KQkq - 0 10
As white, it played Nd4, ignoring the threat of the pawn in b5.

Traces show that at some point during search, QS stopped due to "standing pat" at this position:
[d]5knr/1b2p2p/r1pq1pp1/p2p4/1p6/BPN1P3/P1PP1PPP/R2QK2R w KQ - 0 14

Which is, as far as I can tell, not quiet at all and leads white to lose a piece.

To fix this I naively tried to implement some kind of null-move check in quiescence, which kinda works in this particular case, but is a major elo loss in general.

I'm wondering if I'm asking too much to the QS and maybe that's a problem that should only be fixed by searching faster (and deeper) ?
No4b
Posts: 105
Joined: Thu Jun 18, 2020 3:21 pm
Location: Moscow
Full name: Alexander Litov

Re: Non-quiet position after quiescence...

Post by No4b »

As it is white-to-move and white have no good capture it makes sense to stop here.
I guess its just you overall search depth is low being the problem here.

Weak engines are often try to prolong inevitable losses by giving checks and/or trading pieces (as here) during the search.
This would be somewhat mitigated when your depth would raise (although not completely gone)

Quick solution without losing much elo (and maybe gaining some) as of right now would be adding in recapture extension i guess, but this extension is very hard to get right for stronger engines so it can become hindrance in the future.

More refined solution would be adding specific "hanging" evaluation term, that is present in the most of the (if not all) top engines. It means during evaluation you give a penalty when your piece is attacked by a pawn (or rook by minor, or Q by R/N/B). But from my experience it is hard to come up with good numbers for this eval from the top of your head.

PS. I`m not very experienced in this stuff, so i would take my words with a grain of salt :)
Pio
Posts: 334
Joined: Sat Feb 25, 2012 10:42 pm
Location: Stockholm

Re: Non-quiet position after quiescence...

Post by Pio »

Nomis wrote: Sun Jan 10, 2021 4:04 pm Hello,

I'm investigating a bullet game played (and lost) by my engine this morning, in which it played a rather stupid move.

In this position:
[d]r2qkbnr/1b2p2p/n1p2pp1/pp1p4/8/BPNBPN2/P1PP1PPP/R2QK2R w KQkq - 0 10
As white, it played Nd4, ignoring the threat of the pawn in b5.

Traces show that at some point during search, QS stopped due to "standing pat" at this position:
[d]5knr/1b2p2p/r1pq1pp1/p2p4/1p6/BPN1P3/P1PP1PPP/R2QK2R w KQ - 0 14

Which is, as far as I can tell, not quiet at all and leads white to lose a piece.

To fix this I naively tried to implement some kind of null-move check in quiescence, which kinda works in this particular case, but is a major elo loss in general.

I'm wondering if I'm asking too much to the QS and maybe that's a problem that should only be fixed by searching faster (and deeper) ?
I think a good solution to this problem is evaluating the position statically as pawn minus the least valuable piece, so something like -2.3. I would also give a bonus for the first position of something like -(-2.3)/2 since it is very hard to get out of the threat and the only option is to threaten a piece of greater value.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Non-quiet position after quiescence...

Post by maksimKorzh »

Nomis wrote: Sun Jan 10, 2021 4:04 pm Hello,

I'm investigating a bullet game played (and lost) by my engine this morning, in which it played a rather stupid move.

In this position:
[d]r2qkbnr/1b2p2p/n1p2pp1/pp1p4/8/BPNBPN2/P1PP1PPP/R2QK2R w KQkq - 0 10
As white, it played Nd4, ignoring the threat of the pawn in b5.

Traces show that at some point during search, QS stopped due to "standing pat" at this position:
[d]5knr/1b2p2p/r1pq1pp1/p2p4/1p6/BPN1P3/P1PP1PPP/R2QK2R w KQ - 0 14

Which is, as far as I can tell, not quiet at all and leads white to lose a piece.

To fix this I naively tried to implement some kind of null-move check in quiescence, which kinda works in this particular case, but is a major elo loss in general.

I'm wondering if I'm asking too much to the QS and maybe that's a problem that should only be fixed by searching faster (and deeper) ?
Can't see position, could you please provide bare FEN string?
Position should be considered quiet when either no captures are available or if eval() == quiescence()
Can't say more without seeing actual position.
Nomis
Posts: 18
Joined: Sun Jan 03, 2021 1:19 pm
Full name: Simon Reed

Re: Non-quiet position after quiescence...

Post by Nomis »

Thanks for your replies.

I'll look into the extension.

maksimKorzh, the FEN are:

r2qkbnr/1b2p2p/n1p2pp1/pp1p4/8/BPNBPN2/P1PP1PPP/R2QK2R w KQkq - 0 10

5knr/1b2p2p/r1pq1pp1/p2p4/1p6/BPN1P3/P1PP1PPP/R2QK2R w KQ - 0 14
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Non-quiet position after quiescence...

Post by maksimKorzh »

Nomis wrote: Sun Jan 10, 2021 7:19 pm Thanks for your replies.

I'll look into the extension.

maksimKorzh, the FEN are:

r2qkbnr/1b2p2p/n1p2pp1/pp1p4/8/BPNBPN2/P1PP1PPP/R2QK2R w KQkq - 0 10

5knr/1b2p2p/r1pq1pp1/p2p4/1p6/BPN1P3/P1PP1PPP/R2QK2R w KQ - 0 14
Seems like something is wrong with quiescence.
Neither of positions you've provided are quite.
May be you have depth limit in quiescence along with stand pat?
Otherwise it's hard even to assume what's wrong there.
If you post your alphabeta() and quiescence() code here it would bring some light...

P.S. Are you sure that your quiescence is only dealing with captures and not calculating quiet moves?
Nomis
Posts: 18
Joined: Sun Jan 03, 2021 1:19 pm
Full name: Simon Reed

Re: Non-quiet position after quiescence...

Post by Nomis »

Indeed, neither position is quiet, but in the second position white cannot improve the position with a capture, and thus QS stops. Which as far as I know is expected, and leads to my question.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Non-quiet position after quiescence...

Post by mvanthoor »

info score cp 90 depth 1 seldepth 3 time 0 nodes 24 nps 0 pv e1g1
info score cp 20 depth 2 seldepth 5 time 0 nodes 1830 nps 0 pv e1g1 e7e5
info score cp 20 depth 3 seldepth 5 time 3 nodes 13861 nps 4620333 pv a3b2 e7e5 e1g1
info score cp 10 depth 4 seldepth 5 time 24 nodes 115132 nps 4797167 pv f3d4 e8f7 e1g1 e7e5
info score cp -15 depth 5 seldepth 7 time 353 nodes 1724266 nps 4884606 pv a3b2 e7e5 e1g1 e5e4 c3e4 d5e4 d3e4
info score cp -30 depth 6 seldepth 7 time 3186 nodes 14254442 nps 4474087 pv a3b2 b5b4 c3b1 a6c5 e1g1 e7e5
info score cp -40 depth 7 seldepth 9 time 26813 nodes 127737870 nps 4764028 pv a3b2 e7e5 e1g1 b5b4 d3a6 b7a6 c3e2
info score cp -45 depth 8 seldepth 9 time 163757 nodes 685706576 nps 4187342 pv a3b2 e7e5 e1g1 a6c5 d3e2 b5b4 c3a4 e8f7 a4c5 f8c5
My engine (Rustic) already pulls back the bishop on search depth 3; it briefly considers Nf3d4 at depth 4. It probably wants to put the knight on e5 to attack the queen and then try to capture it. Obviously it doesn't work (and the engine also tries to prevent the knight coming to e5 by playing Ke8f7). On search depth 5, the engine returns to pulling back the a3 bishop, probably due to the b5b4 fork.

Rustic doesn't have anything but MVV-LVA and check extension in its search right now, and the q-search is bog-standard as explained everywhere. Nothing special there. If your engine doesn't prevent losing a piece due to b5b4, you either have bugs in the search/q-search, or your search depth isn't deep enough yet.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
abulmo2
Posts: 433
Joined: Fri Dec 16, 2016 11:04 am
Location: France
Full name: Richard Delorme

Re: Non-quiet position after quiescence...

Post by abulmo2 »

My programs also consider 1.Nd4 at low depths and even Stockfish-12 consider it as a good move at shallow depths. For example after 1... b4, and eventually the exchange 2.Bxa6 Bxa6, if you enter quiescence search, you have the line 3.Nxc6 bxa3 4.Nxd8 taking the Queen (she cannot escape by a capture in quiescence search). Only a deeper search shows that the queen cannot be captured and that Nd4 is losing a piece. It is a typical horizon effect.
Richard Delorme
User avatar
hgm
Posts: 27795
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Non-quiet position after quiescence...

Post by hgm »

Positions are defined as quiet when the side to move doesn't have any captures. (Sometimes 'good captures', according to an exchange analysis on the target square, so that things like capturing a protected Pawn with a Queen are pruned.) So a position where there is a forced loss for the player that has the move, e.g. because of a fork or skewer, are still quiet.

Trying to solve this in QS usually backfires: it solves the problem in the cases where it is relevant, but leads to weaker play on average.

The reasons for that are diverse. For one, it takes significant time to detect the forced losses. You would have to generate opponent moves to see that the Pawn forks anything at all. Then a fork is not always fatal. A forking Pawn could be pinned, not only on the King, but also on the Queen. And perhaps one of the forked pieces can be moved away while gaining a tempo, e.g. with check, or trading it for an equal piece. So even a detected fork is not a guaranteed loss. You would have to figure out whether you can do something about it, or you still wouldn't know how to score the position. And the cure will not always be a capture, so you basically have to extend to d=1 to try everything, in order to see if it helps. You could limit that to known evasion techniques (moving away the threatened pieces, interposing, ...). But you would still miss initially unrelated counter threats that would allow you to take the forking piece in two moves.

A second reason is that positions that chess engines have to evaluate look nothing like normal game positions. In games multiple threats are rare. In engine searches they are common. Because the brute-force nature of the search causes it to search mostly nonsense, the players not reacting immediately to threats on their pieces, but making entirely unrelated moves. Null-move pruning even elevates that to the norm: when your piece gets attacked, first try to leave it hanging, to see if you can afford to lose it! So almost all leaf positions have multiple threats for both sides, which would then trigger your 'threat-recognition' procedure. Which would have to solve a really complex puzzle to see if there are any threats at all.

So the better search strategy is to not waste time on trying to solve the problem statically, and just assume that on the typical complex situation having the move will give you enough advantage to solve any problem. And then use the time you save that way to just search one or more ply deeper, so that you will see the problem anyway, while you still have depth to solve it.