def setUp(self): self.camera = Camera(self.url) self.chessEngine = ChessEngine() self.board = 0 self.current = 0 self.previous = 0 self.CPULastMove = "0"
def __init__(self): self._loadWorld('./main.xml') self._loadSensor('./camera.rob') self.chessEngine = ChessEngine(self.world, self.world.terrain('tabletop')) self.chessEngine.loadPieces() self.chessEngine.loadBoard() self.chessEngine.arrangeBoard(90) self.chessEngine.arrangePieces() self._imageDir = 'image_dataset' self._colorDir = self._imageDir + '/color' self._depthDir = self._imageDir + '/depth' self._rectifiedDir = self._imageDir + '/rectified' self._metaDataFN = self._imageDir + '/metadata.csv' self._dirs = [ self._imageDir, self._colorDir, self._depthDir, self._rectifiedDir ] self._colorFNFormat = self._colorDir + '/%06d_%02d.png' self._depthFNFormat = self._depthDir + '/%06d_%02d.png' self._rectifiedFNFormat = self._rectifiedDir + '/%06d.png' self._rectifiedPictureCorners = np.float32( [[DataUtils.IMAGE_SIZE, 0], [0, 0], [0, DataUtils.IMAGE_SIZE], [DataUtils.IMAGE_SIZE, DataUtils.IMAGE_SIZE]]) self._boardWorldCorners = self.chessEngine.getBoardCorners()
def __init__(self): pg.init() self.screen = pg.display.set_mode((WIDTH + TF_WIDTH, HEIGHT), pg.SRCALPHA, 32) self.clock = pg.time.Clock() pg.display.set_caption(TITLE) icon = pg.image.load(IMAGE_FILE_DICT["wR"]) pg.display.set_icon(icon) self.load_data() self.engine = ChessEngine() self.AI = ChessAI(MAX_SEARCH_DEPTH)
def test_set_board(self): expected_result = [[2,3,4,5,6,4,3,2], [1,1,1,1,1,1,1,1], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [7,7,7,7,7,7,7,7], [8,9,10,11,12,10,9,8]] # Create chess engine engine = ChessEngine() engine.set_board(self.initial_board_description) self.assertEqual(engine.board, expected_result)
def test_move(self): commands_to_test = ['e4', 'e5', 'Qh5', 'Nc6', 'Bc4', 'Nf6'] expected_results = [] expected_results.append([[2,3,4,5,6,4,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [7,7,7,7,7,7,7,7], [8,9,10,11,12,10,9,8]]) expected_results.append([[2,3,4,5,6,4,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,0,0,1,0,0,0], [0,0,0,0,7,0,0,0], [0,0,0,0,0,0,0,0], [7,7,7,7,0,7,7,7], [8,9,10,11,12,10,9,8]]) expected_results.append([[2,3,4,0,6,4,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,0,0,1,0,0,0], [0,0,0,0,7,0,0,5], [0,0,0,0,0,0,0,0], [7,7,7,7,0,7,7,7], [8,9,10,11,12,10,9,8]]) expected_results.append([[2,3,4,0,6,4,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,0,0,1,0,0,10], [0,0,0,0,7,0,0,5], [0,0,0,0,0,0,0,0], [7,7,7,7,0,7,7,7], [8,9,0,11,12,10,9,8]]) expected_results.append([[2,3,4,0,6,0,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,4,0,1,0,0,10], [0,0,0,0,7,0,0,5], [0,0,0,0,0,0,0,0], [7,7,7,7,0,7,7,7], [8,9,0,11,12,10,9,8]]) expected_results.append([[2,3,4,0,6,0,3,2], [1,1,1,1,0,1,1,1], [0,0,0,0,0,0,0,0], [0,0,4,0,1,0,0,10], [0,0,0,0,7,0,0,5], [0,0,0,0,0,9,0,0], [7,7,7,7,0,7,7,7], [8,9,0,11,12,10,0,8]]) # Create chess engine engine = ChessEngine() engine.set_board(self.initial_board_description) # Movement for move, result in zip(commands_to_test, expected_results): engine.parse(move) self.assertEqual(engine.board, expected_results)
class DataGenerator: def __init__(self): self._loadWorld('./main.xml') self._loadSensor('./camera.rob') self.chessEngine = ChessEngine(self.world, self.world.terrain('tabletop')) self.chessEngine.loadPieces() self.chessEngine.loadBoard() self.chessEngine.arrangeBoard(90) self.chessEngine.arrangePieces() self._imageDir = 'image_dataset' self._colorDir = self._imageDir + '/color' self._depthDir = self._imageDir + '/depth' self._rectifiedDir = self._imageDir + '/rectified' self._metaDataFN = self._imageDir + '/metadata.csv' self._dirs = [ self._imageDir, self._colorDir, self._depthDir, self._rectifiedDir ] self._colorFNFormat = self._colorDir + '/%06d_%02d.png' self._depthFNFormat = self._depthDir + '/%06d_%02d.png' self._rectifiedFNFormat = self._rectifiedDir + '/%06d.png' self._rectifiedPictureCorners = np.float32( [[DataUtils.IMAGE_SIZE, 0], [0, 0], [0, DataUtils.IMAGE_SIZE], [DataUtils.IMAGE_SIZE, DataUtils.IMAGE_SIZE]]) self._boardWorldCorners = self.chessEngine.getBoardCorners() def _loadWorld(self, world_fn): world = WorldModel() res = world.readFile(world_fn) if not res: print("Unable to read file", world_fn) exit(0) for i in range(world.numRigidObjects()): obj = world.rigidObject(i) #this will perform a reasonable center of mass / inertia estimate m = obj.getMass() m.estimate(obj.geometry(), mass=0.454, surfaceFraction=0.2) obj.setMass(m) self.world = world def _loadSensor(self, sensor_fn): try: self.world.readFile(sensor_fn) except Exception as e: print(f'Error in loading filename: {e}') robot = self.world.robot(0) if robot is None: print("Robot is none: check sensor filename") exit(1) sensor = self.world.robot(0).sensor(0) if sensor is None: print("Sensor is none: check sensor filename") exit(1) self.robot = robot self.sensor = sensor def _createDatasetDirectory(self): for d in self._dirs: try: os.mkdir(d) except Exception: pass def deleteDataset(self): try: shutil.rmtree(self._imageDir) except OSError as e: print(f'Error deleting {self._imageDir}: {e}') def _randomlyRotateCamera(self, min_r=0, max_r=70, dist=DIST_FROM_BOARD): """ Randomly rotates camera about x-axis and zooms out from the center of the tabletop :param: min_r: the minimum random rotation in degrees :param: max_r: the maximum random rotation in degrees :param: dist: the distance to zoom out from center of the table :return: the angle of rotation sampled """ min_r = math.radians(min_r) max_r = math.radians(max_r) table_center = self.chessEngine.getTableCenter() table_R = so3.from_axis_angle(([1, 0, 0], -math.pi)) table_t = table_center rot_deg = random.uniform(min_r, max_r) zoom_out_R = so3.from_axis_angle(([1, 0, 0], rot_deg)) zoom_out_t = vectorops.mul( [0, math.sin(rot_deg), -math.cos(rot_deg)], dist) xform = se3.mul((table_R, table_t), (zoom_out_R, zoom_out_t)) sensing.set_sensor_xform(self.sensor, xform) return rot_deg def _rotateCamera(self, r, dist=DIST_FROM_BOARD): """ Rotates a camera and zooms out from center of the tabletop :param: r: rotation in degrees :param: dist: distance to zoom out from center of the table :return: angle of rotation """ return self._randomlyRotateCamera(r, r, dist) def generateImages(self, max_pics=100, data_distribution=None): assert max_pics > 0 if data_distribution is None: data_distribution = DataUtils.LIMITED_DISTRIBUTION assert len(data_distribution) == 13 self._createDatasetDirectory() for i in range(self.world.numRigidObjects()): self.world.rigidObject(i).appearance().setSilhouette(0) metadata_f = open(self._metaDataFN, mode='w+') metadata_f.write('color,depth,piece\n') DEPTH_SCALE = 8000 def loop_through_sensors(world=self.world, sensor=self.sensor, max_pics=max_pics): for counter in tqdm(range(max_pics)): if counter > 0: self.chessEngine.randomizePieces(32) # Arrange pieces and model world self.chessEngine.arrangePieces() self._randomlyRotateCamera(20, 40, 0.6) sensor.kinematicReset() sensor.kinematicSimulate(world, 0.01) rgb, depth = sensing.camera_to_images(self.sensor) # Project RGB and depth images to rectify them local_corner_coords = np.float32([ sensing.camera_project(self.sensor, self.robot, pt)[:2] for pt in self._boardWorldCorners ]) H = cv2.getPerspectiveTransform(local_corner_coords, self._rectifiedPictureCorners) color_rectified = cv2.warpPerspective( rgb, H, (DataUtils.IMAGE_SIZE, DataUtils.IMAGE_SIZE)) depth_rectified = cv2.warpPerspective( depth, H, (DataUtils.IMAGE_SIZE, DataUtils.IMAGE_SIZE)) depth_rectified = np.uint8( (depth_rectified - depth_rectified.min()) / (depth_rectified.max() - depth_rectified.min())) pieces_arrangement = self.chessEngine.getPieceArrangement() images, classes = DataUtils.split_image_by_classes( color_rectified, depth_rectified, data_distribution, pieces_arrangement) rectified_fname = self._rectifiedFNFormat % (counter) Image.fromarray(color_rectified).save(rectified_fname) for idx in range(sum(data_distribution)): color_fname = self._colorFNFormat % (counter, idx) depth_fname = self._depthFNFormat % (counter, idx) Image.fromarray(images[idx, :, :, :3]).save(color_fname) Image.fromarray(images[idx, :, :, 3]).save(depth_fname) metadata_f.write( f'{color_fname},{depth_fname},{classes[idx]}\n') vis.show(False) vis.loop(callback=loop_through_sensors) metadata_f.close()
import pygame as p from ChessEngine import ChessEngine from pygame.constants import MOUSEBUTTONDOWN p.init() boardObject = ChessEngine.Board(p) board = boardObject.board boardObject.drawBoard() boardObject.drawPieces() p.display.update() running = True position = (-1, -1) piece = (-1, -1) while running: for event in p.event.get(): if event.type == p.QUIT: running = False if event.type == p.MOUSEBUTTONDOWN: position = p.mouse.get_pos() piece = board[int(position[0] / boardObject.sqWidth)][int(position[1] / boardObject.sqHeight)] if(not boardObject.whiteTurn and piece.isWhite): piece = (-1, -1) elif(boardObject.whiteTurn and not piece.isWhite): piece = (-1, -1) if event.type == p.MOUSEBUTTONUP: if not piece == (-1, -1): nextPos = p.mouse.get_pos() if piece.move(position, nextPos, boardObject): boardObject.switchTurn()
class Game(): def __init__(self): pg.init() self.screen = pg.display.set_mode((WIDTH + TF_WIDTH, HEIGHT), pg.SRCALPHA, 32) self.clock = pg.time.Clock() pg.display.set_caption(TITLE) icon = pg.image.load(IMAGE_FILE_DICT["wR"]) pg.display.set_icon(icon) self.load_data() self.engine = ChessEngine() self.AI = ChessAI(MAX_SEARCH_DEPTH) def load_data(self): self.image_dict = {} for name in IMAGE_FILE_DICT: image = pg.image.load(IMAGE_FILE_DICT[name]) image = pg.transform.scale(image, (TILESIZE, TILESIZE)) self.image_dict[name] = image def new(self): self.piece_matrix = [x[:] for x in STARTING_PIECE_MATRIX] self.start_pos = () self.board_canvas = BoardCanvas(self) self.screen.fill(MAHOGANY) self.board_canvas.draw() self.text_panel = TextPanel() self.checked = "" self.computer_turn = False def run(self): self.running = True while self.running: self.clock.tick(FPS) if self.computer_turn: self.handle_computer_turn() self.events() self.draw() def handle_computer_turn(self): move = self.AI.search(self.piece_matrix, -sys.maxsize, sys.maxsize) piece = self.piece_matrix[move[0][0]][move[0][1]] self.move_piece(move[0], move[1], 'C') text = "Computer moved " + CHAR_TO_STR[ piece[1]] + " to " + BOARD_CANVAS_CHARS[move[1][1]] + str( 7 - move[1][0] + 1) + ". Score: " + str( move[2]) + ". Nodes: " + str( move[3][0]) + " CutOffs: " + str(move[3][1]) self.text_panel.write(text) def animate_movement(self, start_tile, end_tile, piece): current_pos = vector(start_tile[1] * TILESIZE + MARGIN, start_tile[0] * TILESIZE + MARGIN) end_pos = vector(end_tile[1] * TILESIZE + MARGIN, end_tile[0] * TILESIZE + MARGIN) direction = end_pos - current_pos direction = direction.normalize() * 8 image = self.image_dict[piece] while (end_pos.x - 10 > current_pos.x or current_pos.x > end_pos.x + 10 ) or (end_pos.y - 10 > current_pos.y or current_pos.y > end_pos.y + 10): self.clock.tick(FPS) self.events() self.draw() self.screen.blit(image, (current_pos.x, current_pos.y)) pg.display.update() current_pos += direction def move_piece(self, start_tile, end_tile, mover): if self.engine.is_move_allowed(self.piece_matrix, start_tile, end_tile): piece = self.piece_matrix[start_tile[0]][start_tile[1]] self.piece_matrix[start_tile[0]][start_tile[1]] = ".." self.animate_movement(start_tile, end_tile, piece) self.piece_matrix[end_tile[0]][end_tile[1]] = piece self.checked = "" self.computer_turn = not self.computer_turn if "P" in piece: if "w" in piece and end_tile[0] == 0: self.piece_matrix[end_tile[0]][end_tile[1]] = "wQ" elif "b" in piece and end_tile[0] == 7: self.piece_matrix[end_tile[0]][end_tile[1]] = "bQ" if mover == "P": text = "Player moved " + \ CHAR_TO_STR[piece[1]] + " to " + \ BOARD_CANVAS_CHARS[end_tile[1]] + str(7 - end_tile[0] + 1) self.text_panel.write(text) self.check_mate('b') else: self.check_mate('w') def quit(self): self.running = False pg.quit() sys.exit() def check_mate(self, color): if self.engine.check(self.piece_matrix, color): if self.engine.check_mate(self.piece_matrix, color): self.text_panel.write("Check-mate!", RED if color == 'w' else GREEN) self.GO_screen(color) else: self.text_panel.write("Check!", RED if color == 'w' else GREEN) self.checked = color # Returns the mouse positions tranlated into rows and columns of the board def get_mouse_pos_rc(self): pos = pg.mouse.get_pos() col = floor((pos[0] - MARGIN) / TILESIZE) row = floor((pos[1] - MARGIN) / TILESIZE) return (row, col) def events(self): for event in pg.event.get(): if event.type == pg.QUIT: self.quit() if event.type == pg.KEYDOWN: if event.key == pg.K_ESCAPE: self.quit() if event.key == pg.K_r: self.running = False elif event.type == pg.MOUSEBUTTONDOWN and event.button == LEFT: mouse_pos = pg.mouse.get_pos() if mouse_pos[0] > MARGIN and mouse_pos[ 0] < WIDTH - MARGIN and mouse_pos[ 1] > MARGIN and mouse_pos[ 1] < HEIGHT - MARGIN and not self.computer_turn: if self.start_pos: self.move_piece(self.start_pos, self.get_mouse_pos_rc(), 'P') self.start_pos = () else: self.start_pos = self.get_mouse_pos_rc() if "w" not in self.piece_matrix[self.start_pos[0]][ self.start_pos[1]]: self.start_pos = () elif event.type == pg.MOUSEBUTTONDOWN and event.button == RIGHT: self.start_pos = () def draw(self): self.screen.fill(MAHOGANY) self.board_canvas.draw() # Drawing pieces: for row_index, row in enumerate(self.piece_matrix): for col_index, piece in enumerate(row): if piece in self.image_dict.keys(): image = self.image_dict[piece] # Load Image # Scale image to tilesize y = MARGIN + TILESIZE * row_index x = MARGIN + TILESIZE * col_index self.screen.blit(image, (x, y)) if piece == self.checked + "K": pg.draw.rect(self.screen, DARKRED, pg.Rect(x, y, TILESIZE, TILESIZE), 4) if self.start_pos: # if start position is defined, mark it and show allowed moves mark_surface = pg.Surface((TILESIZE, TILESIZE)) mark_surface.set_alpha(80) mark_surface.fill(ORANGE) y = MARGIN + TILESIZE * self.start_pos[0] x = MARGIN + TILESIZE * self.start_pos[1] self.screen.blit(mark_surface, (x, y)) self.show_allowed_moves(self.start_pos) if self.is_mouse_over_piece() and not self.computer_turn: self.show_allowed_moves(self.get_mouse_pos_rc()) # Text field: self.screen.blit(self.text_panel.surface, (WIDTH, MARGIN)) pg.display.update() def is_mouse_over_piece(self): mouse_pos = self.get_mouse_pos_rc() for r in range(len(self.piece_matrix)): for c in range(len(self.piece_matrix[0])): if (r, c) == mouse_pos and ( r, c ) != self.start_pos and 'w' in self.piece_matrix[r][c]: return True return False def show_allowed_moves(self, pos): moves = self.engine.get_allowed_moves(self.piece_matrix, pos) if moves: for move in moves["M"]: mark_surface = pg.Surface((TILESIZE, TILESIZE)) mark_surface.set_alpha(150) y = MARGIN + TILESIZE * move[0] x = MARGIN + TILESIZE * move[1] self.screen.blit(mark_surface, (x, y)) def GO_screen(self, color): self.running = False self.draw() font = pg.font.SysFont("consolas", 40) text = "The computer won, press a key to play again." if color == 'b': text = "Congratulation you won, press a key to play again." text_surface = font.render(text, True, WHITE) self.screen.blit(text_surface, (WIDTH / 8, HEIGHT / 3)) pg.display.update() self.wait_for_key() def wait_for_key(self): pg.event.wait() waiting = True while waiting: self.clock.tick(FPS) for event in pg.event.get(): if event.type == pg.QUIT: waiting = False self.quit() if event.type == pg.KEYUP: waiting = False
import imutils from BoardRecognition import BoardRecognition from Board import Board from ChessEngine import ChessEngine from Game import Game imgpath = '../board/28.jpg' img = cv2.imread(imgpath) img = imutils.resize(img, width=500) cv2.imshow('img', img) br = BoardRecognition(img) thresh, img = br.cleanImage(img) extracted = br.initializeMask(thresh, img) edges, colorEdges = br.detectEdges(extracted) horizontal, vertical = br.detectLines(edges, colorEdges) corners = br.detectCorners(horizontal, vertical, colorEdges) squares = br.detectSquares(corners, colorEdges) board = Board(squares) board.draw(img) cv2.imshow('img2',img) board.assignState() engine = ChessEngine() engine.updateMove('a2a4') print() engine.feedToAI() #game = Game()
class Game: ''' Holds the whole game information Interacting with Board and Chess Engine ''' def __init__(self, url): self.over = False self.CPUMoveError = False self.PlayerMoveError = False self.isCheck = False self.winner = "Me" self.url = url def setUp(self): self.camera = Camera(self.url) self.chessEngine = ChessEngine() self.board = 0 self.current = 0 self.previous = 0 self.CPULastMove = "0" def analyzeBoard(self): boardRec = BoardRecognition(self.camera) self.board = boardRec.initializeBoard() self.board.assignState() def checkBoardIsSet(self): self.current = self.camera.takePicture() cv2.imwrite('./ProcessImage/SetUpBoard.jpg', self.current) def playerMove(self): self.previous = self.current self.current = self.camera.takePicture() move = self.board.determineChanges(self.previous, self.current) code = self.chessEngine.updateMove(move) print('Your move:', move) if code == 1: # Illegal move self.PlayerMoveError = True else: self.PlayerMoveError = False f = open('./Gamelog/Game.txt', 'a+') f.write(chess.Move.from_uci(move).uci() + '\r\n') f.close() # Check game over if self.chessEngine.engBoard.is_checkmate(): self.winner = 'You win' self.over = True def playerPromotion(self, move): print(move) code = self.chessEngine.updateMove(move) if code == 1: # Illegal print('Error') self.PlayerMoveError = True else: self.PlayerMoveError = False f = open('./Gamelog/Game.txt', 'a+') f.write(chess.Move.from_uci(move).uci() + '\r\n') f.close() if self.chessEngine.engBoard.is_checkmate(): self.winner = 'You win' self.over = True def CPUMove(self): self.CPULastMove = self.chessEngine.feedToAI() self.isCheck = self.chessEngine.engBoard.is_check() copy = self.current.copy() if len(self.CPULastMove.uci()) == 4: position1 = self.CPULastMove.uci()[:2] position2 = self.CPULastMove.uci()[2:] CPUMoveSquares = [] for square in self.board.squares: if square.position == position1 or square.position == position2: CPUMoveSquares.append(square) CPUMoveSquares[0].draw(copy, (255, 0, 0), 2) CPUMoveSquares[1].draw(copy, (255, 0, 0), 2) cv2.imwrite('./ProcessImage/CPUMove.jpg', copy) if self.chessEngine.engBoard.is_checkmate(): self.winner = 'CPU win' self.over = True return self.CPULastMove def updateCurrent(self): self.previous = self.current self.current = self.camera.takePicture() move = self.board.determineChanges(self.previous, self.current) move = chess.Move.from_uci(move) print('Your move for cpu:', move) print('Cpu move:', self.CPULastMove) # Check if player moved CPU piece correctly if move == self.CPULastMove: self.CPUMoveError = False else: self.CPUMoveError = True
def __init__(self, max_depth): self.color = "b" self.max_depth = max_depth self.engine = ChessEngine()
class ChessAI(): def __init__(self, max_depth): self.color = "b" self.max_depth = max_depth self.engine = ChessEngine() def search(self, board, alfa, beta, is_maximizer=True, depth=0, is_root=True, N_C=[0, 0]): """ returns a tuple containing: (start_pos, end_pos, score, visited_nodes) """ # Beta is the minimizing players value # alfa is the maximizing player value. N_C[0] += 1 if depth >= self.max_depth: return self.engine.board_score(board, self.color) elif is_maximizer: moves = self.engine.get_all_moves_dict(board, self.color) best_score = -0.1 for start_pos in moves: for end_pos in moves[start_pos]: board_with_move = [row[:] for row in board] self.engine.move(board_with_move, start_pos, end_pos) score = self.search(board_with_move, alfa, beta, is_maximizer=False, depth=depth + 1, is_root=False, N_C=N_C) alfa = max(alfa, best_score) if alfa >= beta: N_C[1] += 1 return best_score if best_score == -0.1 or score > best_score: best_move = end_pos best_score = score result = (start_pos, end_pos, best_score, N_C) if is_root: return result return best_score else: moves = self.engine.get_all_moves_dict( board, 'w' if self.color == 'b' else 'b') best_score = 99999999 for start_pos in moves: for end_pos in moves[start_pos]: board_with_move = [row[:] for row in board] self.engine.move(board_with_move, start_pos, end_pos) best_score = min( best_score, self.search(board_with_move, alfa, beta, is_maximizer=True, depth=depth + 1, is_root=False, N_C=N_C)) beta = min(beta, best_score) if alfa >= beta: N_C[1] += 1 return best_score return best_score
boardPhase.board_status[254-i]=tmp if boardPhase.player == 0: boardPhase.player = 1 else: boardPhase.player = 0 return """ computer_first = False pygame.mixer.pre_init(44100, 16, 2, 4096) pygame.init() boardWindow = BoardWindow(computer_first) boardPhase = MCTSBoardPhase() #boardPhase = BoardPhase() boardWindow.drawBoard(boardPhase) chessEngine = ChessEngine(3) stop = False train_flag = True while True: if train_flag: pygame.event.pump() ret = boardWindow.computer_move(boardPhase, chessEngine) if not ret: boardPhase.reset() else: if computer_first and boardPhase.getSide() == 0 and not stop: if not boardWindow.computer_move(boardPhase, chessEngine): stop = True game_input(pygame.event.get(), boardWindow, boardWindow, chessEngine) boardWindow.drawBoard(boardPhase) pygame.display.flip()
def __init__(self): self.state = UserInterface.STATE_WAITING_FOR_START_POS self.engine = ChessEngine() self.startingPos = np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 1, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8) if sys.platform == 'darwin': self.cv = MockCV() UserInterface.ROTATIONS_RIGHT = 0 else: self.cv = ChessCV() self.cv.continuous = True thread.start_new_thread(self.cvThread, (self,)) self.boardscan = np.ndarray(shape=(8,8), dtype=np.int8) self.boardscan.fill(0) self.chess = None self.lastFullScreenToggle = 0 self.boardScale = 2 self.considering = [] self.lastConsider = None self.requestedMove = None self.dirtyUi = True pygame.init() #self.screen = pygame.display.set_mode((800, 800)) #self.screen = pygame.display.set_mode((1824, 1016)) self.screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) self.bgimage = pygame.image.load("./img/background.png") self.light_sabers = pygame.image.load("./img/light_sabers2.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.checkmate_suckah = pygame.image.load("./img/headings/checkmate_suckah.png") self.my_turn = pygame.image.load("./img/headings/my_turn.png") self.my_turn_move_piece = pygame.image.load("./img/headings/my_turn_move_piece.png") self.one_moment_please = pygame.image.load("./img/headings/one_moment_please.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.your_turn = pygame.image.load("./img/headings/your_turn.png") self.your_turn_cheater = pygame.image.load("./img/headings/your_turn_cheater.png") self.check = pygame.image.load("./img/bottom_headers/check.png") self.checkmate_suckah = pygame.image.load("./img/bottom_headers/checkmate_suckah.png") self.topHeading = None self.bottomHeading = None self.boardbg = self.loadImage("board_v2.gif") self.pieces = {} self.pieces['r'] = self.loadImage("br.png") self.pieces['n'] = self.loadImage("bn.png") self.pieces['b'] = self.loadImage("bb.png") self.pieces['k'] = self.loadImage("bk.png") self.pieces['q'] = self.loadImage("bq.png") self.pieces['p'] = self.loadImage("bp.png") self.pieces['R'] = self.loadImage("wr.png") self.pieces['N'] = self.loadImage("wn.png") self.pieces['B'] = self.loadImage("wb.png") self.pieces['K'] = self.loadImage("wk.png") self.pieces['Q'] = self.loadImage("wq.png") self.pieces['P'] = self.loadImage("wp.png") pygame.display.flip()
class UserInterface: ROTATIONS_RIGHT = 2 STATE_WAITING_FOR_START_POS = 0 STATE_WAITING_FOR_BOARD_CHANGE = 1 STATE_WAITING_FOR_ENGINE = 2 STATE_GAME_OVER = 3 def __init__(self): self.state = UserInterface.STATE_WAITING_FOR_START_POS self.engine = ChessEngine() self.startingPos = np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 1, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8) if sys.platform == 'darwin': self.cv = MockCV() UserInterface.ROTATIONS_RIGHT = 0 else: self.cv = ChessCV() self.cv.continuous = True thread.start_new_thread(self.cvThread, (self,)) self.boardscan = np.ndarray(shape=(8,8), dtype=np.int8) self.boardscan.fill(0) self.chess = None self.lastFullScreenToggle = 0 self.boardScale = 2 self.considering = [] self.lastConsider = None self.requestedMove = None self.dirtyUi = True pygame.init() #self.screen = pygame.display.set_mode((800, 800)) #self.screen = pygame.display.set_mode((1824, 1016)) self.screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) self.bgimage = pygame.image.load("./img/background.png") self.light_sabers = pygame.image.load("./img/light_sabers2.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.checkmate_suckah = pygame.image.load("./img/headings/checkmate_suckah.png") self.my_turn = pygame.image.load("./img/headings/my_turn.png") self.my_turn_move_piece = pygame.image.load("./img/headings/my_turn_move_piece.png") self.one_moment_please = pygame.image.load("./img/headings/one_moment_please.png") self.would_you_like_to_play = pygame.image.load("./img/headings/would_you_like_to_play.png") self.your_turn = pygame.image.load("./img/headings/your_turn.png") self.your_turn_cheater = pygame.image.load("./img/headings/your_turn_cheater.png") self.check = pygame.image.load("./img/bottom_headers/check.png") self.checkmate_suckah = pygame.image.load("./img/bottom_headers/checkmate_suckah.png") self.topHeading = None self.bottomHeading = None self.boardbg = self.loadImage("board_v2.gif") self.pieces = {} self.pieces['r'] = self.loadImage("br.png") self.pieces['n'] = self.loadImage("bn.png") self.pieces['b'] = self.loadImage("bb.png") self.pieces['k'] = self.loadImage("bk.png") self.pieces['q'] = self.loadImage("bq.png") self.pieces['p'] = self.loadImage("bp.png") self.pieces['R'] = self.loadImage("wr.png") self.pieces['N'] = self.loadImage("wn.png") self.pieces['B'] = self.loadImage("wb.png") self.pieces['K'] = self.loadImage("wk.png") self.pieces['Q'] = self.loadImage("wq.png") self.pieces['P'] = self.loadImage("wp.png") pygame.display.flip() def loadImage(self, file): img = pygame.image.load("./img/%s" % file).convert(32, pygame.SRCALPHA) rect = img.get_rect() return pygame.transform.smoothscale(img, (int(rect.w * self.boardScale), int(rect.h * self.boardScale))) def getFont(self, size): return pygame.font.SysFont("freesans", size, bold=True) def mainLoop(self): clock = pygame.time.Clock() self.renderBoard() while 1: clock.tick(30) for event in pygame.event.get(): if event.type == QUIT: return elif event.type == KEYDOWN: print event.key if event.key == K_ESCAPE: return if event.key == 102: # F if time.time() - self.lastFullScreenToggle > 1: self.lastFullScreenToggle = time.time() pygame.display.toggle_fullscreen() if event.key == 32: # space self.cv.snapshot = True if event.key == 49: # 1 self.cv.set_board(self.startingPos.copy()) if event.key == 50: # 2 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) if event.key == 51: # 3 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1, 0,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0,-1, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) if event.key == 52: # 4 self.cv.set_board(np.array( [[-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1,-1, 0,-1,-1,-1,-1], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 1, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0], [ 1, 1, 1, 1, 0, 1, 1, 1], [ 1, 1, 1, 1, 1, 1, 1, 1]], np.int8)) self.gameTick() def gameTick(self): self.updateConsideringLine() if self.state == UserInterface.STATE_WAITING_FOR_START_POS: if np.array_equal(self.boardscan, self.startingPos): print "NEW GAME: Creating chess board" self.chess = ChessBoard() self.lastBoardscan = self.boardscan self.engine.newGame() self.topHeading = self.your_turn self.dirtyUi = True self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE elif self.state == UserInterface.STATE_WAITING_FOR_ENGINE: if self.engine.bestmove is not None: self.requestedMove = self.engine.bestmove self.considering = [] self.state = UserInterface.STATE_WAITING_FOR_BOARD_CHANGE self.topHeading = self.my_turn_move_piece self.dirtyUi = True self.renderBoard() elif self.state == UserInterface.STATE_WAITING_FOR_BOARD_CHANGE: changes = self.boardscan - self.lastBoardscan numChanges = np.count_nonzero(changes) if numChanges == 2 or numChanges == 3 or numChanges == 4: self.dirtyUi = True print "" print "changes:\n" + str(changes) moveFrom = () moveTo = () nonzeroChanges = changes.nonzero() print "nonzeroChanges: " + str(nonzeroChanges) print "len(nonzeroChanges[0]) = %d" % len(nonzeroChanges[0]) for i in range(len(nonzeroChanges[0])): change = (nonzeroChanges[1][i], nonzeroChanges[0][i]) value = changes[change[1], change[0]] colorBefore = self.lastBoardscan[change[1], change[0]] print "\tchange: %s\tvalue: %s\tcolorBefore: %s" % (str(change), value, colorBefore) if self.chess.getTurn() == ChessBoard.WHITE: # WHITE's turn if value == -1: if numChanges != 4 or (change == (4,7)): moveFrom = change else: if numChanges == 4: if change == (6,7) or change == (2,7): moveTo = change elif numChanges == 3: if colorBefore == 0: moveTo = change else: moveTo = change else: # BLACK's turn if value == 1: if numChanges != 4 or (change == (4,0)): print "setting moveFrom to ", change moveFrom = change else: if numChanges == 4: if change == (6,0) or change == (2,0): print "setting moveTo to ", change moveTo = change elif numChanges == 3: if colorBefore == 0: print "setting moveTo to ", change moveTo = change else: moveTo = change print "moveFrom: " + str(moveFrom) print "moveTo: " + str(moveTo) if moveFrom and moveTo: print "getTurn before:", self.chess.getTurn() result = self.chess.addMove(moveFrom, moveTo) print "getTurn after:", self.chess.getTurn() if result is False: print "Could not make move: ", self.chess.getReason() else: lastMove = string.replace(self.chess.getLastTextMove(ChessBoard.AN), '-', '') cheater = False if self.requestedMove is not None and self.requestedMove != lastMove: cheater = True if self.chess.isCheck(): print "**** CHECK ****" self.bottomHeading = self.check else: self.bottomHeading = None self.requestedMove = None self.lastBoardscan = self.boardscan self.chess.printBoard() print "Last move type: " + str(self.chess.getLastMoveType()) print "New FEN: " + self.chess.getFEN() # Check if game is over if self.chess.isGameOver(): result = self.chess.getGameResult() if result == ChessBoard.WHITE_WIN: print "**** WHITE WINS ****" elif result == ChessBoard.BLACK_WIN: print "**** BLACK WINS ****" self.bottomHeading = self.checkmate_suckah else: print "**** STALEMATE ****" self.state = UserInterface.STATE_GAME_OVER elif self.chess.getTurn() == ChessBoard.BLACK: # It's black's turn, engage the engine self.topHeading = self.one_moment_please self.engine.makeMove(self.chess.getFEN()) self.state = UserInterface.STATE_WAITING_FOR_ENGINE else: if cheater: self.topHeading = self.your_turn_cheater else: self.topHeading = self.your_turn self.renderBoard() elif numChanges != 0: print "Invalid number of board changes: ", numChanges self.cv.reset_board() # Set boardscan to the last one just so we don't keep analyzing it until next scan comes in self.boardscan = self.lastBoardscan self.renderBoard() def updateConsideringLine(self): now = time.time() engine_considering = self.engine.considering if self.state == UserInterface.STATE_WAITING_FOR_ENGINE and engine_considering is not None: if len(self.engine.considering) > 0: latest = engine_considering[0] if len(latest) == 0: engine_considering.pop() self.considering = [] self.updateConsideringLine() return self.considering.append(latest.pop()) self.lastConsider = now self.dirtyUi = True self.renderBoard() def renderBoard(self): if not self.dirtyUi: return self.dirtyUi = False self.screen.blit(self.bgimage, (0,0)) if self.chess is None: self.screen.blit(self.would_you_like_to_play, (587, 395)) pygame.display.flip() return files = 'abcdefgh' boardOffsetX = 64 boardOffsetY = 64 square_size = self.pieces['r'].get_rect().w # First the background bgsize = self.boardbg.get_rect().w for y in range(4): for x in range(4): self.screen.blit(self.boardbg, (boardOffsetX+x*bgsize, boardOffsetY+y*bgsize)) # Render the pieces y = 0 for rank in self.chess.getBoard(): x = 0 for p in rank: if p != '.': self.screen.blit(self.pieces[p],(boardOffsetX+x*square_size, boardOffsetY+y*square_size)) x += 1 y += 1 # Heading if self.topHeading is not None: self.screen.blit(self.topHeading, (1105, 84)) # Sabers self.screen.blit(self.light_sabers, (1105, 84 + 140)) # Render considering moves (if any) if len(self.considering) > 0: for move in self.considering: x1 = boardOffsetX+files.find(move[0])*square_size+int(square_size/2) y1 = boardOffsetY+((8-int(move[1]))*square_size)+int(square_size/2) x2 = boardOffsetX+files.find(move[2])*square_size+int(square_size/2) y2 = boardOffsetY+((8-int(move[3]))*square_size)+int(square_size/2) pygame.draw.line(self.screen, (164, 119, 131), (x1,y1), (x2,y2), 15) pygame.draw.circle(self.screen, (127, 91, 102), (x1,y1), 15) pygame.draw.circle(self.screen, (127, 91, 102), (x2,y2), 15) # Render requested move (if any) if self.requestedMove is not None: x1 = boardOffsetX+files.find(self.requestedMove[0])*square_size+int(square_size/2) y1 = boardOffsetY+((8-int(self.requestedMove[1]))*square_size)+int(square_size/2) x2 = boardOffsetX+files.find(self.requestedMove[2])*square_size+int(square_size/2) y2 = boardOffsetY+((8-int(self.requestedMove[3]))*square_size)+int(square_size/2) pygame.draw.line(self.screen, (229, 72, 84), (x1,y1), (x2,y2), 15) pygame.draw.circle(self.screen, (173, 58, 75), (x2,y2), 15) # Redraw piece on "from" square so line comes from underneath it (but covers other pieces, potentially) y = 8-int(self.requestedMove[1]) x = files.find(self.requestedMove[0]) piece = self.chess.getBoard()[y][x] self.screen.blit(self.pieces[piece],(boardOffsetX+x*square_size, boardOffsetY+y*square_size)) # Bottom heading if self.bottomHeading is not None: self.screen.blit(self.bottomHeading, (1105, 84 + 140 + 165 + 403)) # Render chess moves color = (255, 255, 255) x = 1105 startY = 84 + 140 + 165 y = startY font = self.getFont(20) allMoves = self.chess.getAllTextMoves(ChessBoard.LAN) if allMoves is not None: whiteMoves = allMoves[0::2] blackMoves = allMoves[1::2] num = 1 for move in whiteMoves: txt = "%d. %s" % (num, move) if num < 10: txt = " " + txt fs = font.render(txt, True, color) self.screen.blit(fs, (x, y)) y += 25 num = num + 1 if y > startY + 403: break x += 200 y = startY for move in blackMoves: fs = font.render(move, True, color) self.screen.blit(fs, (x, y)) y += 25 if y > startY + 403: break pygame.display.flip() def cvThread(self, cv): while True: try: if self.state == UserInterface.STATE_WAITING_FOR_BOARD_CHANGE or self.state == UserInterface.STATE_WAITING_FOR_START_POS: if self.cv.continuous == True or self.cv.snapshot == True: self.cv.snapshot = False sys.stdout.write('.') sys.stdout.flush() board = self.cv.current_board() if board is not None: self.boardscan = np.rot90(board, UserInterface.ROTATIONS_RIGHT) except Exception, e: print e time.sleep(0.25)