-
Notifications
You must be signed in to change notification settings - Fork 12
Description
There is an issue with the three folds repetition logic, that it does not take into consideration take backs and move variations.
For example from starting position:
e4
take back move
e4 again
take back move
e4 a third time
-> Three folds repetition.
This would also happen with variations
for example:
- e4 e5 <- Main variation
- Nf3 Nf6 <- Main variation
- Bf4 Bf5 <- Variation 1 - first repetition on variation 1
- Ng1 Ng8 <- Main variation
- Bf4 Bf5 <- Main variation - first repetition on main variation but second time over all.
- Bg5 Bg4 <- Main variation
- Bf4 Bf5 <- Main variation - second repetition on main variation but third time over all
Three folds repetition is declared since it's the 3rd time over all this position was reached.
Unfortunately I can't think of a way to fix it without board some how knowing on the position repetition or moving the repetition logic from Board to Game which is why I raise this as an issue, without suggesting a fix as well.
The way I see it, we have a few options:
-
We need to move all move logic, validations and checks to the game object while leaving the Board object as just a representation of the board because everything just follows suit - if we move the check three folds repetition state, we would need to move all other game results as well, then move processing, and basically every other piece of logic.
-
Have Board be a child of game or game be a child of board, I don't like this idea either, since both game and board should be able to exist separately. Board analysis for example does not require a game object but does require a board, while game does not require a board for PGN editors and games between AI where we can assume a UCI compliant AI have their own game logic internally which we can rely on.
-
Create a facade and a chess managing class that will hold nullable references to both game and board objects and pass all the logical and coordination responsibility to it, while leaving both board and game objects as "workers" and data holders for the chess manager.
This is the option I like most as it's the cleanest and has the benefit of simplifying the interface for the developer with ChessKit package, for example, it would save the end developer the need to call both game and board's move functions to play a move, but it's also the one that would require the most amount of work.
All that being said, I don't think this bug is urgent or high priority.
The take back option can be avoided by limiting the take back to the last move and just reducing the count of the position before the current position by 1 before assigning the new position.
The other example presented seems like a rare edge case, but it might pose greater problem if we consider parsed games from other sources that contains any number of variations.
An implementation of the take back functionality can be seen here:
https://github.com/Amir-Zucker/chesskit-swift/pull/6/files
and used by calling
let previousMoveIndex = self.game.undoLastMove()
guard let position = self.game.positions[previousMoveIndex] else {
return
}
self.board.setPosition(position) //setPosition is a workaround to address the above issue. Cheers!