def run(self, player, move, last_board, tree_level, is_max, tree_max_depth, use_memcache, alpha, beta, batch_size):
        new_board = ChessUtils.make_move(move, last_board)

        # Extract the set of possible moves for this level of the board.
        is_check, valid_moves = ChessUtils.get_valid_moves(player, new_board)
        
        # By default, continue recursing.
        end_recursion = False 
        # Two recursion stop conditions.
        #------- Condition #1: Recursion Depth of maximum_depth of the tree.
        #------- Condition #2: No more valid player moves.
        if tree_level >= tree_max_depth or len(valid_moves) == 0: 
            end_recursion = True
        
        
        # Ensure only one yield is generated in the case of recursions end so exit.
        if(end_recursion):
            yield common.Return((ChessUtils.get_state_utility(new_board, player, is_max,
		                                                      is_check, valid_moves), None))
        # If child modes will be generated, then generate them as a fan-out then fan them back in.
        else:
            best_util_so_far = alpha if is_max else beta
            best_util_and_move = (best_util_so_far, None)
            yield MakeMoveIter(player, new_board, tree_level, is_max, tree_max_depth, use_memcache, 
                               alpha, beta, batch_size, best_util_and_move, valid_moves)
    def run(self, player, board, tree_max_depth, use_memcache, alpha, beta, batch_size):
        
        # Extract the set of possible moves for this level of the board.
        is_check, valid_moves = ChessUtils.get_valid_moves(player, board)
        
        # Check that the game did not start in an invalid condition.
        if(is_check and len(valid_moves) == 0):
            raise ValueError("Game starting in checkmate.  That is now allowed...")
        
        # If no moves were found to be valid, return an error message.
        if(len(valid_moves) == 0):
            yield common.Return("ERROR - NO VALID MOVES")
        # If only one move is possible, return that.
        elif(len(valid_moves) == 1):
            yield common.Return((0, valid_moves[0]))
        # If there are multiple valid moves, iterate through the possible valid moves.
        else:
            
            # Determine whether white or black is going first.
            if(player == PlayerType.WHITE):
                is_max = True
            else:
                is_max = False 

            # Define the best move and util so far.
            best_util_so_far = alpha if is_max else beta
            best_util_and_move = (best_util_so_far, None)

            # Generate the Minimax tree.
            yield MakeMoveIter(player, board, 1, is_max, tree_max_depth, use_memcache,
                               alpha, beta, batch_size, best_util_and_move, valid_moves)
    def run(self, player, move, board, tree_level, is_max, depth_tree, batch_size, rationality_prob):
        if move:
            board = ChessUtils.make_move(move, board)

        # Extract the set of possible moves for this level of the board.
        is_check, valid_moves = ChessUtils.get_valid_moves(player, board)

        # By default, continue recursing.
        end_recursion = False
        # Two recursion stop conditions.
        # ------- Condition #1: Recursion Depth of 6
        # ------- Condition #2: No more valid player moves.
        if tree_level >= depth_tree or len(valid_moves) == 0:
            end_recursion = True

        # Ensure only one yield is generated in the case of recursions end so exit.
        if end_recursion:
            yield common.Return((ChessUtils.get_state_utility(board, player, is_max, is_check, valid_moves), None))
            return

        if len(valid_moves) == 1:
            yield common.Return(
                (ChessUtils.get_state_utility(board, player, is_max, is_check, valid_moves), valid_moves[0])
            )
            return

        next_player = 1 - player
        is_next_player_max = not is_max
        utilities_and_moves = []
        for new_move in valid_moves:
            utility_and_move = yield InnerExpectiMaxMakeMove(
                next_player,
                new_move,
                board,
                tree_level + 1,
                is_next_player_max,
                depth_tree,  # Required as part of the player increment.
                batch_size,
                rationality_prob,
            )
            utilities_and_moves.append(utility_and_move)
        if tree_level == 2:
            yield DetermineExpectiMaxUtilAndMove(is_max, valid_moves, rationality_prob, *utilities_and_moves)
        else:
            yield DetermineBestUtilAndMove(is_max, valid_moves, *utilities_and_moves)
def query_server(current_player, board):
    """
    Makes a request of the server to get the computer's
    move. 
    
    Params:
    current_player : Integer - 0 for white and 1 for black.
    board - List of list of integers of the pieces on the board.
    
    Returns: Tuple of two integers.  Index 0 in the Tuple is the 
    current (i.e. source) location of the piece to be moved
    while index 1 is the new (i.e. destination) location of the piece.
    """
    
    sys.stdout.write("The computer is thinking about its move  ")
    
    # Create a queue to get the computers move.
    moveQueue = Queue.Queue()

    # Use a thread to get the player's move.
    #server_thread = threading.Thread(target=execute_server_command, args=(current_player, board, moveQueue, tree_max_depth, batch_size, rationality_prob, use_expectimax))
    server_thread = threading.Thread(target=execute_server_command, args=(current_player, board, moveQueue, \
                                                                          tree_max_depth, batch_size))
    
    server_thread.start()
    # Wait for the thread to finish
    while(server_thread.is_alive()):
        sys.stdout.write("*****")
        time.sleep(1)
    sys.stdout.write("\n\n")
    
    # Handle the error case where the network communication crashed.
    if(moveQueue.empty()):
        sys.exit()
    
    computer_move = moveQueue.get(True)
    
    # Allow for two player debug
    if(two_player_debug):
        _, valid_moves = ChessUtils.get_valid_moves(current_player, board)
        computer_move = make_player_move(False, valid_moves, board) # Use player make move as a placeholder.
    return computer_move
    def run(self, player, board, depth_tree, batch_size, rationality_prob):
        # Extract the set of possible moves for this level of the board.
        is_check, valid_moves = ChessUtils.get_valid_moves(player, board)

        if is_check and len(valid_moves) == 0:
            raise ValueError("Game starting in checkmate.  That is now allowed...")

        # If no moves were found to be valid, return an error message.
        if len(valid_moves) == 0:
            yield common.Return("ERROR - NO VALID MOVES")
        # If only one move is possible, return that.
        elif len(valid_moves) == 1:
            yield common.Return((0, valid_moves[0]))
        # If there are multiple valid moves, iterate through the possible valid moves.
        else:
            # Determine whether white or black is going first.
            if player == PlayerType.WHITE:
                is_max = True
            else:
                is_max = False
            yield InnerExpectiMaxMakeMove(player, None, board, 1, is_max, depth_tree, batch_size)
def play_game(current_player, human_player, board):
    '''
    
    Params:
    current_player: Integer - 0 or 1 to indicate whether it is 
    white's or black's turn to start the game.
    
    human_player: Integer - 0 or 1 indicates whether the human player
    is white or black.  This value should not change.
    
    board: List of lists of integers.  It contains the current board.
    It will be updated at the end of each turn.
    
    Returns: 
    This function runs and never returns.  The program exits directly 
    from this function.
    ''' 
    while(True):
        
        check, valid_moves = ChessUtils.get_valid_moves(current_player, board)
        # Check if the game is over.
        if check and len(valid_moves) == 0:
            ChessUtils.print_board(board)
            print "\nCheckmate!"
            if current_player == human_player:
                print "The computer won!  You lose!"
            else:
                print "You win!"
            sys.exit(0)

        # Check if the game is over due to stalemate.
        elif(not check and len(valid_moves) == 0):
            print "\nStalemate!\n"
            print "No moves possible so its a draw!"
            sys.exit(0)
        
        # Print the current board
        print "\n\nCurrent Board:"
        ChessUtils.print_board(board)
        
        # Human's turn.
        if(current_player == human_player):
            # Keep loop until the user enters a valid move.
            next_move = make_player_move(check, valid_moves, board)

        # Computer's turn.
        else:
            if check:
                print "The computer is in check.  It must enter a move to exit check:\n"
            else:
                print "Its the computer's turn.  It is deciding on its move.\n"
            
            next_move = query_server(current_player, board)
            
            # Print the computer's move.
            print "The computer's move is:  (" + str(next_move[0]) + \
                                              ", " + str(next_move[1]) + ")\n"
        
        board = ChessUtils.make_move(next_move, board) # Apply the move.
        current_player = 1 - current_player # update the player
        
    pass