Search code examples
pythonrecursiongeneratorminimax

Trouble with Python generators in recursive implementation of minimax


I am working on an implementation of minimax algorithm to solve 2048. I am facing problems when iterating over a list of objects, and passing this value to recursive functions. The code is :

def MAXIMIZE(state,deep):
if deep == 10:
    return (None,greed(state))

tup = (None, -1000000) #maxChild, maxUtility 
moves = state.getAvailableMoves()
#children by moves
children = []
children.append(state.clone().move(m) for m in moves)
for child in children:
    temp,utility = MINIMIZE(child,deep + 1)
    if utility > tup[1]:
        tup = (child, utility)

return tup
def MINIMIZE(state,deep):
if deep == 10:
    return (None, greed(state))
tup = (None, +10000000)

cells = state.getAvailableCells() # this is where I get an error - "'generator' object has no attribute 'getAvailableCells'"

children = []
children.append(state.clone().setCellValue(cell, 2) for cell in cells)
for child in children:
    temp,utility = MAXIMIZE(child,deep + 1)
    if utility < tup[1]:
        tup = (child,utility)
return tup

In the MINIMIZE function the line - cells = state.getAvailableCells() gives "'generator' object has no attribute 'getAvailableCells'" Can anyone please help me figure this out? (I am a student of physics and have limited knowledge of Python. I went to various existing questions but couldn't understand much.)


Solution

  • Here

    children = []
    children.append(state.clone().move(m) for m in moves)
    

    You create an empty list, then add one single element to it, this element being a generator (created by the state.clone().move(m) for m in moves generator expression).

    What you want is a list expression instead - replace those two lines with:

    children = [state.clone().move(m) for m in moves)]
    

    This will evaluate the generator and build and populate a list from it.

    Note that you have the same problem here:

    children = []
    children.append(state.clone().setCellValue(cell, 2) for cell in cells)
    

    which requires the same fix:

    children = [state.clone().setCellValue(cell, 2) for cell in cells]