#!/usr/bin/env python
# coding: utf
'''
'''

class Proto:
    '''Протокол игры в крестики-нолики'''
    version = 0.02
    debug = False

    def cell(self, x, y, field=None):
        '''Содержимое клетки (или "E", если coord неправильные)'''
        field = field or self.field
        if  0<=x<self.size and 0<=y<self.size:
            return field[y][x]
        else:
            return "E"

    def diff(self, board1, board2):
        '''Чем board1 отличается от board2'''
        s=self.size
        return [(x,y,board2[x+y*s]) for x in xrange(s) for y in xrange(s) if board1[x+y*s]!=board2[x+y*s]]

    def check(self, who=None):
        '''Проверить, не выиграл ли кто
        Возвращает "X", "O", "DRAW" (ничья) и "NEXT" (пока никто)
        Выигрыш противника не проверяется!
        '''
        if not self.pos: return "."
        x, y = self.pos
        if not who: who = self.last
        swin = who*self.win
        seq = xrange(-self.win+1,self.win)
        lines = (
                    "".join((self.cell(x+i,y) for i in seq)),
                    "".join((self.cell(x,y+i) for i in seq)),
                    "".join((self.cell(x+i,y+i) for i in seq)),
                    "".join((self.cell(x+i,y-i) for i in seq)),
                 )
        for line in lines:
            if swin in line:
               self.winner = who
               return "ENDGAME {}".format(who)
        if self.count == self.size**2:
            self.winner = "DRAW"
            return "ENDGAME DRAW"
        return "NEXT"

    def INIT(self, size, win=0):
        '''(size[, win=size]) Начать игру на поле size*size, длина выигрышной комбинации win'''
        self.size  = int(size)
        self.field = [["." for i in xrange(self.size)] for j in xrange(self.size)]
        self.win = int(win) or self.size
        self.last = "O"
        self.pos = None
        self.count = 0
        self.winner = None
        return "OK"

    def SET(self, board, x, y):
        '''(board, x, y) Задать игровое состояние board, последний ход x,y'''
        pos = int(x),int(y)
        field = [[c for c in board[self.size*i:self.size*(i+1)]] for i in xrange(self.size)]
        last = self.cell(x,y,field)
        if last not in "XO":
            return "ERROR PLACEMENT"
        l,c1,c2 = last == "O", board.count("X"), board.count("O")
        if l and c1 != c2 or not l and c1 != c2+1:
            return "ERROR COUNT"
        self.field=field
        self.last = last
        self.pos = pos
        self.count = self.size*self.size - board.count(".")
        self.winner = None
        return "OK"

    def MOVE(self, coord, who):
        '''(coord, who) Сделать ход фигурой who на поле coord'''
        if self.winner:
            return "ERROR ENDGAME {}".format(self.winner)
        who = who.upper()
        if self.last == who or who not in "XO":
            return "ERROR TURN"
        if type (coord) is str:
            x, y = coord.replace(",", " ").split()
        else:
            x, y = coord
        x, y = int(x), int(y)

        if self.field[y][x] != ".":
            return "ERROR OCCUPIED"
        self.last = who
        self.pos = x,y
        self.field[y][x] = who
        self.count += 1
        return self.check()

    def INFO(self):
        '''Показать информацию об игре'''
        b="".join(("".join((c for c in l)) for l in self.field))
        return "GAME {} {} {} {}".format(self.size, self.win, self.last, b)

    def BOARD(self):
        '''Показать игровое поле'''
        b="\n".join(("".join((c for c in l)) for l in self.field))
        return "FIELD\n{}".format(b)

    def HELP(self):
        '''Помощь по командам'''
        ret = "COMMANDS"
        for cmd in dir(self):
            if cmd == cmd.upper():
                ret+="\n{} {}".format(cmd, getattr(self, cmd).__doc__)
        return ret

    def VERSION(self):
        '''Показать версию протокола'''
        return "XO ver {}".format(self.version)

    def DEBUG(self):
        '''Вклчить/выключить режим отладки'''
        self.debug = not self.debug
        return "OK"

    def command(self, cmd):
        cmd = cmd.split()
        cmd[0]=cmd[0].upper()
        if cmd[0] not in dir(self):
            return "ERROR INVALID '{}'".format(cmd[0])
        try:
            command = getattr(self, cmd[0])
            ret = command(*cmd[1:])
        except Exception, message:
            if self.debug:
                raise
            else:
                return "ERROR PARAMETER {}".format(message)
        return ret

if __name__ == "__main__":
    proto = Proto()
    req, ret = "VERSION", ""
    while req != "." and not ret.startswith("ENDGAME"):
        ret = proto.command(req)
        print ret
        req = raw_input("> ")
