Exemple #1
0
class Ui:
    """Command line user interface

    Manages all the interaction with the user. 
    """
    color_dict = {0: "White", 1: "Black"}
    piece_type_dict = {
        0: "\u2654\u265a",
        1: "\u2655\u265b",
        2: "\u2656\u265c",
        3: "\u2657\u265d",
        4: "\u2658\u265e",
        5: "\u2659\u265f"
    }
    x_str2int = {
        "a": 0,
        "b": 1,
        "c": 2,
        "d": 3,
        "e": 4,
        "f": 5,
        "g": 6,
        "h": 7
    }
    y_str2int = {
        "1": 0,
        "2": 1,
        "3": 2,
        "4": 3,
        "5": 4,
        "6": 5,
        "7": 6,
        "8": 7
    }
    x_int2str = {
        0: "a",
        1: "b",
        2: "c",
        3: "d",
        4: "e",
        5: "f",
        6: "g",
        7: "h"
    }
    y_int2str = {
        0: "1",
        1: "2",
        2: "3",
        3: "4",
        4: "5",
        5: "6",
        6: "7",
        7: "8"
    }

    def __init__(self):
        self.board = Board()
        self.draw()

    def draw(self):
        """Draws the board configuration in the terminal"""
        display = "     a  b  c  d  e  f  g  h      \n" + \
                  "________________________________ \n "
        # Loop over all x and y indices
        for j in range(8):
            display += " " + str(j + 1) + "|"
            for i in range(8):
                # Find the piece index for position [i, j]
                position_ij = Position(i, j)
                piece = self.board.find_piece(position_ij)
                if piece.color != None:
                    display += " " + \
                        Ui.piece_type_dict[piece.type][piece.color] + " "
                else:
                    # Draw an empty cell
                    display += " - "
            # New line for different i value
            display += "|" + str(j + 1) + " \n "
        display += "_______________________________ \n" + \
                   "     a  b  c  d  e  f  g  h    \n"
        self.board_string = display
        print(display)

    def turn(self):
        """"Performs a turn within ui"""
        selected_piece = self.select_piece()
        position = self.select_move(selected_piece)
        self.board.turn(selected_piece, position, self.draw, self.check,
                        self.check_mate)

    def select_piece(self) -> Piece:
        """Asks the user to select a piece to make a move with"""
        question = Ui.color_dict[self.board.turn_color] + \
            ", your turn! Please select a piece. \n"
        piece = Piece(None, None, None, None, None)
        while piece.color is None or piece.color != self.board.turn_color:
            coordinate = input(question)
            position = self.coordinate2position(coordinate)
            piece = self.board.find_piece(position)
            question = "No piece of yours at this field, try again! \n"
        return piece

    def select_move(self, selected_piece: int) -> Position:
        """Asks the user where to move the selected piece"""
        question = "The selected piece can move to " + \
            self.moves2text(selected_piece) + "\n"
        coordinate = input(question)
        position = self.coordinate2position(coordinate)
        while not position in selected_piece.moves:
            question = "Your piece can't move to the selected field, try again! \n"
            coordinate = input(question)
            position = self.coordinate2position(coordinate)
        return position

    def moves2text(self, selected_piece: Piece) -> str:
        """Turns a list of positions into a string with coordinates"""
        text = ""
        for move in selected_piece.moves:
            text += self.position2coordinate(move) + ", "
        return text

    def coordinate2position(self, coordinate: str) -> Position:
        """Converts user input to a board position"""
        x = Ui.x_str2int[coordinate[0]]
        y = Ui.y_str2int[coordinate[1]]
        return Position(x, y)

    def position2coordinate(self, position: Position) -> str:
        """Converts user a position to a  ui coordinate"""
        return Ui.x_int2str[position.x] + Ui.y_int2str[position.y]

    def check(self):
        """Function that notifies players when check"""
        print('Check!')

    def check_mate(self):
        """Function that notifies players when check mate"""
        print('Check mate! The game is over')
Exemple #2
0
class Gui():
    """Grafical user interface for playing chess"""
    font = 'Courier 20'
    color_dict = {0: '#b0b0b0', 1: '#ffffff'}
    piece_type_dict = {
        0: {
            0: '\u2654',
            1: '\u265a'
        },
        1: {
            0: '\u2655',
            1: '\u265b'
        },
        2: {
            0: '\u2656',
            1: '\u265c'
        },
        3: {
            0: '\u2657',
            1: '\u265d'
        },
        4: {
            0: '\u2658',
            1: '\u265e'
        },
        5: {
            0: '\u2659',
            1: '\u265f'
        }
    }
    turn_color_dict = {0: 'White', 1: 'Black'}

    def __init__(self):
        # Init board
        self.board = Board()
        # Init root
        self.root = tk.Tk()
        # Create general structure
        self.board_frame = tk.Frame(self.root)
        self.board_frame.pack()
        self.test_frame = tk.Label(self.root, text='Welcome', font=Gui.font)
        self.test_frame.pack()
        self.user_input = tk.Entry(self.root, font=Gui.font)
        self.user_input.configure(state='readonly')
        self.user_input.pack()
        self.user_input_given = tk.IntVar(master=self.user_input,
                                          name='piece_type',
                                          value=-1)

        # Create buttons/fields
        self.buttons = [[], [], [], [], [], [], [], []]
        self.fields = [[], [], [], [], [], [], [], []]
        for x, y in product(range(8), range(8)):
            field_color = (x + y) % 2
            self.fields[x].append(
                tk.Frame(self.board_frame,
                         height=50,
                         width=50,
                         background=Gui.color_dict[field_color]))
            self.fields[x][y].propagate(False)
            self.fields[x][y].grid(column=x, row=8 - y)
            self.buttons[x].append(
                tk.Button(self.fields[x][y],
                          background=Gui.color_dict[field_color],
                          activebackground='#f2ff00',
                          borderwidth=0,
                          font='Courier 30'))
            self.buttons[x][y].pack(fill='both', expand=True)
        self.draw()
        self.select_piece()
        self.root.mainloop()

    def ask_promotion_type(self):
        """Asks the user which piece to promote"""
        self.user_input.bind('<Return>', self.promote2input)
        self.test_frame.configure(text='Promote to type:')
        self.user_input.configure(state='normal')
        self.reset_buttons()
        self.user_input_given.set(-1)
        self.user_input.wait_variable(name='piece_type')
        user_input = self.user_input_given.get()
        self.user_input.delete(0, len(self.user_input.get()))
        self.user_input.configure(state='readonly')
        return user_input

    def promote2input(self, event) -> int:
        """Gets the entered text from the entry box"""
        type_dict = {
            'king': 0,
            'queen': 1,
            'rook': 2,
            'bishop': 3,
            'knight': 4,
            'pawn': 5
        }
        promotion_type = type_dict[self.user_input.get()]
        # self.board.promote(piece, promotion_type)
        self.user_input.bind('<Return>')
        self.user_input_given.set(promotion_type)

    def select_piece(self):
        """Select piece to move"""
        color = self.board.turn_color
        for x, rows in enumerate(self.buttons):
            for y, button in enumerate(rows):
                piece = self.board.find_piece(Position(x, y))
                if piece.color == color and \
                   piece.moves != [] and \
                   piece.moves != None:
                    func = partial(self.show_moves, piece)
                    button.configure(command=func)

    def show_moves(self, piece: Piece):
        """Marks the fields where the selected piece can move to"""
        self.reset_buttons()
        for move in piece.moves:
            self.buttons[move.x][move.y].configure(background='#f2ff00',
                                                   command=partial(
                                                       self.select_move, piece,
                                                       move))

    def select_move(self, piece: Piece, position):
        """Runs when player selects where to move to"""
        self.reset_buttons()
        self.board.recalculate(piece, position, self.ask_promotion_type)
        self.board.delete_self_check()
        self.board.turn_counter += 1
        self.board.turn_color = int(not self.board.turn_color)
        self.draw()
        if self.board.check == True:
            self.board.check_mate = \
                self.board.ischeckmate(self.board.turn_color)
            if self.board.check_mate == True:
                self.test_frame.configure(text='Check mate!')
            else:
                self.test_frame.configure(text='Check!')
        else:
            message = Gui.turn_color_dict[self.board.turn_color] + \
                ', it\'s your turn'
            self.test_frame.configure(text=message)
        self.select_piece()

    def draw(self):
        """Draws pieces on the board"""
        for (x, y) in product(range(8), range(8)):
            piece = self.board.find_piece(Position(x, y))
            if piece.color != None:
                self.buttons[x][y].config(
                    text=Gui.piece_type_dict[piece.type][piece.color])
            else:
                self.buttons[x][y].config(text='')

    def reset_buttons(self):
        """Resets the buttons colors and commands"""
        for x, y in product(range(8), range(8)):
            button = self.buttons[x][y]
            button.configure(command=False,
                             background=Gui.color_dict[(x + y) % 2])