Exemplo n.º 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)