Friday, February 5, 2016

TTT Enumeration Process Complete

I got busy and distracted for a while, but I think it gave my brain the time it needed to process things and find a more efficient method for enumerating the valid game states. Unfortunately, I didn't comment this code as I went, and now that it's done I don't want to go back and comment it. But this seemed to work, and the basic idea was to mimic the behavior of nested for-next loops. I created a function to increment any list because that allowed me to apply the same code to both the X positions and the O positions. (For some reason, when I was working on the code, I ended up calling the players X and Y, not X and O. I don't know why.)

There ended up being 5889 valid game states. There are some redundancies in this list based on either rotational or reflective symmetry, but I'm okay with that. There are enough game states to make this a little bit interesting. I'll have to think about how I'm going to handle that much data, especially as I start getting into calculations. I'm going to have to think about that one for a while.

Here's the (uncommented) code:

maxNum = 8

def nextInd(myList, big):
    length = len(myList)
    done = 0
    depth = 0
    while done == 0:
        if depth == length:
            done = -1
        elif myList[length-1-depth] < big - depth:
            myList[length-1-depth] += 1
            for i in range(0, depth):
                myList[length-depth+i] = myList[length-depth-1] + i + 1
            done = 1
        else:
            depth += 1
    return myList, done

def init(length):
    myList = [0] * length
    for i in range(0,length):
        myList[i] = i
    return myList

def CheckXWin(game):
    winner = 0
    if game[0]*game[1]*game[2] == 1 \
      or game[3]*game[4]*game[5] == 1 \
      or game[6]*game[7]*game[8] == 1 \
      or game[0]*game[3]*game[6] == 1 \
      or game[1]*game[4]*game[7] == 1 \
      or game[2]*game[5]*game[8] == 1 \
      or game[0]*game[4]*game[8] == 1 \
      or game[2]*game[4]*game[6] == 1:
        winner = 1
    elif game[0]*game[1]*game[2]*game[3]*game[4]*game[5]*game[6]*game[7]*game[8] > 0:
        winner = -1
    return winner

def CheckYWin(game):
    winner = 0
    if game[0]*game[1]*game[2] == 8 \
      or game[3]*game[4]*game[5] == 8 \
      or game[6]*game[7]*game[8] == 8 \
      or game[0]*game[3]*game[6] == 8 \
      or game[1]*game[4]*game[7] == 8 \
      or game[2]*game[5]*game[8] == 8 \
      or game[0]*game[4]*game[8] == 8 \
      or game[2]*game[4]*game[6] == 8:
        winner = 2
    elif game[0]*game[1]*game[2]*game[3]*game[4]*game[5]*game[6]*game[7]*game[8] > 0:
        winner = -1
    return winner

def dispGame(game):
    gameChar = []
    for i in range(0,9):
        if game[i] == 0:
            gameChar.append(" ")
        elif game[i] == 1:
            gameChar.append("X")
        elif game[i] == 2:
            gameChar.append("O")
        else:
            gameChar.append("Something bad happened!")
    print
    print " {} | {} | {}".format(gameChar[0], gameChar[1], gameChar[2])
    print "---+---+---"
    print " {} | {} | {}".format(gameChar[3], gameChar[4], gameChar[5])
    print "---+---+---"
    print " {} | {} | {}".format(gameChar[6], gameChar[7], gameChar[8])
    print

for numX in range(1,6):
    for numY in range(numX - 1, numX + 1):
        if numY < 5:
            XPos = init(numX)
            YPos = [0] * numY
            XLoop = 1
            while XLoop == 1:
                remaining = init(9)
                for i in XPos:
                    remaining.remove(i)
                YList = init(numY)
                for i in range(0,numY):
                    YPos[i] = remaining[YList[i]]
                YLoop = 1
                while YLoop == 1:
                    game = [0]*9
                    XWin = 0
                    YWin = 0
                    for i in XPos:
                        game[i] = 1
                    for i in YPos:
                        game[i] = 2
                    XWin = CheckXWin(game)
                    YWin = CheckYWin(game)
                    print "XPos = {}, YPos = {}, XWin = {}, YWin = {}".format(XPos, YPos, XWin, YWin)
                    if not (XWin == 1 and YWin == 2):
                        if XWin == 1:
                            winner = 1
                        elif YWin == 2:
                            winner = 2
                        elif (XWin == -1 and YWin == -1):
                            winner = -1
                        else:
                            winner = 0
                        print "Saving... winner = {}".format(winner)
                        f = open("TTTValidGames.txt", "a")
                        for item in game:
                            f.write(str(item))
                            f.write(" ")
                        f.write(str(winner))
                        f.write("\n")
                        f.close()

                    YList, YLoop = nextInd(YList, len(remaining)-1)
                    if YLoop == 1:
                        for i in range(0,numY):
                            YPos[i] = remaining[YList[i]]
                XPos, XLoop = nextInd(XPos, maxNum)

No comments:

Post a Comment