def minvalue(state, maxdepth, alpha=None, beta=None): """ The minvalue function for the adversarial tree search. """ board = state[0] turn = state[1] if is_terminal(state, maxdepth): return utility(state) else: v = float('inf') (moves, captures) = crank.get_hints(board, turn) if captures: for a in captures: v = min(v, maxvalue(transition(state, a, "jump"), \ maxdepth, alpha, beta)) if alpha is not None and beta is not None: if v <= alpha: return v beta = min(beta, v) return v elif moves: for a in moves: v = min(v, maxvalue(transition(state, a, "move"), \ maxdepth, alpha, beta)) if alpha is not None and beta is not None: if v <= alpha: return v beta = min(beta, v) return v
def is_terminal(state, maxdepth=None): """ Determines if a tree node is a terminal or not. Returns boolean True/False. """ board = state[0] turn = state[1] depth = state[2] (moves, captures) = crank.get_hints(board, turn) if maxdepth is not None: return ((not moves) and (not captures)) or depth >= maxdepth else: return ((not moves) and (not captures))
def minimax_search(state, maxdepth=None): """ The depth limited minimax tree search. """ board = state[0] turn = state[1] (moves, captures) = crank.get_hints(board, turn) if captures: return max([(a, minvalue(transition(state, a, "jump"), maxdepth)) \ for a in captures], key = lambda v: v[1]) elif moves: return max([(a, minvalue(transition(state, a, "move"), maxdepth)) \ for a in moves], key = lambda v: v[1]) else: return ("pass", -1)
def alphabeta_search(state, maxdepth=None): """ The depth limited alpha-beta tree search, it's 2-times faster than the minimax search. """ board = state[0] turn = state[1] (moves, captures) = crank.get_hints(board, turn) alpha = float('-inf') beta = float('inf') if captures: return max([\ (a, minvalue(transition(state, a, "jump"), \ maxdepth, alpha, beta)) \ for a in captures], key = lambda v: v[1]) elif moves: return max([\ (a, minvalue(transition(state, a, "move"), \ maxdepth, alpha, beta)) \ for a in moves], key = lambda v: v[1]) else: return ("pass", -1)