from timecontrol import TimeControl

class GameSession:
    def __init__(self,whiteEng, blackEng, **kwargs):
        """
        The basic GameSession class.
        whiteEng and blackEng are the two engines, with respective colors

        Note: All times are in milliseconds as per UCI protocol, unless
        time_modifier is used.

        start_time is the time that the engines are given on the clock,
        not including this parameter will result in an untimed game. A tuple
        can be fed to allow different starting times like so:
        start_time = (<white start time>,<black start time>)

        inc is the incremented time value after each turn. Like start_time,
        it can be fed a tuple for different incrementations to each engine.

        time is a tuple that combines start_time and inc 
        in the following format: time=(start_time,inc).

        If time is a single number (int, float, etc.), the value it is passed
        will be considered as start_time, and inc as 0.
        """

        self.white = whiteEng
        self.black = blackEng
        self.gamehistory = ""
        self.write_all_engines('position startpos\n')
        self.timed = False

        #Process TimeControl Arguments
        tc_dict = {}
            #Pass any argument in tc_dict to time control.
        if 'tc_dict' in kwargs:
            tc_dict.update(kwargs['tc_dict'])
        if 'time_unit' in kwargs:
            tc_dict['time_unit'] = kwargs['time_unit']
            

        if 'time' in kwargs:
            self.timeControl = TimeControl(*kwargs['time'], **tc_dict)
            self.timed = True
        elif 'start_time' in kwargs:
            inc = 0
            if 'inc' in kwargs:
                inc = kwargs['inc']
            self.timeControl = TimeControl(kwargs['start_time'],inc, **tc_dict)
            self.timed = True
        
    def get_move(self, engine):
        command = 'go'
        
        if self.timed:
            wtime, btime = self.timeControl.clocks
            winc, binc = self.timeControl.increment
            command += ' wtime {0} btime {1} winc {2} binc {3}'
            command = command.format(wtime, btime, winc, binc)
        
        engine.write('{0}\n'.format(command))
        while True:
            for line in engine.readAll():
                if "bestmove" in line:
                    return line[9:14]
        
    def update_board(self,position):
        if "none" in position:
            return False
        self.gamehistory += " {0}".format(position)
        self.write_all_engines('position startpos moves {0}\n'
                               .format(self.gamehistory))
        return True

    def write_all_engines(self,message):
        self.white.write(message)
        self.black.write(message)

    def play(self):
        engines = [self.white,self.black]
        turn = 0
        while True:
            if self.timed:
                self.timeControl.start(turn)

            newmove = self.get_move(engines[turn])
            if not self.update_board(newmove):
                print self.gamehistory
                if turn == 1:
                    print "White checkmates"
                else:
                    print "Black checkmates"
                break

            # Check for time
            if self.timed:
                if not self.timeControl.stop():
                    print self.gamehistory

                    #Print "loses on time" message.
                    if turn == 0:
                        print "White loses on time"
                    else:
                        print "Black loses on time"
                    break
                        
            turn = -(turn -1) # 0 -> 1; 1 -> 0

@@ -28,16 +28,52 @@
 eControl
+%0Afrom fenoperator import FENOperator
 %0A%0Aclass 
@@ -1226,16 +1226,98 @@
  False%0A%0A
+        self.tied = False%0A        self.tiereason = ''%0A        self.winner = None%0A%0A
         
@@ -1974,32 +1974,215 @@
 = True%0A        %0A
+        #Tie testing (repeated moves)%0A        self.played_positions = %7B%7D%0A        self.FENOp = FENOperator('startpos')%0A        self.played_positions%5Bself.FENOp.getPositionOnly()%5D = 1%0A%0A
     def get_move
@@ -2774,24 +2774,95 @@
 eturn False%0A
+        self.tied = self.check_tie(position) #Also updates FENOperator%0A
         self
@@ -3627,16 +3627,124 @@
  break%0A%0A
+            if self.tied:%0A                print %22Draw by %7B0%7D%22.format(self.tiereason)%0A                break%0A%0A
         
@@ -4142,32 +4142,32 @@
                %0A
-
             turn
@@ -4197,8 +4197,643 @@
  1 -%3E 0%0A
+%0A    def check_tie(self, move):%0A        %22%22%22%0A        Checks for tie and updates FENOperator%0A        %22%22%22%0A        self.FENOp.do_move(move)%0A        newstr = self.FENOp.getPositionOnly()%0A        %0A        if newstr in self.played_positions:%0A            self.played_positions%5Bnewstr%5D += 1%0A            if self.played_positions%5Bnewstr%5D %3E= 3:%0A                self.tiereason = '3 move repeat'%0A                return True%0A        else:%0A            self.played_positions%5Bnewstr%5D = 1%0A%0A        if self.FENOp.cp_clock %3E= 100:%0A            self.tiereason = '50 moves without capture or pawn moving'%0A            return True%0A        %0A        return False%0A

Add tied game recognition