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) ?
Non-quiet position after quiescence...
Moderators: hgm, Rebel, chrisw
-
- Posts: 18
- Joined: Sun Jan 03, 2021 1:19 pm
- Full name: Simon Reed
-
- Posts: 105
- Joined: Thu Jun 18, 2020 3:21 pm
- Location: Moscow
- Full name: Alexander Litov
Re: Non-quiet position after quiescence...
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
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
-
- Posts: 334
- Joined: Sat Feb 25, 2012 10:42 pm
- Location: Stockholm
Re: Non-quiet position after quiescence...
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.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) ?
-
- Posts: 771
- Joined: Sat Sep 08, 2018 5:37 pm
- Location: Ukraine
- Full name: Maksim Korzh
Re: Non-quiet position after quiescence...
Can't see position, could you please provide bare FEN string?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) ?
Position should be considered quiet when either no captures are available or if eval() == quiescence()
Can't say more without seeing actual position.
Didactic chess engines:
https://www.chessprogramming.org/Maksim_Korzh
Chess programming YouTube channel:
https://www.youtube.com/channel/UCB9-pr ... KKqDgXhsMQ
https://www.chessprogramming.org/Maksim_Korzh
Chess programming YouTube channel:
https://www.youtube.com/channel/UCB9-pr ... KKqDgXhsMQ
-
- Posts: 18
- Joined: Sun Jan 03, 2021 1:19 pm
- Full name: Simon Reed
Re: Non-quiet position after quiescence...
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
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
-
- Posts: 771
- Joined: Sat Sep 08, 2018 5:37 pm
- Location: Ukraine
- Full name: Maksim Korzh
Re: Non-quiet position after quiescence...
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?
Didactic chess engines:
https://www.chessprogramming.org/Maksim_Korzh
Chess programming YouTube channel:
https://www.youtube.com/channel/UCB9-pr ... KKqDgXhsMQ
https://www.chessprogramming.org/Maksim_Korzh
Chess programming YouTube channel:
https://www.youtube.com/channel/UCB9-pr ... KKqDgXhsMQ
-
- Posts: 18
- Joined: Sun Jan 03, 2021 1:19 pm
- Full name: Simon Reed
Re: Non-quiet position after quiescence...
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.
-
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Non-quiet position after quiescence...
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.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
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.
-
- Posts: 433
- Joined: Fri Dec 16, 2016 11:04 am
- Location: France
- Full name: Richard Delorme
Re: Non-quiet position after quiescence...
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
-
- Posts: 27811
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Non-quiet position after quiescence...
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.
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.