diff --git a/README.md b/README.md index 008335df..b730cc41 100644 --- a/README.md +++ b/README.md @@ -108,20 +108,20 @@ Environment exposes following `raw` observations: - `right_team_yellow_card` - same as for left team. - `right_team_active` - same as for left team. - `right_team_roles` - same as for left team. -- Controlled player information: - - `active` - a list of {0..N-1} integer denoting indices of the controlled players. In most common case the list will contain just one element, but in multi-agent setup it will be more. - - `sticky_actions` - 11-elements vector of 0s or 1s denoting whether corresponding actions are active: - - `game_left` - - `game_top_left` - - `game_top` - - `game_top_right` - - `game_right` - - `game_bottom_right` - - `game_bottom` - - `game_bottom_left` - - `game_sprint` - - `game_keeper_rush` - - `game_dribble` +- Controlled players information (M is the number of controlled players): + - `active` - M-elements list of {0..N-1} integers denoting indices of the controlled players. In most common case the list will contain just one element, but in multi-agent setup it will be more. + - `sticky_actions` - M-elements list of 11-elements vectors of 0s or 1s denoting whether corresponding action is active: + - `0` - `game_left` + - `1` - `game_top_left` + - `2` - `game_top` + - `3` - `game_top_right` + - `4` - `game_right` + - `5` - `game_bottom_right` + - `6` - `game_bottom` + - `7` - `game_bottom_left` + - `8` - `game_sprint` + - `9` - `game_keeper_rush` + - `10` - `game_dribble` - Match state: - `score` - pair of integers denoting number of goals for left and right teams, respectively. - `steps_left` - how many steps are left till the end of the match. diff --git a/gfootball/env/players/bot.py b/gfootball/env/players/bot.py index f67e362f..1430578b 100644 --- a/gfootball/env/players/bot.py +++ b/gfootball/env/players/bot.py @@ -31,6 +31,7 @@ def __init__(self, player_config, env_config): self._last_observation = None self._last_action = football_action_set.action_idle self._shoot_distance = 0.15 + self._pressure_enabled = False def _object_distance(self, object1, object2): """Computes distance between two objects.""" @@ -175,8 +176,12 @@ def _get_action(self): if self._observation['ball_owned_team'] == (1 if is_active_left else 0): if self._last_action == football_action_set.action_pressure: return football_action_set.action_sprint + self._pressure_enabled = True return football_action_set.action_pressure + if self._pressure_enabled: + self._pressure_enabled = False + return football_action_set.action_release_pressure target_x = 0.85 if is_active_left else -0.85 if (self._shoot_distance > diff --git a/gfootball/env/players/replay.py b/gfootball/env/players/replay.py index d0bd35ea..d1e42b49 100644 --- a/gfootball/env/players/replay.py +++ b/gfootball/env/players/replay.py @@ -30,6 +30,8 @@ def __init__(self, player_config, env_config): self._player = player_config['index'] def take_action(self, observations): + assert len(observations['active'] + ) == 1, 'Replay does not support multiple player control' if self._step == len(self._replay): print("Replay finished.") exit(0) diff --git a/gfootball/env/scenario_builder.py b/gfootball/env/scenario_builder.py index 67292679..61d775cd 100644 --- a/gfootball/env/scenario_builder.py +++ b/gfootball/env/scenario_builder.py @@ -31,10 +31,18 @@ FLAGS = flags.FLAGS + def all_scenarios(): path = os.path.abspath(__file__) - path = os.path.join(os.path.dirname(os.path.dirname(path)), "scenarios") - return [m.name for m in pkgutil.iter_modules([path])] + path = os.path.join(os.path.dirname(os.path.dirname(path)), 'scenarios') + scenarios = [] + for m in pkgutil.iter_modules([path]): + if m.__class__ == tuple: + scenarios.append(m[1]) + else: + scenarios.append(m.name) + return scenarios + class Scenario(object): diff --git a/gfootball/replay.py b/gfootball/replay.py index 412786f3..0abf09ae 100644 --- a/gfootball/replay.py +++ b/gfootball/replay.py @@ -58,9 +58,16 @@ def modify_trace(replay): trace.append(idle_step) return trace +def build_players(dump_file, spec): + players = [] + for player in spec: + player_type = 'replay:path={},players=1'.format(dump_file) + for _ in range(config.parse_number_of_players(player)): + players.append(player_type) + return players -def main(_): - with open(FLAGS.trace_file, 'rb') as f: +def replay(directory, dump, config_update={}): + with open(dump, 'rb') as f: replay = six.moves.cPickle.load(f) trace = modify_trace(replay) fd, temp_path = tempfile.mkstemp(suffix='.dump') @@ -69,17 +76,15 @@ def main(_): assert replay[0]['debug']['frame_cnt'] == 1, ( 'Trace does not start from the beginning of the episode, can not replay') cfg = config.Config(replay[0]['debug']['config']) - player_type = 'replay:path={},players={}'.format( - temp_path, len(replay[0]['debug']['action'])) - cfg['left_players'] = [player_type] * len(cfg['left_players']) - cfg['right_players'] = [player_type] * len(cfg['right_players']) - cfg.update({ - 'physics_steps_per_frame': int(100 / FLAGS.fps), - 'real_time': False, - 'render': True, - 'tracesdir': '/tmp/dumps', - 'write_video': True - }) + cfg['left_players'] = build_players(temp_path, cfg['left_players']) + cfg['right_players'] = build_players(temp_path, cfg['right_players']) + config_update['physics_steps_per_frame'] = int(100 / FLAGS.fps) + config_update['real_time'] = False + if 'render' not in config_update: + config_update['render'] = True + config_update['tracesdir'] = directory + config_update['write_video'] = True + cfg.update(config_update) env = football_env.FootballEnv(cfg) env.reset() done = False @@ -91,6 +96,8 @@ def main(_): exit(1) os.close(fd) +def main(_): + replay('/tmp/dumps', FLAGS.trace_file) if __name__ == '__main__': app.run(main)