Spend speed as a rate, not as a tiebreak #37
No reviewers
Labels
No labels
area/ai
area/build
area/character
area/combat
area/data
area/docs
area/game
area/net
area/ui
area/world
size
l
size
m
size
s
type
bug
type
design
type
feature
type
refactor
type
test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
icub3d/terra-redux-org!37
Loading…
Reference in a new issue
No description provided.
Delete branch "6-turn-scheduler"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Design pillar 2 says turn order is a resource: speed decides how often a unit acts, not
merely who acts first. A round with an initiative sort inside it cannot express that —
everybody acts once regardless, so the gap between 2 speed and 20 speed is the same as
between 2 and 3, and "building for tempo" is not a strategy the game has.
The shape
Every unit carries an interval, the virtual time between its turns, derived once from
its
TurnSpeed. The schedule hands the next turn to whoever is due soonest, then pushesthat unit one interval on. A unit of twice the speed takes twice the turns.
Virtual time is integral.
CADENCEis 720720 — the LCM of 1 through 16 — so every speedin that range divides it exactly and a cadence is a precise ratio rather than a rounded
one. Larger speeds round once, at insertion, and the error never accumulates because an
interval is computed rather than added up.
Ties go to the lower
Deployedordinal, a new component recording the mission'sauthored deployment order.
(due, ordinal)is a total order because ordinals aredistinct, so there is exactly one answer and it never depends on how the ECS stored
anything. Breaking ties by
Entitywould have been free and wrong — entity ids come fromspawn order and reuse, which is precisely what § Determinism forbids depending on.
A unit's next turn is an absolute instant, not a queue position. That is what makes
the awkward cases fall out rather than need rules: a casualty removes one entry and the
survivors keep the turns they were already due; a reinforcement waits its own interval
instead of arriving owed a backlog it never took.
upcomingcopies the schedule and runs the realadvance, so the lookahead the HUD draws(#10) cannot disagree with the turns that follow it.
Acceptance criteria
A A B A A B A A B, worked through in the test's comment.fast == slow * 2over300 turns, not approximately. A second test covers speeds that divide nothing neatly
(13 against 7) and holds the ratio to within 1%.
Deployedordinal, with a test provingthe result does not follow the order units were added in.
against the same schedule with the casualty filtered out.
upcoming(12)compared element-wise against 12actual advances, taken part-way through a run.
Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings, andcargo test—140 passing, up from 122. Thirteen tests on the rules, five on
CombatPlugin.src/combat/schedule.rshas no ECS in it beyondEntityand is tested without anApp,the same discipline as
world::pathand for the same reason: this is the part that willrot silently.
Ran on a Pixel Tablet — new plugin, so it touches startup; enters a mission and takes
touch input with no panic.
ADR 0007
Records the shape and what it costs. The largest cost is unpaid and worth reading before
this merges: there are no rounds any more. Nothing can last "two rounds", so a status
effect (M3) will have to be measured in its bearer's own turns or in virtual time, and
effects will have to say which.
Nothing spends a turn yet — that is #8.
Closes #6
🤖 Generated with Claude Code
https://claude.ai/code/session_01TA4hJHkRSU3XBxZYtMKXdh