def PlayerPass(self, source_player, target_player, simulate, verbosity): assert (self.control.GetControl() is source_player) interceptor, through_chance = self.physics.InterceptTest( source_player.GetPosition(self), target_player.GetPosition(self), self.GetCapableTeamPlayers( TeamSide.Opposite(self.control.GetControl().team_side)), max(0, verbosity - 1)) if not simulate: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.PASS, source_player.name, target_player.name)) if interceptor: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.PASS_INTERCEPT, interceptor.name, source_player.name)) self.control.GiveControl(interceptor) interceptor.ResponseTime(self, self.rules.receive_response_time) else: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.PASS_COMPLETE, target_player.name, source_player.name)) self.control.GiveControl(target_player) target_player.ResponseTime(self, self.rules.receive_response_time) source_player.ResponseTime(self, self.rules.pass_response_time) return through_chance
def RandomlyGiveControl(self): # random player seemed to mostly pick the first player # now alternating teams and picking random player team = int( (self.state.series.home_score + self.state.series.away_score)) % 2 if len(self.team_players[team]) == 0: team = TeamSide.Opposite(team) target = random.choice(self.team_players[team]) self.control.GiveControl(target) target.ResponseTime(self, self.rules.receive_response_time)
def PlayerShot(self, player, simulate, verbosity): if not simulate: assert (self.control.GetControl() is player) on_net_chance = self.ComputeOnNetChance(player) on_net = random.random() < on_net_chance interceptor, through_chance = self.physics.InterceptTest( player.GetPosition(self), player.GetAttackingNetPos(self), self.GetCapableTeamPlayers( TeamSide.Opposite(self.control.GetControl().team_side)), max(0, verbosity - 1)) if not simulate: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.SHOT, player.name, '')) player.ResponseTime(self, self.rules.shot_response_time) if interceptor: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.SHOT_BLOCK, interceptor.name, player.name)) self.control.GiveControl(interceptor) interceptor.ResponseTime(self, self.rules.receive_response_time) else: if on_net: self.AwardGoal(player) self.control.Reset(self) else: self.game_event_history.AddEvent( GameEvent(self.tick, STS2Event.MISSED_SHOT, player.name, '')) # give possession to closest player attacking_net_pos = player.GetAttackingNetPos(self) min_dist = None rebound_player = None for player in self.players: # project player onto trajectory to find unconstrained intercept point dist = numpy.linalg.norm( player.GetPosition(self) - attacking_net_pos) if min_dist is None or dist < min_dist: min_dist = dist rebound_player = player self.control.GiveControl(rebound_player) rebound_player.ResponseTime( self, self.rules.receive_response_time) return through_chance * on_net_chance
def DrawActions(self, game_state): width = 3 for team_side in TeamSide.TEAMSIDES: team_prefix = GameState.TEAMSIDE_PREFIXES[team_side] other_team_prefix = GameState.TEAMSIDE_PREFIXES[TeamSide.Opposite( team_side)] team_players = int(game_state[team_prefix + GameState.TEAM_PLAYERS]) control_team = game_state[GameState.CONTROL_TEAM] control_index = game_state[GameState.CONTROL_INDEX] control_posx = game_state[GameState.TEAMSIDE_PREFIXES[control_team] + str(control_index) + GameState.PLAYER_POS_X] control_posz = game_state[GameState.TEAMSIDE_PREFIXES[control_team] + str(control_index) + GameState.PLAYER_POS_Z] for player_index in range(team_players): player_action = game_state[team_prefix + str(player_index) + GameState.PLAYER_ACTION] posx = game_state[team_prefix + str(player_index) + GameState.PLAYER_POS_X] posz = game_state[team_prefix + str(player_index) + GameState.PLAYER_POS_Z] if player_action is Action.SHOOT: colour = pygame.Color('black') if game_state[GameState. CURRENT_PHASE] != GamePhase.STOPPAGE_GOAL: colour = pygame.Color('red') pygame.draw.line( self.screen, pygame.Color('black'), self.GameCoordToScreenCoord(posx, posz), self.GameCoordToScreenCoord( control_posx, control_posz), width) net_posx = game_state[other_team_prefix + GameState.TEAM_NET_X] net_posz = game_state[other_team_prefix + GameState.TEAM_NET_Z] pygame.draw.line( self.screen, colour, self.GameCoordToScreenCoord(posx, posz), self.GameCoordToScreenCoord(net_posx, net_posz), width) elif player_action in Action.PASSES: for teammate_index, action in zip(range(team_players), Action.PASSES): if action is player_action: teammate_posx = game_state[team_prefix + str(teammate_index) + GameState.PLAYER_POS_X] teammate_posz = game_state[team_prefix + str(teammate_index) + GameState.PLAYER_POS_Z] colour = pygame.Color('black') has_control = control_team == team_side and control_index == teammate_index if not has_control: colour = pygame.Color('red') pygame.draw.line( self.screen, pygame.Color('black'), self.GameCoordToScreenCoord(posx, posz), self.GameCoordToScreenCoord( control_posx, control_posz), width) pygame.draw.line( self.screen, colour, self.GameCoordToScreenCoord(posx, posz), self.GameCoordToScreenCoord( teammate_posx, teammate_posz), width)
def GetAttackingNetPos(self, game): return game.arena.net_position[TeamSide.Opposite(self.team_side)]
class GameState: TICK = "tick" CURRENT_PHASE = 'current_phase' PREVIOUS_PHASE = 'previous_phase' ARENA_MIN_X = 'arena_min_x' ARENA_MAX_X = 'arena_max_x' ARENA_MIN_Z = 'arena_min_z' ARENA_MAX_Z = 'arena_max_z' HOME = TeamSide.GetName(TeamSide.HOME) AWAY = TeamSide.GetName(TeamSide.AWAY) TEAMSIDE_PREFIXES = [HOME, AWAY] # per-team properites TEAM_NET_X = '_net_x' TEAM_NET_Z = '_net_z' TEAM_SCORE = '_score' TEAM_ATTACK_Z = '_attack_z' TEAM_PLAYERS = '_players' # per-player properties PLAYER_NAME = "_name" PLAYER_IS_HUMAN = "_is_human" PLAYER_POS_X = "_pos_x" PLAYER_POS_Z = "_pos_z" PLAYER_VEL_X = "_vel_x" PLAYER_VEL_Z = "_vel_z" PLAYER_INPUT_X = "_input_x" PLAYER_INPUT_Z = "_input_z" PLAYER_ACTION = "_action" PLAYER_ACTION_TIME = "_action_time" CONTROL_TEAM = "control_team" CONTROL_INDEX = "control_index" def __init__(self, game): self.game = game self.series = pandas.Series() self.Init() def Init(self): # static values that don't change # WARNING: assumes home and away don't switch sides self.SetField(self.ARENA_MIN_X, self.game.arena.min_x, init=True) self.SetField(self.ARENA_MAX_X, self.game.arena.max_x, init=True) self.SetField(self.ARENA_MIN_Z, self.game.arena.min_z, init=True) self.SetField(self.ARENA_MAX_Z, self.game.arena.max_z, init=True) self.SetField(self.CONTROL_TEAM, TeamSide.HOME, init=True) self.SetField(self.CONTROL_INDEX, 0, init=True) # set up fields for team values for teamside, sidename in zip(TeamSide.TEAMSIDES, self.TEAMSIDE_PREFIXES): self.SetTeamField(teamside, self.TEAM_NET_X, self.game.arena.net_position[teamside][0], init=True) self.SetTeamField(teamside, self.TEAM_NET_Z, self.game.arena.net_position[teamside][1], init=True) self.SetTeamField(teamside, self.TEAM_ATTACK_Z, numpy.sign( self.game.arena.net_position[teamside][1]), init=True) self.SetTeamField(teamside, self.TEAM_SCORE, 0, init=True) self.SetTeamField(teamside, self.TEAM_PLAYERS, len(self.game.team_players[teamside]), init=True) # set up fields for player values for player in self.game.players: self.SetPlayerField(player, self.PLAYER_NAME, player.name, init=True) self.SetPlayerField(player, self.PLAYER_IS_HUMAN, int(player.IsHuman()), init=True) self.SetPlayerPosition(player, numpy.zeros(2)) self.SetPlayerVelocity(player, numpy.zeros(2)) self.SetPlayerInput(player, numpy.zeros(2)) self.SetPlayerField(player, self.PLAYER_ACTION, Action.NONE, init=True) self.SetPlayerField(player, self.PLAYER_ACTION_TIME, 0, init=True) def GetSnapshot(self): # MAS, generic OpenAI-like use return {field: self.series[field] for field in self.series.index} def SetFromSnapshot(self, json_data): # MAS, used for MCTS load game state """No asserts, assuming json_data matches the columns.""" for field, value in json_data: self.series[field] = value def GetField(self, field): return self.series[field] def SetField(self, field, value, init=False): assert (init or field in self.series) self.series[field] = value def GetTeamFieldPrefix(self, teamside): return TeamSide.GetName(teamside) def GetTeamFieldName(self, teamside, field): return self.GetTeamFieldPrefix(teamside) + field def GetTeamField(self, teamside, field): return self.GetField(self.GetTeamFieldName(teamside, field)) def SetTeamField(self, teamside, field, value, init=False): field_name = self.GetTeamFieldPrefix(teamside) + field assert (init or field_name in self.series) self.series[field_name] = value def GetPlayerFieldPrefix(self, player): team_index = self.game.team_players[player.team_side].index(player) return TeamSide.GetName(player.team_side) + str(team_index) def GetPlayerField(self, player, field): return self.series[self.GetPlayerFieldPrefix(player) + field] def SetPlayerField(self, player, field, value, init=False): field_name = self.GetPlayerFieldPrefix(player) + field # ensure we are not adding incorrect fields through assignment assert (init or field_name in self.series) self.series[field_name] = value def GetPlayerPosition(self, player): prefix = self.GetPlayerFieldPrefix(player) return numpy.array([ self.series[prefix + self.PLAYER_POS_X], self.series[prefix + self.PLAYER_POS_Z] ]) def SetPlayerPosition(self, player, pos): prefix = self.GetPlayerFieldPrefix(player) self.series[prefix + self.PLAYER_POS_X] = pos[0] self.series[prefix + self.PLAYER_POS_Z] = pos[1] def GetPlayerVelocity(self, player): prefix = self.GetPlayerFieldPrefix(player) return numpy.array([ self.series[prefix + self.PLAYER_VEL_X], self.series[prefix + self.PLAYER_VEL_Z] ]) def SetPlayerVelocity(self, player, pos): prefix = self.GetPlayerFieldPrefix(player) self.series[prefix + self.PLAYER_VEL_X] = pos[0] self.series[prefix + self.PLAYER_VEL_Z] = pos[1] def GetPlayerInput(self, player): prefix = self.GetPlayerFieldPrefix(player) return numpy.array([ self.series[prefix + self.PLAYER_INPUT_X], self.series[prefix + self.PLAYER_INPUT_Z] ]) def SetPlayerInput(self, player, pos): prefix = self.GetPlayerFieldPrefix(player) self.series[prefix + self.PLAYER_INPUT_X] = pos[0] self.series[prefix + self.PLAYER_INPUT_Z] = pos[1]
def GetPlayerFieldPrefix(self, player): team_index = self.game.team_players[player.team_side].index(player) return TeamSide.GetName(player.team_side) + str(team_index)
def GetTeamFieldPrefix(self, teamside): return TeamSide.GetName(teamside)