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)