Ejemplo n.º 1
0
 def __init__(self):
     self.board = Gameboard()
     self.chips = {Coordinate.a1: Chip(Chip.Color.white),
                   Coordinate.c1: Chip(Chip.Color.white),
                   Coordinate.e1: Chip(Chip.Color.white),
                   Coordinate.g1: Chip(Chip.Color.white),
                   Coordinate.b2: Chip(Chip.Color.white),
                   Coordinate.d2: Chip(Chip.Color.white),
                   Coordinate.f2: Chip(Chip.Color.white),
                   Coordinate.h2: Chip(Chip.Color.white),
                   Coordinate.a3: Chip(Chip.Color.white),
                   Coordinate.c3: Chip(Chip.Color.white),
                   Coordinate.e3: Chip(Chip.Color.white),
                   Coordinate.g3: Chip(Chip.Color.white),
                   Coordinate.b6: Chip(Chip.Color.black),
                   Coordinate.d6: Chip(Chip.Color.black),
                   Coordinate.f6: Chip(Chip.Color.black),
                   Coordinate.h6: Chip(Chip.Color.black),
                   Coordinate.a7: Chip(Chip.Color.black),
                   Coordinate.c7: Chip(Chip.Color.black),
                   Coordinate.e7: Chip(Chip.Color.black),
                   Coordinate.g7: Chip(Chip.Color.black),
                   Coordinate.b8: Chip(Chip.Color.black),
                   Coordinate.d8: Chip(Chip.Color.black),
                   Coordinate.f8: Chip(Chip.Color.black),
                   Coordinate.h8: Chip(Chip.Color.black)}
     for k in self.chips.keys():
         self.board.set_content(k,self.chips[k])
     self.turn = Chip.Color.white
     self._current_chip = None
Ejemplo n.º 2
0
    def reset(self):
        """Restore pieces for a new game."""

        self._board = Gameboard()
        self._pieces = {}
        # Pawns
        for i in range(1, 63, 8):
            wp = Pawn(Color.WHITE)
            self._pieces[Coordinate(i)] = wp
            bp = Pawn(Color.BLACK)
            self._pieces[Coordinate(i+5)] = bp
        # Other pieces
        self._pieces[Coordinate.a1] = Rook(Color.WHITE)
        self._pieces[Coordinate.h1] = Rook(Color.WHITE)
        self._pieces[Coordinate.a8] = Rook(Color.BLACK)
        self._pieces[Coordinate.h8] = Rook(Color.BLACK)
        self._pieces[Coordinate.b1] = Knight(Color.WHITE)
        self._pieces[Coordinate.g1] = Knight(Color.WHITE)
        self._pieces[Coordinate.b8] = Knight(Color.BLACK)
        self._pieces[Coordinate.g8] = Knight(Color.BLACK)
        self._pieces[Coordinate.c1] = Bishop(Color.WHITE)
        self._pieces[Coordinate.f1] = Bishop(Color.WHITE)
        self._pieces[Coordinate.c8] = Bishop(Color.BLACK)
        self._pieces[Coordinate.f8] = Bishop(Color.BLACK)
        self._pieces[Coordinate.d1] = Queen(Color.WHITE)
        self._pieces[Coordinate.d8] = Queen(Color.BLACK)
        self._pieces[Coordinate.e1] = King(Color.WHITE)
        self._pieces[Coordinate.e8] = King(Color.BLACK)

        for c, p in self._pieces.items():
            self._board.set_content(c,p)
Ejemplo n.º 3
0
class Model:
    class Gamestate(Enum):
        invalidMove = -1
        inProgress = 0
        whiteWon = 1
        blackWon = 2
        tie = 3

    def new_game(self):
        self.__init__()
    
    def __init__(self):
        self.board = Gameboard()
        self.chips = {Coordinate.a1: Chip(Chip.Color.white),
                      Coordinate.c1: Chip(Chip.Color.white),
                      Coordinate.e1: Chip(Chip.Color.white),
                      Coordinate.g1: Chip(Chip.Color.white),
                      Coordinate.b2: Chip(Chip.Color.white),
                      Coordinate.d2: Chip(Chip.Color.white),
                      Coordinate.f2: Chip(Chip.Color.white),
                      Coordinate.h2: Chip(Chip.Color.white),
                      Coordinate.a3: Chip(Chip.Color.white),
                      Coordinate.c3: Chip(Chip.Color.white),
                      Coordinate.e3: Chip(Chip.Color.white),
                      Coordinate.g3: Chip(Chip.Color.white),
                      Coordinate.b6: Chip(Chip.Color.black),
                      Coordinate.d6: Chip(Chip.Color.black),
                      Coordinate.f6: Chip(Chip.Color.black),
                      Coordinate.h6: Chip(Chip.Color.black),
                      Coordinate.a7: Chip(Chip.Color.black),
                      Coordinate.c7: Chip(Chip.Color.black),
                      Coordinate.e7: Chip(Chip.Color.black),
                      Coordinate.g7: Chip(Chip.Color.black),
                      Coordinate.b8: Chip(Chip.Color.black),
                      Coordinate.d8: Chip(Chip.Color.black),
                      Coordinate.f8: Chip(Chip.Color.black),
                      Coordinate.h8: Chip(Chip.Color.black)}
        for k in self.chips.keys():
            self.board.set_content(k,self.chips[k])
        self.turn = Chip.Color.white
        self._current_chip = None

    def _neighbor_in_direction(self, square, direction):
        neighborSquare = self.board.neighbor_in_direction(square, direction)
        return neighborSquare

    def _next_neighbor_in_direction(self, square, direction):
        neighbor_square = self.board.neighbor_in_direction(square, direction)
        if neighbor_square is not None: # check the next
            new_neighbor = \
                self.board.neighbor_in_direction(neighbor_square, direction)
            if new_neighbor is not None:
                return new_neighbor
        return None

    def _enemy_in_neighbor(self, square, direction):
        neighbor = self._neighbor_in_direction(square, direction)
        return neighbor is not None and \
               self.board.get_content(neighbor) is not None and \
               self.board.get_content(neighbor).color != self.turn

    def _directions_for_soldier(self):
        white_directions = [Direction.top_left, Direction.top_right]
        black_directions = [Direction.btm_left, Direction.btm_right]
        return white_directions \
               if self.turn == Chip.Color.white \
               else black_directions

    def _soldier_available_jumps(self, square):
        jumps = set()
        for direction in self._directions_for_soldier():
            if self._enemy_in_neighbor(square, direction):
                next_neighbor = \
                    self._next_neighbor_in_direction(square, direction)
                if next_neighbor is not None and \
                        self.board.get_content(next_neighbor) is None:
                    jumps.add((square, next_neighbor))
        return jumps

    def _soldier_available_regular_moves(self, square):
        moves = set()
        for direction in self._directions_for_soldier():
            neighbor = self._neighbor_in_direction(square, direction)
            if neighbor is not None and \
                    self.board.get_content(neighbor) is None: 
                # empty square, valid move
                moves.add((square, neighbor))
        return moves

    def _soldier_can_jump(self, square):
        return bool(self._soldier_available_jumps(square))

    def _soldier_chip_available_moves(self, square):
        moves = self._soldier_available_jumps(square)
        if len(moves) > 0:
            return moves, True

        return self._soldier_available_regular_moves(square), False

    def _queen_rival_found_moves(self, 
                                 origin, 
                                 square, 
                                 direction, 
                                 moves, 
                                 can_jump):
        my_moves = moves
        neighbor = self._neighbor_in_direction(square, direction)
        if neighbor is not None:
            content = self.board.get_content(neighbor)
            if content is None and can_jump: 
                # another empty square after a jump
                my_moves.add((origin, neighbor))
                return my_moves, True
            elif content is None and not can_jump:
                # just found out queen can jump
                my_moves = set([(origin, neighbor)])
                return my_moves, True
        return moves, can_jump # two chips in a row or out of bounds

    def _queen_moves_in_direction(self, square, direction):
        moves, can_jump = set(), False
        neighbor = self._neighbor_in_direction(square, direction)
        while neighbor is not None: 
            content = self.board.get_content(neighbor)
            if content is None: # empty
                moves.add((square, neighbor))
            elif content.color != self. turn: # rival
                # rival chip found
                old_moves = moves
                moves, can_jump = self._queen_rival_found_moves(square, 
                                                                neighbor, 
                                                                direction, 
                                                                moves, 
                                                                can_jump)
                neighbor = self._neighbor_in_direction(neighbor, direction)
                if moves == old_moves:
                    break # two chips in a row or out of bounds
            else:
                break # ally chip found
            neighbor = self._neighbor_in_direction(neighbor, direction)
        return moves, can_jump

    def _queen_can_jump(self, square):
        moves, can_jump = self._queen_chip_available_moves(square)
        return can_jump

    def _queen_chip_available_moves(self, square):
        directions = [Direction.top_left, Direction.top_right,
                      Direction.btm_left, Direction.btm_right]
        moves, can_jump = set(), False

        for d in directions:
            new_moves, new_can_jump = self._queen_moves_in_direction(square, d)
            if can_jump == new_can_jump: 
                moves = moves | new_moves
            elif not can_jump and new_can_jump: 
                moves = new_moves
                can_jump = True
        return moves, can_jump

    def _chip_can_jump(self, square):
        if square in self.chips:
            if self.chips[square].type == Chip.Type.soldier:
                return self._soldier_can_jump(square)
            else:
                return self._queen_can_jump(square)
        return False

    def chip_available_moves(self, square):
        """Return a tuple (set[available_moves], bool can_jump)

        Args:
            square (Coordinate): the square where the chip is/should be
        Returns:
            set: tuple of Coordinate values of valid moves for the chip. They 
            have the form (Coordinate.origin, Coordinate.destination)
            bool: True if the chip can jump, False otherwise

        """
        if not isinstance(square, Coordinate):
            raise TypeError("square variable must be from Coordinate enum")
        if square not in self.chips.keys() or \
                self.board.get_content(square) is None:
            # chip is not in the game anymore
            return set(), False
        chip = self.chips[square]
        if chip.color != self.turn:
            return set(), False
        if chip.type == Chip.Type.soldier:
            return self._soldier_chip_available_moves(square)
        return self._queen_chip_available_moves(square)

    def available_moves(self):
        """Return a set with tuples of Coordinate values of all available moves

        Returns:
            set: tuple of Coordinate values of valid moves for the chip. They 
            have the form (Coordinate.origin, Coordinate.destination)

        """
        moves = set()
        if self._current_chip is not None:
            moves, can_jump =  self.chip_available_moves(self._current_chip)
            return moves
        can_jump = False
        for coord, chip in self.chips.items(): 
            newMoves, newcan_jump = self.chip_available_moves(coord)
            if can_jump == newcan_jump: 
                moves = moves | newMoves
            elif not can_jump and newcan_jump: # found a jump, delete old moves
                moves = newMoves
                can_jump = True
            # else found regular move, but jump found previously
        return moves

    def _promote(self, square):
        startIndex = 0 if self.turn == Chip.Color.white else 7
        promo_squares = []
        for i in range(startIndex, 64, 8):
            promo_squares.append(Coordinate(i))
        if square in promo_squares:
            self.chips[square].promote()

    def _next_turn(self):
        self.turn = Chip.Color.black \
                    if self.turn == Chip.Color.white \
                    else Chip.Color.white

    def _gamestate(self):
        if len(self.available_moves()) == 0:
            return self.Gamestate.whiteWon \
                   if self.turn == Chip.Color.black \
                   else self.Gamestate.blackWon
        return self.Gamestate.inProgress

    def _remove_chips(self, origin, destination):
        removed = []
        direction = self._direction_of_move(origin, destination)
        squares_jumped = self.board.path_in_direction(origin, 
                                                      destination, 
                                                      direction)
        for s in squares_jumped:
            if self.board.get_content(s) != None:
                self.board.clear_square(s)
                del self.chips[s]
                removed.append(s)
        return removed

    def _direction_of_move(self, origin, destination):
        distance = destination - origin
        direction = None
        if distance < 0: # moved left
            if distance % 7 == 0: # moved top
                direction = Direction.top_left
            else: # distance % 9 == 0, moved btm
                direction = Direction.btm_left
        else: # moved right
            if distance % 9 == 0:
                direction = Direction.top_right
            else:
                direction = Direction.btm_right
        return direction

    def move(self, origin, destination):
        """Perform the requested move and returns a tuple (Gamestate, list)

        Args:
            origin (Coordinate): the square where the chip is currently
            destination (Direction): the square where the chip will end
        Returns:
            Gamestate: value from enum 
            list: Coordinate values indicating the chip(s) removed
        Raises:
            TypeError: if origin or destination is not Coordinate
            
        """
        if not isinstance(origin, Coordinate):
            raise TypeError("origin variable must be from Coordinate enum")
        if not isinstance(destination, Coordinate):
            raise TypeError("destination must be from Coordinate enum")
        if not (origin, destination) in self.available_moves():
            return self.Gamestate.invalidMove, []
        turnFinished = True
        _, jumped = self.chip_available_moves(origin)
        # move chip
        self.board.move(origin, destination)
        self.chips[destination] = self.chips[origin]
        del self.chips[origin]
        self._promote(destination)
        # remove chips if jump occured
        distance = destination - origin
        removed = []
        if jumped:
            removed = self._remove_chips(origin, destination)
            if self._chip_can_jump(destination):
                turnFinished = False
                self._current_chip = destination

        if turnFinished:
            self._next_turn()
            self._current_chip = None
            self._promote(destination)
        return (self._gamestate(), removed)

    def square_contains_teammate(self, square):
        """Returns True if the chip belongs to the team whose turn it is

        Args:
            square (Coordinate): the square to check for an ally chip
        Returns:
            bool: True if the chip belongs to the team whose turn it is
        Raises:
            TypeError: if square is not Coordinate

        """
        if not isinstance(square, Coordinate):
            raise TypeError("square variable must be from Coordinate enum")
        # Python's lazy evaluation makes sure this expression will never
        # throw KeyError because if the key is not in the dictionary, the
        # second expression will not be evaluated
        return square in self.chips.keys() and \
                self.chips[square].color == self.turn
Ejemplo n.º 4
0
class TestBoard(unittest.TestCase):

    def setUp(self):
        self.board = Gameboard()

    def test_64_squares(self):
        self.assertEqual(len(self.board._squares),64)

    def test_index_raises_TypeError(self):
        self.assertRaises(TypeError,self.board._indexOf,"notCoordinate")

    def test_index_of_coordinate_corner(self):
        index = self.board._indexOf(Coordinate.a1)
        self.assertEqual(index,(7,0))

    def test_index_of_coordinate_top(self):
        index = self.board._indexOf(Coordinate.c8)
        self.assertEqual(index,(0,2))

    def test_index_of_coordinate_right(self):
        index = self.board._indexOf(Coordinate.h7)
        self.assertEqual(index,(1,7))

    def test_index_of_coordinate_bottom(self):
        index = self.board._indexOf(Coordinate.d1)
        self.assertEqual(index,(7,3))

    def test_index_of_coordinate_left(self):
        index = self.board._indexOf(Coordinate.a5)
        self.assertEqual(index,(3,0))

    def test_index_of_coordinate_center(self):
        index = self.board._indexOf(Coordinate.d3)
        self.assertEqual(index,(5,3))

    def test_neighbor_top_with_top_square(self):
        n = self.board._neighbor_top(Coordinate.a8)
        self.assertEqual(n, None)

    def test_neighbor_top(self):
        n = self.board._neighbor_top(Coordinate.d3)
        self.assertEqual(n, Coordinate.d4)

    def test_neighbor_top_right_with_top_square(self):
        n = self.board._neighbor_top_right(Coordinate.b8)
        self.assertEqual(n, None)

    def test_neighbor_top_right_with_right_square(self):
        n = self.board._neighbor_top_right(Coordinate.h5)
        self.assertEqual(n, None)

    def test_neighbor_top_right(self):
        n = self.board._neighbor_top_right(Coordinate.f3)
        self.assertEqual(n, Coordinate.g4)

    def test_neighbor_right_with_right_square(self):
        n = self.board._neighbor_right(Coordinate.h5)
        self.assertEqual(n, None)

    def test_neighbor_right(self):
        n = self.board._neighbor_right(Coordinate.d3)
        self.assertEqual(n, Coordinate.e3)

    def test_neighbor_btm_right_with_btm_square(self):
        n = self.board._neighbor_btm_right(Coordinate.b1)
        self.assertEqual(n, None)

    def test_neighbor_btm_right_with_right_square(self):
        n = self.board._neighbor_btm_right(Coordinate.h5)
        self.assertEqual(n, None)

    def test_neighbor_btm_right(self):
        n = self.board._neighbor_btm_right(Coordinate.f3)
        self.assertEqual(n, Coordinate.g2)

    def test_neighbor_btm_with_btm_square(self):
        n = self.board._neighbor_btm(Coordinate.a1)
        self.assertEqual(n, None)

    def test_neighbor_btm(self):
        n = self.board._neighbor_btm(Coordinate.d3)
        self.assertEqual(n, Coordinate.d2)

    def test_neighbor_btm_left_with_btm_square(self):
        n = self.board._neighbor_btm_left(Coordinate.b1)
        self.assertEqual(n, None)

    def test_neighbor_btm_left_with_left_square(self):
        n = self.board._neighbor_btm_left(Coordinate.a6)
        self.assertEqual(n, None)

    def test_neighbor_btm_left(self):
        n = self.board._neighbor_btm_left(Coordinate.f3)
        self.assertEqual(n, Coordinate.e2)

    def test_neighbor_left_with_left_square(self):
        n = self.board._neighbor_left(Coordinate.a5)
        self.assertEqual(n, None)

    def test_neighbor_left(self):
        n = self.board._neighbor_left(Coordinate.d3)
        self.assertEqual(n, Coordinate.c3)

    def test_neighbor_top_left_with_top_square(self):
        n = self.board._neighbor_top_left(Coordinate.b8)
        self.assertEqual(n, None)

    def test_neighbor_top_left_with_left_square(self):
        n = self.board._neighbor_top_left(Coordinate.a5)
        self.assertEqual(n, None)

    def test_neighbor_top_left(self):
        n = self.board._neighbor_top_left(Coordinate.f3)
        self.assertEqual(n, Coordinate.e4)

    def test_neighbor_in_direction_raises_TypeError(self):
        self.assertRaises(TypeError, self.board.neighbor_in_direction,
            square = "notCoordinate",
            direction = Direction.top)
        self.assertRaises(TypeError, self.board.neighbor_in_direction,
            square = Coordinate.a1,
            direction = "notDirection")

    def test_neighbor_in_direction_top(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.top)
        self.assertEqual(n, Coordinate.d4)

    def test_neighbor_in_direction_top_right(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.top_right)
        self.assertEqual(n, Coordinate.e4)

    def test_neighbor_in_direction_right(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.right)
        self.assertEqual(n, Coordinate.e3)

    def test_neighbor_in_direction_btm_right(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.btm_right)
        self.assertEqual(n, Coordinate.e2)

    def test_neighbor_in_direction_btm(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.btm)
        self.assertEqual(n, Coordinate.d2)

    def test_neighbor_in_directino_btm_left(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.btm_left)
        self.assertEqual(n, Coordinate.c2)

    def test_neighbor_in_direction_left(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.left)
        self.assertEqual(n, Coordinate.c3)

    def test_neighbor_in_direction_top_left(self):
        n = self.board.neighbor_in_direction(Coordinate.d3, Direction.top_left)
        self.assertEqual(n, Coordinate.c4)

    def test_neighbors_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.neighbors,"notCoordinate")

    def test_neighbors_corner(self):
        n = self.board.neighbors(Coordinate.a1)
        correct = {Direction.top: Coordinate.a2,
                    Direction.top_right: Coordinate.b2,
                    Direction.right: Coordinate.b1,
                    Direction.btm_right: None,
                    Direction.btm: None,
                    Direction.btm_left: None,
                    Direction.left: None,
                    Direction.top_left: None}
        self.assertEqual(n, correct)

    def test_neighbors_top(self):
        n = self.board.neighbors(Coordinate.c8)
        correct = {Direction.top: None,
                    Direction.top_right: None,
                    Direction.right: Coordinate.d8,
                    Direction.btm_right: Coordinate.d7,
                    Direction.btm: Coordinate.c7,
                    Direction.btm_left: Coordinate.b7,
                    Direction.left: Coordinate.b8,
                    Direction.top_left: None}
        self.assertEqual(n, correct)

    def test_neighbors_right(self):
        n = self.board.neighbors(Coordinate.h7)
        correct = {Direction.top: Coordinate.h8,
                    Direction.top_right: None,
                    Direction.right: None,
                    Direction.btm_right: None,
                    Direction.btm: Coordinate.h6,
                    Direction.btm_left: Coordinate.g6,
                    Direction.left: Coordinate.g7,
                    Direction.top_left: Coordinate.g8}
        self.assertEqual(n, correct)

    def test_neighbors_bottom(self):
        n = self.board.neighbors(Coordinate.d1)
        correct = {Direction.top: Coordinate.d2,
                    Direction.top_right: Coordinate.e2,
                    Direction.right: Coordinate.e1,
                    Direction.btm_right: None,
                    Direction.btm: None,
                    Direction.btm_left: None,
                    Direction.left: Coordinate.c1,
                    Direction.top_left: Coordinate.c2}
        self.assertEqual(n, correct)

    def test_neighbors_left(self):
        n = self.board.neighbors(Coordinate.a5)
        correct = {Direction.top: Coordinate.a6,
                    Direction.top_right: Coordinate.b6,
                    Direction.right: Coordinate.b5,
                    Direction.btm_right: Coordinate.b4,
                    Direction.btm: Coordinate.a4,
                    Direction.btm_left: None,
                    Direction.left: None,
                    Direction.top_left: None}
        self.assertEqual(n, correct)

    def test_neighbors_center(self):
        n = self.board.neighbors(Coordinate.d3)
        correct = {Direction.top: Coordinate.d4,
                    Direction.top_right: Coordinate.e4,
                    Direction.right: Coordinate.e3,
                    Direction.btm_right: Coordinate.e2,
                    Direction.btm: Coordinate.d2,
                    Direction.btm_left: Coordinate.c2,
                    Direction.left: Coordinate.c3,
                    Direction.top_left: Coordinate.c4}
        self.assertEqual(n, correct)

    def test_squares_in_direction_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.squares_in_direction,
            origin = "notCoordinate",
            direction = Direction.top)
        self.assertRaises(TypeError, self.board.squares_in_direction,
            origin = Coordinate.a1,
            direction = "notDirection")

    def test_squares_in_direction_center_to_edge(self):
        s = self.board.squares_in_direction(Coordinate.d4, Direction.top)
        correct = [Coordinate.d5,
                   Coordinate.d6,
                   Coordinate.d7,
                   Coordinate.d8]
        self.assertEqual(s, correct)

    def test_squares_in_direction_along_edge(self):
        s = self.board.squares_in_direction(Coordinate.a5, Direction.btm)
        correct = [Coordinate.a4,
                   Coordinate.a3,
                   Coordinate.a2,
                   Coordinate.a1]
        self.assertEqual(s, correct)

    def test_squares_in_direction_edge_to_outside(self):
        s = self.board.squares_in_direction(Coordinate.a1, Direction.left)
        self.assertEqual(s, [])

    def test_squares_in_direction_with_non_empty_square_ignored(self):
        self.board.set_content(Coordinate.g5, "boo")
        s = self.board.squares_in_direction(Coordinate.a5, Direction.right)
        correct = [Coordinate.b5,
                   Coordinate.c5,
                   Coordinate.d5,
                   Coordinate.e5,
                   Coordinate.f5]
        self.assertEqual(s, correct)

    def test_squares_in_direction_with_non_empty_square_included(self):
        self.board.set_content(Coordinate.g5, "boo")
        s = self.board.squares_in_direction(Coordinate.d2, Direction.top_right,
            include_last_non_empty_square = True)
        correct = [Coordinate.e3,
                   Coordinate.f4,
                   Coordinate.g5]
        self.assertEqual(s, correct)

    def test_path_in_direction_raises_TypeError(self):
        self.assertRaises(TypeError, self.board.path_in_direction,
            origin = "notCoordinate",
            destination = Coordinate.a3,
            direction = Direction.top)
        self.assertRaises(TypeError, self.board.path_in_direction,
            origin = Coordinate.a1,
            destination = "notCoordinate",
            direction = Direction.btm)
        self.assertRaises(TypeError, self.board.path_in_direction,
            origin = Coordinate.a1,
            destination = Coordinate.b4,
            direction = "notDirection")

    def test_path_in_direction_top(self):
        path = self.board.path_in_direction(Coordinate.d3, Coordinate.d7, \
                                            Direction.top) 
        correctPath = [Coordinate.d4,
                        Coordinate.d5,
                        Coordinate.d6]
        self.assertEqual(path, correctPath)                  

    def test_path_in_direction_top_right(self):
        path = self.board.path_in_direction(Coordinate.a1, Coordinate.h8, \
                                            Direction.top_right)
        correctPath = [Coordinate.b2,
                        Coordinate.c3,
                        Coordinate.d4,
                        Coordinate.e5,
                        Coordinate.f6,
                        Coordinate.g7]
        self.assertEqual(path, correctPath)

    def test_path_in_direction_unreachable(self):
        path = self.board.path_in_direction(Coordinate.a8, Coordinate.h8, \
                                            Direction.btm)
        correctPath = []
        self.assertEqual(path, correctPath)

    def test_path_in_direction_out_of_bounds(self):
        path = self.board.path_in_direction(Coordinate.a8, Coordinate.a1, \
                                            Direction.left)
        correctPath = []
        self.assertEqual(path, correctPath)

    def test_square_content_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.get_content,"notCoordinate")

    def test_square_content(self):
        self.board.set_content(Coordinate.a3, "white piece")
        self.assertEqual(self.board.get_content(Coordinate.a3), "white piece")

    def test_is_square_emtpy_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.is_empty,"notCoordinate")

    def test_is_square_empty_true(self):
        self.assertTrue(self.board.is_empty(Coordinate.d2))

    def test_is_square_empty_false(self):
        self.board.set_content(Coordinate.e3, 2)
        self.assertFalse(self.board.is_empty(Coordinate.e3))

    def test_clear_square_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.clear_square,"notCoordinate")

    def test_clear_square(self):
        self.board.set_content(Coordinate.h4, [1,2])
        self.board.clear_square(Coordinate.h4)
        self.assertTrue(self.board.is_empty(Coordinate.h4))

    def test_clear_board(self):
        for i in range(10):
            square = Coordinate(random.randrange(1,64))
            self.board.set_content(square,"pawn")
        self.board.clear_board()
        for square in Coordinate:
            self.assertTrue(self.board.is_empty(square))

    def test_move_content_raises_TypeError(self):
        self.assertRaises(TypeError,self.board.move,
            origin = Coordinate.a3,
            destination = "notCoordinate")
        self.assertRaises(TypeError,self.board.move,
            origin = "notCoordinate",
            destination = Coordinate.a3)

    def test_move_content(self):
        self.board.set_content(Coordinate.g8, "knight")
        self.board.move(Coordinate.g8, Coordinate.f6)
        self.assertEqual(self.board.get_content(Coordinate.f6),"knight")
Ejemplo n.º 5
0
 def setUp(self):
     self.board = Gameboard()
Ejemplo n.º 6
0
class Chess:
    """Chess game logic"""

    @property
    def board(self):
        return self._board

    @property
    def pieces(self):
        return self._pieces

    @property
    def moves(self):
        """List of tuples of the form (origin, destination), both Coordinate"""
        return self._board.moves

    @property
    def last_move(self):
        return self._board.moves[-1]

    def __init__(self):
        self.reset()

    def valid_moves_for_piece_at_coordinate(self, coordinate):
        """Return a set of coordinates where Piece can move.

        Args:
            coordinate (gameboard.Coordinate): position to check for moves
        Returns:
            Set of gameboard.gameboard.Coordinate elements. The piece can
            move to any of these coordinates in the current gamestate. Returns
            empty set if there is no piece in the given coordinate.
        Raises:
            TypeError: if coordinate is not Coordinate
            
        """
        if not isinstance(coordinate, Coordinate):
            raise TypeError("coordinate variable must be from Coordinate enum")
        piece = self._pieces.get(coordinate)
        return piece.valid_moves(self.board, coordinate) \
               if piece is not None else \
               set()

    def squares_attacked_by_piece_at_coordinate(self, coordinate):
        """Return a set of coordinates which Piece is attacking.

        Args:
            coordinate (gameboard.Coordinate): position to check for piece
        Returns:
            Set of gameboard.gameboard.Coordinate elements. The piece is
            attacking all of these in the current gamestate. Returns empty set 
            if there is no piece in the given coordinate.
        Raises:
            TypeError: if coordinate is not Coordinate
            
        """
        if not isinstance(coordinate, Coordinate):
            raise TypeError("coordinate variable must be from Coordinate enum")
        piece = self._pieces.get(coordinate)
        return piece.squares_attacked(self.board, coordinate) \
               if piece is not None else \
               set()

    def move(self, origin, destination):
        """Perform the requested move and returns a Move_Type

        Args:
            origin (Coordinate): the square where the piece is currently
            destination (Coordinate): the square where the piece will end
        Returns:
            Move_Type: Normal, Castle, or En_passant
        Raises:
            TypeError: if origin or destination is not Coordinate
            
        """
        piece = self._pieces[origin]
        self._board.move(origin, destination)
        self._pieces[destination] = self._pieces[origin]
        del self._pieces[origin]
        if piece.type is Type.PAWN or piece.type is Type.KING:
            piece.has_moved = True

    def reset(self):
        """Restore pieces for a new game."""

        self._board = Gameboard()
        self._pieces = {}
        # Pawns
        for i in range(1, 63, 8):
            wp = Pawn(Color.WHITE)
            self._pieces[Coordinate(i)] = wp
            bp = Pawn(Color.BLACK)
            self._pieces[Coordinate(i+5)] = bp
        # Other pieces
        self._pieces[Coordinate.a1] = Rook(Color.WHITE)
        self._pieces[Coordinate.h1] = Rook(Color.WHITE)
        self._pieces[Coordinate.a8] = Rook(Color.BLACK)
        self._pieces[Coordinate.h8] = Rook(Color.BLACK)
        self._pieces[Coordinate.b1] = Knight(Color.WHITE)
        self._pieces[Coordinate.g1] = Knight(Color.WHITE)
        self._pieces[Coordinate.b8] = Knight(Color.BLACK)
        self._pieces[Coordinate.g8] = Knight(Color.BLACK)
        self._pieces[Coordinate.c1] = Bishop(Color.WHITE)
        self._pieces[Coordinate.f1] = Bishop(Color.WHITE)
        self._pieces[Coordinate.c8] = Bishop(Color.BLACK)
        self._pieces[Coordinate.f8] = Bishop(Color.BLACK)
        self._pieces[Coordinate.d1] = Queen(Color.WHITE)
        self._pieces[Coordinate.d8] = Queen(Color.BLACK)
        self._pieces[Coordinate.e1] = King(Color.WHITE)
        self._pieces[Coordinate.e8] = King(Color.BLACK)

        for c, p in self._pieces.items():
            self._board.set_content(c,p)

    def __str__(self):
        string = ""
        for r in self._board.rows:
            for s in r:
                piece = self._pieces[s] if not self._board.is_empty(s) else "."
                string = string + str(piece) + '\t'
            string = string + '\n'
        return string