Beispiel #1
0
class Game(object):
    def __init__(self, gold, silver,
                 timecontrol=None,
                 start_position=None,
                 strict_setup=True,
                 min_timeleft=None):
        self.engines = (gold, silver)
        try:
            self.timecontrol = timecontrol[0]
            self.side_tc = timecontrol
        except TypeError:
            self.timecontrol = timecontrol
            self.side_tc = [timecontrol, timecontrol]
        self.reserves = [None, None]
        if timecontrol:
            for side, eng in enumerate(self.engines):
                if not self.side_tc[side]:
                    continue
                self.reserves[side] = self.side_tc[side].reserve
                eng.setoption("tcmove", self.side_tc[side].move)
                eng.setoption("tcreserve", self.side_tc[side].reserve)
                eng.setoption("tcpercent", self.side_tc[side].percent)
                eng.setoption("tcmax", self.side_tc[side].max_reserve)
                eng.setoption("tcturns", self.side_tc[side].turn_limit)
                eng.setoption("tctotal", self.side_tc[side].time_limit)
                eng.setoption("tcturntime", self.side_tc[side].max_turntime)
        for eng in self.engines:
            eng.newgame()
            if start_position:
                eng.setposition(start_position)
            resps = eng.isready()
            side = "gs" [self.engines.index(eng)]
            eng_name = eng.ident["name"]
            for response in resps:
                if response.type == "info":
                    log.info("%s (%s) info: %s", eng_name, side,
                             response.message)
                elif response.type == "log":
                    log.info("%s (%s) log: %s", eng_name, side,
                             response.message)
                else:
                    log.warn(
                        "Unexpected response while initializing %s (%s) (%s).",
                        eng_name, side, response.type)

        self.insetup = False
        self.position = start_position
        if not start_position:
            self.insetup = True
            self.position = Position(Color.GOLD, 4, BLANK_BOARD)
        self.strict_setup = strict_setup
        self.min_timeleft = min_timeleft
        self.movenumber = 1
        self.limit_winner = 1
        self.moves = []
        self.repetition_count = defaultdict(int)
        self.result = None

    def play(self):
        if self.result:
            raise RuntimeError("Tried to play a game that was already played.")
        starttime = time.time()
        while not self.position.is_end_state() or self.insetup:
            try:
                result = self.play_next_move(starttime)
                if result:
                    break
            except IllegalMove as e:
                log.info("Illegal move played: %s" % e)
                result = (self.position.color ^ 1, "i")
                break
        if not result:
            if self.position.is_goal():
                result = (0 - min(self.position.is_goal(), 0), "g")
            elif self.position.is_rabbit_loss():
                result = (0 - min(self.position.is_rabbit_loss(), 0), "e")
            else:  # immobilization
                assert len(self.position.get_steps()) == 0
                result = (self.position.color ^ 1, "m")
        self.result = result
        return result

    def play_next_move(self, starttime):
        position = self.position
        side = position.color
        engine = self.engines[side]
        tc = self.side_tc[side]
        if tc:
            if tc.time_limit:
                endtime_limit = starttime + tc.time_limit
            if engine.protocol_version == 0:
                if self.reserves[0] is not None:
                    engine.setoption("wreserve", int(self.reserves[0]))
                if self.reserves[1] is not None:
                    engine.setoption("breserve", int(self.reserves[1]))
                engine.setoption("tcmoveused", 0)
            if self.reserves[0] is not None:
                engine.setoption("greserve", int(self.reserves[0]))
            if self.reserves[1] is not None:
                engine.setoption("sreserve", int(self.reserves[1]))
            engine.setoption("moveused", 0)
        movestart = time.time()
        engine.go()
        if tc:
            timeout = movestart + tc.move + self.reserves[side]
            if tc.max_turntime and movestart + tc.max_turntime < timeout:
                timeout = movestart + tc.max_turntime
            if tc.time_limit and endtime_limit < timeout:
                timeout = endtime_limit
        else:
            timeout = None
        waittime = None
        resp = None
        stopsent = False
        stoptime = None
        if timeout and self.min_timeleft:
            stoptime = timeout - self.min_timeleft
        while True:
            now = time.time()
            if stoptime and not stopsent and now >= stoptime:
                # try and get a move before time runs out
                engine.stop()
                log.info("Engine sent stop command to prevent timeout")
                stopsent = True
            if timeout and now > timeout:
                if not stopsent:
                    engine.stop()
                break
            if timeout:
                waittime = timeout - now
                if stoptime and not stopsent and now + waittime > stoptime:
                    waittime = max(0, (stoptime - now) + 0.2)
            try:
                resp = engine.get_response(waittime)
                if resp.type == "bestmove":
                    break
                if resp.type == "info":
                    log.info("%s (%s) info: %s", engine.ident["name"],
                             "gs" [side], resp.message)
                elif resp.type == "log":
                    log.info("%s (%s) log: %s", engine.ident["name"],
                             "gs" [side], resp.message)
            except socket.timeout:
                pass
        moveend = time.time()

        if tc and moveend > timeout:
            if tc.time_limit and endtime_limit < moveend:
                return (self.limit_winner, "s")
            else:
                return (side ^ 1, "t")
        if not resp or resp.type != "bestmove": # pragma: no cover
            raise RuntimeError(
                "Stopped waiting without a timeout or a move")
        if tc:
            if not self.insetup:
                reserve_change = tc.move - (moveend - movestart)
                if reserve_change > 0:
                    # if we are adding to the reserve only apply the
                    # percentage specified by the time control
                    reserve_change *= tc.percent / 100.0
                self.reserves[side] += reserve_change
                if tc.max_reserve:
                    self.reserves[side] = min(self.reserves[side],
                                              tc.max_reserve)
        move = resp.move
        if move.lower() == "resign":
            return (side ^ 1, "r")
        self.moves.append("%d%s %s" % (self.movenumber,
                                       "gs" [position.color], move))
        if self.insetup:
            position = position.do_move_str(
                move,
                strict_checks=self.strict_setup)
        else:
            position = position.do_move_str(move)
        if position.bitBoards == self.position.bitBoards:
            raise IllegalMove("Tried move that did not change the position, %s" % move)
        self.repetition_count[position] += 1
        if self.repetition_count[position] > 2:
            raise IllegalMove("Tried move resulting in a 3rd time repetition")
        self.position = position
        if position.color == Color.GOLD:
            self.movenumber += 1
        log.debug("position:\n%s", position.board_to_str())
        for eng in self.engines:
            eng.makemove(move)
        if self.insetup and side == Color.SILVER:
            self.insetup = False
        if not self.insetup:
            bstr = position.board_to_str("short")
            gp = 0
            for p in "EMHDCR":
                gp += bstr.count(p)
            sp = 0
            for p in "emhdcr":
                sp += bstr.count(p)
            if gp > sp:
                limit_winner = 0
            elif sp > gp:
                limit_winner = 1
        if tc and tc.turn_limit and self.movenumber > tc.turn_limit:
            return (limit_winner, "s")
Beispiel #2
0
def playgame(gold_eng, silver_eng, timecontrol=None, position=None):
    engines = (gold_eng, silver_eng)
    if timecontrol:
        time_incr = timecontrol['move']
        reserves = [0, 0]
        reserves[0] = reserves[1] = timecontrol['reserve']
        reserve_per = timecontrol['percent'] / 100.0
        reserve_max = timecontrol['max']
        max_moves = timecontrol['turns']
        max_gametime = timecontrol['total']
        max_turn = timecontrol['turntime']
        for eng in engines:
            eng.setoption("tcmove", time_incr)
            eng.setoption("tcreserve", timecontrol['reserve'])
            eng.setoption("tcpercent", timecontrol['percent'])
            eng.setoption("tcmax", reserve_max)
            eng.setoption("tcturns", max_moves)
            eng.setoption("tctotal", max_gametime)
            eng.setoption("tcturntime", max_turn)
    else:
        max_gametime = 0
        max_moves = 0
    for eng in engines:
        eng.newgame()
        if position:
            eng.setposition(position)
        eng.isready()
    insetup = False
    if not position:
        insetup = True
        position = Position(Color.GOLD, 4, board.BLANK_BOARD)
    starttime = time.time()
    if max_gametime:
        endtime_limit = starttime + max_gametime
    position.movenumber = 1
    limit_winner = 1
    while insetup or not position.is_end_state():
        #print "%d%s" % (position.movenumber, "gs"[position.color])
        #print position.board_to_str()
        side = position.color
        engine = engines[side]
        if timecontrol:
            if engine.protocol_version > 0:
                engine.setoption("greserve", int(reserves[0]))
                engine.setoption("sreserve", int(reserves[1]))
            else:
                engine.setoption("wreserve", int(reserves[0]))
                engine.setoption("breserve", int(reserves[1]))
                engine.setoption("tcmoveused", 0)
            movestart = time.time()
            engine.setoption("moveused", 0)
        engine.go()
        if timecontrol:
            timeout = movestart + time_incr + reserves[side]
            if max_turn and starttime + max_turn > timeout:
                timeout = starttime + max_turn
            if max_gametime and endtime_limit < timeout:
                timeout = endtime_limit
            bstr = position.board_to_str("short")
            gp = 0
            for p in "EMHDCR":
                gp += bstr.count(p)
            sp = 0
            for p in "emhdcr":
                sp += bstr.count(p)
            if gp > sp:
                limit_winner = 0
            elif sp > gp:
                limit_winner = 1
        else:
            timeout = None
        resp = None
        try:
            while not timeout or time.time() < timeout:
                if timeout:
                    wait = timeout - time.time()
                else:
                    wait = None
                resp = engine.get_response(wait)
                if resp.type == "bestmove":
                    break
                if resp.type == "info":
                    log.info("%s info: %s" % ("gs"[side], resp.message))
                elif resp.type == "log":
                    log.info("%s log: %s" % ("gs"[side], resp.message))
        except socket.timeout:
            engine.stop()
        endtime = time.time()

        if resp and resp.type == "bestmove":
            if timecontrol:
                moveend = time.time()
                if moveend > timeout:
                    return (side ^ 1, "t", position)
                if not insetup:
                    reserve_incr = ((time_incr - (moveend - movestart)) *
                                    reserve_per)
                    reserves[side] += reserve_incr
                    if reserve_max:
                        reserves[side] = min(reserves[side], reserve_max)
            move = resp.move
            mn = position.movenumber
            position = position.do_move_str(move)
            if position.color == Color.GOLD:
                mn += 1
            position.movenumber = mn
            log.info("position:\n%s", position.board_to_str())
            for eng in engines:
                eng.makemove(move)
            if insetup and side == Color.SILVER:
                insetup = False
            if max_moves and position.movenumber > max_moves:
                return (limit_winner, "s", position)
        elif not max_gametime or endtime < endtime_limit:
            return (side ^ 1, "t", position)
        else:  # exceeded game time limit
            return (limit_winner, "s", position)

    if position.is_goal():
        result = (min(position.is_goal(), 0), "g", position)
    elif position.is_rabbit_loss():
        result = (min(position.is_rabbit_loss(), 0), "e", position)
    else:  # immobilization
        assert len(position.get_steps()) == 0
        result = (position.color ^ 1, "m", position)
    return result
Beispiel #3
0
class Game(object):
    def __init__(self,
                 gold,
                 silver,
                 timecontrol=None,
                 start_position=None,
                 strict_setup=True,
                 min_timeleft=None):
        self.engines = (gold, silver)
        try:
            self.timecontrol = timecontrol[0]
            self.side_tc = timecontrol
        except TypeError:
            self.timecontrol = timecontrol
            self.side_tc = [timecontrol, timecontrol]
        self.reserves = [None, None]
        if timecontrol:
            for side, eng in enumerate(self.engines):
                if not self.side_tc[side]:
                    continue
                self.reserves[side] = self.side_tc[side].reserve
                eng.setoption("tcmove", self.side_tc[side].move)
                eng.setoption("tcreserve", self.side_tc[side].reserve)
                eng.setoption("tcpercent", self.side_tc[side].percent)
                eng.setoption("tcmax", self.side_tc[side].max_reserve)
                eng.setoption("tcturns", self.side_tc[side].turn_limit)
                eng.setoption("tctotal", self.side_tc[side].time_limit)
                eng.setoption("tcturntime", self.side_tc[side].max_turntime)
        for eng in self.engines:
            eng.newgame()
            if start_position:
                eng.setposition(start_position)
            resps = eng.isready()
            side = "gs"[self.engines.index(eng)]
            eng_name = eng.ident["name"]
            for response in resps:
                if response.type == "info":
                    log.info("%s (%s) info: %s", eng_name, side,
                             response.message)
                elif response.type == "log":
                    log.info("%s (%s) log: %s", eng_name, side,
                             response.message)
                else:
                    log.warn(
                        "Unexpected response while initializing %s (%s) (%s).",
                        eng_name, side, response.type)

        self.insetup = False
        self.position = start_position
        if not start_position:
            self.insetup = True
            self.position = Position(Color.GOLD, 4, BLANK_BOARD)
        self.strict_setup = strict_setup
        self.min_timeleft = min_timeleft
        self.movenumber = 1
        self.limit_winner = 1
        self.moves = []
        self.repetition_count = defaultdict(int)
        self.result = None

    def play(self):
        if self.result:
            raise RuntimeError("Tried to play a game that was already played.")
        starttime = time.time()
        while not self.position.is_end_state() or self.insetup:
            try:
                result = self.play_next_move(starttime)
                if result:
                    break
            except IllegalMove as e:
                log.info("Illegal move played: %s" % e)
                result = (self.position.color ^ 1, "i")
                break
        if not result:
            if self.position.is_goal():
                result = (0 - min(self.position.is_goal(), 0), "g")
            elif self.position.is_rabbit_loss():
                result = (0 - min(self.position.is_rabbit_loss(), 0), "e")
            else:  # immobilization
                assert len(self.position.get_steps()) == 0
                result = (self.position.color ^ 1, "m")
        self.result = result
        return result

    def play_next_move(self, starttime):
        position = self.position
        side = position.color
        engine = self.engines[side]
        tc = self.side_tc[side]
        if tc:
            if tc.time_limit:
                endtime_limit = starttime + tc.time_limit
            if engine.protocol_version == 0:
                if self.reserves[0] is not None:
                    engine.setoption("wreserve", int(self.reserves[0]))
                if self.reserves[1] is not None:
                    engine.setoption("breserve", int(self.reserves[1]))
                engine.setoption("tcmoveused", 0)
            if self.reserves[0] is not None:
                engine.setoption("greserve", int(self.reserves[0]))
            if self.reserves[1] is not None:
                engine.setoption("sreserve", int(self.reserves[1]))
            engine.setoption("moveused", 0)
        movestart = time.time()
        engine.go()
        if tc:
            timeout = movestart + tc.move + self.reserves[side]
            if tc.max_turntime and movestart + tc.max_turntime < timeout:
                timeout = movestart + tc.max_turntime
            if tc.time_limit and endtime_limit < timeout:
                timeout = endtime_limit
        else:
            timeout = None
        waittime = None
        resp = None
        stopsent = False
        stoptime = None
        if timeout and self.min_timeleft:
            stoptime = timeout - self.min_timeleft
        while True:
            now = time.time()
            if stoptime and not stopsent and now >= stoptime:
                # try and get a move before time runs out
                engine.stop()
                log.info("Engine sent stop command to prevent timeout")
                stopsent = True
            if timeout and now > timeout:
                if not stopsent:
                    engine.stop()
                break
            if timeout:
                waittime = timeout - now
                if stoptime and not stopsent and now + waittime > stoptime:
                    waittime = max(0, (stoptime - now) + 0.2)
            try:
                resp = engine.get_response(waittime)
                if resp.type == "bestmove":
                    break
                if resp.type == "info":
                    log.info("%s (%s) info: %s", engine.ident["name"],
                             "gs"[side], resp.message)
                elif resp.type == "log":
                    log.info("%s (%s) log: %s", engine.ident["name"],
                             "gs"[side], resp.message)
            except socket.timeout:
                pass
        moveend = time.time()

        if tc and moveend > timeout:
            if tc.time_limit and endtime_limit < moveend:
                return (self.limit_winner, "s")
            else:
                return (side ^ 1, "t")
        if not resp or resp.type != "bestmove":  # pragma: no cover
            raise RuntimeError("Stopped waiting without a timeout or a move")
        if tc:
            if not self.insetup:
                reserve_change = tc.move - (moveend - movestart)
                if reserve_change > 0:
                    # if we are adding to the reserve only apply the
                    # percentage specified by the time control
                    reserve_change *= tc.percent / 100.0
                self.reserves[side] += reserve_change
                if tc.max_reserve:
                    self.reserves[side] = min(self.reserves[side],
                                              tc.max_reserve)
        move = resp.move
        if move.lower() == "resign":
            return (side ^ 1, "r")
        self.moves.append("%d%s %s" %
                          (self.movenumber, "gs"[position.color], move))
        if self.insetup:
            position = position.do_move_str(move,
                                            strict_checks=self.strict_setup)
        else:
            position = position.do_move_str(move)
        if position.bitBoards == self.position.bitBoards:
            raise IllegalMove(
                "Tried move that did not change the position, %s" % move)
        self.repetition_count[position] += 1
        if self.repetition_count[position] > 2:
            raise IllegalMove("Tried move resulting in a 3rd time repetition")
        self.position = position
        if position.color == Color.GOLD:
            self.movenumber += 1
        log.debug("position:\n%s", position.board_to_str())
        for eng in self.engines:
            eng.makemove(move)
        if self.insetup and side == Color.SILVER:
            self.insetup = False
        if not self.insetup:
            bstr = position.board_to_str("short")
            gp = 0
            for p in "EMHDCR":
                gp += bstr.count(p)
            sp = 0
            for p in "emhdcr":
                sp += bstr.count(p)
            if gp > sp:
                limit_winner = 0
            elif sp > gp:
                limit_winner = 1
        if tc and tc.turn_limit and self.movenumber > tc.turn_limit:
            return (limit_winner, "s")
Beispiel #4
0
def playgame(gold_eng, silver_eng, timecontrol=None, position=None):
    engines = (gold_eng, silver_eng)
    if timecontrol:
        time_incr = timecontrol['move']
        reserves = [0, 0]
        reserves[0] = reserves[1] = timecontrol['reserve']
        reserve_per = timecontrol['percent'] / 100.0
        reserve_max = timecontrol['max']
        max_moves = timecontrol['turns']
        max_gametime = timecontrol['total']
        max_turn = timecontrol['turntime']
        for eng in engines:
            eng.setoption("tcmove", time_incr)
            eng.setoption("tcreserve", timecontrol['reserve'])
            eng.setoption("tcpercent", timecontrol['percent'])
            eng.setoption("tcmax", reserve_max)
            eng.setoption("tcturns", max_moves)
            eng.setoption("tctotal", max_gametime)
            eng.setoption("tcturntime", max_turn)
    else:
        max_gametime = 0
        max_moves = 0
    for eng in engines:
        eng.newgame()
        if position:
            eng.setposition(position)
        eng.isready()
    insetup = False
    if not position:
        insetup = True
        position = Position(Color.GOLD, 4, board.BLANK_BOARD)
    starttime = time.time()
    if max_gametime:
        endtime_limit = starttime + max_gametime
    position.movenumber = 1
    limit_winner = 1
    while insetup or not position.is_end_state():
        #print "%d%s" % (position.movenumber, "gs"[position.color])
        #print position.board_to_str()
        side = position.color
        engine = engines[side]
        if timecontrol:
            if engine.protocol_version > 0:
                engine.setoption("greserve", int(reserves[0]))
                engine.setoption("sreserve", int(reserves[1]))
            else:
                engine.setoption("wreserve", int(reserves[0]))
                engine.setoption("breserve", int(reserves[1]))
                engine.setoption("tcmoveused", 0)
            movestart = time.time()
            engine.setoption("moveused", 0)
        engine.go()
        if timecontrol:
            timeout = movestart + time_incr + reserves[side]
            if max_turn and starttime + max_turn > timeout:
                timeout = starttime + max_turn
            if max_gametime and endtime_limit < timeout:
                timeout = endtime_limit
            bstr = position.board_to_str("short")
            gp = 0
            for p in "EMHDCR":
                gp += bstr.count(p)
            sp = 0
            for p in "emhdcr":
                sp += bstr.count(p)
            if gp > sp:
                limit_winner = 0
            elif sp > gp:
                limit_winner = 1
        else:
            timeout = None
        resp = None
        try:
            while not timeout or time.time() < timeout:
                if timeout:
                    wait = timeout - time.time()
                else:
                    wait = None
                resp = engine.get_response(wait)
                if resp.type == "bestmove":
                    break
                if resp.type == "info":
                    log.info("%s info: %s" % ("gs"[side], resp.message))
                elif resp.type == "log":
                    log.info("%s log: %s" % ("gs"[side], resp.message))
        except socket.timeout:
            engine.stop()
        endtime = time.time()

        if resp and resp.type == "bestmove":
            if timecontrol:
                moveend = time.time()
                if moveend > timeout:
                    return (side^1, "t", position)
                if not insetup:
                    reserve_incr = ((time_incr - (moveend - movestart))
                            * reserve_per)
                    reserves[side] += reserve_incr
                    if reserve_max:
                        reserves[side] = min(reserves[side], reserve_max)
            move = resp.move
            mn = position.movenumber
            position = position.do_move_str(move)
            if position.color == Color.GOLD:
                mn += 1
            position.movenumber = mn
            log.info("position:\n%s", position.board_to_str())
            for eng in engines:
                eng.makemove(move)
            if insetup and side == Color.SILVER:
                insetup = False
            if max_moves and position.movenumber > max_moves:
                return (limit_winner, "s", position)
        elif not max_gametime or endtime < endtime_limit:
            return (side^1, "t", position)
        else: # exceeded game time limit
            return (limit_winner, "s", position)

    if position.is_goal():
        result = (min(position.is_goal(), 0), "g", position)
    elif position.is_rabbit_loss():
        result = (min(position.is_rabbit_loss(), 0), "e", position)
    else: # immobilization
        assert len(position.get_steps()) == 0
        result = (position.color^1, "m", position)
    return result