private void FindKingCastleMoves( List <Move> moves, ThreatMatrix threats, Player player, BoardLocation playerPieceLocation) { //When are you not allowed to castle? // There are a number of cases when castling is not permitted: // -Your king has been moved earlier in the game. // -The rook that castles has been moved earlier in the game. // -There are pieces standing between your king and rook. // -The king is in check. // -The king moves through a square that is attacked by a piece of the opponent. // -The king would be in check after castling. if ((KingHasMoved(player)) || //king has moved (threats.ContainsKey(playerPieceLocation))) //king in check { return; } if (CastleQueensideMoveAvailable(player, threats)) { moves.Add(new Move(playerPieceLocation, player == Player.White ? BoardLocation.C1 : BoardLocation.C8, SpecialMoveType.CastleQueenside)); } if (CastleKingsideMoveAvailable(player, threats)) { moves.Add(new Move(playerPieceLocation, player == Player.White ? BoardLocation.G1 : BoardLocation.G8, SpecialMoveType.CastleKingside)); } }
private void DetermineGameState() { //find the king and moves for this player var kingLocation = _board.GetKingsLocation(CurrentPlayer); var moves = FindMoves(); //if we have no moves, this gets easy... if (!moves.Any()) { //checkmate, son if (_threatMatrix.ContainsKey(kingLocation)) { GameState = CurrentPlayer == Player.White ? GameState.BlackWin : GameState.WhiteWin; } else { GameState = GameState.DrawStalemate; } return; } //we need to check for draw due to insufficient material if (HasInsufficientMaterialForMate(CurrentPlayer) && HasInsufficientMaterialForMate(CurrentPlayer.OpposingPlayer())) { GameState = GameState.DrawInsufficientMaterial; } //TODO //https://en.wikipedia.org/wiki/Draw_(chess) //TODO:Check threefold repetition //TODO:Check fifty-move rule //TODO: Check 'dead position' (not sure how that is done) }
private bool CastleKingsideMoveAvailable(Player player, ThreatMatrix threats) { if (player == Player.White) { return ((!_moveHistory.Any(a => a.Source == BoardLocation.H1)) && //rook has not moved (!threats.ContainsKey(BoardLocation.F1) && !threats.ContainsKey(BoardLocation.G1)) && //no threats in path (_board[BoardLocation.G1].IsEmpty() && _board[BoardLocation.G1].IsEmpty())); //path is empty } else { return ((!_moveHistory.Any(a => a.Source == BoardLocation.H8)) && //rook has not moved (!threats.ContainsKey(BoardLocation.F8) && !threats.ContainsKey(BoardLocation.G8)) && //no threats in path (_board[BoardLocation.F8].IsEmpty() && _board[BoardLocation.G8].IsEmpty())); //path is empty } }
private void FindMoves( List <Move> moves, ThreatMatrix threats, BoardLocation playerPieceLocation) { var chessPiece = _board[playerPieceLocation]; var player = chessPiece.Player(); var playerPiecePinDirection = threats.ContainsKey(playerPieceLocation) ? threats[playerPieceLocation].Pin : default(ThreatDirection?); switch (chessPiece) { case ChessPiece.BlackPawn: case ChessPiece.WhitePawn: FindPawnMoves(moves, threats, player, playerPieceLocation, playerPiecePinDirection); break; case ChessPiece.BlackKnight: case ChessPiece.WhiteKnight: FindKnightMoves(moves, threats, player, playerPieceLocation, playerPiecePinDirection); break; case ChessPiece.BlackBishop: case ChessPiece.WhiteBishop: FindBishopMoves(moves, threats, player, playerPieceLocation, playerPiecePinDirection); break; case ChessPiece.BlackRook: case ChessPiece.WhiteRook: FindRookMoves(moves, threats, player, playerPieceLocation, playerPiecePinDirection); break; case ChessPiece.BlackQueen: case ChessPiece.WhiteQueen: FindQueenMoves(moves, threats, player, playerPieceLocation, playerPiecePinDirection); break; case ChessPiece.BlackKing: case ChessPiece.WhiteKing: //da king cant be pinned yo! FindKingMoves(moves, threats, player, playerPieceLocation); break; default: break; } }
private void AddThreat( ThreatMatrix threatMatrix, BoardLocation playerKingLocation, BoardLocation threateningPieceLocation, BoardLocation boardLocationBeingThreatening, ThreatDirection direction, ThreatDirection?pin = null) { if (!threatMatrix.ContainsKey(boardLocationBeingThreatening)) { threatMatrix.Add(boardLocationBeingThreatening, direction, pin); } else { //update the threat direction threatMatrix[boardLocationBeingThreatening].AddDirection(direction); //can only be pinned in one direction (since there is only one king) if (pin != null) { threatMatrix[boardLocationBeingThreatening].AddPin(pin.Value); } } //if this is a king threat if (playerKingLocation == boardLocationBeingThreatening) { //we set the piece that is threatening the king here. Please note that it is possible more than one piece //is threatening the king but it is IMPOSSIBLE for a triple check to occur. var threat = threatMatrix[boardLocationBeingThreatening]; if (threat.FirstPieceThreateningKingBoardLocation.HasValue) { threat.SecondPieceThreateningKingBoardLocation = threateningPieceLocation; } else { threat.FirstPieceThreateningKingBoardLocation = threateningPieceLocation; } } }
private void FindKingMoves( List <Move> moves, ThreatMatrix threats, Player player, BoardLocation playerPieceLocation) { //we will use the threats matrix for this king to calculate our moves... var kingThreatLocations = _threatProvider.FindThreatsForBoardLocation(_board, playerPieceLocation); foreach (var location in kingThreatLocations.Keys) { //only add moves that do not have a threat on them if ((_board.LocationIsEmptyOrOccupiedBy(location, player.OpposingPlayer())) && (threats.ContainsKey(location) == false)) { moves.Add(new Move(playerPieceLocation, location, _board[location])); } } //find our castle moves FindKingCastleMoves(moves, threats, player, playerPieceLocation); }