Skip to content

sprint 024: playtest quick wins (combat feel, gear polish, item properties UI)#38

Merged
vladmesh merged 19 commits into
mainfrom
sprint/024-playtest-quick-wins
Jul 16, 2026
Merged

sprint 024: playtest quick wins (combat feel, gear polish, item properties UI)#38
vladmesh merged 19 commits into
mainfrom
sprint/024-playtest-quick-wins

Conversation

@vladmesh

Copy link
Copy Markdown
Owner

Closes sprint 024. Eight items from the live session of 2026-07-15, picked for maximum effect per line of code. Does not advance the simulation-core epic; this was an operator-requested UX sprint.

Phase 1 — combat readability and tactics

  • Movement budget accounting unified: MOVECostType.FREE, handle_move charges the distance actually moved atomically, CostType.MOVEMENT removed. The dispatcher owns action/bonus/reaction; movement handlers own movement_remaining.
  • Other creatures' technical errors no longer leak into the player's log (build_action_result gates error/budget on the player).
  • faction_hostility_check INFO → DEBUG, and the relation fn is built once per awareness rebuild instead of once per pair. That single event was 70.8% of the backend log in the live session.
  • Second Wind at full HP reads "already at full health" instead of "regaining 0 HP".

Phase 2 — trading and equipment polish

  • SRD price on all 31 catalog entries, so starting gear can be unequipped and sold. No code changes needed; the plumbing already carried price through.
  • Equip/unequip buttons and descriptions localized (10 slot labels + 12 RU descriptions).

Phase 3 — item properties UI

  • Machine-readable JSON-safe props built from the typed defs across all four player-facing channels (inventory, equipment, merchant, loot).
  • ItemDetails card renders localized properties in inventory and trade, RU and EN, for all five item kinds.

Notable

The premise of combat-move-budget-not-consumed ("budget is never charged, kiting is infinite") turned out to be wrong. Code recon before the fix showed the dispatcher was charging the budget correctly and speed=30 stopped at 30 ft. The real defect was the split accounting, where the latent bugs lived: diagonals charged a flat 5 ft instead of 5/10, and a blocked or partial step charged the request rather than the distance travelled. The task was reformulated rather than implemented as written.

hide-world-travel-in-combat was found already fixed since sprint 009 and marked superseded.

Verification

  • backend 2573 unit, frontend 299, integration 166 — all green
  • post-audit E2E 26/26, 0 blockers
  • audit 2026-07-16: 13 findings, 2 quick-fixed, remaining 11 already tracked in BACKLOG

Closing also ran a full /update-docs, which found documentation drift wider than this sprint's delta: master/ was documented as a live LLM orchestrator (an empty stub since the first commit that nothing imports), CLI/Telegram adapters described as existing, xp_for_kill vs the real xp_for_cr, and 7 e2e-playbook scenarios that disagreed with actual behavior. Also fixes a pre-existing flake in test_timeout_preserves_lifecycle_until_same_thread_stops (a 10ms round-stop deadline was never restored, racing the fixture teardown against a live round thread).

Produced autonomously.

vladmesh added 19 commits July 16, 2026 00:09
Reformulated after code recon: the "budget not consumed" premise was
wrong — the dispatcher already charged movement via
action_cost(MOVE)=MOVEMENT, gated by check_budget. The real issue was
split accounting: MOVE charged requested ft in the dispatcher while
MOVE_TO/DASH charged actual distance in their handlers, causing latent
diagonal undercharge and blocked-step overcharge.

- MOVE -> cost_type=FREE; remove CostType.MOVEMENT. handle_move now
  checks and decrements the distance actually walked, atomically (no
  partial placement on rejection).
- Add check_movement_available so a spent-out creature is still not
  offered MOVE (check_budget no longer gates a FREE action).
- handle_move_to distinguishes "no path" from "not enough movement".
- Surface movement_remaining + reachable targets to the LLM prompt
  (player and RuleBrain already had it).

Updated dispatcher/multi-action/session-awareness tests to the new
contract; new i18n strings translated to ru.
…og, build faction relation fn once per awareness rebuild
…tions

Add 10 slot labels (equip_armor..unequip_ring) plus a short 'use' key to
en/ru game.json; route InventoryPanel USE/EQUIP literals through t(). Add
RU translations for the 12 equip/unequip ActionDef descriptions to the .po
and recompile the .mo, so a Russian player sees Russian labels and tooltips
instead of raw ids and English base strings. Web contract of the 12
ActionType is untouched.
…k phase complete

E2E surfaced pre-existing ac-stale-on-unequip bug (unequip armor raises AC),
logged to backlog. Not a phase-2 regression.
Rename private _reaction_to_dict to public reaction_to_dict (was imported
across the transport_payloads/session module boundary). Drop the dead
check_faction_hostility wrapper left without production callers by the
relation-fn refactor; tests now exercise _hostility_from_relation through
a helper that mirrors the production path.
item-properties-ui closed by phase 3, leftover split to loot-panel-item-props;
second-wind-zero-heal narrowed to use_item perceptor; new: round-stop-timeout-on-disconnect,
nearby-shows-raw-id, ru-duplicate-condition-label, combat-panel-weapon-summary-truncated,
master-player-brain-label
Full review of all managed docs against current code, first since 2026-07-14.

Sprint 024 changes reflected: movement budget ownership (MOVE/MOVE_TO are FREE
at the dispatcher, handlers charge actual distance), structured item props in
player-facing payloads, SRD prices on catalog items, item details card and
equip i18n scenarios in the e2e playbook.

Stale claims found and fixed beyond the sprint delta:
- master/ was documented as a live LLM orchestrator; it has been an empty stub
  since the first commit and nothing imports it
- CLI/Telegram adapters described as existing; only adapters/api/ exists
- xp_for_kill -> xp_for_cr, perform_level_up moved to its own module
- rules/ docstring listed physics/economics (nonexistent), omitted six modules,
  and claimed all functions are pure
- CLAUDE.md put effective_speed/attack_advantage in rules/conditions.py; they
  are in rules/modifiers.py (attack_advantage does not exist)
- README claimed make serve auto-builds the frontend
- e2e-playbook: 7 scenarios asserted UI behavior that does not match the code
  (clock location, move buttons, prone speed, log rendering, depleted action
  buttons, combat inspect fields, encounter roll trigger)

BACKLOG: 7 sprint-024 items marked fixed, use-item-zero-heal split out of
second-wind-zero-heal. ROADMAP: sprint 024 Done entry.
…em properties UI)

Eight items from the 2026-07-15 live session, closed across three phases:
combat movement budget accounting unified, other creatures' technical errors
gated out of the player log, faction_hostility_check INFO->DEBUG, Second Wind
at full HP no longer reads "0 HP", SRD prices on all catalog items, equip and
unequip buttons localized, item properties card in inventory and trade (RU+EN).

Backend 2573 unit, frontend 299, integration 166. Post-audit E2E 26/26, no
blockers. Audit triaged: 2 quick-fixes applied, the rest already tracked.

Also fixes a pre-existing flake in test_timeout_preserves_lifecycle_until_same_
thread_stops: the test lowered the round-stop deadline to 10ms to exercise the
timeout path and never restored it, so the later stop_round and the fixture
teardown raced a live round thread against a 10ms join. Restore the default
once the timeout assertions are done. Verified over 12 consecutive runs.
@vladmesh
vladmesh enabled auto-merge July 16, 2026 17:06
@vladmesh
vladmesh merged commit 8acc260 into main Jul 16, 2026
4 checks passed
@vladmesh
vladmesh deleted the sprint/024-playtest-quick-wins branch July 16, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant