Beispiel #1
0
async def _join_game(players,
                     realtime,
                     portconfig,
                     save_replay_as=None,
                     step_time_limit=None,
                     game_time_limit=None,
                     rgb_render_config=None):
    async with SC2Process() as server:
        await server.ping()

        client = Client(server._ws)

        try:
            result = await _play_game(players[1],
                                      client,
                                      realtime,
                                      portconfig,
                                      step_time_limit,
                                      game_time_limit,
                                      rgb_render_config=rgb_render_config)
            if save_replay_as is not None:
                await client.save_replay(save_replay_as)
            await client.leave()
            await client.quit()
        except ConnectionAlreadyClosed:
            logging.error(f"Connection was closed before the game ended")
            return None

        return result
Beispiel #2
0
async def _join_game(
    players,
    realtime,
    portconfig,
    save_replay_as=None,
    game_time_limit=None,
):
    async with SC2Process(fullscreen=players[1].fullscreen) as server:
        await server.ping()

        client = Client(server._ws)
        # Bot can decide if it wants to launch with 'raw_affects_selection=True'
        if not isinstance(players[1], Human) and getattr(players[1].ai, "raw_affects_selection", None) is not None:
            client.raw_affects_selection = players[1].ai.raw_affects_selection

        result = await _play_game(players[1], client, realtime, portconfig, game_time_limit)
        if save_replay_as is not None:
            await client.save_replay(save_replay_as)
        try:
            await client.leave()
        except ConnectionAlreadyClosed:
            logger.error("Connection was closed before the game ended")
        await client.quit()

        return result
Beispiel #3
0
async def _host_game_aiter(
    map_settings,
    players,
    realtime,
    portconfig=None,
    save_replay_as=None,
    game_time_limit=None,
):
    assert players, "Can't create a game without players"

    assert any(isinstance(p, (Human, Bot)) for p in players)

    async with SC2Process() as server:
        while True:
            await server.ping()

            client = await _setup_host_game(server, map_settings, players, realtime)
            if not isinstance(players[0], Human) and getattr(players[0].ai, "raw_affects_selection", None) is not None:
                client.raw_affects_selection = players[0].ai.raw_affects_selection

            try:
                result = await _play_game(players[0], client, realtime, portconfig, game_time_limit)

                if save_replay_as is not None:
                    await client.save_replay(save_replay_as)
                await client.leave()
            except ConnectionAlreadyClosed:
                logger.error("Connection was closed before the game ended")
                return

            new_players = yield result
            if new_players is not None:
                players = new_players
Beispiel #4
0
    async def _join_game(
            task_dict,
            players,
            aio_event,
            alive_evnet,
            req_kill_event,
            exc_queue,
            n_games,
            realtime=False, 
            portconfig=None,
            save_replay_as=None, 
            step_time_limit=None, 
            game_time_limit=None,
        ):

        async with SC2Process() as server:
            try:
                for _ in range(n_games):
                    # host에서 게임을 세팅할 때까지 기다림
                    await aio_event.wait()
                    aio_event.clear()
                    # 게임을 재시작했음을 부모 프로세스에 알림
                    alive_evnet.set()

                    # 게임 시작
                    await server.ping()
                    client = Client(server._ws)

                    result = await _play_game(
                        players[1], client, realtime, portconfig, 
                        step_time_limit, game_time_limit
                    )
                    if save_replay_as is not None:
                        await client.save_replay(save_replay_as)
                    await client.leave()
                    # await client.quit()  # 게임 인스턴스 재시작을 위해 프로세스 종료하지 않음
            except:
                # 예외가 발생하면 부모 프로세스에 전달
                import traceback
                exc_queue.put(traceback.format_exc())             

            # n_games 만큼 게임을 반복했음을 부모 프로세스에 알림
            # join에서 host를 죽이거나, host에서 join을 죽일 경우를 대비해서,
            # host와 join 양쪽에 req_kill_evnet를 set 해야함 
            # -> 어떤 경우에도 부모는 이 프로세스를 종료해야함을 알 수 있음
            req_kill_event.set()
Beispiel #5
0
async def _host_game(
    map_settings,
    players,
    realtime=False,
    portconfig=None,
    save_replay_as=None,
    game_time_limit=None,
    rgb_render_config=None,
    random_seed=None,
    sc2_version=None,
    disable_fog=None,
):

    assert players, "Can't create a game without players"

    assert any(isinstance(p, (Human, Bot)) for p in players)

    async with SC2Process(
        fullscreen=players[0].fullscreen, render=rgb_render_config is not None, sc2_version=sc2_version
    ) as server:
        await server.ping()

        client = await _setup_host_game(
            server, map_settings, players, realtime, random_seed, disable_fog, save_replay_as
        )
        # Bot can decide if it wants to launch with 'raw_affects_selection=True'
        if not isinstance(players[0], Human) and getattr(players[0].ai, "raw_affects_selection", None) is not None:
            client.raw_affects_selection = players[0].ai.raw_affects_selection

        result = await _play_game(players[0], client, realtime, portconfig, game_time_limit, rgb_render_config)
        if client.save_replay_path is not None:
            await client.save_replay(client.save_replay_path)
        try:
            await client.leave()
        except ConnectionAlreadyClosed:
            logger.error("Connection was closed before the game ended")
        await client.quit()

        return result
async def _join_game_aiter(players, realtime, portconfig):
    assert players, "Can't create a game without players"

    assert any(isinstance(p, (Human, Bot)) for p in players)

    async with SC2Process() as server:
        while True:
            await server.ping()

            client = Client(server._ws)

            try:
                result = await _play_game(players[1], client, realtime,
                                          portconfig)
                await client.leave()
            except ConnectionAlreadyClosed:
                print(f"Connection was closed before the game ended")
                return

            new_players = yield result
            if new_players is not None:
                players = new_players
Beispiel #7
0
    async def _host_game(
        hostname,
        sock,
        task_dict,
        players,
        aio_event,
        alive_evnet,
        req_kill_event,
        exc_queue,
        n_games,
        realtime=False,
        portconfig=None,
        save_replay_as=None,
        step_time_limit=None,
        game_time_limit=None,
        rgb_render_config=None,
        random_seed=None,
    ):

        async with SC2Process(render=rgb_render_config is not None) as server:
            try:
                for _ in range(n_games):
                    # Learner에게 다음에 실행할 게임 세팅을 요청
                    sock.send_multipart([CommandType.REQ_TASK])
                    task_dict.update(pickle.loads(sock.recv_multipart()[0]))
                    # 게임 세팅 설정
                    # !주의!: join쪽 task_dict, players와 동일한 인스턴스를 유지해야 하기 때문에,
                    # 절대 여기서 새로 생성하지 말고 업데이트만 해야함,
                    # 불가: players = [_Bot(), _Bot()], 가능 players[0] = _Bot(); players[1] = _Bot()
                    step_interval = task_dict['step_interval']
                    players[0] = _Bot(Race.Terran,
                                      MyBot(step_interval, hostname, sock))
                    players[1] = _Bot(Race.Terran, OppBot())

                    # 게임 세팅이 완료되면 event를 set해서 join 쪽도 다음 과정을 진행하도록 함
                    aio_event.set()
                    # 게임이 새로 시작했음을 부모 프로세스에 알림
                    alive_evnet.set()

                    # 게임 시작
                    map_settings = sc2.maps.get(task_dict['game_map'])
                    await server.ping()
                    client = await _setup_host_game(server, map_settings,
                                                    players, realtime,
                                                    random_seed)

                    result = await _play_game(players[0], client, realtime,
                                              portconfig, step_time_limit,
                                              game_time_limit,
                                              rgb_render_config)
                    if save_replay_as is not None:
                        await client.save_replay(save_replay_as)
                    await client.leave()
                    # await client.quit()  # 게임 인스턴스 재시작을 위해 프로세스 종료하지 않음
            except:
                # 예외가 발생하면 부모 프로세스에 전달
                import traceback
                exc_queue.put(traceback.format_exc())

            # n_games 만큼 게임을 반복했음을 부모 프로세스에 알림
            # join에서 host를 죽이거나, host에서 join을 죽일 경우를 대비해서,
            # host와 join 양쪽에 req_kill_evnet를 set 해야함
            # -> 어떤 경우에도 부모는 이 프로세스를 종료해야함을 알 수 있음
            req_kill_event.set()
Beispiel #8
0
async def maintain_SCII_count(count: int, controllers: List[Controller], proc_args: List[Dict] = None):
    """Modifies the given list of controllers to reflect the desired amount of SCII processes"""
    # kill unhealthy ones.
    if controllers:
        to_remove = []
        alive = await asyncio.wait_for(
            asyncio.gather(*(c.ping() for c in controllers if not c._ws.closed), return_exceptions=True), timeout=20
        )
        i = 0  # for alive
        for controller in controllers:
            if controller._ws.closed:
                if not controller._process._session.closed:
                    await controller._process._session.close()
                to_remove.append(controller)
            else:
                if not isinstance(alive[i], sc_pb.Response):
                    try:
                        await controller._process._close_connection()
                    finally:
                        to_remove.append(controller)
                i += 1
        for c in to_remove:
            c._process._clean(verbose=False)
            if c._process in kill_switch._to_kill:
                kill_switch._to_kill.remove(c._process)
            controllers.remove(c)

    # spawn more
    if len(controllers) < count:
        needed = count - len(controllers)
        if proc_args:
            index = len(controllers) % len(proc_args)
        else:
            proc_args = [{} for _ in range(needed)]
            index = 0
        extra = [SC2Process(**proc_args[(index + _) % len(proc_args)]) for _ in range(needed)]
        logger.info(f"Creating {needed} more SC2 Processes")
        for _ in range(3):
            if platform.system() == "Linux":
                # Works on linux: start one client after the other
                new_controllers = [await asyncio.wait_for(sc.__aenter__(), timeout=50) for sc in extra]
            else:
                # Doesnt seem to work on linux: starting 2 clients nearly at the same time
                new_controllers = await asyncio.wait_for(
                    asyncio.gather(*[sc.__aenter__() for sc in extra], return_exceptions=True), timeout=50
                )

            controllers.extend(c for c in new_controllers if isinstance(c, Controller))
            if len(controllers) == count:
                await asyncio.wait_for(asyncio.gather(*(c.ping() for c in controllers)), timeout=20)
                break
            extra = [
                extra[i] for i, result in enumerate(new_controllers) if not isinstance(new_controllers, Controller)
            ]
        else:
            logger.critical("Could not launch sufficient SC2")
            raise RuntimeError

    # kill excess
    while len(controllers) > count:
        proc = controllers.pop()
        proc = proc._process
        logger.info(f"Removing SCII listening to {proc._port}")
        await proc._close_connection()
        proc._clean(verbose=False)
        if proc in kill_switch._to_kill:
            kill_switch._to_kill.remove(proc)
Beispiel #9
0
async def _host_replay(replay_path, ai, realtime, _portconfig, base_build, data_version, observed_id):
    async with SC2Process(fullscreen=False, base_build=base_build, data_hash=data_version) as server:
        client = await _setup_replay(server, replay_path, realtime, observed_id)
        result = await _play_replay(client, ai, realtime)
        return result
Beispiel #10
0
    async def _host_game(hostname,
                         sock,
                         task_dict,
                         players,
                         aio_event,
                         alive_evnet,
                         req_kill_event,
                         exc_queue,
                         n_games,
                         realtime=False,
                         portconfig=None,
                         save_replay_as=None,
                         step_time_limit=None,
                         game_time_limit=None,
                         rgb_render_config=None,
                         random_seed=None):

        async with SC2Process(render=rgb_render_config is not None) as server:
            try:
                for j in range(n_games):
                    # Learner에게 다음에 실행할 게임 세팅을 요청
                    sock.send_multipart([CommandType.REQ_TASK])

                    tmp = sock.recv_multipart()
                    task_dict.update(pickle.loads(tmp[0]))

                    # 게임 세팅 설정
                    # !주의!: join쪽 task_dict, players와 동일한 인스턴스를 유지해야 하기 때문에,
                    # 절대 여기서 새로 생성하지 말고 업데이트만 해야함,
                    # 불가: players = [_Bot(), _Bot()], 가능 players[0] = _Bot(); players[1] = _Bot()
                    step_interval = task_dict['step_interval']

                    # pool
                    # set으로 중복 방지
                    # pool은 opp2bot 1개 + (배틀,밤까) 봇 1개 + 배틀 봇 1개 + 탱크 봇 1개 + 밴시 봇 1개 + 타 팀 봇(flash/magic) 6개 + pool 4개 = max 15개의 봇으로 구성
                    # pool = ["Opp2Bot", "OppBotBattle", "OppBotBattleNoRaven", \
                    #            "OppBotTank", "OppBotBanshee", "OppBotFlash", "OppBotFlash", "OppBotFlashFast", "OppBotFlashFast", "OppBotMagic", "OppBotMagic"]
                    pool = ["Opp2Bot", "OppBotBattle", "OppBotBattleNoRaven", \
                                "OppBotTank", "OppBotBanshee", "OppBotFlashNew", "OppBotFlashNewRaven", "OppBotFlashFast", "OppBotFlashFast", "OppBotMagic", "OppBotMagic"]
                    for i in range(1, 4):
                        model_path = pathlib.Path(__file__).parent / (
                            'model' + str(i) + '.pt')
                        if os.path.isfile(model_path):
                            pool.append(str(i))
                    '''
                    win = pickle.loads(tmp[1])

                    rates = []
                    # 뽑을 확률 설정
                    probs = np.repeat(0.5 / len(pool), len(pool))

                    for p in pool:
                        win_tmp = win[p]

                        if len(win_tmp) > 10:
                            win_tmp = win_tmp[-10:-1]
                        if not win_tmp:  # 비어있으면 => 게임 한판도 안했으면
                            rates.append(1 - 1 / len(pool))
                        else:
                            rates.append(1 - np.mean(win_tmp))

                    for i, rate in enumerate(rates) :
                        prob = (rate / np.sum(rates) / 2)
                        probs[i] = probs[i] + prob

                    bot_str = list(np.random.choice(pool, 1, False, probs))[0]

                    players[0] = _Bot(Race.Terran, MyBot(step_interval, hostname, sock, bot_str))
                    '''
                    bot_str = list(np.random.choice(pool, 1))[0]

                    players[0] = _Bot(
                        Race.Terran,
                        MyBot(step_interval, hostname, sock, bot_str))

                    if bot_str == "Opp2Bot":
                        players[1] = _Bot(Race.Terran, Opp2Bot())
                    elif bot_str == "OppBotBattle":
                        players[1] = _Bot(Race.Terran, OppBotBattle())
                    elif bot_str == "OppBotBattleNoRaven":
                        players[1] = _Bot(Race.Terran, OppBotBattleNoRaven())
                    elif bot_str == "OppBotTank":
                        players[1] = _Bot(Race.Terran, OppBotTank())
                    elif bot_str == "OppBotBanshee":
                        players[1] = _Bot(Race.Terran, OppBotBanshee())
                    elif bot_str == "OppBotFlashNew":
                        players[1] = _Bot(Race.Terran, OppBotFlashNew())
                    elif bot_str == "OppBotFlashNewRaven":
                        players[1] = _Bot(Race.Terran, OppBotFlashNewRaven())
                    elif bot_str == "OppBotFlashFast":
                        players[1] = _Bot(Race.Terran, OppBotFlashFast())
                    elif bot_str == "OppBotMagic":
                        players[1] = _Bot(Race.Terran, OppBotMagic())
                    else:
                        players[1] = _Bot(
                            Race.Terran,
                            MyBot(step_interval, hostname, None, None,
                                  bot_str))

                    # 게임 세팅이 완료되면 event를 set해서 join 쪽도 다음 과정을 진행하도록 함
                    aio_event.set()
                    # 게임이 새로 시작했음을 부모 프로세스에 알림
                    alive_evnet.set()

                    # 게임 시작
                    map_settings = sc2.maps.get(task_dict['game_map'])
                    await server.ping()
                    client = await _setup_host_game(server, map_settings,
                                                    players, realtime,
                                                    random_seed)

                    result = await _play_game(players[0], client, realtime,
                                              portconfig, step_time_limit,
                                              game_time_limit,
                                              rgb_render_config)

                    # Result.Defeat, Result.Tie, Result.Victory
                    #if result == Result.Defeat :
                    #    self.win[bot_str].append(-1)
                    #elif result == Result.Tie :
                    #    self.win[bot_str].append(0)
                    #elif result == Result.Victory :
                    #    self.win[bot_str].append(1)
                    # print(result)

                    if save_replay_as is not None:
                        await client.save_replay(save_replay_as)
                    await client.leave()
                    # await client.quit()  # 게임 인스턴스 재시작을 위해 프로세스 종료하지 않음
            except:
                # 예외가 발생하면 부모 프로세스에 전달
                import traceback
                exc_queue.put(traceback.format_exc())

            # n_games 만큼 게임을 반복했음을 부모 프로세스에 알림
            # join에서 host를 죽이거나, host에서 join을 죽일 경우를 대비해서,
            # host와 join 양쪽에 req_kill_evnet를 set 해야함
            # -> 어떤 경우에도 부모는 이 프로세스를 종료해야함을 알 수 있음
            req_kill_event.set()