1126 lines
45 KiB
Swift
1126 lines
45 KiB
Swift
//
|
|
// BoardTests.swift
|
|
// SwiftChess
|
|
//
|
|
// Created by Steve Barnegren on 11/10/2016.
|
|
// Copyright © 2016 CocoaPods. All rights reserved.
|
|
//
|
|
|
|
// swiftlint:disable type_body_length
|
|
// swiftlint:disable file_length
|
|
// swiftlint:disable function_body_length
|
|
|
|
import XCTest
|
|
@testable import SwiftChess
|
|
|
|
class BoardTests: XCTestCase {
|
|
|
|
// MARK: - Setup / Tear Down
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
|
}
|
|
|
|
override func tearDown() {
|
|
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
|
super.tearDown()
|
|
}
|
|
|
|
// MARK: - Creation
|
|
|
|
func testNewEmptyBoardContainsNoPieces() {
|
|
|
|
let board = Board(state: .empty)
|
|
|
|
(0..<64).forEach {
|
|
let piece = board.getPiece(at: BoardLocation(index: $0))
|
|
XCTAssert(piece == nil, "Expected piece at index \($0) to be nil")
|
|
}
|
|
}
|
|
|
|
func testNewGameBoardContainsCorrectGamePieces() {
|
|
|
|
let expectedPieces: [(index: Int, type: Piece.PieceType, color: Color)] = [
|
|
|
|
// white back row
|
|
(0, .rook, .white),
|
|
(1, .knight, .white),
|
|
(2, .bishop, .white),
|
|
(3, .queen, .white),
|
|
(4, .king, .white),
|
|
(5, .bishop, .white),
|
|
(6, .knight, .white),
|
|
(7, .rook, .white),
|
|
|
|
// white pawn row
|
|
(8, .pawn, .white),
|
|
(9, .pawn, .white),
|
|
(10, .pawn, .white),
|
|
(11, .pawn, .white),
|
|
(12, .pawn, .white),
|
|
(13, .pawn, .white),
|
|
(14, .pawn, .white),
|
|
(15, .pawn, .white),
|
|
|
|
// black back row
|
|
(56, .rook, .black),
|
|
(57, .knight, .black),
|
|
(58, .bishop, .black),
|
|
(59, .queen, .black),
|
|
(60, .king, .black),
|
|
(61, .bishop, .black),
|
|
(62, .knight, .black),
|
|
(63, .rook, .black),
|
|
|
|
// black pawn row
|
|
(48, .pawn, .black),
|
|
(49, .pawn, .black),
|
|
(50, .pawn, .black),
|
|
(51, .pawn, .black),
|
|
(52, .pawn, .black),
|
|
(53, .pawn, .black),
|
|
(54, .pawn, .black),
|
|
(55, .pawn, .black)
|
|
|
|
]
|
|
|
|
let board = Board(state: .newGame)
|
|
|
|
for expectedPiece in expectedPieces {
|
|
|
|
guard let piece = board.getPiece(at: BoardLocation(index: expectedPiece.index)) else {
|
|
XCTFail("Expected piece to exist at index: \(expectedPiece.index)")
|
|
return
|
|
}
|
|
|
|
XCTAssert(piece.type == expectedPiece.type,
|
|
"Expected idx \(expectedPiece.index) to be type \(expectedPiece.type), but was \(piece.type)")
|
|
XCTAssert(piece.color == expectedPiece.color,
|
|
"Expected idx \(expectedPiece.index) to be color \(expectedPiece.color), but was \(piece.color)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Board Location
|
|
|
|
func testBoardLocationStrideToReturnsExpectedStride() {
|
|
|
|
let fromLocation = BoardLocation(x: 1, y: 1)
|
|
let toLocation = BoardLocation(x: 3, y: 4)
|
|
|
|
let stride = fromLocation.strideTo(location: toLocation)
|
|
XCTAssertEqual(stride.x, 2)
|
|
XCTAssertEqual(stride.y, 3)
|
|
}
|
|
|
|
func testBoardLocationStrideFromReturnsExpectedStride() {
|
|
|
|
let fromLocation = BoardLocation(x: 1, y: 1)
|
|
let toLocation = BoardLocation(x: 3, y: 4)
|
|
|
|
let stride = toLocation.strideFrom(location: fromLocation)
|
|
XCTAssertEqual(stride.x, 2)
|
|
XCTAssertEqual(stride.y, 3)
|
|
}
|
|
|
|
// MARK: - Piece Manipulation
|
|
|
|
func testSetAndGetPiece() {
|
|
|
|
var board = Board(state: .empty)
|
|
|
|
let piece = Piece(type: .king, color: .black)
|
|
let location = BoardLocation(index: 5)
|
|
|
|
board.setPiece(piece, at: location)
|
|
|
|
guard let returnedPiece = board.getPiece(at: location) else {
|
|
print("Expected piece to exist at location")
|
|
return
|
|
}
|
|
|
|
XCTAssert(returnedPiece.isSameTypeAndColor(asPiece: piece), "Expected pieces to be the same")
|
|
|
|
}
|
|
|
|
func testRemovePieceRemovesPiece() {
|
|
|
|
var board = Board(state: .newGame)
|
|
let location = BoardLocation(index: 10)
|
|
board.setPiece(Piece(type: .pawn, color: .white),
|
|
at: location)
|
|
board.removePiece(at: location)
|
|
|
|
XCTAssertNil(board.getPiece(at: location))
|
|
}
|
|
|
|
func testMovePieceResultsInPieceMoved() {
|
|
|
|
var board = Board(state: .empty)
|
|
|
|
let piece = Piece(type: .king, color: .black)
|
|
|
|
let startLocation = BoardLocation(index: 10)
|
|
let endLocation = BoardLocation(index: 20)
|
|
|
|
board.setPiece(piece, at: startLocation)
|
|
board.movePiece(from: startLocation, to: endLocation)
|
|
|
|
guard let returnedPiece = board.getPiece(at: endLocation) else {
|
|
XCTFail("Expected piece to exist at location")
|
|
return
|
|
}
|
|
|
|
XCTAssert(returnedPiece.isSameTypeAndColor(asPiece: piece), "Expected pieces to be the same")
|
|
|
|
}
|
|
|
|
func testPieceHasMovedPropertyIsFalseForNewBoard() {
|
|
|
|
let board = Board(state: .newGame)
|
|
|
|
let whitePieces = board.getPieces(color: .white)
|
|
let blackPieces = board.getPieces(color: .black)
|
|
let allPieces = whitePieces + blackPieces
|
|
|
|
allPieces.forEach {
|
|
XCTAssertFalse($0.hasMoved)
|
|
}
|
|
}
|
|
|
|
func testMovePieceChangesPieceHasMovedProperty() {
|
|
|
|
let board = ASCIIBoard(colors: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"* - - - - - - -" +
|
|
"W - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let fromLocation = board.locationOfCharacter("W")
|
|
let toLocation = board.locationOfCharacter("*")
|
|
|
|
var gameBoard = board.board
|
|
|
|
gameBoard.movePiece(from: fromLocation, to: toLocation)
|
|
|
|
guard let piece = gameBoard.getPiece(at: toLocation) else {
|
|
XCTFail("Couldn't find piece at new position")
|
|
return
|
|
}
|
|
|
|
XCTAssertTrue(piece.hasMoved, "Expected piece hasMoved property to be true")
|
|
|
|
}
|
|
|
|
func testGetPiecesReturnsCorrectPieces() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- R P Q G B K -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let pieces = board.board.getPieces(color: .white)
|
|
|
|
board.board.printBoardPieces()
|
|
|
|
func verifyPieceExistance(piece: Piece) {
|
|
|
|
let matchingPieces = pieces.filter {
|
|
return $0.isSameTypeAndColor(asPiece: piece)
|
|
}
|
|
|
|
XCTAssert(matchingPieces.count != 0,
|
|
"No instances of piece with type \(piece.type) and color \(piece.color) found")
|
|
XCTAssert(matchingPieces.count == 1,
|
|
"Multiple instances of piece with type \(piece.type) and color \(piece.color) found")
|
|
}
|
|
|
|
verifyPieceExistance(piece: Piece(type: .king, color: .white))
|
|
verifyPieceExistance(piece: Piece(type: .queen, color: .white))
|
|
verifyPieceExistance(piece: Piece(type: .rook, color: .white))
|
|
verifyPieceExistance(piece: Piece(type: .bishop, color: .white))
|
|
verifyPieceExistance(piece: Piece(type: .pawn, color: .white))
|
|
verifyPieceExistance(piece: Piece(type: .knight, color: .white))
|
|
}
|
|
|
|
func testGetKingLocationReturnsCorrectLocation() {
|
|
|
|
var board = Board(state: .empty)
|
|
|
|
let whiteLocation = BoardLocation(index: 5)
|
|
let blackLocation = BoardLocation(index: 10)
|
|
|
|
board.setPiece( Piece(type: .king, color: .white), at: whiteLocation)
|
|
board.setPiece( Piece(type: .king, color: .black), at: blackLocation)
|
|
|
|
XCTAssert( board.getKingLocation(color: .white) == whiteLocation,
|
|
"Expected white king to be at location \(whiteLocation)")
|
|
|
|
XCTAssert( board.getKingLocation(color: .black) == blackLocation,
|
|
"Expected black king to be at location \(blackLocation)")
|
|
|
|
}
|
|
|
|
func testGetKingReturnsKing() {
|
|
|
|
let whiteKing = Piece(type: .king, color: .white)
|
|
let blackKing = Piece(type: .king, color: .black)
|
|
|
|
var board = Board(state: .empty)
|
|
board.setPiece(whiteKing, at: BoardLocation(index: 0))
|
|
board.setPiece(blackKing, at: BoardLocation(index: 1))
|
|
|
|
XCTAssert(board.getKing(color: .white).isSameTypeAndColor(asPiece: whiteKing), "Unable to find white king")
|
|
XCTAssert(board.getKing(color: .black).isSameTypeAndColor(asPiece: blackKing), "Unable to find black king")
|
|
|
|
}
|
|
|
|
func testGetLocationsOfColorReturnsCorrectLocations() {
|
|
|
|
let whiteLocations = [BoardLocation(index: 1), BoardLocation(index: 2), BoardLocation(index: 3)]
|
|
let blackLocations = [BoardLocation(index: 11), BoardLocation(index: 12), BoardLocation(index: 13)]
|
|
|
|
var board = Board(state: .empty)
|
|
|
|
whiteLocations.forEach {
|
|
board.setPiece(Piece(type: .pawn, color: .white), at: $0)
|
|
}
|
|
|
|
blackLocations.forEach {
|
|
board.setPiece(Piece(type: .pawn, color: .black), at: $0)
|
|
}
|
|
|
|
let returnedWhitelocations = board.getLocations(of: .white)
|
|
XCTAssertEqual(whiteLocations.count, returnedWhitelocations.count)
|
|
|
|
let returnedBlacklocations = board.getLocations(of: .black)
|
|
XCTAssertEqual(blackLocations.count, returnedBlacklocations.count)
|
|
|
|
whiteLocations.forEach { (location) in
|
|
XCTAssertEqual(returnedWhitelocations.filter { location == $0 }.count, 1)
|
|
}
|
|
|
|
blackLocations.forEach { (location) in
|
|
XCTAssertEqual(returnedBlacklocations.filter { location == $0 }.count, 1)
|
|
}
|
|
}
|
|
|
|
func testIsColorInCheckReturnsTrueWhenInCheck() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- Q - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - g - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheck(color: .black), "Expected king to be in check")
|
|
}
|
|
|
|
func testIsColorInCheckReturnsFalseWhenNotInCheck() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - Q - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - g - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheck(color: .black) == false, "Expected king to not be in check")
|
|
}
|
|
|
|
func testIsColorInCheckMateReturnsTrueWhenInCheckMate() {
|
|
|
|
let board = ASCIIBoard(pieces: "- p - - - - - K" +
|
|
"- - - - - P - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"r - - - - - - -" +
|
|
"r - - G - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheckMate(color: .white) == true, "Expected white to be in check mate")
|
|
}
|
|
|
|
func testIsColorInCheckMateReturnsFalseWhenNotInCheckMate() {
|
|
|
|
let board = ASCIIBoard(pieces: "- p - - - - - K" +
|
|
"- - - - - P - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - G - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheckMate(color: .white) == false, "Expected white to not be in check mate")
|
|
}
|
|
|
|
func testIsColorInCheckMateReturnsFalseWhenInCheckButNotCheckMate() {
|
|
|
|
let board = ASCIIBoard(pieces: "- p - - - - - K" +
|
|
"- - - - - P - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"r - - G - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheck(color: .white) == true,
|
|
"Expected white to not be in check - test may be set up incorrectly")
|
|
XCTAssert(board.board.isColorInCheckMate(color: .white) == false,
|
|
"Expected white to not be in check mate")
|
|
}
|
|
|
|
func testIsColorInCheckMateReturnsFalseWhenInStaleMate() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - r - r - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"r - - - - - - -" +
|
|
"- - - G - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheck(color: .white) == false,
|
|
"Expected white to not be in check - test may be set up incorrectly")
|
|
XCTAssert(board.board.isColorInCheckMate(color: .white) == false,
|
|
"Expected white to not be in check mate")
|
|
}
|
|
|
|
func testColorIsInStaleMateReturnsTrueWhenStaleMate() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - r - r - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"q - - - - - - -" +
|
|
"- - - G - - - -" )
|
|
|
|
XCTAssert(board.board.isColorInCheck(color: .white) == false,
|
|
"Expected white to not be in check - test may be set up incorrectly")
|
|
XCTAssert(board.board.isColorInStalemate(color: .white) == true,
|
|
"Expected white to be in stale mate")
|
|
}
|
|
|
|
func testColorIsInStaleMateReturnsFalseWhenStaleMate() {
|
|
|
|
let board = Board(state: .newGame)
|
|
|
|
XCTAssert(board.isColorInCheckMate(color: .white) == false, "Expected white to not be in stale mate")
|
|
}
|
|
|
|
// Get Promotable pawns
|
|
|
|
func testGetWhitePromotablePawnsReturnsLastAllWhiteFinalRowPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "P P P P P P P P" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .white)
|
|
|
|
XCTAssert(promotable.count == 8)
|
|
}
|
|
|
|
func testGetWhitePromotablePawnsReturnsDoesntReturnWhiteNonPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "B K G R R R Q B" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .white)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
func testGetWhitePromotablePawnsDoesntReturnBlackPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "p p p p p p p p" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .white)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
func testGetWhitePromotablePawnsDoesntReturnNonPromotableWhitePawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"P - - - - P - -" +
|
|
"- - - P - - - -" +
|
|
"- - - - - P - -" +
|
|
"- - - - - - - -" +
|
|
"- - - P - - - -" +
|
|
"- - - - - - - P" +
|
|
"- - - - - - - -" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .white)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
func testGetBlackPromotablePawnsReturnsLastAllBlackFinalRowPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"p p p p p p p p" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .black)
|
|
|
|
XCTAssert(promotable.count == 8)
|
|
}
|
|
|
|
func testGetBlackPromotablePawnsReturnsDoesntReturnBlackNonPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"b k g r r r q b" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .black)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
func testGetBlackPromotablePawnsDoesntReturnWhitePawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"P P P P P P P P" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .black)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
func testGetBlackPromotablePawnsDoesntReturnNonPromotableBlackPawns() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"p - - - - p - -" +
|
|
"- - - p - - - -" +
|
|
"- - - - - p - -" +
|
|
"- - - - - - - -" +
|
|
"- - - p - - - -" +
|
|
"- - - - - - - p" +
|
|
"- - - - - - - -" )
|
|
|
|
let promotable = board.board.getLocationsOfPromotablePawns(color: .black)
|
|
|
|
XCTAssert(promotable.count == 0)
|
|
}
|
|
|
|
// MARK: - Can Castle? Logic
|
|
|
|
func assertKingAndRookStartLocationsAndColor(kingLocation: BoardLocation,
|
|
rookLocation: BoardLocation,
|
|
color: Color) {
|
|
|
|
let board = Board(state: .newGame)
|
|
|
|
guard let king = board.getPiece(at: kingLocation) else {
|
|
XCTFail("Could not find king")
|
|
return
|
|
}
|
|
|
|
guard let rook = board.getPiece(at: rookLocation) else {
|
|
XCTFail("Could not find king")
|
|
return
|
|
}
|
|
|
|
// Assert king color and type
|
|
XCTAssert(king.color == color)
|
|
XCTAssert(king.type == .king)
|
|
|
|
// Assert rook color and type
|
|
XCTAssert(rook.color == color)
|
|
XCTAssert(rook.type == .rook)
|
|
}
|
|
|
|
func testCastleMoveWhiteKingSideKingAndRookStartLocationsAreCorrect() {
|
|
|
|
let castleMove = Board.CastleMove(color: .white, side: .kingSide)
|
|
assertKingAndRookStartLocationsAndColor(kingLocation: castleMove.kingStartLocation,
|
|
rookLocation: castleMove.rookStartLocation,
|
|
color: .white)
|
|
}
|
|
|
|
func testCastleMoveWhiteQueenSideKingAndRookStartLocationsAreCorrect() {
|
|
|
|
let castleMove = Board.CastleMove(color: .white, side: .queenSide)
|
|
assertKingAndRookStartLocationsAndColor(kingLocation: castleMove.kingStartLocation,
|
|
rookLocation: castleMove.rookStartLocation,
|
|
color: .white)
|
|
}
|
|
|
|
func testCastleMoveBlackKingSideKingAndRookStartLocationsAreCorrect() {
|
|
|
|
let castleMove = Board.CastleMove(color: .black, side: .kingSide)
|
|
assertKingAndRookStartLocationsAndColor(kingLocation: castleMove.kingStartLocation,
|
|
rookLocation: castleMove.rookStartLocation,
|
|
color: .black)
|
|
}
|
|
|
|
func testCastleMoveBlackQueenSideKingAndRookStartLocationsAreCorrect() {
|
|
|
|
let castleMove = Board.CastleMove(color: .black, side: .queenSide)
|
|
assertKingAndRookStartLocationsAndColor(kingLocation: castleMove.kingStartLocation,
|
|
rookLocation: castleMove.rookStartLocation,
|
|
color: .black)
|
|
}
|
|
|
|
func testCanCastle() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - G - - R" )
|
|
|
|
XCTAssertTrue(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfKingInIncorrectPostion() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - G - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - R" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfRookInIncorrectPostion() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - R" +
|
|
"- - - - G - - -" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfKingHasPreviouslyMoved() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
let startLocation = BoardLocation(index: board.indexOfCharacter("G") )
|
|
let newLocation = BoardLocation(index: 0)
|
|
var gameBoard = board.board
|
|
|
|
// move then back
|
|
gameBoard.movePiece(from: startLocation, to: newLocation)
|
|
gameBoard.movePiece(from: newLocation, to: startLocation)
|
|
|
|
XCTAssertFalse(gameBoard.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfRookHasPreviouslyMoved() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
let startLocation = BoardLocation(index: board.indexOfCharacter("R") )
|
|
let newLocation = BoardLocation(index: 0)
|
|
var gameBoard = board.board
|
|
|
|
// move then back
|
|
gameBoard.movePiece(from: startLocation, to: newLocation)
|
|
gameBoard.movePiece(from: newLocation, to: startLocation)
|
|
|
|
XCTAssertFalse(gameBoard.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfPiecesAreBetweenKingAndRook() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - P R" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfKingIsInCheck() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - q - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfKingWillMoveThroughCheck() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - q - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCannotCastleIfKingWillMoveEndUpInCheck() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - q -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
XCTAssertFalse(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
func testCanStillCastleIfRookUnderAttack() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - r" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - --" +
|
|
"- - - - G - - R" )
|
|
|
|
XCTAssertTrue(board.board.canColorCastle(color: .white, side: .kingSide))
|
|
}
|
|
|
|
// MARK: - Perform Castle
|
|
|
|
func createPerformCastleBoard() -> Board {
|
|
|
|
let board = ASCIIBoard(pieces: "r - - - g - - r" +
|
|
"p p p p p p p p" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"P P P P P P P P" +
|
|
"R - - - G - - R" )
|
|
|
|
return board.board
|
|
}
|
|
|
|
func testWhiteKingSideCastleUpdatesPiecePositions() {
|
|
|
|
var board = createPerformCastleBoard()
|
|
board.performCastle(color: .white, side: .kingSide)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 6, y: 0))?.type == .king)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 5, y: 0))?.type == .rook)
|
|
}
|
|
|
|
func testWhiteQueenSideCastleUpdatesPiecePositions() {
|
|
|
|
var board = createPerformCastleBoard()
|
|
board.performCastle(color: .white, side: .queenSide)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 2, y: 0))?.type == .king)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 3, y: 0))?.type == .rook)
|
|
}
|
|
|
|
func testBlackKingSideCastleUpdatesPiecePositions() {
|
|
|
|
var board = createPerformCastleBoard()
|
|
board.performCastle(color: .black, side: .kingSide)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 6, y: 7))?.type == .king)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 5, y: 7))?.type == .rook)
|
|
}
|
|
|
|
func testBlackQueenSideCastleUpdatesPiecePositions() {
|
|
|
|
var board = createPerformCastleBoard()
|
|
board.performCastle(color: .black, side: .queenSide)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 2, y: 7))?.type == .king)
|
|
XCTAssert(board.getPiece(at: BoardLocation(x: 3, y: 7))?.type == .rook)
|
|
}
|
|
|
|
// MARK: - Check hasMoved flag isn't accidentally set
|
|
|
|
func createHasMovedTestBoard() -> Board {
|
|
|
|
let board = ASCIIBoard(pieces: "r - - g - - - r" +
|
|
"- - p p p - - -" +
|
|
"- - - - - q - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- Q - - - - - -" +
|
|
"- - - P P P --" +
|
|
"R - - - G - - R" )
|
|
|
|
return board.board
|
|
}
|
|
|
|
func areAnyPiecesHasMovedFlagsSet(on board: Board) -> Bool {
|
|
|
|
for (index, square) in board.squares.enumerated() {
|
|
|
|
guard let piece = square.piece else {
|
|
continue
|
|
}
|
|
|
|
if piece.hasMoved {
|
|
print("Has moved flag set at index \(index)")
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func testCheckingForCheckDoesntResultInHasMovedFlagChange() {
|
|
|
|
let board = createHasMovedTestBoard()
|
|
_ = board.isColorInCheck(color: .white)
|
|
_ = board.isColorInCheck(color: .black)
|
|
|
|
XCTAssertFalse(areAnyPiecesHasMovedFlagsSet(on: board))
|
|
}
|
|
|
|
func testCheckingForCheckMateDoesntResultInHasMovedFlagChange() {
|
|
|
|
let board = createHasMovedTestBoard()
|
|
_ = board.isColorInCheckMate(color: .white)
|
|
_ = board.isColorInCheckMate(color: .black)
|
|
|
|
XCTAssertFalse(areAnyPiecesHasMovedFlagsSet(on: board))
|
|
}
|
|
|
|
func testCheckingForStaleMateDoesntResultInHasMovedFlagChange() {
|
|
|
|
let board = createHasMovedTestBoard()
|
|
_ = board.isColorInStalemate(color: .white)
|
|
_ = board.isColorInStalemate(color: .black)
|
|
|
|
XCTAssertFalse(areAnyPiecesHasMovedFlagsSet(on: board))
|
|
}
|
|
|
|
func testCheckingForAbilityToMoveDoesntResultInHasMovedFlagChange() {
|
|
|
|
let board = createHasMovedTestBoard()
|
|
_ = board.isColorAbleToMove(color: .white)
|
|
_ = board.isColorAbleToMove(color: .black)
|
|
|
|
XCTAssertFalse(areAnyPiecesHasMovedFlagsSet(on: board))
|
|
}
|
|
|
|
func testCheckingForAbilityToCastleDoesntResultInHasMovedFlagChange() {
|
|
|
|
let board = createHasMovedTestBoard()
|
|
_ = board.canColorCastle(color: .white, side: .kingSide)
|
|
_ = board.canColorCastle(color: .white, side: .queenSide)
|
|
_ = board.canColorCastle(color: .black, side: .kingSide)
|
|
_ = board.canColorCastle(color: .black, side: .queenSide)
|
|
|
|
XCTAssertFalse(areAnyPiecesHasMovedFlagsSet(on: board))
|
|
}
|
|
|
|
// MARK: - Test canColorMoveAnyPieceToLocation method
|
|
|
|
func testCanColorMoveAnyPieceToLocationReturnsYesIfCanMakeMove() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"R - - - - - - *" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let targetLocation = board.locationOfCharacter("*")
|
|
XCTAssertTrue(board.board.canColorMoveAnyPieceToLocation(color: .white, location: targetLocation))
|
|
}
|
|
|
|
func testCanColorMoveAnyPieceToLocationReturnsFalseIfCannotMakeMove() {
|
|
|
|
let board = ASCIIBoard(pieces: "B - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"R - - - - - - -" +
|
|
"- - - - - - - *" +
|
|
"R - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - Q - - - -" )
|
|
|
|
let targetLocation = board.locationOfCharacter("*")
|
|
XCTAssertFalse(board.board.canColorMoveAnyPieceToLocation(color: .white, location: targetLocation))
|
|
}
|
|
|
|
func testCanColorMoveAnyPieceToLocationReturnsFalseIfCannotMakeMoveButOpponentCan() {
|
|
|
|
let board = ASCIIBoard(pieces: "B - - - - - - q" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"R - - - - - - -" +
|
|
"- - - - - - - *" +
|
|
"R - - - - - - -" +
|
|
"- - - - - - k -" +
|
|
"- - - Q - - - r" )
|
|
|
|
let targetLocation = board.locationOfCharacter("*")
|
|
XCTAssertFalse(board.board.canColorMoveAnyPieceToLocation(color: .white, location: targetLocation))
|
|
}
|
|
|
|
// MARK: - Test doesColorOccupyLocation method
|
|
|
|
func testDoesColorOccupyLocationReturnsTrueForWhiteOccupation() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - Q - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let location = board.locationOfCharacter("Q")
|
|
XCTAssertTrue(board.board.doesColorOccupyLocation(color: .white, location: location))
|
|
}
|
|
|
|
func testDoesColorOccupyLocationReturnsTrueForBlackOccupation() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - q - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let location = board.locationOfCharacter("q")
|
|
XCTAssertTrue(board.board.doesColorOccupyLocation(color: .black, location: location))
|
|
}
|
|
|
|
func testDoesColorOccupyLocationReturnsFalseForWhiteOpponentOccupation() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - q - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let location = board.locationOfCharacter("q")
|
|
XCTAssertFalse(board.board.doesColorOccupyLocation(color: .white, location: location))
|
|
}
|
|
|
|
func testDoesColorOccupyLocationReturnsFalseForBlackOpponentOccupation() {
|
|
|
|
let board = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - Q - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let location = board.locationOfCharacter("Q")
|
|
XCTAssertFalse(board.board.doesColorOccupyLocation(color: .black, location: location))
|
|
}
|
|
|
|
func testDoesColorOccupyLocationReturnsFalseForNonOccupation() {
|
|
|
|
let board = Board(state: .empty)
|
|
|
|
let location = BoardLocation(x: 4, y: 4)
|
|
XCTAssertFalse(board.doesColorOccupyLocation(color: .white, location: location))
|
|
XCTAssertFalse(board.doesColorOccupyLocation(color: .black, location: location))
|
|
}
|
|
|
|
// MARK: Test Possible Move Locations
|
|
|
|
func testPossibleMoveLocationsReturnsExpectedLocations() {
|
|
|
|
let asciiBoard = ASCIIBoard(pieces: "- - - - - - - -" +
|
|
"- - * - * - - -" +
|
|
"- * - - - * - -" +
|
|
"- - - K - - - -" +
|
|
"- * - - - * - -" +
|
|
"- - * - * - - -" +
|
|
"- - - - - - - -" +
|
|
"- - - - - - - -" )
|
|
|
|
let board = asciiBoard.board
|
|
|
|
let sourceLocation = asciiBoard.locationOfCharacter("K")
|
|
let locations = board.possibleMoveLocationsForPiece(atLocation: sourceLocation)
|
|
XCTAssertEqual(locations.count, 8)
|
|
|
|
let expectedLocations = asciiBoard.locationsWithCharacter("*")
|
|
|
|
expectedLocations.forEach { expectedLocation in
|
|
XCTAssertEqual(locations.filter {$0 == expectedLocation}.count, 1)
|
|
}
|
|
}
|
|
|
|
// MARK: - Test Board Equality
|
|
|
|
func testEqualBoardsAreEqual() {
|
|
|
|
var board1 = Board(state: .newGame)
|
|
var board2 = Board(state: .newGame)
|
|
|
|
let sourceLocation = BoardLocation(x: 0, y: 1)
|
|
let targetLocation = BoardLocation(x: 0, y: 3)
|
|
|
|
board1.movePiece(from: sourceLocation, to: targetLocation)
|
|
board2.movePiece(from: sourceLocation, to: targetLocation)
|
|
|
|
XCTAssertEqual(board1, board2)
|
|
}
|
|
|
|
func testNonEqualBoardsAreNotEqual() {
|
|
|
|
var board1 = Board(state: .newGame)
|
|
board1.movePiece(from: BoardLocation(x: 0, y: 1),
|
|
to: BoardLocation(x: 0, y: 3))
|
|
|
|
let board2 = Board(state: .newGame)
|
|
|
|
XCTAssertNotEqual(board1, board2)
|
|
}
|
|
|
|
// MARK: - Piece Location tests
|
|
|
|
func testPieceLocationsAreCorrectForNewBoard() {
|
|
|
|
let board = Board(state: .newGame)
|
|
|
|
for location in BoardLocation.all {
|
|
|
|
guard let piece = board.getPiece(at: location) else {
|
|
continue
|
|
}
|
|
|
|
XCTAssertEqual(piece.location, location)
|
|
}
|
|
}
|
|
|
|
func testPieceLocationsAreCorrectAfterMoves() {
|
|
|
|
var board = Board(state: .newGame)
|
|
board.movePiece(from: BoardLocation(gridPosition: .e2),
|
|
to: BoardLocation(gridPosition: .e4))
|
|
|
|
board.movePiece(from: BoardLocation(gridPosition: .d7),
|
|
to: BoardLocation(gridPosition: .d5))
|
|
|
|
for location in BoardLocation.all {
|
|
|
|
guard let piece = board.getPiece(at: location) else {
|
|
continue
|
|
}
|
|
|
|
XCTAssertEqual(piece.location, location)
|
|
}
|
|
}
|
|
|
|
// MARK: - Dictionary Representable
|
|
|
|
func testDictionaryRepresentable() {
|
|
|
|
let asciiBoard = ASCIIBoard(pieces: "r - - - g - - r" +
|
|
"p p p p p p p p" +
|
|
"- - - - - - - -" +
|
|
"- K - - - b - -" +
|
|
"- - B - - - k -" +
|
|
"- - - - - - - -" +
|
|
"P P P P P P P P" +
|
|
"R - - - G - - R" )
|
|
|
|
let board = asciiBoard.board
|
|
XCTAssertEqual(board, board.toDictionaryAndBack)
|
|
}
|
|
|
|
}
|