def utility(self, board): "Return the utility of the specified board" val = 0 boardTuple = board rowCtr = 0 for row in boardTuple: col = 0 for piece in row: if CheckerBoard.isplayer(self.maxplayer, piece): val += 1 if CheckerBoard.isking(piece): #if a king val += 2 if (row == 3 & col == 4) | (row == 4 & col == 3): #if player has control of center val += 3 val += board.disttoking( self.maxplayer, rowCtr) #if player closer to king row if CheckerBoard.isplayer( self.minplayer, piece): #same heuristics but for other player val -= 1 if CheckerBoard.isking(piece): val -= 2 if (row == 3 & col == 4) | (row == 4 & col == 3): val -= 3 val += board.disttoking(self.minplayer, rowCtr) col += 1 rowCtr += 1 return val
class Game: def __init__(self, size: tuple, p1, p2, win_length): self.checkerboard = CheckerBoard(size) self.p1 = p1 self.p2 = p2 self.win_length = min(size[0], win_length) def __str__(self): return str(self.checkerboard) def play(self): player = self.p1 while len(self.checkerboard.empty_locations) > 0: try: loc = player.next_loc(self.checkerboard, self.win_length) self.checkerboard.move(player.color, loc) print(self.checkerboard) except Exception as ex: print(ex) return 0 if self.checkerboard.judge(player.color, self.win_length): return player.color player = self._next(player) return 0 def _next(self, player): if player == self.p1: return self.p2 else: return self.p1 def refresh(self): self.checkerboard = CheckerBoard(self.checkerboard.size)
def setup(self, nrows, nrows_center = None, check_width = None, check_width_center = None, screen_background_color = 'neutral-gray', show_fixation_dot = False, flash_rate_left = DEFAULT_FLASH_RATE, flash_rate_right = DEFAULT_FLASH_RATE, flash_rate_center = DEFAULT_FLASH_RATE, #rate_compensation = None, inv_gamma_func = None, vsync_patch = 'bottom-right', ): Screen.setup(self, background_color = screen_background_color, vsync_patch = vsync_patch, ) # check if we are rendering center board if flash_rate_center == None: self.render_center = False else: self.render_center = True # unless otherwise specified, center checkerboard will be same as others if nrows_center == None: nrows_center = nrows if check_width_center == None: check_width_center = check_width # set checkerboard-related attributes if check_width is None: check_width = 2.0/nrows #fill whole screen self.board_width = check_width*nrows if self.render_center: self.board_width_center = check_width_center * nrows_center self.nrows = nrows self.CB_left = CheckerBoard(nrows, check_width, show_fixation_dot = show_fixation_dot) self.CB_right = CheckerBoard(nrows, check_width, show_fixation_dot = show_fixation_dot) #reversed pattern if self.render_center: self.CB_center = CheckerBoard(nrows_center, check_width_center, show_fixation_dot = False)#show_fixation_dot) # set time-related attributes self.overall_start_time = None self.flash_rate_left = flash_rate_left self.flash_rate_right = flash_rate_right if self.render_center: self.flash_rate_center = flash_rate_center #self.rate_compensation = rate_compensation self.inv_gamma_func = inv_gamma_func #for removing gamma correction # get useful coordinate values for checkerboard rendering locations self.xC, self.yC = (-0.5*self.board_width,-0.5*self.board_width) self.xL, self.yL = (self.xC - 0.7*self.screen_right, self.yC) self.xR, self.yR = (self.xC + 0.7*self.screen_right, self.yC) # quantities for checking things self.r1_list = [] self.t_list = []
def edgePieces(self, board): ''' How many pieces do I have on the edges ''' pieces = 0 playerIndex = CheckerBoard.playeridx(self.maxplayer) for row, column, piece in board: playeridx, king = CheckerBoard.identifypiece(piece) if playeridx == playerIndex: if row is 0 or column is 0 or row is 7 or column is 7: pieces += 1 return pieces
def totalPieces(self, board): ''' How many pieces do I have - how many does the other player have ''' pieces = 0 playerIndex = CheckerBoard.playeridx(self.maxplayer) for row, column, piece in board: playeridx, king = CheckerBoard.identifypiece(piece) if playeridx == playerIndex: pieces += 1 else: pieces -= 1 return pieces
def pieceDefense(self, board): defense = 0 playerIndex = CheckerBoard.playeridx(self.maxplayer) for row, column, piece in board: playeridx, king = CheckerBoard.identifypiece(piece) if playeridx == playerIndex: if not king: defense += self.positionDefense(board, row, column) defense += self.kingDefense(board, row, column) #else: # if not king: # defense -= self.positionDefense(board, row, column) # defense -= self.kingDefense(board, row, column) return defense
def distanceToKings(self, board): ''' How far is each side from being "Kinged" ''' distance = 0 playerIndex = CheckerBoard.playeridx(self.maxplayer) for row, column, piece in board: playeridx, king = CheckerBoard.identifypiece(piece) if playeridx == playerIndex: if not king: distance -= board.disttoking(self.maxplayer, row) #else: # if not king: # distance += board.disttoking(self.minplayer, row) return distance
def minvalue(self, depth, state, alpha, beta): self.depthLvl += 1 isDone = CheckerBoard.is_terminal(state) if isDone[0]: v = self.strategy.utility(state) #if terminal state elif self.depthLvl >= depth: #if cutoff depth hit v = float('inf') actions = state.get_actions(self.maxP) for a in actions: #choose move at depth newboard = state.move(a) w = self.strategy.utility(newboard) v = min(v, w) else: #if neither, then keep searching v = float("inf") actions = state.get_actions(self.minP) for a in actions: newboard = state.move(a) v = min(v, self.maxvalue(depth, newboard, alpha, beta)) if v <= alpha: break else: beta = max(alpha, v) return v
def next_loc(self, checkerboard: CheckerBoard, win_length: int) -> Location: wins = {} state = checkerboard.state if len(checkerboard.empty_locations) > 0: locations = set(checkerboard.empty_locations) for loc in locations: res = self.simulate(checkerboard, loc, self.color, self.depth, win_length) checkerboard.state = state wins[loc] = res print(loc, res) return min(wins, key=lambda k: (wins[k][-1 * self.color]) / (sum(wins[k].values()))) else: raise Exception
def simulate(self, checkerboard: CheckerBoard, loc: Location, color: int, depth: int, win_length: int): res = {1: 0, -1: 0, 0: 0} checkerboard.move(color, loc) if checkerboard.judge(color, win_length): # win the game res[color] += 1 return res elif depth == 0: # random play player = player1 = Player(-color) player2 = Player(color) while True: try: loc = player.next_loc(checkerboard, win_length) checkerboard.move(player.color, loc) except: res[0] += 1 return res if checkerboard.judge(player.color, win_length): res[player.color] += 1 return res player = player == player1 and player2 or player1 else: state = checkerboard.state locations = set(checkerboard.empty_locations) if len(locations) > 0: for loc in locations: result = self.simulate(checkerboard, loc, -color, depth - 1, win_length) res[0] += result[0] res[1] += result[1] res[-1] += result[-1] checkerboard.state = state else: return res return res
def __init__(self, size: tuple, p1, p2, win_length): self.checkerboard = CheckerBoard(size) self.p1 = p1 self.p2 = p2 self.win_length = min(size[0], win_length)
def refresh(self): self.checkerboard = CheckerBoard(self.checkerboard.size)
class TripleCheckerBoardSinFlasher(Screen): def setup(self, nrows, nrows_center = None, check_width = None, check_width_center = None, screen_background_color = 'neutral-gray', show_fixation_dot = False, flash_rate_left = DEFAULT_FLASH_RATE, flash_rate_right = DEFAULT_FLASH_RATE, flash_rate_center = DEFAULT_FLASH_RATE, #rate_compensation = None, inv_gamma_func = None, vsync_patch = 'bottom-right', ): Screen.setup(self, background_color = screen_background_color, vsync_patch = vsync_patch, ) # check if we are rendering center board if flash_rate_center == None: self.render_center = False else: self.render_center = True # unless otherwise specified, center checkerboard will be same as others if nrows_center == None: nrows_center = nrows if check_width_center == None: check_width_center = check_width # set checkerboard-related attributes if check_width is None: check_width = 2.0/nrows #fill whole screen self.board_width = check_width*nrows if self.render_center: self.board_width_center = check_width_center * nrows_center self.nrows = nrows self.CB_left = CheckerBoard(nrows, check_width, show_fixation_dot = show_fixation_dot) self.CB_right = CheckerBoard(nrows, check_width, show_fixation_dot = show_fixation_dot) #reversed pattern if self.render_center: self.CB_center = CheckerBoard(nrows_center, check_width_center, show_fixation_dot = False)#show_fixation_dot) # set time-related attributes self.overall_start_time = None self.flash_rate_left = flash_rate_left self.flash_rate_right = flash_rate_right if self.render_center: self.flash_rate_center = flash_rate_center #self.rate_compensation = rate_compensation self.inv_gamma_func = inv_gamma_func #for removing gamma correction # get useful coordinate values for checkerboard rendering locations self.xC, self.yC = (-0.5*self.board_width,-0.5*self.board_width) self.xL, self.yL = (self.xC - 0.7*self.screen_right, self.yC) self.xR, self.yR = (self.xC + 0.7*self.screen_right, self.yC) # quantities for checking things self.r1_list = [] self.t_list = [] def start_time(self,t): # get start time and set current CB objects (and their change times) Screen.start_time(self,t) self._color_func_left = self._get_color_func(start_time = t, flash_rate = self.flash_rate_left, shape = "sin", inv_gamma_func = self.inv_gamma_func, ) self._color_func_right = self._get_color_func(start_time = t, flash_rate = self.flash_rate_right, shape = "sin", inv_gamma_func = self.inv_gamma_func, ) self._color_func_center = self._get_color_func(start_time = t, flash_rate = self.flash_rate_center, shape = "square", inv_gamma_func = self.inv_gamma_func, ) def render(self): # do general OpenGL stuff as well as FixationCross and Vsync Patch if needed Screen.render(self) # translate to position of left board and render gl.glLoadIdentity() gl.glTranslatef(self.xL, self.yL, 0.0) self.CB_left.render() # translate to position of right board and render gl.glLoadIdentity() gl.glTranslatef(self.xR, self.yR, 0.0) self.CB_right.render() # render center board if self.render_center: gl.glLoadIdentity() gl.glTranslatef(-self.board_width_center / 2.0, -self.board_width_center / 2.0, 0.0) self.CB_center.render() def update(self, t, dt): self.ready_to_render = True # render on every Screen.pygame_display_loop loop # update check colors on left checkerboard c1, c2 = self._color_func_left(t) self.CB_left.color1 = c1 self.CB_left.color2 = c2 # get some values for checking what was displayed self.r1_list.append(c1[0]) self.t_list.append(t-self.t0) # update check colors on right checkerboard c1, c2 = self._color_func_right(t) self.CB_right.color1 = c1 self.CB_right.color2 = c2 # update check colors on center checkerboard if self.render_center: c1, c2 = self._color_func_center(t) self.CB_center.color1 = c1 self.CB_center.color2 = c2 def _get_color_func(self, start_time, flash_rate, shape="sin", inv_gamma_func = None, ): color_func = None # get color functions if shape == "sin": # Contrasts will go from 0 and 1 at flash_rate Hz, # that is the half-cycle of full contrast change # to which the SSVEP is sensitive. # The intensities are inverse gamma corrected. def color_func(t): te = t - start_time # compute elapsed time cos_term = np.cos(flash_rate * np.pi * te) / 2.0 c1 = (-cos_term + 0.5) c2 = ( cos_term + 0.5) if not inv_gamma_func is None: c1 = float(inv_gamma_func(c1)) c2 = float(inv_gamma_func(c2)) return ((c1,c1,c1), (c2,c2,c2)) elif shape == "square": def color_func(t): te = t - start_time # compute elapsed time c = -1.0 * np.cos(flash_rate * np.pi * te) / 2.0 if c > 0.0: return ((1.0,1.0,1.0), (0.0,0.0,0.0)) else: return ((0.0,0.0,0.0), (1.0,1.0,1.0)) else: raise ValueError("shape = '%s' is not valid, try 'sin' or 'square'" % shape) return color_func def run(self, **kwargs): # loop rate set too high so that it should run effectively as fast as python is capable of looping Screen.run(self, display_loop_rate = 10000, **kwargs)
def Game(red=ai.Strategy, black=tonto.Strategy, maxplies=5, init=None, verbose=True, firstmove=0): """Game(red, black, maxplies, init, verbose, turn) Start a game of checkers red,black - Strategy classes (not instances) maxplies - # of turns to explore (default 10) init - Start with given board (default None uses a brand new game) verbose - Show messages (default True) firstmove - Player N starts 0 (red) or 1 (black). Default 0. """ # Don't forget to create instances of your strategy, # e.g. black('b', checkerboard.CheckerBoard, maxplies) ### Still unsure what firstmove is supposed to do ### # Initialize board if init is None: board = CheckerBoard() # New game else: board = init # Initialize board to given config # Display Board if verbose: print('Initial Board:') print(board, '\n') # Initialize Players red = red('r', board, maxplies) black = black('b', board, maxplies) # Start playing while not board.is_terminal()[0]: # Nobody has won yet state = red.play(board) # Get tuple of new board following an action and the action itself board = state[0] action = state[1] if verbose and action is not None: print('Red Move: ', board.get_action_str(action)) print(board) # Player has forfeited -> exit loop if action is None: print('Red Player has forfeited the game') break if not board.is_terminal()[0]: # Still nobody has won yet state = black.play(board) # Get tuple of new board following an action and the action itself board = state[0] action = state[1] if verbose and action is not None: print('Black Move: ', board.get_action_str(action)) print(board) # Player has forfeited -> exit loop if action is None: print('Black Player has forfeited the game') break if (board.is_terminal()[1] == 'r'): print('Red Player wins') elif (board.is_terminal()[1] == 'b'): print('Black Player wins') else: print('Game has ended in a stalemate')
def testEdgePieces(self): testBoard = CheckerBoard() redplayer = AI.Strategy('r', CheckerBoard(), 8) self.assertEqual( redplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for red starting board. Count was: ' + str(redplayer.totalPieces(testBoard))) blackplayer = AI.Strategy('b', CheckerBoard(), 8) self.assertEqual( blackplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for red starting board. Count was: ' + str(redplayer.totalPieces(testBoard))) testBoard.clearboard() testBoard.place(0, 1, 'r') testBoard.update_counts() self.assertEqual( redplayer.totalPieces(testBoard), 1, 'AI.totalPieces failed for red one piece board. Count was: ' + str(redplayer.totalPieces(testBoard))) self.assertEqual( blackplayer.totalPieces(testBoard), -1, 'AI.totalPieces failed for black one piece board. Count was: ' + str(blackplayer.totalPieces(testBoard))) testBoard.place(0, 3, 'b') testBoard.update_counts() self.assertEqual( redplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for red two piece board. Count was: ' + str(redplayer.totalPieces(testBoard))) self.assertEqual( blackplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for black two piece board. Count was: ' + str(blackplayer.totalPieces(testBoard))) testBoard.place(0, 5, 'R') testBoard.update_counts() self.assertEqual( redplayer.totalPieces(testBoard), 1, 'AI.totalPieces failed for red three piece board. Count was: ' + str(redplayer.totalPieces(testBoard))) self.assertEqual( blackplayer.totalPieces(testBoard), -1, 'AI.totalPieces failed for black three piece board. Count was: ' + str(blackplayer.totalPieces(testBoard))) testBoard.place(0, 7, 'B') testBoard.update_counts() self.assertEqual( redplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for red four piece board. Count was: ' + str(redplayer.totalPieces(testBoard))) self.assertEqual( blackplayer.totalPieces(testBoard), 0, 'AI.totalPieces failed for black four piece board. Count was: ' + str(blackplayer.totalPieces(testBoard)))