Example #1
0
    def possibleMoves(self, start):
        """Return list of possible moves.

        Each item is itself a list of moves in one direction.        
        """
        row, col = position(start)
        directions = []
        # Go round the clock starting with the two top moves
        if row < 6:
            if col > 0:
                directions.append([squarify(row + 2, col - 1)])
            if col < 7:
                directions.append([squarify(row + 2, col + 1)])
        # Try the two right moves
        if col < 6:
            if row < 7:
                directions.append([squarify(row + 1, col + 2)])
            if row > 0:
                directions.append([squarify(row - 1, col + 2)])
        # Try the two bottom moves
        if row > 1:
            if col < 7:
                directions.append([squarify(row - 2, col + 1)])
            if col > 0:
                directions.append([squarify(row - 2, col - 1)])
        # Try the two left moves
        if col > 1:
            if row > 0:
                directions.append([squarify(row - 1, col - 2)])
            if row < 7:
                directions.append([squarify(row + 1, col - 2)])

        return directions
Example #2
0
    def possibleMoves(self, start):
        """Return list of possible moves.

        Each item is itself a list of moves in one direction.        
        """
        row, col = position(start)
        directions = []
        # Go round the clock starting at the top left
        if row < 7:
            if col > 0:
                directions.append([squarify(row + 1, col - 1)])
            directions.append([squarify(row + 1, col)])
            if col < 7:
                directions.append([squarify(row + 1, col + 1)])
        # Try to move right
        if col < 7:
            directions.append([squarify(row, col + 1)])
        # Try the three bottom moves
        if row > 0:
            if col < 7:
                directions.append([squarify(row - 1, col + 1)])
            directions.append([squarify(row - 1, col)])
            if col > 0:
                directions.append([squarify(row - 1, col - 1)])
        # Try to move left
        if col > 0:
            directions.append([squarify(row, col - 1)])
        return directions
Example #3
0
 def attackMoves(self, start):
     """Return list of square that this pawn can attack.
     Also return the matching squares that can be an en passant target.
     """
     row, col = position(start)
     directions = []
     if self.colour == WHITE and row < 7:
         if col > 0:
             target = squarify(row+1, col-1)
             en_passant = squarify(row, col-1)
             directions.append((target, en_passant))
         if col < 7:
             target = squarify(row+1, col+1)
             en_passant = squarify(row, col+1)
             directions.append((target, en_passant))
     if self.colour == BLACK and row > 0:
         if col > 0:
             target = squarify(row-1, col-1)
             en_passant = squarify(row, col-1)
             directions.append((target, en_passant))
         if col < 7:
             target = squarify(row-1, col+1)
             en_passant = squarify(row, col+1)
             directions.append((target, en_passant))
     return directions
Example #4
0
    def possibleMoves(self, start):
        """Return list of possible moves.

        Each item is itself a list of moves in one direction.        
        """
        row, col = position(start)
        directions = []
        # Go round the clock starting with the two top moves
        if row < 6:
            if col > 0:
                directions.append([squarify(row+2, col-1)])
            if col < 7:
                directions.append([squarify(row+2, col+1)])
        # Try the two right moves
        if col < 6:
            if row < 7:
                directions.append([squarify(row+1, col+2)])
            if row > 0:
                directions.append([squarify(row-1, col+2)])
        # Try the two bottom moves
        if row > 1:
            if col < 7:
                directions.append([squarify(row-2, col+1)])
            if col > 0:
                directions.append([squarify(row-2, col-1)])
        # Try the two left moves
        if col > 1:
            if row > 0:
                directions.append([squarify(row-1, col-2)])
            if row < 7:
                directions.append([squarify(row+1, col-2)])

        return directions
Example #5
0
    def possibleMoves(self, start):
        """Return list of possible moves.

        Each item is itself a list of moves in one direction.        
        """
        row, col = position(start)
        directions = []
        # Go round the clock starting at the top left
        if row < 7:
            if col > 0:
                directions.append([squarify(row+1, col-1)])
            directions.append([squarify(row+1, col)])
            if col < 7:
                directions.append([squarify(row+1, col+1)])
        # Try to move right
        if col < 7:
            directions.append([squarify(row, col+1)])
        # Try the three bottom moves
        if row > 0:
            if col < 7:
                directions.append([squarify(row-1, col+1)])
            directions.append([squarify(row-1, col)])
            if col > 0:
                directions.append([squarify(row-1, col-1)])
        # Try to move left
        if col > 0:
            directions.append([squarify(row, col-1)])
        return directions
Example #6
0
    def diagonalMoves(self, startrow, startcol):
        """List possible diagonal moves.
        """
        directions = []

        # Go to the top left.
        row = startrow
        col = startcol
        direction = []
        while row < 7 and col > 0:
            row += 1
            col -= 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the top right.
        row = startrow
        col = startcol
        direction = []
        while row < 7 and col < 7:
            row += 1
            col += 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the bottom right.
        row = startrow
        col = startcol
        direction = []
        while row > 0 and col < 7:
            row -= 1
            col += 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the bottom left.
        row = startrow
        col = startcol
        direction = []
        while row > 0 and col > 0:
            row -= 1
            col -= 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        return directions
Example #7
0
    def diagonalMoves(self, startrow, startcol):
        """List possible diagonal moves.
        """
        directions = []

        # Go to the top left.
        row = startrow
        col = startcol
        direction = []
        while row < 7 and col > 0:
            row += 1
            col -= 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the top right.
        row = startrow
        col = startcol
        direction = []
        while row < 7 and col < 7:
            row += 1
            col += 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the bottom right.
        row = startrow
        col = startcol
        direction = []
        while row > 0 and col < 7:
            row -= 1
            col += 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        # Go to the bottom left.
        row = startrow
        col = startcol
        direction = []
        while row > 0 and col > 0:
            row -= 1
            col -= 1
            direction.append(squarify(row, col))
        if len(direction) > 0:
            directions.append(direction)

        return directions
Example #8
0
 def attackMoves(self, start):
     """Return list of square that this pawn can attack.
     Also return the matching squares that can be an en passant target.
     """
     row, col = position(start)
     directions = []
     if self.colour == WHITE and row < 7:
         if col > 0:
             target = squarify(row + 1, col - 1)
             en_passant = squarify(row, col - 1)
             directions.append((target, en_passant))
         if col < 7:
             target = squarify(row + 1, col + 1)
             en_passant = squarify(row, col + 1)
             directions.append((target, en_passant))
     if self.colour == BLACK and row > 0:
         if col > 0:
             target = squarify(row - 1, col - 1)
             en_passant = squarify(row, col - 1)
             directions.append((target, en_passant))
         if col < 7:
             target = squarify(row - 1, col + 1)
             en_passant = squarify(row, col + 1)
             directions.append((target, en_passant))
     return directions
Example #9
0
    def findPiece(self, symbol, colour):
        """Find a piece with this symbol and colour.

        Find white rooks.

        >>> board = ChessBoard()
        >>> board.findPiece('R', WHITE)
        ['A1', 'H1']

        Lowercase is also acceptable.

        >>> board.findPiece('r', WHITE)
        ['A1', 'H1']

        Give me all black pawns.

        >>> board.findPiece('P', BLACK)
        ['A7', 'B7', 'C7', 'D7', 'E7', 'F7', 'G7', 'H7']
        """
        symbol = symbol.upper()
        results = []
        for row in range(self.nrows):
            for col in range(self.ncols):
                if self[row, col].symbol == symbol and \
                   self[row, col].colour == colour:
                    results.append(position.squarify(row, col))
        return results
Example #10
0
    def value(self):
        """Return value of current board.

        Positive: white is in a better position
        Negative: black is in a better position


        An empty chess board is worth nothing

        >>> board = ChessBoard(EMPTY_CHESS_BOARD)
        >>> board.value()
        0

        In the beginning white and black should be equal.  White
        begins first though, so maybe we want to give him a small
        advantage later on.

        >>> board = ChessBoard()
        >>> board.value()
        0

        On our castling board, black and white are equal.

        >>> board = ChessBoard(CASTLING_BOARD)
        >>> board.value()
        0

        Let's inspect our end game board.

        >>> board = ChessBoard(ENDGAME_BOARD)
        >>> board.printPieces()
        KQ----N-P-------
        kqr-b---pp------

        The white knight and black bishop even out, but black has a
        rook and a pawn more.

        >>> board.value()
        -6

        Let's inspect our end promotion board.

        >>> board = ChessBoard(PROMOTION_BOARD)
        >>> board.printPieces()
        K-R---N-PPPP----
        k-r-----ppp-----

        White has a knight and a pawn more.

        >>> board.value()
        4

        """
        total = 0
        for row in range(self.nrows):
            for col in range(self.ncols):
                square = position.squarify(row, col)
                total += self.pieceWorth(square)
        return total
Example #11
0
 def sideWaysMoves(self, row, col, direction=1):
     """List possible sideways moves.
     """
     moves = []
     count = 0
     while count < CHESS_COLS:
         count += 1
         col += direction
         if 0 <= col < CHESS_COLS:
             moves.append(squarify(row, col))
         else:
             break
     return moves
Example #12
0
 def sideWaysMoves(self, row, col, direction=1):
     """List possible sideways moves.
     """
     moves = []
     count = 0
     while count < CHESS_COLS:
         count += 1
         col += direction
         if 0 <= col < CHESS_COLS:
             moves.append(squarify(row, col))
         else:
             break
     return moves
Example #13
0
 def upDownMoves(self, row, col, max=None, direction=1):
     """List possible forward moves.
     """
     moves = []
     count = 0
     max = max or self.max_moves or CHESS_ROWS
     while count < max:
         count += 1
         row += direction
         if 0 <= row < CHESS_ROWS:
             moves.append(squarify(row, col))
         else:
             break
     return moves
Example #14
0
 def upDownMoves(self, row, col, max=None, direction=1):
     """List possible forward moves.
     """
     moves = []
     count = 0
     max = max or self.max_moves or CHESS_ROWS
     while count < max:
         count += 1
         row += direction
         if 0 <= row < CHESS_ROWS:
             moves.append(squarify(row, col))
         else:
             break
     return moves
Example #15
0
    def hint(self, depth=0):
        """Give a hint for the current player.

        Our hints are pretty lousy currently.

        >>> board = ChessBoard(HINT_BOARD)
        >>> board.hint()
        {'start': 'D7', 'target': 'A7', 'value': 5}
        """
        options = []
        for row in range(self.nrows):
            for col in range(self.ncols):
                if self[row, col].colour == self.player:
                    friend = position.squarify(row, col)
                    moves = self.calcMovesForPiece(friend)
                    moves.extend([x[0] for x in self.specialAttackMoves(friend)])
                    for move in moves:
                        board = copy.deepcopy(self)
                        try:
                            board.move(friend, move)
                        except position.PromotionException:
                            continue
                        if depth > 0:
                            value = board.hint(depth-1)['value']
                        if depth == 0:
                            value = board.value()
                        options.append({'start': friend,
                                        'target': move,
                                        'value': value})
        if self.player == WHITE:
            fun = max
        else:
            fun = min
        if len(options) == 0:
            return None
        best_value = fun([x['value'] for x in options])
        best_move = [x for x in options if x['value'] == best_value]
        return best_move[0]
Example #16
0
    def isAttacked(self, ownColour, square):
        """Is the square, owned by ownColour, attacked?

        - Mostly used for the King of course.

        Let's start with a castling board.

        >>> board = ChessBoard(CASTLING_BOARD)

        The white and black kings are safe in their starting
        positions.

        >>> board.isAttacked(WHITE, 'E1')
        False
        >>> board.isAttacked(BLACK, 'E8')
        False

        They are even safe in the squares that they would normally use
        for castling.

        >>> for square in ('D1', 'C1', 'F1', 'G1'):
        ...     if board.isAttacked(WHITE, square):
        ...         print True
        >>> for square in ('D8', 'C8', 'F8', 'G8'):
        ...     if board.isAttacked(BLACK, square):
        ...         print True


        They are not safe when they are at the enemy's last line,
        being attacked by the opposite rooks.

        >>> board.isAttacked(WHITE, 'B8')
        True
        >>> board.isAttacked(BLACK, 'D1')
        True

        Now we add some pieces to the board and see what effect they
        have.  First we add a black knight on E3.  That makes D1 and
        F1 unsafe.

        >>> board['E3'] = piece.Knight(BLACK)
        >>> for square in ('C1', 'E1', 'G1'):
        ...     if board.isAttacked(WHITE, square):
        ...         print True
        >>> board.isAttacked(WHITE, 'D1')
        True
        >>> board.isAttacked(WHITE, 'F1')
        True

        We will attack black with a pawn right in front of the King.
        The King should be safe in his current spot, but he cannot
        move one square to the left or the right.

        >>> board['E7'] = piece.Pawn(WHITE)
        >>> for square in ('C8', 'E8', 'G8'):
        ...     if board.isAttacked(BLACK, square):
        ...         print True
        >>> board.isAttacked(BLACK, 'D8')
        True
        >>> board.isAttacked(BLACK, 'F8')
        True

        """
        king = piece.King(ownColour)
        for row in range(self.nrows):
            for col in range(self.ncols):
                if self[row, col].isEnemy(king):
                    attacker = position.squarify(row, col)
                    moves = self.calcMovesForPiece(attacker, unconditional=True)
                    if square in moves:
                        return True
                    # Take a list of squares (without their en passant
                    # friends) that can be attacked by this piece,
                    # presumably a Pawn if anything ends up in this
                    # list.
                    special = [sq for (sq, ep) in
                               self[attacker].attackMoves(attacker)]
                    if square in special:
                        return True
        return False
Example #17
0
    def isMate(self):
        """Check to see if the player is mate.

        That is: if no legel moves can be made.  Still can be
        checkmate or stalemate.

        We have a nice board for checking this.  At first there is no
        mate.

        >>> board = ChessBoard(MATE_BOARD)
        >>> board.isMate()
        False
        >>> board.isCheckMate()
        False
        >>> board.isStaleMate()
        False

        White plays and wins.

        >>> board.move('E5', 'F7')
        >>> board.player == BLACK
        True
        >>> board.isMate()
        True
        >>> board.isCheckMate()
        True
        >>> board.isStaleMate()
        False

        If we look at this from White's point of view, there is no
        mate.

        >>> board.switchPlayers()
        >>> board.isMate()
        False
        >>> board.isCheckMate()
        False
        >>> board.isStaleMate()
        False

        Let's try again, but now with black starting.

        >>> board = ChessBoard(MATE_BOARD)
        >>> board.switchPlayers()
        >>> board.isMate()
        False
        >>> board.isCheckMate()
        False
        >>> board.isStaleMate()
        False

        Black thinks he is smart in getting rid of the white knight.

        >>> board.move('D6', 'E5')
        >>> board.isMate()
        True
        >>> board.isCheckMate()
        False
        >>> board.isStaleMate()
        True

        Oops, that was a stalemate.  Let's give black another chance
        by cheating.

        >>> board.switchPlayers()
        >>> board.move('G3', 'G2')
        >>> board.isMate()
        True
        >>> board.isCheckMate()
        True
        >>> board.isStaleMate()
        False

        """
        for row in range(self.nrows):
            for col in range(self.ncols):
                if self[row, col].colour == self.player:
                    friend = position.squarify(row, col)
                    moves = self.calcMovesForPiece(friend)
                    if len(moves) > 0:
                        return False
                    # Take a list of squares (without their en passant
                    # friends) that can be attacked by this piece,
                    # presumably a Pawn if anything ends up in this
                    # list.
                    special = self.specialAttackMoves(friend)
                    if len(special) > 0:
                        return False
        return True