def _optimal_placement_helper(state, depth=config.MAX_DEPTH, alpha=-inf, beta=inf): ''' Helper function for optimal_placement's recursion. Returns the max/min value taking that path can produce. ''' global wincount global losscount global zerocount state.winner = gamestate.check_for_victory(state) #Return the score of a win, modified by the depth (to encourage continuing) if state.winner != 0: if state.winner > 0: wincount += 1 return config.PLAYERWIN - depth elif state.winner < 0: losscount += 1 return config.COMPWIN + depth if state.num_pieces >= (config.MAX_PIECES * 2): return _optimal_move_helper(state, depth) available_spots = _all_possible_placements(state) if state.turn == 0: #Player's turn v = alpha for spot in [x - 1 for x in available_spots]: #Make next iteration's state copystate = copy.deepcopy(state) copystate.board[spot] = 'p' copystate.num_pieces += 1 copystate.turn = 1 #Use new state in the next iteration v_prime = _optimal_placement_helper(copystate, depth-1, v, beta) if v_prime > v: v = v_prime if v > beta: return beta return v else: #Computer's turn v = beta for spot in [x - 1 for x in available_spots]: #Make next iteration's state copystate = copy.deepcopy(state) copystate.board[spot] = 'c' copystate.num_pieces += 1 copystate.turn = 0 #Use new state in the next iteration v_prime = _optimal_placement_helper(copystate, depth-1, alpha, v) if v_prime < v: v = v_prime if v < alpha: return alpha return v
def _optimal_move_helper(state, depth=config.MAX_DEPTH, alpha=-inf, beta=inf): state.winner = gamestate.check_for_victory(state) global wincount global losscount global zerocount #Max depth, just return 0. See config note for this. if state.winner != 0: if state.winner > 0: wincount += 1 return config.PLAYERWIN - depth elif state.winner < 0: losscount += 1 return config.COMPWIN + depth elif depth <= 0: zerocount += 1 return 0 available_moves = _all_possible_moves(state) ''' This loop makes a copy of the state for each possible destination, moves the piece to that destination, and updates the statedict to the proper value for that move. ''' if state.turn == 0: v = alpha for move in available_moves: #source is the source piece's location, adjusted to be 0-indexed source = move[0] #dests is a list of destinations source can move to, adjusted to be 0-indexed dests = move[1:] for dest in dests: #constructing the next iteration's state copystate = copy.deepcopy(state) copystate.board[source - 1] = '-' copystate.board[dest - 1] = 'p' copystate.turn = 1 #running the next iteration v_prime = _optimal_move_helper(copystate, depth-1, v, beta) if v_prime > v: v = v_prime if v > beta: return beta return v else: v = inf for move in available_moves: #source is the source piece's location, adjusted to be 0-indexed source = move[0] #dests is a list of destinations source can move to, adjusted to be 0-indexed dests = move[1:] for dest in dests: #constructing the next iteration's state copystate = copy.deepcopy(state) copystate.board[source - 1] = '-' copystate.board[dest - 1] = 'c' copystate.turn = 0 #Running the next iteration v_prime = _optimal_move_helper(copystate, depth-1, alpha, v) if v_prime < v: v = v_prime if v < alpha: return alpha return v