def test_getCoordinatesFromUserInput_long_simple(self): """ Get coordinates from a long input without extra notation """ actualValue = interface.getCoordinatesFromUserInput('4637') expectedValue0 = coordinate.Coordinate(4, 6) expectedValue1 = coordinate.Coordinate(3, 7) self.assertCoordinatesMatch(actualValue[0], expectedValue0) self.assertCoordinatesMatch(actualValue[1], expectedValue1)
def parseBoardInput(description): """ Takes a description of a board and returns the corresponding GameNode """ gnObject1 = gamenode.GameNode() # Remove any lines that are not part of the board cleanDescription = [] for line in description: if line[0] != ' ': cleanDescription.append(line) # Set board state where coordinate Y is even for i in range(5): for j in range(5): pieceChar = cleanDescription[2 * i][6 * j + 5] gnObject1.setState(coordinate.Coordinate(2 * j + 2, 10 - 2 * i), types.getPieceIntValueFromChar(pieceChar)) # Set board state where coordinate Y is odd for i in range(5): for j in range(5): pieceChar = cleanDescription[2 * i + 1][6 * j + 2] gnObject1.setState(coordinate.Coordinate(2 * j + 1, 9 - 2 * i), types.getPieceIntValueFromChar(pieceChar)) return gnObject1
def test_getLastMoveInEachDirection(self): """ Test getting furtherst move a king can move in each direction""" # Given board = boardParser.parseBoardInput(helper.kingCapture2) king = coordinate.Coordinate(5, 5) # When actualResult = ai.getLastMoveInEachDirection(board, king) # Then expectedDeltasAndKings = [((-1, -1), coordinate.Coordinate(1, 1)), ((-1, 1), coordinate.Coordinate(3, 7)), ((1, -1), coordinate.Coordinate(9, 1)), ((1, 1), coordinate.Coordinate(10, 10))] expectedLength = len(expectedDeltasAndKings) expectedState = types.PLAYER_A_KING self.assertEqual(expectedLength, len(actualResult)) for i in range(expectedLength): expectedDelta = expectedDeltasAndKings[i][0] actualDelta = actualResult[i].deltaLastMoved actualState = actualResult[i].getState( expectedDeltasAndKings[i][1]) self.assertEqual(expectedDelta, actualDelta) self.assertEqual(expectedState, actualState)
def test_getCoordinatesFromUserInput_long(self): """ Get coordinates from a long input """ actualValue = interface.getCoordinatesFromUserInput('9,7-0,8') expectedValue0 = coordinate.Coordinate(9, 7) expectedValue1 = coordinate.Coordinate(10, 8) self.assertCoordinatesMatch(actualValue[0], expectedValue0) self.assertCoordinatesMatch(actualValue[1], expectedValue1)
def test_parseBoardInput_good(self): """ Verify a board description is parsed correctly """ board_description = [ " 1 2 3 4 5 6 7 8 9 0", "0 . b . b b 0", "9 b b . b b 9", "8 b . b . b 8", "7 b b b b b 7", "6 . . . B . 6", "5 . a . . . 5", "4 A . a . a 4", "3 a . a a a 3", "2 . a . . a 2", "1 a a a a a 1", " 1 2 3 4 5 6 7 8 9 0", ] actualResult = boardParser.parseBoardInput(board_description) self.assertEqual(actualResult.getState(coordinate.Coordinate(10, 6)), types.EMPTY) self.assertEqual(actualResult.getState(coordinate.Coordinate(3, 5)), types.PLAYER_A_REGULAR) self.assertEqual(actualResult.getState(coordinate.Coordinate(2, 4)), types.PLAYER_A_KING) self.assertEqual(actualResult.getState(coordinate.Coordinate(4, 10)), types.PLAYER_B_REGULAR) self.assertEqual(actualResult.getState(coordinate.Coordinate(8, 6)), types.PLAYER_B_KING)
def test_makeCapture_bad_type(self): """ Check TypeError is raised when capturingPiece is empty space """ board = boardParser.parseBoardInput( helper.simpleCaptureBoardDescription) capturingPiece = coordinate.Coordinate(6, 6) endLocation = coordinate.Coordinate(4, 8) self.assertRaises(TypeError, rules.makeCapture, board, capturingPiece, endLocation)
def test_getPossiblePromotedPiece_b_backwards(self): """ Tests retrieval of a regular piece promoting to king for pB """ board = boardParser.parseBoardInput(helper.piecePromotions) expectedPiece = types.PLAYER_B_KING pieceLocation = coordinate.Coordinate(2, 2) pieceDestination = coordinate.Coordinate(1, 1) actualPiece = rules.getPossiblePromotedPiece(board, pieceDestination, pieceLocation) self.assertEqual(expectedPiece, actualPiece)
def test_makeCapture_bad_y_capture(self): """ Try to capture too close along the y axis """ board = boardParser.parseBoardInput( helper.simpleCaptureBoardDescription) capturingPiece = coordinate.Coordinate(6, 6) board.setState(capturingPiece, types.PLAYER_A_REGULAR) endLocation = coordinate.Coordinate(6, 8) self.assertRaises(ValueError, rules.makeCapture, board, capturingPiece, endLocation)
def test_isACaptureP_edges(self): """ Check captures near the edge of the board """ board = boardParser.parseBoardInput( helper.simpleCaptureBoardDescription) capturingPiece = coordinate.Coordinate(2, 8) self.assertFalse(rules.isACaptureP(board, capturingPiece, 8, False)) self.assertTrue(rules.isACaptureP(board, capturingPiece, 2, False)) capturingPiece = coordinate.Coordinate(1, 9) self.assertFalse(rules.isACaptureP(board, capturingPiece, 8, True)) self.assertFalse(rules.isACaptureP(board, capturingPiece, 6, True))
def test_makeCapture_bad_same_coordinates(self): """ Try to capture where start and end locations are the same """ board = boardParser.parseBoardInput( helper.simpleCaptureBoardDescription) capturingPiece = coordinate.Coordinate(6, 6) board.setState(capturingPiece, types.PLAYER_A_REGULAR) endLocation = coordinate.Coordinate(6, 6) self.assertRaises(ValueError, rules.makeCapture, board, capturingPiece, endLocation)
def test_createStartingPosition(self): """ Check that the starting position is set correctly """ gnObject = gamenode.GameNode() gnObject.createStartingPosition() self.assertEqual(gnObject.getState(coordinate.Coordinate(2, 2)), types.PLAYER_A_REGULAR) self.assertEqual(gnObject.getState(coordinate.Coordinate(6, 10)), types.PLAYER_B_REGULAR) self.assertEqual(gnObject.getState(coordinate.Coordinate(9, 5)), types.EMPTY)
def test_getPossiblePromotedPiece_b_backwards_no_promotion(self): """ Tests retrieval of a regular piece without promoting to king for pB """ board = boardParser.parseBoardInput(helper.piecePromotions) expectedPiece = types.PLAYER_B_REGULAR pieceLocation = coordinate.Coordinate(7, 5) pieceDestination = coordinate.Coordinate(6, 4) actualPiece = rules.getPossiblePromotedPiece(board, pieceDestination, pieceLocation) self.assertEqual(expectedPiece, actualPiece)
def test_makeCapture_good(self): """ Make a legal capture """ board = boardParser.parseBoardInput( helper.simpleCaptureBoardDescription) capturingPiece = coordinate.Coordinate(8, 8) endLocation = coordinate.Coordinate(6, 10) capturedLocation = coordinate.Coordinate(7, 9) rules.makeCapture(board, capturingPiece, endLocation) self.assertEqual(board.getState(capturingPiece), types.EMPTY) self.assertEqual(board.getState(capturedLocation), types.EMPTY) self.assertEqual(board.getState(endLocation), types.PLAYER_A_KING)
def test_getAllNoncaptureMovesForKingPiece_1MoveAvailable(self): """ Tests getting noncaptures moves for a king that has 3 available """ board = boardParser.parseBoardInput(helper.multipleKings) pieceLocation = coordinate.Coordinate(7, 7) actualResult = ai.getAllNoncaptureMovesForKingPiece( board, pieceLocation) expectedResultLength = 3 self.assertEqual(expectedResultLength, len(actualResult)) self.assertEqual(types.EMPTY, actualResult[0].getState(pieceLocation)) self.assertEqual(types.PLAYER_B_KING, actualResult[0].getState(coordinate.Coordinate(6, 8)))
def test_getAllMovesForPlayer_1_move_2_players(self): """ Test getting moves for a particular player when both players have legal moves """ # Given gnObject = gamenode.GameNode() pieceLocationA = coordinate.Coordinate(6, 2) gnObject.setState(pieceLocationA, types.PLAYER_A_REGULAR) pieceLocationB = coordinate.Coordinate(5, 7) gnObject.setState(pieceLocationB, types.PLAYER_B_REGULAR) # When actualResult = ai.getAllMovesForPlayer(gnObject, False) # Then expectedResultLength = 2 self.assertEqual(len(actualResult), expectedResultLength)
def makeCapture(theGame, startCoordinate, endCoordinate): """ Update the board for a capture between a start and end coordinate """ startX = startCoordinate.get_x_board() startY = startCoordinate.get_y_board() endX = endCoordinate.get_x_board() endY = endCoordinate.get_y_board() startPieceType = theGame.getState(startCoordinate) if startPieceType in (types.EMPTY, types.OFF_BOARD): error_template = "Illegal start piece type: {0} at ({1}, {2})" raise TypeError(error_template.format(startPieceType, startX, startY)) elif abs(startX - endX) not in (0, 2): error_template = "Illegal X capture: {0} -> {1}" raise ValueError(error_template.format(startX, endX)) elif abs(startY - endY) not in (0, 2): error_template = "Illegal Y capture: {0} -> {1}" raise ValueError(error_template.format(startY, endY)) elif startX == endX and startY == endY: error_template = ("Start and end capture coordinates are the " "same: ({0}, {1})") raise ValueError(error_template.format(startX, startY)) captureStartX = int(startX + (endX - startX) / 2) captureStartY = int(startY + (endY - startY) / 2) captureCoordinate = coordinate.Coordinate(captureStartX, captureStartY) theGame.setState( endCoordinate, getPossiblePromotedPiece(theGame, endCoordinate, startCoordinate)) theGame.setState(captureCoordinate, types.EMPTY) theGame.setState(startCoordinate, types.EMPTY) theGame.pieceLastMoved = endCoordinate
def test_destinationIsEmpty_true(self): """ Test when destination is Empty """ gnObject = gamenode.GameNode() pieceDestination = coordinate.Coordinate(4, 6) actualResult = ai.destinationIsEmpty(gnObject, pieceDestination) expectedResult = True self.assertEqual(actualResult, expectedResult)
def getCapturesForRegularPiece(theGame, pieceLocation, playerAToPlay): """ This recursively finds all available captures for a single piece and returns the list of captures. Checks for duplicates from loops""" if theGame.getState(pieceLocation) is types.EMPTY: return [] tempCaptureList = [] x_board = pieceLocation.get_x_board() y_board = pieceLocation.get_y_board() # 2, 4, 6, 8 are the four directions a piece might capture for direction in (2, 4, 6, 8): if rules.isACaptureP(theGame, pieceLocation, direction, playerAToPlay): deltaX = rules.findXDeltaFromDirection(direction) deltaY = rules.findYDeltaFromDirection(direction) newMoveNode = transferNode(theGame) destination = coordinate.Coordinate(x_board + deltaX, y_board + deltaY) rules.makeCapture(newMoveNode, pieceLocation, destination) newMoveNode.isCapture = True tempCaptureList.append(newMoveNode) nextCapture = getCapturesForRegularPiece(newMoveNode, destination, playerAToPlay) if nextCapture: tempCaptureList.extend(nextCapture) captureList = removeBoardDuplicates(tempCaptureList) captureList = filterForFewestOpposingPieces(captureList, playerAToPlay) return captureList
def test_isCoordinateMatch_player_A_no_match(self): """ Test coordinate no match with user as player A """ userIsPlayerB = False gnObject = gamenode.GameNode() testCoordinate = coordinate.Coordinate(3, 7) self.assertFalse( interface.isCoordinateMatch(gnObject, testCoordinate, userIsPlayerB))
def test_destinationIsEmpty_false(self): """ Test when destination is not Empty """ gnObject = gamenode.GameNode() pieceDestination = coordinate.Coordinate(9, 3) gnObject.setState(pieceDestination, types.PLAYER_A_REGULAR) actualResult = ai.destinationIsEmpty(gnObject, pieceDestination) expectedResult = False self.assertEqual(actualResult, expectedResult)
def test_setState(self): """ Test setting the board state at a Coordinate with a value """ gnObject = gamenode.GameNode() testCoordinate = coordinate.Coordinate(5, 1) testValue = types.PLAYER_A_KING gnObject.setState(testCoordinate, testValue) self.assertEqual(gnObject.getState(testCoordinate), types.PLAYER_A_KING)
def test_getNoncaptureMovesForRegularPiece_2_moves(self): """ Test that regular piece has to possible moves """ gnObject = gamenode.GameNode() pieceLocation = coordinate.Coordinate(4, 4) gnObject.setState(pieceLocation, types.PLAYER_A_REGULAR) actualResult = ai.getNoncaptureMovesForRegularPiece( gnObject, pieceLocation) expectedResultLength = 2 self.assertEqual(len(actualResult), expectedResultLength)
def test_getCaptureCoordinateFromDirection_edge_of_board(self): """ Tests getting coordinate from a bad direction """ # Given testCoordinate = coordinate.Coordinate(9, 5) testDirection = 2 # Then self.assertRaises(ValueError, rules.getCaptureCoordinateFromDirection, testCoordinate, testDirection)
def test_isCoordinateMatch_player_B_good(self): """ Test coordinate match with user as player B """ userIsPlayerB = True gnObject = gamenode.GameNode() testCoordinate = coordinate.Coordinate(3, 7) gnObject.setState(testCoordinate, types.PLAYER_B_REGULAR) self.assertTrue( interface.isCoordinateMatch(gnObject, testCoordinate, userIsPlayerB))
def test_getNoncaptureMovesForRegularPiece_1_move(self): """ Test regular piece on the edge of the board, which has 1 move """ gnObject = gamenode.GameNode() pieceLocation = coordinate.Coordinate(10, 4) gnObject.setState(pieceLocation, types.PLAYER_A_REGULAR) actualResult = ai.getNoncaptureMovesForRegularPiece( gnObject, pieceLocation) expectedResultLength = 1 self.assertEqual(len(actualResult), expectedResultLength)
def test_isCoordinateMatch_player_B_wrong_piece(self): """ Test coordinate match with user as player B but destination does not match""" userIsPlayerB = True gnObject = gamenode.GameNode() testCoordinate = coordinate.Coordinate(3, 7) gnObject.setState(testCoordinate, types.PLAYER_A_REGULAR) self.assertFalse( interface.isCoordinateMatch(gnObject, testCoordinate, userIsPlayerB))
def test_getNoncaptureMovesForRegularPiece_0_moves(self): """ Test regular piece that is completely blocked from moving """ gnObject = gamenode.GameNode() gnObject.createStartingPosition() pieceLocation = coordinate.Coordinate(1, 1) gnObject.setState(pieceLocation, types.PLAYER_A_REGULAR) actualResult = ai.getNoncaptureMovesForRegularPiece( gnObject, pieceLocation) expectedResultLength = 0 self.assertEqual(len(actualResult), expectedResultLength)
def test_getDiagonalNonCaptureMovesForKing(self): board = boardParser.parseBoardInput(helper.oneKing) startingPiece = coordinate.Coordinate(5, 5) actualResult = ai.getDiagonalNonCaptureMovesForKing( board, startingPiece, 1, 1) expectedLength = 5 self.assertEqual(expectedLength, len(actualResult))
def test_makePieceMove_good(self): """ Test executing a happy-path piece move """ # Given gnObject = gamenode.GameNode() pieceDestination = coordinate.Coordinate(9, 3) pieceLocation = coordinate.Coordinate(8, 2) gnObject.setState(pieceLocation, types.PLAYER_A_REGULAR) # When actualResult = ai.makePieceMove(gnObject, pieceDestination, pieceLocation) # Then actualResultLocationType = actualResult.getState(pieceLocation) actualResultDestinationType = actualResult.getState(pieceDestination) expectedResultLocationType = types.EMPTY expectedResultDestinationType = types.PLAYER_A_REGULAR self.assertEqual(actualResultLocationType, expectedResultLocationType) self.assertEqual(actualResultDestinationType, expectedResultDestinationType)
def test_getAllNoncaptureMovesForKingPiece_4MoveAvailable(self): """ Tests getting noncaptures moves for a king that has 8 available """ board = boardParser.parseBoardInput(helper.multipleKings) pieceLocation = coordinate.Coordinate(3, 3) actualResult = ai.getAllNoncaptureMovesForKingPiece( board, pieceLocation) expectedResultLength = 8 self.assertEqual(expectedResultLength, len(actualResult))