import pwnlib

dimensions = [4,4,10]

ZERO = False
ONE = True

# check if board is all 0s
def winningboard(board):
    for elem in board:
        if elem == ONE:
            return False
    return True

# xors two boards, result is a new board (originals unchanged)
def xorboard(boardA, boardB):
    newBoard = []
    for i in range(len(boardA)):
        newBoard.append(boardA[i] != boardB[i])
    return newBoard

# read a board from pipe, return representation with True/False
def readboard(pipe, dimension):
    move = []
    for _ in range(dimension):
        line = pipe.recvline()
        #print(line)
        for field in line.split(b" "):
            if field == b"0" or field == b"0\n":
                move.append(ZERO)
            elif field == b"1" or field == b"1\n":
                move.append(ONE)
            else:
                print("assumption fail: ")
                print(line)
                print(field)
                quit()
    return move

# search recursively for solutions
def recursive_search(currentBoard, moves, maxindex):
    for i in range(maxindex):
        board = xorboard(currentBoard, moves[i][0])
        if winningboard(board):
            return [i]
        result = recursive_search(board, moves, i)
        if result != None:
            return result + [i]
    return None
        

fridge = pwnlib.tubes.remote.remote("ppc-fridge.ctfz.one", 31337)

# do all this once per stage
for stage in range(len(dimensions)):
    dim = dimensions[stage]
    moves= []
    before = readboard(fridge, dim)
    # does all possible moves once, records the changes they make
    for x in range(dim):
        for y in range(dim):
            move_str = "{0},{1}".format(x,y)
            fridge.sendline(move_str)
            after = readboard(fridge, dim)
            moves.append((xorboard(before, after),move_str,))
            before = after
    # from the current board, find a solution
    moves_list = recursive_search(before, moves, len(moves))
    if moves_list == None:
        print("ERROR: No moves found")
        quit()
    print("BEFORE: ",before)
    # apply moves, skipping the last one because it doesn't print a board
    for i in moves_list[:-1]:
        print(moves[i][1])
        fridge.sendline(moves[i][1])
        print(readboard(fridge, dim))
    # handle last move
    print(moves[-1][1])
    fridge.sendline(moves[-1][1])
    print(fridge.recvline())    # this one is solved

fridge.interactive()