def loadGame(self, jsonText):
        jsonData = json.loads(jsonText, encoding = "utf-8")
        game = Game(jsonData)

       # init state
        self.game = game
        self.gameField = game.startField
        self.rndGenerator = Random(game.sourceSeeds[0])

        self.unitIndex = self.rndGenerator.next() % len(self.game.units)
        self.currentUnit = self.game.units[self.unitIndex]
        self.currentUnitOffsets = self.game.unitStartOffsets[self.unitIndex]
        self.currentUnitRotation = 0
        self.lastCleanedLines = 0
        self.score = 0

        self.drawField()
        drawUnit(self.scene, self.currentUnit, self.currentUnitOffsets)
        return
class VizFrame(QtGui.QWidget):
    def __init__(self):
        super(VizFrame, self).__init__()
        self.initUI()

        self.currentFile = "test_data/problem_23.json"
        self.loadFileData(self.currentFile)


    def initUI(self):

        self.setGeometry(300,300,250,150)
        self.setWindowTitle('Event handler')
        self.resize(800, 600)

        grview = QGraphicsView(self)
        self.scene = QGraphicsScene()
        grview.setScene(self.scene)
        grview.resize(640, 480)

        sidebar = QWidget(self)
        sidebarLayout = QVBoxLayout()
        sidebar.move(640, 0)
        sidebar.setFixedWidth(160)

        self.srcTextEdit = QTextEdit(self)
        self.srcTextEdit.setFixedHeight(100)
        self.solTextEdit = QTextEdit(self)
        self.solTextEdit.setFixedHeight(100)

        panel = QWidget(self)
        panel.setGeometry(QRect(640, 100, 160, 40))
        panelButtons = QHBoxLayout(self)

        btnLoad = QPushButton ("Load")
        def onLoadClick():
            jsonStr = str(self.srcTextEdit.toPlainText())
            self.loadGame(jsonStr)
            return
        btnLoad.clicked.connect(onLoadClick)

        btnPrev = QPushButton ("<<")
        def onPrevClick():
            dir = os.path.dirname(self.currentFile)
            file = os.path.basename(self.currentFile)
            files = filter(lambda f: fnmatch.fnmatch(f, '*.json'), os.listdir(dir))
            jsonFile = files[files.index(file) - 1]
            self.loadFileData(os.path.join(dir, jsonFile))
        btnPrev.clicked.connect(onPrevClick)
        btnNext = QPushButton (">>")
        def onNextClick():
            dir = os.path.dirname(self.currentFile)
            file = os.path.basename(self.currentFile)
            files = filter(lambda f: fnmatch.fnmatch(f, '*.json'), os.listdir(dir))
            jsonFile = files[files.index(file) + 1]
            self.loadFileData(os.path.join(dir, jsonFile))
        btnNext.clicked.connect(onNextClick)

        panelButtons.addWidget(btnPrev)
        panelButtons.addWidget(btnLoad)
        panelButtons.addWidget(btnNext)
        panel.setLayout(panelButtons)

        btnPlay = QPushButton("Play")
        def onPlayClick():
            solStr = str(self.solTextEdit.toPlainText())
            self.play(solStr)
            return
        btnPlay.clicked.connect(onPlayClick)

        btnSolve = QPushButton("Solve")
        def onSolveClick():
            solver = icfp_solver.Solver(self.game)
            solStr = solver.solve(self.game.sourceSeeds[0])
            solStr = self.game.makeCommands(self.game.sourceSeeds[0], [solStr])
            self.solTextEdit.setText(solStr)
            return
        btnSolve.clicked.connect(onSolveClick)

        sidebarLayout.addWidget(self.srcTextEdit)
        sidebarLayout.addWidget(panel)
        sidebarLayout.addWidget(self.solTextEdit)
        sidebarLayout.addWidget(btnPlay)
        sidebarLayout.addWidget(btnSolve)
        sidebar.setLayout(sidebarLayout)

        self.show()
        return

    def keyPressEvent(self, e):
        if e.key() == QtCore.Qt.Key_Space:
            self.nextUnit()
        elif e.key() == QtCore.Qt.Key_S:
            self.makeMove(MoveType.RC)
        elif e.key() == QtCore.Qt.Key_W:
            self.makeMove(MoveType.RCC)
        elif e.key() == QtCore.Qt.Key_Q:
            self.makeMove(MoveType.W)
        elif e.key() == QtCore.Qt.Key_E:
            self.makeMove(MoveType.E)
        elif e.key() == QtCore.Qt.Key_A:
            self.makeMove(MoveType.SW)
        elif e.key() == QtCore.Qt.Key_D:
            self.makeMove(MoveType.SE)
        return

    def makeMove(self, moveType):
        (_a, o, r) = self.game.makeMove(self.gameField , self.currentUnit, self.currentUnitOffsets, self.currentUnitRotation, moveType)
        result = True
        if _a:
            self.currentUnitOffsets = o
            self.currentUnitRotation = r
        else:
            # lock unit
            cells = self.currentUnit.moveAndRotate(self.currentUnitOffsets, self.currentUnitRotation)
            self.gameField = self.gameField.fillCells(cells)
            [self.game.filledCells.append(c) for c in cells]

            # clear lines
            lines = self.gameField.countLines()
            if lines > 0:
                self.gameField = self.gameField.cleanLines()

            # calculate score
            points = len(self.currentUnit.members) + 100 * (1 + lines) * lines / 2
            if self.lastCleanedLines > 1:
                line_bonus =  math.floor((self.lastCleanedLines - 1) * points / 10)
            else:
                line_bonus = 0
            move_score = points + line_bonus
            self.lastCleanedLines = lines
            self.score += move_score
            print("Score: ", move_score, self.score)

            # spawn next unit
            self.nextUnit()
            cells = self.currentUnit.moveAndRotate(self.currentUnitOffsets, self.currentUnitRotation)
            result = self.gameField.checkCells(cells)

        self.redraw()
        return result

    def loadGame(self, jsonText):
        jsonData = json.loads(jsonText, encoding = "utf-8")
        game = Game(jsonData)

       # init state
        self.game = game
        self.gameField = game.startField
        self.rndGenerator = Random(game.sourceSeeds[0])

        self.unitIndex = self.rndGenerator.next() % len(self.game.units)
        self.currentUnit = self.game.units[self.unitIndex]
        self.currentUnitOffsets = self.game.unitStartOffsets[self.unitIndex]
        self.currentUnitRotation = 0
        self.lastCleanedLines = 0
        self.score = 0

        self.drawField()
        drawUnit(self.scene, self.currentUnit, self.currentUnitOffsets)
        return

    def loadFileData(self, file):
        self.currentFile = file
        with open(self.currentFile) as data_file:
            data = data_file.read()
            self.srcTextEdit.setText(data)
            self.loadGame(data)


    def nextUnit(self):
        self.unitIndex = self.rndGenerator.next() % len(self.game.units)
        self.currentUnit = self.game.units[self.unitIndex]
        self.currentUnitOffsets = self.game.unitStartOffsets[self.unitIndex]
        self.currentUnitRotation = 0
        self.drawField()
        drawUnit(self.scene, self.currentUnit, self.currentUnitOffsets)
        return

    def drawField(self):
        w = self.game.startField.width
        h = self.game.startField.height
        self.scene.clear()
        for x in xrange(0, w):
            for y in xrange(0, h):
                drawHex(self.scene, x, y, not self.gameField.field[y, x])

        return

    def redraw(self):
        self.drawField()
        drawUnit(self.scene, self.currentUnit, self.currentUnitOffsets, self.currentUnitRotation)
        return

    def play(self, solStr):
        moveCount = 0
        for c in solStr.lower():
            moveCount += 1
            if (c not in ['\r', '\n', '\t']):
                move = MoveType.fromChar(c)
                res = self.makeMove(move)
                if not res:
                    break
            QtGui.QApplication.processEvents()
        print "moves {0} / {1}".format(moveCount, len(solStr))
        return
 def convert(self, str, seed):
     rnd = Random(seed + 1)
     return "".join([MoveType.toChars[s][rnd.next() % len(MoveType.toChars[s])] for s in str])
 def makeCommands(self, seed, default_commands, einificate = True):
     """
     main method - should return sequence of commands
     """
     self.rndGenerator = Random(seed)
     unitIndex = self.rndGenerator.next() % len(self.units)
     currentUnit = self.units[unitIndex]
     currentOffset = self.unitStartOffsets[unitIndex]
     currentRotation = 0
     currentField = self.startField
     cmds = self.strToCommands(default_commands[0])
     valid_commands = []
     previousWasBad = False
     last_cmd = MoveType.IGN
     unitsCounter = 0
     while(True):
         if previousWasBad:
             break
         cmd_index = -1
         for cmd in cmds:
             cmd_index = (cmd_index + 1) % len(cmds)
             (moveResult, newOffset, newRotation, cmd2) = self.substituteMove(currentField, currentUnit, currentOffset, currentRotation, cmd)
             if moveResult:
                 if einificate and cmd2 == MoveType.SW and last_cmd != MoveType.W:
                     #print "eification"
                     offset = currentOffset
                     rotation = currentRotation
                     eiResult = True
                     for ei in self.strToCommands("Ei!"):
                         (mr, offset, rotation) = self.makeMove(currentField, currentUnit, offset, rotation, ei)
                         if not mr:
                             eiResult = False
                             break
                     if eiResult:
                         valid_commands.append("Ei!")
                         #print "eificated"
                     else:
                         if cmd2 == cmd:
                             valid_commands.append(default_commands[0][cmd_index])
                         else:
                             valid_commands.append(cmd2)
                 else:
                     if cmd2 == cmd:
                         valid_commands.append(default_commands[0][cmd_index])
                     else:
                         valid_commands.append(cmd2)
                 previousWasBad = False
                 currentOffset = newOffset
                 currentRotation = newRotation
                 last_cmd = cmd2
             else:
                 #todo: spawn new Unit here
                 if previousWasBad:
                     break
                 valid_commands.append(default_commands[0][cmd_index])
                 previousWasBad = True
                 if unitsCounter >= self.sourceLength:
                     break
                 currentField = currentField.fillCells(currentUnit.moveAndRotate(currentOffset, currentRotation)).cleanLines()
                 unitIndex = self.rndGenerator.next() % len(self.units)
                 currentUnit = self.units[unitIndex]
                 currentOffset = self.unitStartOffsets[unitIndex]
                 currentRotation = 0
                 unitsCounter += 1
     #return "".join([
     #    default_commands[0] for i in range(len(valid_commands) // len(default_commands[0]))]) + default_commands[0][:(len(valid_commands) % len(default_commands[0]))]
     return "".join(valid_commands)
class Game(object):
    def __init__(self, data):
        logging.debug("in game construction")
        logging.debug(data)
        self.startField = Field(**data)
        self.filledCells = [Cell(**cell_info) for cell_info in data["filled"]]
        self.sourceLength = data["sourceLength"]
        self.sourceSeeds = data["sourceSeeds"]
        self.id = data["id"]
        self.startField = self.startField.fillCells(self.filledCells)
        self.units = [Unit(**unit_info) for unit_info in data["units"]]
        self.unitStartOffsets = [self.startField.computePivotStartOffset(unit) for unit in self.units]
    def convert(self, str, seed):
        rnd = Random(seed + 1)
        return "".join([MoveType.toChars[s][rnd.next() % len(MoveType.toChars[s])] for s in str])
        ##following line is an example of cells emptyness check:
        #print self.startField.fillCells([Cell({"x":1, "y":1})]).checkCells([Cell({"x":1, "y":1})])
    def process(self, phrasesOfPower):
        return [Solution(self.id, seed, self, phrasesOfPower) for seed in self.sourceSeeds]
    def makeMove(self, currentField, unit, currentOffset, currentRotation, moveType):
        """
        performs move for current unit and checks it position in currentField
        """
        newOffset = currentOffset
        newRotation = currentRotation
        if moveType == MoveType.W:
            newOffset = Cell.fromTriplet(currentOffset.toTriplet().west())
        if moveType == MoveType.E:
            newOffset = Cell.fromTriplet(currentOffset.toTriplet().east())
        if moveType == MoveType.SE:
            newOffset = Cell.fromTriplet(currentOffset.toTriplet().southEast())
        if moveType == MoveType.SW:
            newOffset = Cell.fromTriplet(currentOffset.toTriplet().southWest())
        if moveType == MoveType.RC:
            newRotation = (currentRotation + 1) % 6
        if moveType == MoveType.RCC:
            newRotation = (currentRotation - 1) % 6
        #next - check if unit can be placed at new position
        cells = unit.moveAndRotate(newOffset, newRotation)
        moveResult = currentField.checkCells(cells)
        return (moveResult, newOffset, newRotation)
    def strToCommands(self, str):
        return filter(lambda x: x!= MoveType.IGN, [MoveType.fromChar(ch) for ch in str])
    def substituteMove(self, currentField, currentUnit, currentOffset, currentRotation, cmd):
        for cmd2 in [cmd, MoveType.SE, MoveType.SW, MoveType.RC, MoveType.RCC, MoveType.E, MoveType.W]:
            (moveResult, newOffset, newRotation) = self.makeMove(currentField, currentUnit, currentOffset, currentRotation, cmd)
            if moveResult:
                return (moveResult, newOffset, newRotation, cmd2)
        return (False, currentOffset, currentRotation, cmd)
    def makeCommands(self, seed, default_commands, einificate = True):
        """
        main method - should return sequence of commands
        """
        self.rndGenerator = Random(seed)
        unitIndex = self.rndGenerator.next() % len(self.units)
        currentUnit = self.units[unitIndex]
        currentOffset = self.unitStartOffsets[unitIndex]
        currentRotation = 0
        currentField = self.startField
        cmds = self.strToCommands(default_commands[0])
        valid_commands = []
        previousWasBad = False
        last_cmd = MoveType.IGN
        unitsCounter = 0
        while(True):
            if previousWasBad:
                break
            cmd_index = -1
            for cmd in cmds:
                cmd_index = (cmd_index + 1) % len(cmds)
                (moveResult, newOffset, newRotation, cmd2) = self.substituteMove(currentField, currentUnit, currentOffset, currentRotation, cmd)
                if moveResult:
                    if einificate and cmd2 == MoveType.SW and last_cmd != MoveType.W:
                        #print "eification"
                        offset = currentOffset
                        rotation = currentRotation
                        eiResult = True
                        for ei in self.strToCommands("Ei!"):
                            (mr, offset, rotation) = self.makeMove(currentField, currentUnit, offset, rotation, ei)
                            if not mr:
                                eiResult = False
                                break
                        if eiResult:
                            valid_commands.append("Ei!")
                            #print "eificated"
                        else:
                            if cmd2 == cmd:
                                valid_commands.append(default_commands[0][cmd_index])
                            else:
                                valid_commands.append(cmd2)
                    else:
                        if cmd2 == cmd:
                            valid_commands.append(default_commands[0][cmd_index])
                        else:
                            valid_commands.append(cmd2)
                    previousWasBad = False
                    currentOffset = newOffset
                    currentRotation = newRotation
                    last_cmd = cmd2
                else:
                    #todo: spawn new Unit here
                    if previousWasBad:
                        break
                    valid_commands.append(default_commands[0][cmd_index])
                    previousWasBad = True
                    if unitsCounter >= self.sourceLength:
                        break
                    currentField = currentField.fillCells(currentUnit.moveAndRotate(currentOffset, currentRotation)).cleanLines()
                    unitIndex = self.rndGenerator.next() % len(self.units)
                    currentUnit = self.units[unitIndex]
                    currentOffset = self.unitStartOffsets[unitIndex]
                    currentRotation = 0
                    unitsCounter += 1
        #return "".join([
        #    default_commands[0] for i in range(len(valid_commands) // len(default_commands[0]))]) + default_commands[0][:(len(valid_commands) % len(default_commands[0]))]
        return "".join(valid_commands)