Gym

One car on a session’s map, driven over its own connection. Session.connect() is the usual way to get one.

Ticks

The race advances in ticks of 10 ms. Gym.reset() plays the countdown and answers at race tick -1, the state before the first race tick. A step of n ticks simulates the window from Gym.next_tick to next_tick + n - 1 and answers the state at its end. Inputs given by keyword are written at the window’s first tick and hold until changed, as in the game; explicit Action records go at ticks of your choosing inside the window.

class Gym(
host: str,
port: int,
session_id: int,
telemetry: TelemetryGroup,
lidar: Lidar | None = None,
*,
timeout: float | None = 60.0,
)

A world on a session’s map, driven over its own connection.

Session.connect is the usual way to get one. Every request is one round trip. A request that fails on the connection, or whose answer the client cannot read, closes the gym and raises TransportError or ProtocolError, because whether it ran is then unknown: open a new gym, reset, and step the exported record if the race is to go on.

Parameters:
  • host – The address of the session’s gym socket.

  • port – Its port.

  • session_id – The session to open the gym on.

  • telemetry – The groups every sample carries, combined with |.

  • lidar – The rays to cast on every sample. TelemetryGroup.LIDAR is its scan, and is in the telemetry exactly when a lidar is given.

  • timeout – Seconds to wait on the server before giving up, for connecting and for every read and write; None waits forever.

session_id: int

The session the gym is on.

info: GymInfo

The server as it introduced itself.

id: int

The gym’s id on the server, as Session.gyms lists it.

map: MapInfo

The map the gym drives on.

property telemetry: TelemetryGroup

The groups every sample carries, combined with |.

property lidar: Lidar | None

The rays cast on every sample, or None when the gym has no lidar.

property race_tick: int

The tick of the last computed state, which is -1 before the first reset and right after one.

property next_tick: int

The first tick the next step simulates, where its explicit actions may start.

property finished: bool

Whether the race is finished. A finished gym answers its final state and ignores actions until a reset or a restore.

property closed: bool

Whether the connection is closed, by close() or by a failed request.

reset(seed: int = 0) → Telemetry

Starts a new race and discards the gym’s snapshots.

The countdown is played, so the answer is at race tick -1, the state before the first race tick, and the next step’s window starts at tick 0.

Parameters:

seed – The race’s random seed; the same seed and inputs give the same race.

Returns:

The state at race tick -1.

step(
ticks: int,
actions: Sequence[Action] = (),
*,
steer: int | None = None,
accelerate: bool | None = None,
brake: bool | None = None,
respawn: bool = False,
standing_respawn: bool = False,
restore: Snapshot | int | None = None,
) → Telemetry

Advances the race by ticks ticks and answers the state at the end.

The window simulated is next_tick through next_tick + ticks - 1 (after the restore, if one is named). Inputs given by keyword are written at the window’s first tick and hold afterwards, as in the game; an input not given keeps its value. Explicit actions carry their own ticks, which must lie inside the window.

A recorded race plays as it is: in the first step after a reset(), the record’s seed record starts the race over with that seed, and its inputs follow at their ticks. The same record gives the same race on any gym of the map.

Parameters:
  • ticks – How many ticks to simulate, 1 to 60000. A tick is 10 ms.

  • actions – Inputs at chosen ticks inside the window, or a whole record.

  • steer – Steering from -127 (full left) to 127 (full right).

  • accelerate – Whether the accelerator is held.

  • brake – Whether the brake is held.

  • respawn – Respawn at the last checkpoint at the window’s first tick.

  • standing_respawn – Respawn standing still at the window’s first tick.

  • restore – A snapshot to put the gym back at before the window, in the same round trip.

Returns:

The state at the window’s end. A race that finishes inside the window stops there.

Raises:
  • ValueError – ticks or steer is out of range.

  • BadActionError – An explicit action is outside the window, or a seed record comes once the race has started.

  • SnapshotUnknownError – restore names a snapshot this gym does not hold.

snapshot() → Snapshot

Saves the gym’s state on the server.

Returns:

The handle to restore() or pass as restore= to step().

Raises:

SnapshotLimitError – The gym already holds GymInfo.max_snapshots_per_gym snapshots.

restore(snapshot: Snapshot | int) → Telemetry

Puts the gym back at a snapshot.

Parameters:

snapshot – The snapshot, or its id.

Returns:

The state at the snapshot’s tick.

Raises:

SnapshotUnknownError – The snapshot is not one this gym holds.

discard(*snapshots: Snapshot | int) → None

Frees snapshots on the server.

Parameters:

*snapshots – The snapshots, or their ids. All or none are freed.

Raises:

SnapshotUnknownError – One of them is not a snapshot this gym holds.

raycast(rays: Sequence[Ray]) → LidarScan

Casts rays at the car’s current pose, each from its origin along its direction up to its range, in its frame.

Parameters:

rays – The rays to cast.

Returns:

One entry per ray, in the order given, like a sampled lidar scan.

checkpoints() → tuple[Checkpoint, ...]

Where the race stands against the map’s waypoints: one entry per MapInfo.waypoints, in that order.

A waypoint is taken once the car has passed it in the current lap, with the race time of that passage. On a lap race the entries clear as a lap ends, as the game’s own checkpoint state does.

Returns:

The checkpoints, finish included.

export() → ExportedRace

The race so far: the finish time and every input since the reset, the seed first.

Returns:

What TICK replays; InputText.write saves the actions as input text.

close() → None

Closes the connection, and with it the gym and its snapshots.

Values

class GymInfo

The server as it introduced itself when the gym opened.

cores: int

Processor cores the host runs gyms on.

gyms_open: int

Gyms open on the host at that moment, this one included.

gyms_available: int

Gyms that could still be opened at that moment.

max_snapshots_per_gym: int

Snapshots a gym may hold at once.

server_version: str

The server’s build version.

class MapInfo

The session’s map as the server knows it.

map_uid: str

The map’s UID, as the game names it.

checkpoint_count: int

Checkpoints a race passes, the finish included, over every lap.

lap_count: int

Laps the race drives; 1 for a point-to-point map.

vehicle: VehicleType

The car the race starts in.

start_position: Vec3

Where the car stands after a reset, in metres. Shape (3,).

start_rotation: Quat

How it faces. Shape (4,).

waypoints: tuple[Waypoint, ...]

The checkpoints and the finish, each with the trigger the race tests the car against. The start has no trigger: start_position and start_rotation stand for it.

class Waypoint

A waypoint of the map, with its trigger as a triangle mesh in world space: the car passes the waypoint when its collision shape meets one of the triangles.

id: int

The id Gym.checkpoints() names it by.

kind: WaypointKind

What passing it counts as.

vertices: FloatArray

The mesh’s vertices, in metres. Shape (N, 3).

triangles: IntArray

Each triangle as three indices into vertices. Shape (M, 3).

class Checkpoint

One waypoint of the map in Gym.checkpoints(): whether the race has passed it in the current lap, and when.

waypoint_id: int

The Waypoint.id.

taken: bool

Whether the car has passed it in the current lap.

race_time_ms: int | None

The race time of that passage in milliseconds, None while not taken.

class Snapshot

A server-held snapshot of the gym, as Gym.snapshot returns it.

id: int

The handle the server knows it by.

tick: int

The race tick a restore puts the gym at.

class ExportedRace

A gym’s record since its reset, as Gym.export returns it.

finish_ms: int | None

The finish time, or None while the race is unfinished.

actions: tuple[Action, ...]

Every input since the reset, the seed record first; what TICK replays.

class VehicleType(value)
STADIUM = 0
SNOW = 1
RALLY = 2
DESERT = 3
class WaypointKind(value)
CHECKPOINT = 1
FINISH = 2
MULTILAP = 3