Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 91
Input and Output Data
The base agent has some useful values that we can read from in order to get some basic information about the car that we are controlling, the team our car is on, and even the name of our car in the game.
These values can be accessed at any time from the base agent using the self parameter:
definitialize_agent(self):
# Print the bot's teamprint(self.team)
defget_output(self, packet: GameTickPacket) ->SimpleControllerState:
# Get our carmy_car=packet.game_cars[self.index]Some useful values to know are:
self.team=0# The team that our bot is onself.name="ExampleBot"# Our bot's in-game nameself.index=2# The index of the car our agent is controllingEvery tick, your bot will receive a GameTickPacket from the framework. The packet will contain all the raw values from the game (such as car and ball locations). Your bot receives the packet in the get_output(self, packet) function and you should return a ControllerState which describes what your bot's response is.
Getting values from the packet is simple:
defget_output(self, packet: GameTickPacket) ->SimpleControllerState:
# You can get values out of the packet like this:x_location_of_first_car=packet.game_cars[0].physics.location.x;NOTE: Some structs/lists in the GameTickPacket has a fixed length. So make sure you use the num_cars and the num_boosts values as lengths if you iterate through the associated lists.
packet: {
'game_cars': [
{
'physics': {
'location': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'rotation': {'pitch': 0.0, 'yaw': 0.0, 'roll': 0.0},
'velocity': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'angular_velocity': {'x': 0.0, 'y': 0.0, 'z': 0.0}
},
'is_demolished': False,
'has_wheel_contact': True,
'is_super_sonic': False,
'is_bot': True,
'jumped': False,
'double_jumped': True,
'name': 'Jupiter',
'team': 0,
'boost': 48.0,
'hitbox': {'length': 118, 'width': 84, 'height': 36},
'hitbox_offset': {'x': 13.88, 'y': 0.0, 'z': 20.75},
'score_info': {
'score': 340,
'goals': 2,
'own_goals': 0,
'assists': 1,
'saves': 1,
'shots': 3,
'demolitions': 1
}
},
{ ... }
],
'num_cars': 2,
'game_boosts': [
{
'is_active': True,
'timer': 0.0
},
{ ... }
],
'num_boost': 36,
'game_ball': {
'physics': {
'location': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'rotation': {'pitch': 0.0, 'yaw': 0.0, 'roll': 0.0},
'velocity': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'angular_velocity': {'x': 0.0, 'y': 0.0, 'z': 0.0}
},
'latest_touch': {
'player_name': 'Beavis',
'time_seconds': 120.63,
'hit_location': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'hit_normal': {'x': 0.0, 'y': 0.0, 'z': 0.0},
'team': 0,
'player_index': 0
},
'drop_shot_info': {
'damage_index': 0,
'absorbed_force': 0,
'force_accum_recent': 0
},
'collision_shape': {
'type': 1,
'box': {'length': 153.0, 'width': 153.0, 'height': 153.0},
'sphere': {'diameter': 184.0},
'cylinder': {'diameter': 184.0, 'height': 30.0}
}
},
'game_info': {
'seconds_elapsed': 405.12,
'game_time_remaining': 34.0,
'is_overtime': False,
'is_unlimited_time': False,
'is_round_active': True,
'is_kickoff_pause': False,
'is_match_ended': False,
'world_gravity_z': -650.0,
'game_speed': 1.0,
'frame_num': 3923
},
'teams': [
{
'team_index': 0,
'score': 7
},
{ ... }
],
'num_teams': 2,
}A ControllerState is the controller input the bot should perform. Import ControllerState like this: from rlbot.agents.base_agent import SimpleControllerState, and create a new instance with SimpleControllerState()
Example:
fromrlbot.agents.base_agentimportBaseAgent, SimpleControllerStatefromrlbot.utils.structures.game_data_structimportGameTickPacketclassExampleBot(BaseAgent):
definitialize_agent(self):
passdefget_output(self, packet: GameTickPacket) ->SimpleControllerState:
# Make the bot go forwards by setting throttle to 1controller=SimpleControllerState()
controller.throttle=1returncontrollerThe ControllerState has the following attributes:
{
throttle:float; /// -1 for full reverse, 1 for full forward
steer:float; /// -1 for full left, 1 for full right
pitch:float; /// -1 for nose down, 1 for nose up
yaw:float; /// -1 for full left, 1 for full right
roll:float; /// -1 for roll left, 1 for roll right
jump:bool; /// true if you want to press the jump button
boost:bool; /// true if you want to press the boost button
handbrake:bool; /// true if you want to press the handbrake button
use_item:bool; /// true if you want to use a rumble item
}
A few values are constant, like the locations of boosts and goals. Some of these can be found in the FieldInfo data. FieldInfo contains the following:
field_info: {
'boost_pads': [
{
'location': Vector3,
'is_full_boost': boolean
},
{ ... }
],
'num_boosts': int,
'goals': [
{
'team_num': int,
'location': Vector3,
'direction': Vector3,
'width': float,
'height': float
},
{ ... }
],
'num_goals': int
}Note: Dropshot tiles can be found in FieldInfo as GoalInfo objects.
Note2: Boost pads and Dropshot tiles will be sorted according to y * 100 + x, just like their counterparts (game_boosts and dropshot_tiles that contain their current state) in the game tick packet.
In Python, you can retrieve this information by calling get_field_info() on the BaseAgent:
fromrlbot.agents.base_agentimportBaseAgent, SimpleControllerStatefromrlbot.utils.structures.game_data_structimportGameTickPacketclassExampleBot(BaseAgent):
definitialize_agent(self):
passdefget_output(self, packet: GameTickPacket) ->SimpleControllerState:
# Constant values can be found the the FieldInfo:info=self.get_field_info()
# Manually construct a list of all big boost pads# info.boost_pads has a fixed size but info.num_boosts is how many pads there actually arebig_pads= []
foriinrange(info.num_boosts):
pad=info.boost_pads[i]
ifpad.is_full_boost:
big_pads.append(pad)Mutators can only be set before the game starts by a human.
To get the current mutators, do something like this:
fromrlbot.messages.flat.BoostOptionimportBoostOptiondefinitialize_agent(self):
# See all of the match settings at https://github.com/RLBot/RLBot/blob/master/src/main/flatbuffers/rlbot.fbs#L784match_settings=self.get_match_settings()
mutators=match_settings.MutatorSettings()
# Examples# Game modegame_mode= (
"soccer",
"hoops",
"dropshot",
"hockey",
"rumble",
"heatseeker"
)
self.gamemode=game_mode[match_settings.GameMode()]
# View all mutator options at https://github.com/RLBot/RLBot/blob/master/src/main/flatbuffers/rlbot.fbs#L753# Boost amountifmutators.BoostOption() ==BoostOption.Unlimited_Boost:
# Do whatever# Boost acceleration# Leverage some known constants to get an acceleration value based on the setting.# These values are from the Physics section of the Useful Game Values wiki -> https://github.com/RLBot/RLBot/wiki/Useful-Game-Values#physicsbase_boost_accel=991+ (2/3)
boost_accel= (
base_boost_accel, # Defaultbase_boost_accel*1.5, # Strength x 1.5base_boost_accel*2, # Strength x 2base_boost_accel*10# Strength x 10
)
self.boost_accel=boost_accel[mutators.BoostStrengthOption()]
You can find descriptions of the tricky values in this file:
https://github.com/RLBot/RLBot/blob/master/src/main/flatbuffers/rlbot.fbs
You will recognize some of the previous mentioned classes as tables. I.e. packet.score_info is a ScoreInfo table.