ddugovic/Stockfish

Atomic castling with touching kings

niklasf opened this issue ยท 25 comments

According the the atomic rules (lichess study, pdf) castling O-O-O should be legal in the following Atomic position:

image

8/8/8/8/8/8/4k3/R3K2q w Q - 0 1

Stockfish does not currently recognize this.

White is not in atomic check, would not be in atomic check on the path to the new king position (excluding the final king position!), and the final king position is supposed to be checked as if castling has already been completed.


More test positions we should not regress on:

8/8/8/8/8/8/4k3/R3K2q w Q - 0 1 (O-O-O illegal, because king would be in atomic check on d1)

8/8/8/8/8/8/6k1/R5Kr w Q - 0 1 (same idea in Atomic 960)


Same bug in python-chess: niklasf/python-chess#437

cc @ProgramFOX

To me this rule does not make sense, since the king and rook can not be moved simultaneously, so the king of course temporarily is in check on c1. However, if this rule is really established already, we should of course implement it.

I agree with Fabian's interpretation; FIDE rule 3.8 specifies that castling is prevented temporarily if the square on which the king stands, or the square which it must cross, or the square which it is to occupy, is attacked by one or more of the opponent's pieces (for atomic, add "and not attacked by the opponent's king" since adjacent kings negate the effect of a check).

So the critical test is: can it be shown that a regression was introduced Stockfish ever allowed this FICS-style castling?

There is no regression in Stockfish, just a bug. That is, if we accept the Atomic rules as established by FICS.

FICS says O-O-O should be legal in 8/8/8/8/8/8/4k3/R3K2q w Q - 0 1, Stockfish says it should not.

FIDE rule 3.8 is explicit about "pieces attacking squares" so I'm inclined to believe the FICS rule is incorrect.

This raises an occasional concern with analyzing a small percentage of FICS atomic games. For other variants I don't think there's been any issue (even antichess/giveaway which have different castling rights are both handled by Stockfish and Lichess by having different start positions)... so players have some expectation about the rules being the same. What I don't understand is why FICS and FIDE castling rules are so different.

The FIDE rules are simply ambiguous (for variants) and we need variant rules to clarify them. For example: Should the attacks on the final destination square be considered before or after castling is complete?

Assuming after: This would be consistent with the FICS atomic rules and inconsistent with the current Stockfish implementation.

Assuming before: This would be inconsistent with Chess960 positions such as https://lichess.org/analysis/standard/4k3/8/8/8/8/8/8/rR2K3_w_Q_- (where I hope we all agree that O-O-O should not be legal).

I feel that "the square which it is to occupy, is attacked" is still ambiguous because it does not describe whether it must be attacked before or after the rook moved - and in standard chess, that doesn't matter. But here, you could ask the question if you should view castling as two sub-moves (i.e. first king, then rook) or one simultaneous move. In the first interpretation the castling would be invalid, in the second one it would not be. Now, there is no official Atomic ruleset, so I'd argue it's best to go with what FICS established over 15 years ago and adjust Stockfish to allow castling here.

Well, to me a rule can not be incorrect as long as the set of rules is consistent. It is only inconsistent with standard chess, but for chess variants this does not really matter. I also do not like the rule, but it is insufficient reason to create a mess of subvariants as there unfortunately is for antichess (antichess, giveaway, suicide, etc.).

"Should the attacks on the final destination square be considered before or after castling is complete?"

If I'm making an attempt to think this through - and maybe I shouldn't try thinking about this - I should read the entire rule:

Castling is prevented temporarily if the square on which the king stands, or the square which it must cross, or the square which it is to occupy, is attacked by one or more of the opponent's pieces

In atomic, should castling out of check be legal? After all, by the end of the castling move, the square on which the king stands is not attacked. Regardless, if we apply the FICS rules...

Are we prepared to update the rules explanation on https://lichess.org/variant/atomic , and are there further special considerations for atomic960? If there are rules, humans need to be able to understand them, so if we're going to use FICS rules those rules should be explained somewhere highly visible instead of being repeatedly raised as questions in Discord, forums, etc.

In atomic, should castling out of check be legal?

No. Quoting Rekursiv's paper, linked by Niklas:

It is also illegal to castle if you are currently in atomic check, if moving the king one square closer to the rook (with the rook staying put) would place you in atomic check (i.e. you cannot castle through check), or if completing castling would place you in atomic check.

"It is also illegal to castle if you are currently in atomic check"

After all, by the end of the castling move, the square on which the king stands is not attacked.

Note that this argument does not work because castling in https://lichess.org/analysis/atomic/8/8/8/8/8/8/5k2/R3K2r_w_Q_- should be illegal (yes, Lichess wrongly allows it), despite d1 not being attacked after the rook would have moved.

Following Rekursiv's written rule (which is how things were on FICS) by the letter should handle all dubious cases.

OK, Rekursiv's paper does explain these situations, and this could be explained on Lichess... I'll change Stockfish to apply it. I'll certainly appreciate help testing the change.

Are we prepared to update the rules explanation on https://lichess.org/variant/atomic

this could be explained on Lichess

Yes, but I'll refrain from touching the page until the Lichess implementation is entirely consistent with Rekursiv's paper, which it is not for https://lichess.org/analysis/atomic/8/8/8/8/8/8/5k2/R3K2r_w_Q_- at this moment. That should be fixed first.

While testing, I found an atomic960 castling validation bug with this position, because the black king and white rook are adjacent:

setoption name UCI_Chess960 value true
8/8/8/8/8/8/4k3/r2RK2r w D - 0 1
go perft 1

I submitted a regression test: http://35.161.250.236:6543/tests/view/5d6d639f6e23db3768ec07bc

@niklasf FYI it may be necessary to regenerate atomic tablebases to accommodate the castling rule. I suppose we'll cross that bridge when we get there!

Unfortunately d183f6f (atomic960_castling) breaks en passant validation (noticed by comparing node counts of bench atomic 16 1 4 default perft). I'll have to submit a different patch.

Syzygy tablebases do not cover positions that have castling rights, so luckily we're fine in that regard, at least.

@niklasf Are you sure? Clicking the opening book on https://lichess.org/analysis/atomic/8/8/8/8/8/8/4k3/R3K2r_w_Q_- shows tablebase info - and it misses O-O-O.

@ProgramFOX That is because any legal white move in this position loses the castling right, and since the probing is done after the respective move is applied it is able to probe the positions without castling rights. If you e.g. add a pawn, you will see that moves retaining the castling right do not get a tablebase score: https://lichess.org/analysis/atomic/8/8/8/8/8/8/P3k3/R3K2r_w_Q_-_0_1

@ianfab Makes sense, thank you. So the fact that O-O-O is missing from the move list in the position I linked, is an error in the tablebase server, not in the tablebase files?

@ProgramFOX I don't know how the probing is done exactly on the server, but I assume that the issue is probably the move generation in python-chess, the tablebase files should not be affected.

That's correct. I have fixes for shakmaty (used in the tablebase server), and python-chess, but I'll wait for perft numbers from Stockfish before I make a release.

I tested effects on atomic960 for some positions as well (go perft 1 or bench atomic 16 1 1 test.fen perft indicates castling moves where expected to be legal). Curiously atomic960 castling was already legal in 8/8/8/8/8/8/4k3/3RK2r w D - 0 1 and 8/8/8/8/8/8/4k3/r3KR2 w F - 0 1 where the rook doesn't move:

setoption name UCI_Chess960 value false
8/8/8/8/8/8/3k4/R3K2q w Q - 0 1
8/8/8/8/8/8/4k3/R3K2q w Q - 0 1
8/8/8/8/8/8/5k2/R3K2q w Q - 0 1

setoption name UCI_Chess960 value true
8/8/8/8/8/8/6k1/R5Kr w Q - 0 1
8/8/8/8/8/8/3k4/R3K1Rq w GA - 0 1
8/8/8/8/8/8/4k3/R3K1Rq w GA - 0 1
8/8/8/8/8/8/5k2/R3K1Rq w GA - 0 1
8/8/8/8/8/8/6k1/R4KRr w GA - 0 1

8/8/8/8/8/8/4k3/rR2K2r w B - 0 1
8/8/8/8/8/8/4k3/r1R1K2r w C - 0 1
8/8/8/8/8/8/4k3/r2RK2r w D - 0 1
8/8/8/8/8/8/4k3/r3KR1r w F - 0 1
8/8/8/8/8/8/4k3/r3K1Rr w G - 0 1

8/8/8/8/8/8/4k3/1R2K2r w B - 0 1
8/8/8/8/8/8/4k3/2R1K2r w C - 0 1
8/8/8/8/8/8/4k3/3RK2r w D - 0 1
8/8/8/8/8/8/4k3/r3KR2 w F - 0 1
8/8/8/8/8/8/4k3/r3K1R1 w G - 0 1

I submitted a regression test (STC):
http://35.161.250.236:6543/tests/view/5d6e41f86e23db3768ec07da

I found a perft difference between 14bbdc335355537c89ad671bbaf5696565114c48 and python-chess master in 7R/8/8/8/8/8/3k4/rR4K1 w Q -.

I tracked it down to this issue:

setoption name uci_variant value atomic
setoption name uci_chess960 value true
position fen 7R/8/8/8/8/8/3k4/rR4K1 w Q - 2 2 moves g1b1
d
go perft 1

produces

Stockfish 2019-09-03 64 BMI2 Multi-Variant by D. Dugovic, F. Fichter et al.
info string variant atomic startpos rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   | R |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   | k |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 | r |   | K | R |   |   |   |   |
 +---+---+---+---+---+---+---+---+

Fen: 7R/8/8/8/8/8/3k4/r1KR4 b - - 3 2
Key: B6B4F75A8A7271B4
Checkers: c1 d1                                        <-- Note the checkers!
d2c3: 1
d2c2: 1
d2e2: 1

Nodes searched: 3

but should be identical to setting up the position directly:

setoption name uci_variant value atomic
setoption name uci_chess960 value true
position fen 7R/8/8/8/8/8/3k4/r1KR4 b - - 3 2
d
go perft 1
Stockfish 2019-09-03 64 BMI2 Multi-Variant by D. Dugovic, F. Fichter et al.
info string variant atomic startpos rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   | R |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 |   |   |   | k |   |   |   |   |
 +---+---+---+---+---+---+---+---+
 | r |   | K | R |   |   |   |   |
 +---+---+---+---+---+---+---+---+

Fen: 7R/8/8/8/8/8/3k4/r1KR4 b - - 3 2
Key: B6B4F75A8A7271B4
Checkers: 
a1b1: 1
a1a2: 1
a1a3: 1
a1a4: 1
a1a5: 1
a1a6: 1
a1a7: 1
a1a8: 1
d2e3: 1
d2c2: 1
d2e2: 1
d2c3: 1

Nodes searched: 12

Yay, after merging these latest patches with your patch for FICS rules the perfts are now in agreement! ๐ŸŽ‰

Here they are, for reference:
https://github.com/niklasf/python-chess/blob/master/examples/perft/atomic.perft. In particular the positions reachable from Rr2k1rR/3K4/3p4/8/8/8/7P/8 w kq - should exercise a lot of edge cases.

Now that we have some perft numbers for critical positions, I think that we should include them in the perft tests (e.g., analogous to https://github.com/ianfab/Fairy-Stockfish/blob/master/tests/perft.sh), in order to avoid future regressions.

I've added perft tests for variants. Which positions do we deem critical enough to be added to those tests?

(Also, I guess the reason tests/perft.sh doesn't exercise all of the benchmark positions is because that would create unnecessary coupling considering that move generation is rarely at risk of breaking.)