예제 #1
0
class Terminal(object):
    """ Defines the kernel interface """
    def __init__(self):
        self.validMove = re.compile(r"(?P<l_c>[a-h])(?P<l_r>[1-8])(?P<n_c>[a-h])(?P<n_r>[1-8])")
        #algebraic notation
        self.profilesManager = ProfilesManager("../profiles.chess")
        self.savesManager = SavesManager("../saves/")
        self.aid = Help()

    def print_board(self, p, turn, white):
        """Prints the board. The board inverses positions
        depending on who's turn it is. Unicode style grid.
        """
        if turn is not white:
            reverse = False
        else:
            reverse = True
        header = [chr(i) for i in
                  reverse_range(not reverse, ord('A'), ord('H') + 1)]
        print("")
        print("    ", end="")  # padding
        print(*header, sep=" " * 3)
        print("  \u2554", "\u2550\u2550\u2550\u2564" * 7,
              "\u2550\u2550\u2550\u2557", sep="")
        for i in reverse_range(reverse, 8):
            left = True
            for j in reverse_range(not reverse, 8):
                if left:
                    print(i + 1, "\u2551", end=" ")
                    left = False
                else:
                    print("\u2502", end=" ")
                if p.getPiece(i, j) is not None:
                    player = p.getPiece(i, j).getPlayer
                    piece = p.getPiece(i, j).getRepres
                    if player is white:
                        print(piece.upper(), end=" ")
                    else:
                        print(piece, end=" ")
                else:
                    print(" ", end=" ")
            print("\u2551", i + 1)
            if i == 7 and not reverse or i == 0 and reverse:
                print("  \u255A", "\u2550\u2550\u2550\u2567" * 7,
                      "\u2550\u2550\u2550\u255D", sep="")
            else:
                print("  \u255F", "\u2500\u2500\u2500\u253C" * 7,
                      "\u2500\u2500\u2500\u2562", sep="")
        print("    ", end="")  # padding
        print(*header, sep=" " * 3)
        print("")
        
    def selectProfile(self, name, taken=[]):
        """After menu screen: 2 profiles must be chosen in 
        order to advance"""

        profiles = self.profilesManager.getProfiles()
        takennames = [profile.name for profile in taken]
        profiles = [profile for profile in profiles.values()
                    if profile.name not in takennames]
        print("Hello ", name, ", choose your profile.", sep="")
        i = 1
        for profile in profiles:
            print(i, ": ", profile.name, " (elo: ", profile.elo, ")", sep="")
            i += 1
        print("n: New profile")
        run = True
        while run:
            entry = safe_input(">>> ", str)
            try:
                entry = int(entry)
            except ValueError:
                if entry.startswith("n"):
                    choisi = self.newProfile()
                    run = False
            else:
                if entry >= 1 and entry <= i - 1:
                    choisi = profiles[entry - 1]
                    run = False
            if run:
                print("Invalid entry.")
        return choisi

    def newProfile(self, name=""):
        """New profile interface."""

        run = True
        profiles = self.profilesManager.getProfiles()
        while name == "":
            name = safe_input("Enter profile name : ", str)
            if name in profiles.keys():
                print("The name has been used previosly."
                      "Please enter a new one.")
                name = ""
        player = Player(name, 1200)  
        # novice ELO
        print("Indicate your ELO score,"
              "or leave this part blank (hit ENTER)")
        while run:
            entry = input("Your ELO score (1200) : ")
            try:
                player.elo = int(entry)
            except:
                if(entry == ""):
                    run = False
                else:
                    print("Plaese enter an integer.")
            else:
                run = False
        self.profilesManager.saveProfile(player)
        return player

    def start(self):
        """Kick off the interface."""

        run = True
        print("Welcome! Enjoy this game of chess. Brought to you by Terral, Geshkovski. (Programmation 2, 2015)\n")
        while run:
            save = None
            start = False
            print("What choose you ?\n\n [N]ew Game\n [l]oad game\n [h]elp\n [q]uit\n")
            entry = safe_input(">>> ", str).lower()
            if entry.startswith('l'):
                start = True
                save = self.loadGame()
                if save is not None:
                    self.print_history(save)
            elif entry.startswith('q'):
                run = False
            elif entry.startswith('n') or entry == "":
                start = True
            elif entry.startswith('h'):
                print(" \n [R]ules\n [e]ntries\n [t]ips\n [N]ew Game\n")
                entry = safe_input(">>> ", str).lower()
                if entry.startswith('r'):
                    print(self.aid.rules)
                elif entry.startswith('e'):
                    print(self.aid.entries)
                elif entry.startswith('t'):
                    print(self.aid.tips)
                elif entry.startswith('n') or entry == "":
                    start = True
                else:
                    print("Invalid entry.") 
            else:
                print("Invalid entry.")
            if start:
                self.startGame(save)
        print("Thank you. Goodbye.")

    def loadGame(self):
        """ Load game screen """

        print("Here are the available savegames :")
        i = 1
        save = None
        saves = self.savesManager.getSaves()
        for filename, save in saves:
            print(filename, " (", i, ") ", ":", sep="")
            print("=" * len(filename), "=" * (len(str(i)) + 2), "===", sep="")
            print("\tGame between", save.white, "and", save.black)
            print("\tPlayed the", time.ctime(save.crea), "and modified the", time.ctime(save.date))
            print("")
            i += 1
        print("Which file do you load?")
        error = True
        while error:
            error = False
            entry = input(">>> ")
            try:
                id = int(entry)
            except:
                if entry in [filename for filename, unused_save in saves]:
                    self.savesManager.getSave(entry)
                elif entry != "":
                    error = True
            else:
                if id > 0 and id < i:
                    save = saves[id - 1][1]
                else:
                    error = True
            if error:
                print("Invalid entry.")
        return save

    def print_history(self, save):
        pass

    def ask(self, player, s):
        """Asks for user input."""

        p = Board()
        action = data.useraction.UserAction(data.useraction.INVALID)
        entry = safe_input(player + ", choose the case of the piece you want to move and its next case: ", str).lower()   
        m = self.validMove.match(entry)
        if m is not None:
            action.action = data.useraction.MOVE
            action.data["ini"] = (int(m.group("l_r")) - 1,
                                  ord(m.group("l_c")) - ord('a'))
            action.data["now"] = (int(m.group("n_r")) - 1,
                                  ord(m.group("n_c")) - ord('a'))
            action.data["prom"] = 0
            self.canPromote = isinstance(s.p.t[action.data["ini"][0]][action.data["ini"][1]], data.pieces.Pawn) and action.data["now"][0] in [0,7]
            if action.data["now"][0] in [0,7] and self.canPromote == True :
                entry_promote = safe_input(player + ", you can promote. [Q] for queen (♛) , [r] for rook (♜) , [k] for knight (♞) , [b] for bishop (♝) : ", str).lower() 
                while entry_promote not in ("q", "r", "k", "b"):
                    entry_promote = safe_input(player + ", you can promote. [Q] for queen (♛) , [r] for rook (♜) , [k] for knight (♞) , [b] for bishop (♝): ", str).lower() 
                if entry_promote == "q":
                    prom = 1
                elif entry_promote == "r":
                    prom = 2
                elif entry_promote == "k":
                    prom = 3
                elif entry_promote == "b":   
                    prom = 4
                action.data["prom"] = prom 
        elif entry == "castle" or entry == "0-0":
            action.action = data.useraction.CASTLE
            action.data["sens"] = 1
        elif entry == "gcastle" or entry == "0-0-0":
            action.action = data.useraction.GCASTLE
            action.data["sens"] = -1
        elif entry == "exit":
            action.action = data.useraction.EXIT
        elif entry == "help":
            action.action = data.useraction.HELP
        elif entry == "draw":
            action.action = data.useraction.DRAW
        elif entry.startswith("save"):
            action.action = data.useraction.SAVE
            try:
                action.data["name"] = entry.split(" ", 1)[1]
            except IndexError:
                action.data["name"] = None
        return action
    
    def initSave(self, save=None):
        """ Saves the game at choice or as game goes on """

        if save is None:
            white = self.selectProfile("white")
            black = self.selectProfile("black", [white])
            p = Board()
            p.setup(white.name, black.name)
            s = Save(p, white.name, black.name)
        else:
            s = save
            if self.profilesManager.getProfileByName(s.white) is None:
                print("The", s.white, "profile doesn't exist. Please create it.")
                self.newProfile(s.white)
            if self.profilesManager.getProfileByName(s.black) is None:
                print("The", s.black, "profile doesn't exist. Please create it.")
                self.newProfile(s.black)
        return s
        
    def startGame(self, save=None):
        """ New game """

        winner = None
        stop = False
        s = self.initSave(save)
        header = "♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜  "
        footer = "♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖  "
        if s.whites_turn:
            turn, waiting = s.white, s.black
        else:
            turn, waiting = s.black, s.white
        while winner is None and not stop:
            self.print_board(s.p, turn, s.white)
            switch_turn = False
            if s.p.check(turn):
                sentence = str(turn)+", you are checked."
                if s.p.checkmate(turn):
                    if turn is s.white:
                        winner = s.black
                    else:
                        winner = s.white
                    sentence = "Checkmate. The winner is: " + str(winner) + ". Well done."
                print(header*3)
                print(sentence)
                print(footer*3)
                print("")
            if s.p.stalemate(turn):
                sentence = "Stalemate."
                print(header*3)
                print(sentence)
                print(footer*3)
                print("")
                stop = True
                winner = "Draw"
            while not switch_turn and winner is None:
                action = self.ask(turn,s)
                if action.action == data.useraction.MOVE:
                    try:
                        s.p.movePiece(turn, action.data["ini"][0],
                                        action.data["ini"][1], action.data["now"][0],
                                        action.data["now"][1], 
                                        action.data["prom"])
                        #if s.p.check(turn):
                        #   k = "+"
                        #else:
                        #   k = ""
                        #self.pgn_save((action.data["now"][0], action.data["now"][1]), k)   
                    except ChessException as e:
                        print(e)
                    else:
                        switch_turn = True
                elif action.action == data.useraction.CASTLE:
                    try:
                        s.p.Castle(turn, action.data["sens"])
                        #self.pgn_save("0-0", "")
                    except ChessException as e:
                        print(e)
                    else:
                        switch_turn = True
                #Added on 14.12 , how could we actually forget to implement it is beyond me..
                elif action.action == data.useraction.GCASTLE:
                    try:
                        s.p.Castle(turn, action.data["sens"])
                        #self.pgn_save("0-0-0","")
                    except ChessException as e:
                        print(e)
                    else:
                        switch_turn = True
                elif action.action == data.useraction.HELP:
                    print(" \n [R]ules\n [e]ntries\n [t]ips\n")
                    entry = safe_input(">>> ", str).lower()
                    if entry.startswith('r'):
                        print(self.aid.rules)
                    elif entry.startswith('e'):
                        print(self.aid.entries)
                    elif entry.startswith('t'):
                        print(self.aid.tips)
                    else:
                        print("Invalid entry.") 
                elif action.action == data.useraction.DRAW:
                    if turn == s.white:
                        decider = s.black
                        forfeit = s.white
                    else:
                        decider = s.white
                        forfeit = s.black
                    print("")
                    print(forfeit, "wants to forfeit the match.", "Do you both wish to draw,", decider, "?\n")
                    print("[Y]es/[n]o\n")
                    entry = safe_input(">>> ", str).lower()
                    if entry == "y":
                        winner = "Draw"
                        stop = True
                    elif entry == "n":
                        print(decider, "wants to keep on playing.")
                        switch_turn = True
                    else:
                        print("Invalid entry.")
                elif action.action == data.useraction.SAVE:
                    if action.data["name"] is not None:
                        self.savesManager.save(s, action.data["name"])
                        print("File saved as" + action.data["name"])
                    else:
                        name = safe_input("Enter a name for the file: ", str)
                        try:
                            self.savesManager.save(s, name)
                        except:
                            print("Could not save.")
                        else:
                            print("File saved as: " + action.data["name"]) 
                elif action.action == data.useraction.EXIT:
                    switch_turn = True
                    stop = True
            s.whites_turn = not s.whites_turn
            turn, waiting = waiting, turn
            self.savesManager.save(s, "autosave")
        #Modif for elo
        data.elo.saveElo(s.white, s.black, winner)
예제 #2
0
파일: gui.py 프로젝트: borjanG/Prog2-Chess
class BoardGame(tk.Frame):
    
    #Needed properties
    rows = 8
    columns = 8
    color1 = "light goldenrod"
    color2 = "saddle brown"
    square_size = 64
    pieces = {}
    icons = {}
    player1 = Player("Borjan", 1200)
    player2 = Player("Naomie", 1200)
    tour = 0

    def __init__(self, interface, chessboard, loaded):

        #Window properties
        super().__init__(interface.root)
        self.chessboard = chessboard
        if not loaded:
            self.chessboard.setup(self.player1, self.player2)
        self.interface = interface
        canvas_width = self.columns * self.square_size
        canvas_height = self.rows * self.square_size

        #Entry converter
        self.validMove = re.compile(r"(?P<l_c>[a-h])(?P<l_r>[1-8])(?P<n_c>[a-h])(?P<n_r>[1-8])")
        self.savesManager = SavesManager("../saves/")

        #Main Frame
        gui = tk.Frame(self, relief=tk.SOLID, bg='black', border=2)
        gui.pack(side="top", fill="both", expand="true", padx=4, pady=4)

        #Paint the canvas
        self.canvas = tk.Canvas(self, width=canvas_width, height=canvas_height, background="grey")
        self.canvas.pack(side="top", fill="both", anchor="c", expand=True)

        #Create the statusbar at the bottom of the window
        self.statusbar = tk.Frame(self, height=64)

        #Move button
        self.button_move = tk.Button(self.statusbar, text = "Move", fg="black", command = self.move)
        self.button_move.pack(side = tk.LEFT, in_ = self.statusbar)

        #Entry widget
        self.entry = tk.Entry(self.statusbar)
        self.entry.bind("<Return>", lambda event: self.move())
        self.entry.pack(side = tk.LEFT, in_= self.statusbar)

        #Status label in the statusbar
        self.label_status = tk.Label(self.statusbar, text =" " + self.player1.name + "'s turn ", fg = "black")
        self.label_status.pack(side = tk.LEFT, expand=0, in_ = self.statusbar)
        
        #Save button
        self.button_move = tk.Button(self.statusbar, text = "Save", fg="black", command = self.savegame)
        self.button_move.pack(side = tk.RIGHT, in_ = self.statusbar)

        #Help button
        self.button_help = tk.Button(self.statusbar, text = "?", fg="black", command = self.help)
        self.button_help.pack(side = tk.RIGHT, in_ = self.statusbar)

        self.my_var = tk.IntVar()

        #Set
        self.statusbar.pack(expand=False, fill = "x", side = 'bottom')
        self.draw_pieces()
        self.canvas.bind("<Configure>", self.refresh)

    def help(self):
        HelpWindow()

    def move(self):
        """ Main function of the GUI game """

        action = data.useraction.UserAction(data.useraction.INVALID)
        entry = self.entry.get()
        m = self.validMove.match(entry)

        if self.tour == 0:
            turn, waiting = self.player1, self.player2
        else:
            turn, waiting = self.player2, self.player1

        if self.chessboard.check(turn):
            sentence = turn.name + ", you are checked. "
            self.label_status["text"] = sentence

            if self.chessboard.checkmate(turn):
                if turn is self.player1:
                    winner = self.player2
                else:
                    winner = self.player1
                sentence = "Checkmate. The winner is: " + winner.name + ". Well done."
                self.label_status["text"] = sentence 
                Checkmate(winner.name)

        if self.chessboard.stalemate(turn):
            sentence = "Stalemate."
            self.label_status["text"] = sentence
            Stalemate()

        #Move
        if m is not None:
            #If entry box has logical entry
            action.data["ini"] = (int(m.group("l_r")) - 1,
                                  ord(m.group("l_c")) - ord('a'))
            action.data["now"] = (int(m.group("n_r")) - 1,
                                  ord(m.group("n_c")) - ord('a'))
            action.data["prom"] = 0

            self.canPromote = isinstance(self.chessboard.t[action.data["ini"][0]][action.data["ini"][1]], data.pieces.Pawn) and action.data["now"][0] in [0,7]
            
            if action.data["now"][0] in [0,7] and self.canPromote == True :
                self.label_status["text"] = " " + turn.name + "You can promote: [q] [r] [k] [b] "
                self.entry.delete(0, "end")
                prom_entry = self.entry.get()
                #Fix problem with promotion!
                if prom_entry == "q":
                    prom = 1
                elif prom_entry == "r":
                    prom = 2
                elif prom_entry == "k":
                    prom = 3
                elif prom_entry == "b":
                    prom = 4
                else:
                    prom = 1
                action.data["prom"] = prom
            try:
                self.chessboard.movePiece(turn, action.data["ini"][0], action.data["ini"][1],
                                                action.data["now"][0], action.data["now"][1],
                                                action.data["prom"])
                self.entry.delete(0, "end") 
            except ChessException as e:
                self.label_status["text"] = e
            else:
                self.label_status["text"] = " " + waiting.name + "'s turn "
                self.tour = 1 - self.tour

        #Castling
        elif entry == "castle" or entry == "0-0":
            action.data["sens"] = 1
            try:
                self.chessboard.Castle(turn, action.data["sens"])
                self.entry.delete(0, "end")
            except ChessException as e:
                self.label_status["text"] = e
            else:
                self.tour = 1 - self.tour

        #Grand castle
        elif entry == "gcastle" or entry == "0-0-0":
            action.data["sens"] = -1
            try:
                self.chessboard.Castle(turn, action.data["sens"])
                self.entry.delete(0, "end")
            except ChessException as e:
                self.label_status["text"] = e
            else:
                self.tour = 1 - self.tour

        #Draw decision
        elif entry == "draw":
            Stalemate()     

        # self.label_status["text"] = waiting.name + "'s turn "
        self.draw_pieces()
    
    def send(self):
        return(self.myEntryBox.get())
        self.top.destroy()    

    def addpiece(self, name, image, row = 0, column = 0):
        """ Add a piece to the playing board """

        self.canvas.create_image(0, 0, image = image, tags = (name, "piece"), anchor = "c")
        self.placepiece(name, row, column)

    def placepiece(self, name, row, column):
        """ Place a piece at the given row/column """

        self.pieces[name] = (row, column)
        x0 = (column * self.square_size) + int(self.square_size/2)
        y0 = ((7-row) * self.square_size) + int(self.square_size/2)
        self.canvas.coords(name, x0, y0)

    def refresh(self, event={}):
        """Redraw the board, possibly in response to window being resized"""

        if event:
            xsize = int((event.width-1) / self.columns)
            ysize = int((event.height-1) / self.rows)
            self.square_size = min(xsize, ysize)

        self.canvas.delete("square")
        color = self.color2
        for row in range(self.rows):
            color = self.color1 if color == self.color2 else self.color2
            for col in range(self.columns):
                x1 = (col * self.square_size)
                y1 = ((7-row) * self.square_size)
                x2 = x1 + self.square_size
                y2 = y1 + self.square_size
                self.canvas.create_rectangle(x1, y1, x2, y2, outline="black", fill=color, tags="square")
                color = self.color1 if color == self.color2 else self.color2
        for name in self.pieces:
            self.placepiece(name, self.pieces[name][0], self.pieces[name][1])
        self.canvas.tag_raise("piece")
        self.canvas.tag_lower("square")

    def draw_pieces(self):
        """ Draws the pieces """

        p = self.chessboard
        self.canvas.delete("piece")
        for i in range(8):
            for j in range(8):
                piece = p.getPiece(i,j)
                if p.getPiece(i,j) is not None:
                    #Check the platform. Could've imported
                    #PIL for .png images, but had some trouble.
                    #.png works with tk in linux only..
                    if sys.platform.startswith("win"):
                        filename = "graphics/img/%s%s.gif" % (piece.getColor, piece.getRepres.lower())
                    else: 
                        filename = "graphics/img/%s%s.png" % (piece.getColor, piece.getRepres.lower())
                    piecename = "%s%s%s" % (piece.getRepres, i, j)

                    if (filename not in self.icons):
                        self.icons[filename] = tk.PhotoImage(file=filename, width=64, height=64)

                    self.addpiece(piecename, self.icons[filename], i, j)
                    self.placepiece(piecename, i, j)

    def savegame(self):
        """ Saves the game """
        
        self.label_status["text"] = "Saved"
        name = self.entry.get()
        if name is None:
            pass
        else:
            white = self.player1
            black = self.player2
            p = self.chessboard
            s = Save(p, white.name, black.name)
            self.savesManager.save(s, name)