Give the enemy something to do with its turn #41
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!41
Loading…
Reference in a new issue
No description provided.
Delete branch "11-stub-enemy-behaviour"
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?
#8 left hostiles giving their turns up instantly, purely so the loop would turn.
src/ai/replaces that with a placeholder that closes, shoots, and otherwise holds — deliberately
not interesting, only enough that a mission is a fight rather than a solo walk.
The boundary is the part that is not placeholder
The AI reads the same
Battlesnapshot the HUD forecasts from, and submits the sameActionvalues a player's press becomes. By the time resolution sees one there is nothingleft to say who sent it — which is what makes the enemy replayable, and what will make it
runnable on a server.
Behaviournames the seam M4 implements. Everything around it — how a turn is handed out,how an action is submitted, how it resolves — stays exactly as it is.
Every decision goes through
forecastbefore it is returned, and falls back to waiting ifrefused. That is not tidiness: a refused action spends nothing, and a unit that spends
nothing never ends its turn. A test walks every combination of action points and distance
and asserts the rules allow whatever came back.
Three bugs the enemy exposed, all older than this change
Once hostiles actually shot, the loop stopped hiding its faults.
The player was being denied turns.
begin_turnandfinish_animatingshare a set, andinsert_resourceis deferred — sofinish_animatingsaw no turn, took its "that one isover" branch, and revoked the turn
begin_turnhad just granted. A probe caught a turnhanded to a player unit and taken away the next frame. Their conditions are now exclusive,
so exactly one acts on any frame. This is why the mission never waited for the player.
A stale message ate the player's turn.
notice_submissionasked whether the messagebuffer was non-empty. A message lives about two frames, so an action submitted last turn
still sat there and marched the next unit through
Resolvingwithout it having doneanything. It has its own reader now, and sees each message once.
The dead were still getting turns. Nothing despawns a unit that falls, so corpses stayed
in the schedule and were handed turns they could not spend.
reconcilenow keeps only unitsstill standing; #12 decides what a mission does about the bodies.
Each has a regression test.
Acceptance criteria
a decision is a function of the battle. Asserted by repeating the same battle.
ActionAPI as player input — resolution genuinely cannot tell them apart;there is one message type and one route.
paragraph.
forecastand falling backto
Wait, which is always available and always terminal. Tested exhaustively over thepoints/distance grid.
Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test—188 passing, up from 180.
On a Pixel Tablet a mission is now a fight: the HUD showed Nadia Feuerbach at 7/10 with her
turn waiting on the player. The trooper's range is 5 on a 12x8 map, so it shoots from near
its spawn rather than closing — correct for a behaviour that shoots first.
Closes #11
🤖 Generated with Claude Code
https://claude.ai/code/session_01TA4hJHkRSU3XBxZYtMKXdh