Closed cesarvarela closed 8 years ago
Making a Game
from a Board
or Position
doesn't guarantee that the game would be a valid one. The execute(move:)
and execute(uncheckedMove:)
methods make the assumption that the game is in a valid state. For example, it assumes that rooks haven't moved if the appropriate castling rights are available.
Something close to this that I want to implement is creating a Game
from a valid PGN
.
Mmm not sure I follow.
Let's say I play a game until X position, generate a FEN string from there, store it, and continue playing another time from that same FEN string. Are you saying the FEN string does not have enough information to continue playing a valid game from a specific position?
If you're handling things like that, then yes you do know that the game is a valid one. You're guaranteeing it is because it originated from a game. However, putting in just any FEN string could lead to an invalid game state or a legally unreachable position.
I'm not saying this isn't possible. An initializer from a FEN string would just need a validator that checks for things such as there's only one king per side and that castling rights correspond to king and rook squares.
This would be a great feature to have because it would allow for deserialization of stored file data into Game
instances.
I've added this initializer and seems be working:
/// Creates a new chess game from a FEN string
///
/// - parameter whitePlayer: The game's white player. Default is a nameless human.
/// - parameter blackPlayer: The game's black player. Default is a nameless human.
/// - parameter fen: FEN string to start from
public init(whitePlayer: Player = Player(),
blackPlayer: Player = Player(),
fen: String) {
let position = Game.Position(fen: fen)! // asume the fen string is valid
self._moveHistory = []
self._undoHistory = []
self.board = position.board
self.playerTurn = position.playerTurn
self.castlingRights = position.castlingRights
self.whitePlayer = whitePlayer
self.blackPlayer = blackPlayer
self.variant = .standard
self.attackersToKing = position.board.attackersToKing(for: position.playerTurn)
self.halfmoves = position.halfmoves
}
It's good enough for my needs since I'm not saving moves history (at the moment)
(Let me know if I'm missing something)
It would be a lot safer to pass a Position
as a parameter than assuming fen
is valid. I'll add this functionality soon. Thank you
FYI: With that change, and starting from a FEN string, everything seems to work, except the en passant rule, since it's calculated using _moveHistory and it's empty there.
I've tried a quick hack but couldn't get it to work, I'll wait for you to implement it.
You can use this FEN to test it: rnbqkbnr/pp2pppp/8/2ppP3/8/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 3
Done: c5550d16df1ffc8d50ca18a22d8dca1a51c363fc + 892c2a9aa54f0688f75f39fee396140260df4faa + be761674c7d70bc8ad6a71b9bf4fb1f2b7edfb1a
The en passant target is added to the game's history in order to have a target when undoing even if the game was originally started with a Position
.
HI!, thanks for the previous issue!
Seems like you can create boards and positions, but I'm not seeing how to create a Game from it.