コード例 #1
0
ファイル: actions_tests.py プロジェクト: Delaunay/LuaFun
    def __init__(self,
                 send_actions,
                 check_action,
                 draft=0,
                 action_wait=0.26,
                 timeout=1,
                 **kwargs):
        super(DotaTestEnvironment,
              self).__init__(option('dota.path', guess_path()),
                             True,
                             draft=draft)

        self.options.game_mode = int(DOTA_GameMode.DOTA_GAMEMODE_AP)
        self.options.ticks_per_observation = 4
        self.options.host_timescale = 2

        self.err = None
        self.action_sent = False
        self.check_action = check_action
        self.send_actions = send_actions
        self.action_checked = False
        self.kwargs = kwargs
        self.timeout = 0
        self.timeout_deadline = timeout
        self.action_wait = action_wait
コード例 #2
0
ファイル: scratch.py プロジェクト: Delaunay/LuaFun
def gym_main():
    import sys

    from luafun.utils.options import option
    sys.stderr = sys.stdout

    p = option('dota.path', guess_path())
    main(p)
コード例 #3
0
ファイル: game.py プロジェクト: Delaunay/LuaFun
    def __init__(self,
                 path=option('dota.path', None),
                 dedicated=True,
                 draft=0,
                 config=None):
        self.paths = DotaPaths(path)
        self.options = DotaOptions(dedicated=dedicated, draft=draft)
        self.args = None

        self.process = None
        self.reply_count = defaultdict(int)

        self.manager = None
        self.state = None

        self.dire_state_process = None
        self.radiant_state_process = None

        self.dire_state_delta_queue = None
        self.radiant_state_delta_queue = None

        self.ipc_recv_process = None
        self.ipc_recv_queue = None

        self.config = config
        self.http_server = None
        self.http_rpc_send = None
        self.http_rpc_recv = None

        self.heroes = None
        self.uid = StateHolder()
        self.ready = False
        self.pending_ready = True
        self.bot_count = 10
        self.stats = Stats()
        self.players = {TEAM_RADIANT: 0, TEAM_DIRE: 0}

        self.dire_bots = []
        self.rad_bots = []

        self.dire_perf = None
        self.rad_perf = None
        self.dire_perf_prev = None
        self.rad_perf_prev = None
        self.perf = ProcessingStates(0, 0, 0, 0, 0, 0, 0, 0)

        self.extractor = Extractor()
        self.replay = SaveReplay('replay.txt')
        log.debug(f'Main Process: {os.getpid()}')
        self._bots = []

        # IPC config to configure bots
        self.ipc_config = {
            'draft_start_wait': 10,
            'draft_pick_wait': 1,
        }
        ipc_send(self.paths.ipc_config_handle, self.ipc_config, StateHolder())
コード例 #4
0
    def __init__(self,
                 path=option('dota.path', None),
                 dedicated=True,
                 draft=0,
                 stitcher=None,
                 reward=None,
                 _config=None):
        super(Dota2Env, self).__init__(path, dedicated, draft, config=_config)
        # For debugging only
        # self.radiant_message = open(self.paths.bot_file('out_radiant.txt'), 'w')
        # self.dire_message = open(self.paths.bot_file('out_dire.txt'), 'w')

        self._action_space = action_space()

        # Function to stich state together
        if stitcher is None:
            stitcher = Stitcher

        self.sticher_factory = stitcher
        self.dire_stitcher = stitcher(faction=TEAM_DIRE)
        self.radiant_stitcher = stitcher(faction=TEAM_RADIANT)

        # Reward function
        if reward is None:
            reward = Reward()

        self.reward = reward

        # Draft tracker for the drafting AI
        self.draft_tracker = DraftTracker()
        self.radiant_stitcher.draft = self.draft_tracker.draft
        self.dire_stitcher.draft = self.draft_tracker.draft

        self.has_next = 0
        self.step_start = None
        self.step_end = 0
        self.cnt = 0
        self.avg = 0
コード例 #5
0
class OpenDotaAPI(WebAPI):
    URL = 'https://api.opendota.com/api/{method}'
    KEY = option('opendota.api', None)

    def __init__(self):
        super(OpenDotaAPI, self).__init__('opendota')

        now = datetime.datetime.now()
        day_count = calendar.monthrange(now.year, now.month)[1]

        # 50000 per month
        self.max_api_call_day = 50000 // day_count
        # 60 calls per minute
        self.wait_time = 2

    def explore(self, sql):
        params = {
            'sql': sql,
            'key': self.KEY,
        }

        url = self.URL.format(method='explorer')
        response = requests.get(url, params=params)

        self.handle_errors(response)
        self.limit()

        data = response.json()
        rows = data.get('rows')

        if rows is not None:
            return rows

        return data

    def get_player(self, player_id):
        """

        >>> OpenDotaAPI().get_player(81280209)
        {
          "tracked_until": "1621953083",
          "leaderboard_rank": null,
          "solo_competitive_rank": null,
          "profile": {
            "account_id": 81280209,
            "personaname": "Sétepenrê",
            "name": null,
            "plus": false,
            "cheese": 0,
            "steamid": "76561198041545937",
            "avatar": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/e6/e68a0b9be84eafb21eadd5fa73a32c995fc7991b.jpg",
            "avatarmedium": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/e6/e68a0b9be84eafb21eadd5fa73a32c995fc7991b_medium.jpg",
            "avatarfull": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/e6/e68a0b9be84eafb21eadd5fa73a32c995fc7991b_full.jpg",
            "profileurl": "https://steamcommunity.com/id/setepenre/",
            "last_login": "******",
            "loccountrycode": null,
            "is_contributor": false
          },
          "rank_tier": 24,
          "competitive_rank": null,
          "mmr_estimate": {
            "estimate": 2223
          }
        }
        """
        params = {
            'key': self.KEY,
        }

        url = self.URL.format(method='players') + f'/{player_id}'
        response = requests.get(url, params=params)

        self.handle_errors(response)
        self.limit()

        return response.json()

    def get_all_pick_draft(self, count, offset, version="7.28"):
        """Does not work, opendota does not save pick order for public matches only
        pro matches"""
        mode = int(DOTA_GameMode.DOTA_GAMEMODE_ALL_DRAFT)
        start7_28 = 1608249726
        start7_29 = 1617981499

        # Game mode in open dota is not correct
        # matches.game_mode = {mode}        AND
        query = f"""
        SELECT 
            public_matches.match_id,
            public_matches.radiant_win,
            match_patch.patch,
            public_matches.avg_rank_tier,
            public_matches.num_rank_tier,
            picks_bans.is_pick, 
            picks_bans.hero_id, 
            picks_bans.team, 
            picks_bans.ord  
        FROM 
            public_matches,
            picks_bans
        INNER JOIN match_patch USING(match_id)
        INNER JOIN picks_bans USING(match_id)
        WHERE
            public_matches.start_time >= {start7_28} AND
            public_matches.start_time <= {start7_29} AND
            match_patch.patch = '{version}'
        LIMIT {count}
        """

        if offset is not None:
            query = f'{query} OFFSET {offset}'

        query = f'{query};'

        return self.explore(query)

    def get_all_pick_draft_match_id(self, count, offset):
        """Does not work, opendota does not save pick order for public matches only
        pro matches"""
        mode = int(DOTA_GameMode.DOTA_GAMEMODE_ALL_DRAFT)
        start7_28 = 1608249726
        start7_29 = 1617981499

        # Game mode in open dota is not correct
        # matches.game_mode = {mode}        AND
        query = f"""
        SELECT 
            *
        FROM 
            public_matches
        WHERE
            public_matches.start_time >= {start7_28} AND
            public_matches.start_time <= {start7_29} AND
            public_matches.game_mode = 22
        LIMIT {count}
        """

        if offset is not None:
            query = f'{query} OFFSET {offset}'

        query = f'{query};'

        return self.explore(query)

    def get_captains_mode_matches(self, count, offset, version="7.28", mode=2):
        """To make sure your query is fast you should use a time constrain
        so the DB can focus on the partition that matters
        """
        query = f"""
        SELECT 
            matches.match_id,
            matches.radiant_win,
            matches.picks_bans,
            match_patch.patch
        FROM 
            matches
        INNER JOIN match_patch USING(match_id)
        WHERE
            matches.human_players = 10          AND
            matches.game_mode = {mode}          AND
            matches.picks_bans IS NOT NULL
        LIMIT {count}
        """

        if offset is not None:
            query = f'{query} OFFSET {offset}'

        query = f'{query};'

        return self.explore(query)
コード例 #6
0
from collections import defaultdict
import json
import logging

from luafun.utils.options import option


log = logging.getLogger(__name__)


EXTRACT_ENABLED = option('extract', False, bool)
REPLAY_ENABLED = option('replay', True, bool)


class SaveReplay:
    """Save Proto messages we receive to replay the match for debugging purposes"""
    def __init__(self, filename):
        self.store = open(filename, 'w')

    def save(self, radiant, dire):
        if not REPLAY_ENABLED:
            return

        radiant.pop('perf', None)
        dire.pop('perf', None)

        self.store.write(f'RAD, {json.dumps(radiant)}\nDIRE,  {json.dumps(dire)}\n')

    def close(self):
        self.store.close()
コード例 #7
0
    def connect(self):
        port = option('debug.port', 8080, int)
        host = "127.0.0.1"

        self.sock = socket.create_server((host, port))
        log.debug(f'Listening to {host}:{port}')
コード例 #8
0
ファイル: steamapi.py プロジェクト: Delaunay/LuaFun
from dataclasses import dataclass
import json
import time
from typing import List
import zipfile
import os
import gzip
import datetime
import requests

from luafun.utils.options import option
from luafun.game.game import DOTA_GameMode
from luafun.steamapi.api import WebAPI, ServerError, LimitExceeded

# set export LUAFUN_STEAM_API=XXXX
STEAM_API_KEY = option('steam.api', None)
DOTA_ID = 570
DOTA_PRIVATE_BETA = 816
DOTA_BETA_TEST = 205790


@dataclass
class MatchHistory_Match_Player:
    account_id: int
    player_slot: int
    hero_id: int

    def is_dire(self):
        return (self.player_slot & 0b10000000) >> 7

    def position(self):
コード例 #9
0
def main(config=None):
    """This simply runs the environment until the game finishes, default to RandomActor (actions are random)
    It means bots will not do anything game winning, if drafting is enabled nothing will be drafted
    """

    parser = ArgumentParser()
    parser.add_argument('--draft',
                        action='store_true',
                        default=False,
                        help='Enable bot drafting')

    parser.add_argument('--mode',
                        type=str,
                        default='allpick_nobans',
                        help='Game mode')

    parser.add_argument('--path',
                        type=str,
                        default=option('dota.path', None),
                        help='Custom Dota2 game location')

    parser.add_argument('--render',
                        action='store_true',
                        default=False,
                        help='Render the game on screen')

    parser.add_argument('--speed',
                        type=float,
                        default=4,
                        help='Speed multiplier')

    parser.add_argument('--interactive',
                        action='store_true',
                        default=False,
                        help='Make a human create the lobby')

    # --model socket://192.163.0.102:8080
    parser.add_argument(
        '--model',
        type=str,
        default='random',
        help='Model name factory, defaults to a random action sampler')

    # --trainer socket://192.163.0.103:8081
    parser.add_argument('--trainer', type=str, default='random', help='')

    args = parser.parse_args()
    game = dota2_environment(args.mode, args.path, config=config)

    if game is None:
        return

    # logging.basicConfig(level=logging.INFO)
    logging.basicConfig(level=logging.DEBUG)

    game.options.dedicated = not args.render
    game.options.interactive = args.interactive
    game.options.host_timescale = args.speed
    game.options.draft = int(args.draft)

    obs_size = game.observation_space
    train = TrainEngine(args.trainer, args.model, (obs_size, 10, 16))
    model = InferenceEngine(args.model, train)

    with game:
        # Initialize Drafter & Encoders
        if game.options.draft:
            model.init_draft()
        # ---

        state, reward, done, info = game.initial()

        # Draft here if enabled
        while game.running:

            if game.options.draft:
                pass

            break

        game.wait_end_draft()
        model.close_draft()
        model.init_play(game)

        uid = game.options.game_id

        # Play the game
        while game.running:
            # start issuing orders here
            action, logprob, filter = model.action(uid, state)

            # select an action to perform
            state, reward, done, info = game.step(action)

            # push the new observation
            train.push(uid, state, reward, done, info, action, logprob, filter)

            if train.ready():
                train.train()

            if state is None:
                break

            if game.cnt > 0 and game.cnt % 100 == 0:
                print(
                    f'Step time {game.avg / game.cnt:.4f} Reward {reward[0]}')

        print('Game Finished')

    print('Done')