Skip to content

osrlib.core.clock

Time units and the game clock.

B/X time comes in three units: the round (10 seconds), the turn (10 minutes = 60 rounds), and the day (144 turns). Internally the clock is a single integer count of rounds — the finest unit — so arithmetic is exact and serialization is one field.

Advancing the clock reports which turn and day boundaries were crossed, in order, so the effects engine can resolve expirations and ticks at each boundary per the canonical tick order. An advance that lands exactly on a boundary reports that boundary: a torch lit at turn 0 expires when the clock reaches turn 6, not turn 7.

ROUNDS_PER_DAY module-attribute

ROUNDS_PER_DAY = ROUNDS_PER_TURN * TURNS_PER_DAY

Rounds per day (8640).

ROUNDS_PER_TURN module-attribute

ROUNDS_PER_TURN = 60

Rounds per exploration turn (10 minutes).

SECONDS_PER_ROUND module-attribute

SECONDS_PER_ROUND = 10

Length of a combat round in seconds.

TURNS_PER_DAY module-attribute

TURNS_PER_DAY = 144

Exploration turns per day.

BoundaryCrossing

Bases: BaseModel

A turn or day boundary crossed by a clock advance.

index is the ordinal of the boundary in its own unit: crossing into turn 6 has unit=TimeUnit.TURN, index=6, and lies at absolute round round (here 360). When a day boundary coincides with a turn boundary (every day boundary does), the turn crossing is reported first — finer units before coarser.

unit instance-attribute

unit: TimeUnit

index class-attribute instance-attribute

index: int = Field(ge=1)

round class-attribute instance-attribute

round: int = Field(ge=1)

GameClock

Bases: BaseModel

The game clock: elapsed time as a single count of rounds.

Examples:

from osrlib.core.clock import GameClock, TimeUnit

clock = GameClock()
crossings = clock.advance(2, TimeUnit.TURN)
assert clock.turns == 2
assert [c.index for c in crossings if c.unit is TimeUnit.TURN] == [1, 2]

rounds class-attribute instance-attribute

rounds: int = Field(default=0, ge=0)

turns property

turns: int

Whole turns elapsed.

days property

days: int

Whole days elapsed.

advance

advance(n: int, unit: TimeUnit = ROUND) -> list[BoundaryCrossing]

Advance the clock and report the turn and day boundaries crossed.

Parameters:

Name Type Description Default
n int

How many units to advance. Must be non-negative; zero is a legal no-op that crosses nothing.

required
unit TimeUnit

The unit to advance in.

ROUND

Returns:

Type Description
list[BoundaryCrossing]

Every turn and day boundary in the advanced span, in chronological order,

list[BoundaryCrossing]

with a coinciding turn boundary before its day boundary. A boundary landed

list[BoundaryCrossing]

on exactly is included; the starting position is not (it was reported by

list[BoundaryCrossing]

the advance that reached it).

Raises:

Type Description
ValueError

If n is negative.

TimeUnit

Bases: StrEnum

The B/X time units.

ROUND class-attribute instance-attribute

ROUND = 'round'

TURN class-attribute instance-attribute

TURN = 'turn'

DAY class-attribute instance-attribute

DAY = 'day'