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)
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)