예제 #1
0
def AStarSearchBasic(game, cap):
    '''
    Uses the A* algorithm, with the same heuristic function as greedySearchBasic.
    '''

    # For more detailed docstrings, comments, see greedySearch

    def gameOver(parentState=None):
        ''' Handles what to do when a game ends. '''

        isWon = True
        if not parentState:
            print('Game could not be solved :(')
            toContinue = input('See the best the program could do? (y or n): ')
            if toContinue is not 'y':
                return None
            isWon = False
            parentState = S.findLowestState(statesToCheck.union\
                                              (statesChecked), S.hFunctionBasic)
        answerLst = S.constructPath(parentState, parentAndPathDict)
        totalTime = time() - timeA
        numOfMoves = len(answerLst)
        statesEval = counter
        S.remakeGame(firstState, answerLst)
        print(f'Number of moves in solution: {numOfMoves}')
        print(f'Total time: {totalTime} seconds')
        print(f'States evaluated: {counter}')
        return answerLst

    timeA = time()
    buckets = [set() for i in range(300)]
    statesToCheck = set()
    statesChecked = set()
    parentAndPathDict = {}
    fScores = {}
    # states --> fScores = gScores + hScores
    # hScores are same as those calculated in greedySearch
    gScores = {}
    # states --> gScores (number of moves to reach that state)
    counter = 0

    firstState = G.makeImmutableState(game)
    S.printState(firstState)
    parentAndPathDict[firstState] = None
    gScores[firstState] = 0  # since 0 moves to reach first state
    hVal = S.hFunctionBasic(firstState)
    fScores[firstState] = hVal  # since fScore = gScore + hScore = 0 + hVal
    buckets[hVal].add(firstState)
    statesToCheck.add(firstState)

    while True:
        try:
            isStateToCheck = False
            for i in range(300):
                if buckets[i]:
                    parentState = buckets[i].pop()
                    isStateToCheck = True
                    break
            counter += 1
            print(counter)

            if not isStateToCheck:  # almost impossible
                return gameOver()
            if S.game_is_won(parentState):
                return gameOver(parentState)
            if counter == cap:
                return gameOver()

            i = counter % 500000 + 160
            if i < 300 and counter > 300:
                for state in buckets[i]:
                    del fScores[state]
                    del gScores[state]
                    del parentAndPathDict[state]
                    statesToCheck.remove(state)
                buckets[i].clear()

            statesToCheck.remove(parentState)
            statesChecked.add(parentState)
            nodesGenerated = S.findSuccessorsBasic(parentState)
            for (child, move) in nodesGenerated:
                if child in statesChecked:
                    continue
                if child not in statesToCheck:
                    parentAndPathDict[child] = (parentState, move)
                    statesToCheck.add(child)
                    gVal = gScores[parentState] + 1  # Since only 1 extra move
                    gScores[child] = gVal
                    hVal = S.hFunctionBasic(child)
                    fScores[child] = gVal + hVal
                    buckets[gVal + hVal].add(child)
        except KeyboardInterrupt:
            print(f'States Evaluated: {counter}')
            print(f'Time: {time()-timeA} seconds')
            toQuit = input('Would you like to quit? (y or n): ')
            if toQuit is not 'y':
                continue
            return gameOver()
예제 #2
0
def greedySearchBasic(game, cap):
    '''
    Another greedySearch algorith using a simpler heuristic function. Only
    calculates how many cards are in the foundation for a given state, ignoring
    cycles.
    '''

    # For more detailed docstrings, comments, see greedySearch

    def gameOver(parentState=None):
        isWon = True
        if not parentState:
            print('Game could not be solved :(')
            toContinue = input('See the best the program could do? (y or n): ')
            if toContinue is not 'y':
                return None
            isWon = False
            parentState = S.findLowestState(statesToCheck.union\
                                              (statesChecked), S.hFunctionBasic)
        answerLst = S.constructPath(parentState, parentAndPathDict)
        totalTime = time() - timeA
        numOfMoves = len(answerLst)
        statesEval = counter
        S.remakeGame(firstState, answerLst)
        print(f'Number of moves in solution: {numOfMoves}')
        print(f'Total time: {totalTime} seconds')
        print(f'States evaluated: {counter}')
        return answerLst

    timeA = time()
    buckets = [set() for i in range(200)]
    statesToCheck = set()
    statesChecked = set()
    parentAndPathDict = {}
    # Notice the lack of a cycles dictionary
    hScores = {}
    counter = 0

    firstState = G.makeImmutableState(game)
    S.printState(firstState)
    parentAndPathDict[firstState] = None

    hVal = S.hFunctionBasic(firstState)
    # hFunctionBasic only counts # of cards in foundation for a state,
    # it is much simpler than hFunction used in other algorithms, which has
    # an additional argument of the set of cycles for a given state.
    hScores[firstState] = hVal
    buckets[hVal].add(firstState)
    statesToCheck.add(firstState)

    while True:
        try:
            isStateToCheck = False
            for i in range(53):
                if buckets[i]:
                    parentState = buckets[i].pop()
                    isStateToCheck = True
                    break
            counter += 1
            print(counter)

            if not isStateToCheck:
                return gameOver()
            if S.game_is_won(parentState):
                return gameOver(parentState)
            elif counter == cap:
                return gameOver()

            i = counter % 500000 + 70
            if i < 200 and counter > 200:
                for state in buckets[i]:
                    del hScores[state]
                    del parentAndPathDict[state]
                    statesToCheck.remove(state)
                buckets[i].clear()

            statesToCheck.remove(parentState)
            statesChecked.add(parentState)
            nodesGenerated = S.findSuccessorsBasic(parentState)
            # Again, findSuccessorsBasic is like findSuccessors, but
            # simpler because there is no cycle information, and therefore
            # one less argument. Also notice that it returns a list of 2-tuples,
            # as opposed to 3-tuples.
            for (child, move) in nodesGenerated:
                if child in statesChecked:
                    continue
                if child not in statesToCheck:
                    parentAndPathDict[child] = (parentState, move)
                    statesToCheck.add(child)
                    hVal = S.hFunctionBasic(child)
                    hScores[child] = hVal
                    buckets[hVal].add(child)
        except KeyboardInterrupt:
            print(f'States Evaluated: {counter}')
            print(f'Time: {time()-timeA} seconds')
            toQuit = input('Would you like to quit? (y or n): ')
            if toQuit is not 'y':
                continue
            return gameOver()