class MainWindow(QWidget): """ Main UI Window """ def __init__(self, parent=None): """ Initialize the chess board. """ super().__init__(parent) ## NN param set self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print('Processing device: ',self.device) self.path = "best_policy.model" self.learning_rate = 0.0001 self.mcts_iteration = 100 #self.Chess_read = CHESS_READ() ## self.setWindowTitle("GrandmasterFLEX") self.resize(1280, 720) self.svgWidget = QSvgWidget(parent=self) self.svgWidget.setGeometry(10, 10, 700, 700) self.boardSize = min(self.svgWidget.width(), self.svgWidget.height()) self.margin = 0.05 * self.boardSize self.squareSize = (self.boardSize - 2*self.margin)/8 self.board = chess.Board() self.lastmove = None self.pieceToMove = [None, None] self.drawBoard() self.enginePath = "./stockfish.exe" self.time = 0.1 self.pbar = QProgressBar(self) self.pbarlabel = QLabel('Training Progress: ') self.maxtimelabel = QLabel("Max number of examples from ./Training Games") self.engineLabel = QLabel("Selfplay games#") self.engineButton = QPushButton("Find move") self.moveButton = QPushButton("Make move") self.undoButton = QPushButton("Undo move") self.testButton = QPushButton("Selfplay") self.gendataButton = QPushButton("Generate Dataset") self.trainButton = QPushButton("Train AI") self.newgameButton = QPushButton("New Game") self.undoButton.setMaximumWidth(175) self.pathField = QLineEdit() self.pathField1 = QLabel("0") self.examples = QLineEdit() self.engineResult = QLineEdit() self.pathField.setText("5") self.examples.setText('10000000') self.pbar.setValue(0) self.main_layout = QHBoxLayout() self.tool_layout = QGridLayout() ### widget design ##QT top row self.tool_layout.addWidget(self.engineLabel, 0, 0) self.tool_layout.addWidget(self.pathField, 0, 1) self.tool_layout.addWidget(self.pathField1, 0, 2) self.tool_layout.addWidget(self.testButton, 0, 3) #second row self.tool_layout.addWidget(self.maxtimelabel, 1, 0) self.tool_layout.addWidget(self.examples, 1, 1) self.tool_layout.addWidget(self.gendataButton, 1, 2) self.tool_layout.addWidget(self.trainButton, 1, 3) #third row self.tool_layout.addWidget(self.pbarlabel, 2, 0) self.tool_layout.addWidget(self.pbar, 2, 1) #4th row self.tool_layout.addWidget(self.engineButton, 3, 0) self.tool_layout.addWidget(self.moveButton, 3, 1) self.tool_layout.addWidget(self.engineResult, 3, 2) self.tool_layout.addWidget(self.undoButton, 3, 3) self.tool_layout.addWidget(self.newgameButton, 3, 4) ### self.main_layout.addWidget(self.svgWidget, 55) self.main_layout.addLayout(self.tool_layout, 45) self.setLayout(self.main_layout) self.engineButton.clicked.connect(self.find_move) self.moveButton.clicked.connect(self.make_move) self.undoButton.clicked.connect(self.undo_move) self.testButton.clicked.connect(self.selfplay) self.gendataButton.clicked.connect(self.gendata) self.trainButton.clicked.connect(self.trainnet) self.newgameButton.clicked.connect(self.newgame) #self.NN = NEURAL_NETWORK(self.learning_rate, self.path, self.device) #self.mcts_tree = MCTS(self.mcts_iteration, self.NN, self.Chess_read, self.device) def updarepbar(epoch1): self.pbar.setValue(epoch1) def gendata(self): numexamples = int(self.examples.text()) gendata.get_dataset(numexamples) print(colored('Model saved','green')) def trainnet(self): with open("train.py") as f: code = compile(f.read(), "train.py", 'exec') exec(code) def selfplay(self): x = self.pathField.text() if x == '': print('no games') return else: self.itr = 1 while self.itr <= int(x): while not self.board.is_game_over(): self.pathField1.setText('#games played: '+ str(self.itr)) go = self.make_move() if go =='gameover': self.post() self.itr += 1 return print("GAME OVER: game: ",str(self.itr)) self.newgame() def newgame(self): moves = [] x1 = np.array([0]) y1 = np.array([0]) viz.line(x1,y1,update='replace',opts=layoutb,name='GrandmasterFlex - BLACK',win='GrandmasterFlex3') viz.line(x1,y1,update='replace',opts=layoutw,name='GrandmasterFlex - WHITE',win='GrandmasterFlex2') self.board.reset() s.board.reset() with open('si.pickle', 'wb') as p: pickle.dump(s, p) i = 0 with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) with open('g.pickle','wb')as g: moves = [] pickle.dump(moves, g) @Slot(QWidget) def mousePressEvent(self, event): """ Handles the left mouse click and enables moving the chess pieces by first clicking on the chess piece and then on the target square. """ if not self.board.is_game_over(): if event.x() <= self.boardSize and event.y() <= self.boardSize: if self.margin<event.x()<self.boardSize-self.margin and self.margin<event.y()<self.boardSize-self.margin: if event.buttons()==Qt.LeftButton: file = int((event.x() - self.margin) / self.squareSize) rank = 7 - int((event.y() - self.margin) / self.squareSize) square = chess.square(file, rank) piece = self.board.piece_at(square) coordinates = "{}{}".format(chr(file + 97), str(rank + 1)) if self.pieceToMove[0] is not None: move = chess.Move.from_uci("{}{}".format(self.pieceToMove[1], coordinates)) if move in self.board.legal_moves: self.board.push(move) s.board.push(move) self.lastmove = str(self.pieceToMove[1]) + str(coordinates) print('Last Move: ',self.lastmove) piece = None coordinates = None with open('rnd.pickle','rb') as rnd: i = pickle.load(rnd) i = 1 + i with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) print(colored("move: " + str(i),'yellow')) self.pieceToMove = [piece, coordinates] self.drawBoard() go = self.make_move() if go == 'gameover': print(colored(Style.BRIGHT + "********************* GAME IS OVER *********************",'red')) self.post() def drawBoard(self): """ Draw a chess board for the starting position and then redraw it for every move. """ self.svgBoard = self.board._repr_svg_().encode("UTF-8") self.svgDrawBoard = self.svgWidget.load(self.svgBoard) return self.svgDrawBoard def find_move(self,lastmove): """ Calculate the best move according to Stockfish """ #spinner = Halo(text='SEARCHING MINDSTATE',text_color='cyan', spinner='simpleDotsScrolling',color='cyan') #spinner.start() with open('si.pickle', 'rb') as f: s = pickle.load(f) try: times = float(self.engineTime.text()) except: times = float(1) self.time = times #engine = chess.engine.SimpleEngine.popen_uci(self.enginePath) #result = engine.play(self.board, chess.engine.Limit(time=self.time)) print(self.board,'\n',self.lastmove) #move, prob = self.mcts_tree.play(self.board, self.lastmove) move,s,prob = computer_move(s, v) self.engineResult.setText(str(move)) #engine.quit() #spinner.stop() return move,s, prob def make_move(self): """ Finds and plays the best move """ try: with open('rnd.pickle','rb') as rnd: i = pickle.load(rnd) i = 1 + i except: i = 0 with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) try: move,s,prob = self.find_move(self.lastmove) print(colored('move: ' + str(i),'yellow')) if (i % 2) == 0: prob1 = np.array([float(prob)]) i1 = np.array([(i/2)]) #viz.line(prob1,i1,update='append',opts=layoutb,name='GrandmasterFlex - BLACK',win='GrandmasterFlex3') plotter.plot('Round', 'Prob', 'Win Probability - Black' , i1, prob) else: prob1 = np.array([float(prob)]) i1 = np.array([(i/2)]) #viz.line(prob1,i1,update='append',opts=layoutw,name='GrandmasterFlex - WHITE',win='GrandmasterFlex2') plotter.plot('Round', 'Prob', 'Win Probability - White' , i1, prob) #print(move) nf3 = chess.Move.from_uci(move) #print('uci eq: ',nf3) #x = input('waiting') with open('g.pickle','rb')as g: moves = pickle.load(g) moves.append(move) with open('g.pickle','wb')as g: pickle.dump(moves, g) print(colored(moves,'cyan')) self.board.push(nf3) s.board.push(nf3) self.drawBoard() time.sleep(0.2) QApplication.processEvents() self.lastmove = move with open('si.pickle', 'wb') as p: pickle.dump(s, p) except: print(colored(Style.BRIGHT + "********************* GAME IS OVER *********************",'red')) #self.post() return 'gameover' def undo_move(self): """ Undo the last move played on the board """ self.board.pop() s = self self.drawBoard() def post(self): game = chess.pgn.Game() game.headers["Event"] = "GMFLEX" game.headers["Site"] = "local" game.headers["Date"] = datetime.now() game.headers["White"] = "White" game.headers["Black"] = "Black" with open('g.pickle','rb')as g: moves = pickle.load(g) i = 0 for move in moves: i += 1 if i == 1: print(move) node = game.add_variation(chess.Move.from_uci(move)) else: node = node.add_variation(chess.Move.from_uci(move)) with open('si.pickle', 'rb') as f: si = pickle.load(f) b = si.board # game over values if b.result() == "1-0": game.headers["Result"] = "1-0" winner = "WHITE" elif b.result() == "0-1": game.headers["Result"] = "0-1" winner = "BLACK" else: winner = "BLACK" win = open('winner.txt', 'a') stamp = str(datetime.now()).replace(":","_") log = open('TrainingGames/'+ stamp +".pgn", 'w') print(game, file=log, end="\n\n") try: sgame = "Final Board:\n" + str(game) except: print(colored(Style.BRIGHT + "Save Game Fail",'red')) win.write(winner + ":\n" + sgame) if winner == "BLACK": res1 = 0 res2 = 1 else: res1 = 1 res2 = 0 with open('w.pickle','rb')as w: wins = pickle.load(w) win1 = pd.DataFrame({'W':[res1],'B':[res2],'Winner':[winner]}) pd.DataFrame.append(wins,win1) with open('w.pickle','wb')as w: pickle.dump(wins,w) with open('rnd.pickle','wb') as rnd: pickle.dump(i,rnd) with open('g.pickle','wb')as g: moves = [] pickle.dump(moves, g) def update(self): """Update the gui with the current value.""" self.drawBoard()
class MainWindow(QWidget): """ Main UI Window """ def __init__(self, parent=None): """ Initialize the chess board. """ super().__init__(parent) self.setWindowTitle("PyChess") self.resize(1280, 720) self.svgWidget = QSvgWidget(parent=self) self.svgWidget.setGeometry(10, 10, 700, 700) self.boardSize = min(self.svgWidget.width(), self.svgWidget.height()) self.margin = 0.05 * self.boardSize self.squareSize = (self.boardSize - 2 * self.margin) / 8 self.board = chess.Board() self.pieceToMove = [None, None] self.drawBoard() self.enginePath = "Use double \ instead of \ when on Windows system." self.time = 0.1 self.maxtimelabel = QLabel("Max. time per move(in s):") self.engineLabel = QLabel("Enter path to engine:") self.engineButton = QPushButton("Find move") self.moveButton = QPushButton("Make move") self.undoButton = QPushButton("Undo move") self.undoButton.setMaximumWidth(175) self.pathField = QLineEdit() self.engineTime = QLineEdit() self.engineResult = QLineEdit() self.pathField.setText( "Use double \ instead of \ when on Windows system.") self.main_layout = QHBoxLayout() self.tool_layout = QGridLayout() self.tool_layout.addWidget(self.engineLabel, 0, 0) self.tool_layout.addWidget(self.pathField, 0, 1) self.tool_layout.addWidget(self.maxtimelabel, 1, 0) self.tool_layout.addWidget(self.engineTime, 1, 1) self.tool_layout.addWidget(self.engineButton, 2, 0) self.tool_layout.addWidget(self.engineResult, 2, 1) self.tool_layout.addWidget(self.moveButton, 3, 0) self.tool_layout.addWidget(self.undoButton, 3, 1) self.main_layout.addWidget(self.svgWidget, 55) self.main_layout.addLayout(self.tool_layout, 45) self.setLayout(self.main_layout) self.engineButton.clicked.connect(self.find_move) self.moveButton.clicked.connect(self.make_move) self.undoButton.clicked.connect(self.undo_move) @Slot(QWidget) def mousePressEvent(self, event): """ Handles the left mouse click and enables moving the chess pieces by first clicking on the chess piece and then on the target square. """ if event.x() <= self.boardSize and event.y() <= self.boardSize: if self.margin < event.x( ) < self.boardSize - self.margin and self.margin < event.y( ) < self.boardSize - self.margin: if event.buttons() == Qt.LeftButton: file = int((event.x() - self.margin) / self.squareSize) rank = 7 - int((event.y() - self.margin) / self.squareSize) square = chess.square(file, rank) piece = self.board.piece_at(square) coordinates = "{}{}".format(chr(file + 97), str(rank + 1)) if self.pieceToMove[0] is not None: move = chess.Move.from_uci("{}{}".format( self.pieceToMove[1], coordinates)) if move in self.board.legal_moves: self.board.push(move) piece = None coordinates = None self.pieceToMove = [piece, coordinates] self.drawBoard() def drawBoard(self): """ Draw a chess board for the starting position and then redraw it for every move. """ self.svgBoard = self.board._repr_svg_().encode("UTF-8") self.svgDrawBoard = self.svgWidget.load(self.svgBoard) return self.svgDrawBoard def find_move(self): """ Calculate the best move according to Stockfish """ self.enginePath = self.pathField.text() self.time = float(self.engineTime.text()) engine = chess.engine.SimpleEngine.popen_uci(self.enginePath) result = engine.play(self.board, chess.engine.Limit(time=self.time)) self.engineResult.setText(str(result.move)) engine.quit() return result.move def make_move(self): """ Finds and plays the best move """ move = self.find_move() self.board.push(move) self.drawBoard() def undo_move(self): """ Undo the last move played on the board """ self.board.pop() self.drawBoard()