Commit Graph

223 Commits

Author SHA1 Message Date
CosmicClash Training Bot a4f60e5b40 chore(training): Add 20260818-0210-gen5-s5-intercepts-retry2 checkpoints, logs, and exported policy 2026-08-18 11:16:23 +01:00
CosmicClash Training Bot dadfdb2903 chore(training): Add 20260817-1701-gen5-s5-intercepts-retry1 checkpoints, logs, and exported policy 2026-08-18 02:09:04 +01:00
CosmicClash Training Bot 89b1790728 chore(training): Add 20260817-0750-gen5-s5-intercepts checkpoints, logs, and exported policy 2026-08-17 17:00:05 +01:00
Josh Creek 0b6679e84b chore(training): promote stage-4 retry2 to medium and open stage 5
20260816-2126-gen5-s4-handling-retry2 exhausted its three attempts and
missed only the 0.80 training goal-rate floor, at 0.7731. Every
evaluation gate passed: 65-22-13 versus promoted/easy.json, 87% non-draw
against an 80% floor, 12.6% physical-side imbalance against a 20%
ceiling, and both handling telemetry floors clear. The round improved the
goal rate monotonically across attempts (0.537 -> 0.683 -> 0.773) and the
checkpoint plays well by hand, so close Stage 4 by human override.

Promote it to Game/bots/promoted/medium.json. Medium and Hard both point
at the new policy: Hard stays a label-only duplicate until a stronger one
earns hard.json, which keeps the tiers monotonic rather than leaving Hard
weaker than Medium.

generation5_state.json flips that log entry to "pass" with a
decision_override block preserving the original verdict and reasoning,
and advances to Stage 5 attempt 1. This is what passing_entry() needs to
resolve Stage 5's resume checkpoint and evaluation reference, and what
league_pool() will need at Stage 6; --skip-to-next-stage would advance
the stage without marking anything as passing and die immediately.

generation5.sh now pulls before launching. Each stage ends in
commit_progress()'s push, which fails and kills the run hours in if the
box is behind origin.
2026-08-17 07:49:21 +01:00
CosmicClash Training Bot ad2bda4ad7 chore(training): Add 20260816-2126-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-17 03:35:11 +01:00
CosmicClash Training Bot 24534459b1 chore(training): Add 20260816-1513-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-16 21:25:24 +01:00
CosmicClash Training Bot ff7d1579cb chore(training): Add 20260816-0858-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-16 15:11:55 +01:00
Josh Creek ea756bd5ba fix(physics): make upright a real state, and actually start ships on the floor
Six rounds of reward shaping (~700M steps) failed to produce upright ground
driving. A critical review of the simulation rather than the reward found
why:

1. The hull was a 1x1x4 box with inertia (1,1,1) and no restoring torque
   anywhere, so belly-down and rolled-90 were geometrically identical
   resting states. "Upright" was not a physically distinguished state at
   all - the reward was paying for a property the simulation did not have.
2. ~65% of episodes spawned ships via _random_position, which samples Y
   uniformly over the full 18m volume (mean ~8.7m). The measured
   airborne_fraction ~0.44 was largely that spawn distribution, and every
   ground-handling term fades out above 3m, so the shaping being tuned
   barely ever applied.
3. air_drill_chance 0.20 spawned deliberately unreachable-without-climbing
   states in the stage meant to teach ground driving, and its own
   air_touch_fraction (0.0002) shows the drills were never solved.

Fixes land in the physics and the task distribution, not the reward:
- ship.tscn: hull 1x1x4 -> 1.6x0.6x4 so it has one stable resting face;
  inertia (1,1,1) -> (7,1,7), physically correct for the hull, making
  tumbling reluctant while keeping yaw snappy.
- ship.gd: new altitude-faded righting torque (spring-damper toward
  belly-down, faded out by 3m so aerials keep full attitude freedom).
  This is the grav-plating analogue of Rocket League's auto-righting and
  helps human pilots land cleanly too.
- training_mode.gd: new ground_start_chance branch spawning ships level and
  resting on the floor with a floor-level ball - the state the handling
  stage's rewards are actually written for.
- generation5.py: ground-start-chance 0.50, air-drill-chance 0.20 -> 0.0.

Reward terms are left exactly as they were; they should finally pull in a
direction the ship can go.
2026-08-16 08:17:16 +01:00
CosmicClash Training Bot aeeb730636 chore(training): Add 20260815-0812-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-15 14:28:21 +01:00
CosmicClash Training Bot 34f883cf46 chore(training): Add 20260815-0156-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-15 08:11:33 +01:00
CosmicClash Training Bot 84e0ebf771 chore(training): Add 20260814-1939-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-15 01:54:55 +01:00
Josh Creek 8f7f672a15 fix(training): restore ground_tilt_penalty, add grounded_upright_fraction diagnostic
Round 4 changed three things at once and two of them cut upright pressure:
grounded_upright_reward went to 0 and ground_tilt_penalty was cut 2.5x,
while the new uprightness multiplier only pays below GROUND_HANDLING_HEIGHT
*and* while moving forward *and* facing the ball - a far narrower slice of
ticks than the penalty it was meant to replace. Net pressure fell and
upright_fraction fell with it (0.268 -> 0.239 -> 0.238, the lowest of any
round). Restore ground_tilt_penalty to 0.05 and change nothing else, so
this is a genuine single-variable test of multiplier plus full tilt
pressure.

The conjunctive mechanism itself held up: forward_motion_fraction reached
its best sustained value (0.242) without goal_rate sagging, ep_rew_mean
turned positive for the first time (+0.28), and eval win rate hit 49% with
no reward hacking.

Also adds grounded_upright_fraction: a diagnostic, deliberately ungated
metric measuring uprightness over real floor-contact ticks instead of
sub-3m ticks. upright_fraction has never exceeded 0.331 across four rounds
and ~560M steps without cheating, and its denominator is dominated by
ballistic transit (airborne_fraction ~0.45, mean_altitude ~4.4m) where
attitude is not meaningfully controllable - so it likely cannot measure
what the 0.45 floor was meant to capture. Re-baseline that floor from what
this reports rather than from another round of reshaping.
2026-08-14 19:36:45 +01:00
CosmicClash Training Bot f08ecbe651 chore(training): Add 20260813-0134-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-13 07:44:31 +01:00
CosmicClash Training Bot 4d78e89e95 chore(training): Add 20260812-1922-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-13 01:32:50 +01:00
CosmicClash Training Bot 9e7b93af2b chore(training): Add 20260812-1307-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-12 19:20:31 +01:00
Josh Creek 4f3cf56e28 fix(training): make uprightness a multiplier on the forward-approach reward
Rounds 2 and 3 showed that tuning grounded_upright_reward's magnitude only
slides along a tradeoff instead of resolving it: at 0.015 upright_fraction
climbed to 0.331 while goal_rate sagged to 0.542 (then farmed outright at
0.696/0.366), and at 0.004 goal_rate climbed 0.569->0.604 while
upright_fraction went flat at ~0.26. An additive uprightness bonus is an
alternative to playing well, so the policy just picks whichever is cheaper
and no magnitude buys both behaviours.

Change the mechanism rather than the number: grounded_upright_reward drops
to 0, and uprightness becomes a multiplier inside the nose-led approach
term, which already requires moving forward at the ball. Parked-and-upright
and fast-but-sideways now both pay zero; only upright, forward, nose-on to
the ball pays full. forward-velocity-to-ball rises 0.06 -> 0.15 to offset
the ~2-3x expected-value cut from the new factor, and ground-tilt-penalty
drops 0.05 -> 0.02 now that uprightness is paid positively during play.
Delete the three blocked attempts and reset state to restart from the
Stage-3 foundation.
2026-08-12 13:04:20 +01:00
CosmicClash Training Bot 8e5eea4f46 chore(training): Add 20260812-0424-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-12 10:30:03 +01:00
CosmicClash Training Bot 739c4b09d5 chore(training): Add 20260811-2216-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-12 04:22:59 +01:00
CosmicClash Training Bot 722ad7cc85 chore(training): Add 20260811-1606-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-11 22:14:46 +01:00
Josh Creek b8e2a7b57a fix(training): cut grounded_upright_reward, restart stage-4 from Stage-3 foundation
grounded_upright_reward at 0.015 overshot: four force-retries pushed
upright_fraction from 0.265 to a plateauing 0.331, then the fifth jumped it
to 0.696 (55% over the 0.45 floor) while goal_rate collapsed 0.542->0.366
and forward_motion_fraction fell 0.244->0.184 (vertical_thrust_mean went
negative) - the policy learned to sit pinned upright and farm the bonus
instead of chasing the ball. It was sized "comparable to
time_penalty/ball_distance_penalty" but at 0.015/tick it was actually above
ball_distance_penalty's 0.01/tick worst case, so idling near the ball beat
playing. Cut to 0.004/tick (episode ceiling ~7.2, below
ball_distance_penalty's ~18 worst case). Delete the five blocked attempts
and reset generation5_state.json so the next run starts fresh from the
Stage-3 foundation rather than continuing from the farming checkpoint.
2026-08-11 15:57:27 +01:00
CosmicClash Training Bot 25560a65b5 chore(training): Add 20260811-0858-gen5-s4-handling-retry4 checkpoints, logs, and exported policy 2026-08-11 15:10:43 +01:00
CosmicClash Training Bot 651c048115 chore(training): Add 20260810-1338-gen5-s4-handling-retry3 checkpoints, logs, and exported policy 2026-08-10 19:50:40 +01:00
CosmicClash Training Bot 677fff2c82 chore(training): Add 20260810-0211-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-10 08:21:17 +01:00
CosmicClash Training Bot aa8d895b14 chore(training): Add 20260809-1955-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-10 02:10:10 +01:00
CosmicClash Training Bot dcf618dda1 chore(training): Add 20260809-1340-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-09 19:53:46 +01:00
Josh Creek 6f7536f03c fix(training): correct non-forward penalty math and add a grounding incentive
Adversarial review of the previous stage-4 retune found two problems:
non_forward_speed used planar_speed - forward_component, which under-charges
diagonal motion relative to true lateral speed (e.g. ~29% penalty at 45
degrees off the nose instead of the correct ~71%); fixed to the Pythagorean
magnitude for forward-facing angles, full speed for backward-facing ones.

Also, ground_tilt_penalty and non_forward_penalty only ever cost reward near
the floor with nothing offsetting them above it, which could teach a policy
that's still bad at ground handling to just avoid the floor rather than get
better at it. Added grounded_upright_reward (ship_ai_controller.gd) plus a
new ShipObservations.is_floor_contact helper for genuine belly-on-floor
contact detection, so grounding well while upright is the locally profitable
choice, not just the least-punished one.
2026-08-09 13:23:00 +01:00
Josh Creek c56f5ed1a3 chore(training): retune stage-4 handling penalties and restart from Stage-3 foundation
Stage 4's upright/forward-motion telemetry plateaued flat across all three
blocked attempts because ground_tilt_penalty (0.003) was too weak to matter
and nothing penalized sideways/reverse motion at all. Raise
ground_tilt_penalty to 0.05 and add a new non_forward_penalty term
(ship_ai_controller.gd) that directly costs non-forward planar velocity near
the floor, independent of the ball. Delete the three blocked attempts'
checkpoints/logs/exports and reset generation5_state.json so the next run
starts fresh from the Stage-3 foundation checkpoint instead of continuing
from the drifted retry2 weights.
2026-08-09 13:09:12 +01:00
CosmicClash Training Bot c6f0f2084f chore(training): Add 20260809-0328-gen5-s4-handling-retry2 checkpoints, logs, and exported policy 2026-08-09 09:35:20 +01:00
CosmicClash Training Bot 686b115b88 chore(training): Add 20260808-2120-gen5-s4-handling-retry1 checkpoints, logs, and exported policy 2026-08-09 03:27:31 +01:00
CosmicClash Training Bot 11b41ab562 chore(training): Add 20260808-1508-gen5-s4-handling checkpoints, logs, and exported policy 2026-08-08 21:18:39 +01:00
Josh Creek d229bccd19 fix(arena): contain goal pockets 2026-08-08 15:03:46 +01:00
Josh Creek 341a67f6da feat(training): add generation 5 curriculum 2026-08-08 14:56:17 +01:00
Josh Creek 57a298dc06 fix(ai): map team-relative rotation actions 2026-08-08 14:54:27 +01:00
Josh Creek 7e217df898 feat(ai): promote stage 3 policy as easy bot 2026-08-08 14:52:36 +01:00
Josh Creek 0285116ddc fix(feedback): remove ball contact screen flash 2026-08-08 08:52:39 +01:00
Josh Creek 0223b55de8 fix(vfx): remove ball contact sparks 2026-08-08 08:47:48 +01:00
Josh Creek e0a1cbaf6d fix(presentation): simplify camera and engine effects 2026-08-08 08:44:26 +01:00
CosmicClash Training Bot b7f646ba48 chore(training): Add 20260806-1939-curric-s3-gauntlet checkpoints, logs, and exported policy 2026-08-08 08:24:30 +01:00
Josh Creek 8fa40769a8 feat(rendering): add cinematic post processing 2026-08-07 22:54:01 +01:00
Josh Creek 0a7eb0b742 feat(ui): theme HUD with Orbitron typography 2026-08-07 22:48:56 +01:00
Josh Creek 8bd65290fc feat(goals): add cinematic celebration sequence 2026-08-07 22:45:33 +01:00
Josh Creek 28eb45338a feat(feedback): add responsive camera and impacts 2026-08-07 22:37:49 +01:00
Josh Creek 78ef0cb1f8 feat(vfx): animate movement and scoring effects 2026-08-07 22:31:17 +01:00
Josh Creek 8d4078989c feat(arena): add grounded lighting and asteroid dressing 2026-08-07 22:26:02 +01:00
CosmicClash Training Bot a370b15020 chore(training): Add 20260805-1926-curric-s2-selfplay checkpoints, logs, and exported policy 2026-08-06 19:37:58 +01:00
CosmicClash Training Bot 9f78d37c79 chore(training): Add 20260805-0953-curric-s1-bootstrap checkpoints, logs, and exported policy 2026-08-05 19:26:20 +01:00
Josh Creek 401d882ff0 fix(assets): remove unreferenced duplicate planet_surface texture
assets/textures/planet_surface.png was byte-identical to and unused
in favor of assets/models/nebula_planet_planet_surface.png, the
sidecar Godot's glTF importer actually extracted from nebula_planet.glb
and uses at runtime. Deleted the orphan (+ its .import) and stopped
gen_planet_surface.py from writing it.

Also measured nebula_dust.gdshader's per-fragment depth-texture sample
cost (~0.07ms/frame at 500 particles, within noise) -- negligible, so
no budgeting concern for further particle work.
2026-08-05 09:51:33 +01:00
Josh Creek 3049c42867 feat(training): support N-vs-M matches with persistent per-ship spawn IDs
Extends ShipObservations beyond the old self+1-opponent layout to padded
teammate/opponent arrays (MAX_TEAMMATES=4, MAX_OPPONENTS=5, SIZE=83),
zero-filling slots past the real roster size the same way the old single-
opponent slot was zero-filled when absent.

Slot stability across ticks requires a persistent identity: Ship gains
spawn_index (set once by GameMode.spawn_ship, never reassigned — there's no
despawn path anywhere in this codebase, so a roster is fixed for the whole
episode/match). ai_ship_controller.gd's opponent discovery is rewritten from
"first non-self ship" to classify every other ship by team and sort by
spawn_index; training_mode.gd/ship_ai_controller.gd carry the equivalent
sorted lists through the training path so both agree on slot assignment for
the same roster.

training_mode.gd and match_mode.gd both gain a team_size export (default 1,
so every existing curriculum script and match keeps today's 1v1 behaviour
unchanged). This is plumbing only: no 2v2+ curriculum or reward design, and
no match-mode UI to pick team size, has been done yet. The two checkpoints
in Game/bots/promoted/ are fitted to the old 35-float layout and are not
migrated — expected to go stale until the next training run.
2026-08-05 09:17:56 +01:00
Josh Creek 18fdb0f232 feat(arena): resize for 5v5, cut a real goal-wall hole, and bake collision geometry
Retraining from scratch removes the constraint that blocked these: the
existing checkpoints in Game/bots/promoted/ no longer need byte-identical
geometry.

- Fix the goal aperture constants (were 1.85/1.65, now match
  objects/goal.tscn's actual sensor exactly at 1.75/1.5) so a ball crossing
  the visible edge can't fail to score.
- Cut a real navigable hole in each end wall's collision
  (_build_end_wall_colliders), replacing the previous solid box — the ball
  now genuinely enters the net instead of triggering the sensor a hair
  before hitting a solid wall. Correct for both FLOOR and ELEVATED goal
  modes via _goal_surround_bounds. A separate, slightly wider
  GOAL_VISUAL_APERTURE_* pair keeps the collision hole exact while still
  giving goal.gd's bezel/rim frame clearance to be seen against the hull cut.
- Resize the play volume 1.5x (INNER_HALF_X/Z/HEIGHT 12/18/12 -> 18/27/18) to
  comfortably fit a 5v5 roster: updates every hand-authored literal in
  arena_boundary.tscn/arena_base.tscn/the elevated arena variants that
  doesn't derive from those constants, adds 5 spawn markers per team, and
  rescales ship_observations.gd's normalization scales and arena_02's
  cosmetic decoration/nebula-dust shader uniforms to match.
- Bake the ~170 runtime-generated CollisionShape3D nodes into the scene via
  a new bake_colliders()/tools/bake_arena_boundary.gd instead of rebuilding
  them on every load — a real load-time cost repeated in every parallel
  headless training env. Colliders must be direct children of the
  StaticBody3D to register at all, so bake_colliders() parents them onto
  self and tags them with a group for idempotent re-baking, rather than
  grouping them under an intermediate container node. _ready() self-heals:
  it skips regenerating only when an existing bake's goal_mode metadata
  matches the current one, so the FLOOR-mode bake in the shared scene is
  never silently reused by an ELEVATED arena variant.
2026-08-05 09:17:13 +01:00
Josh Creek a02e0770af fix(training): avoid ship-ship overlap when placing a multi-ship roster
_place_ships_random/_place_air_drill sampled each ship's randomized episode-
start position independently, so a team_size > 1 roster could spawn
interpenetrating (ships are ~1x1x4). Both now resample (up to 20 attempts,
matching the existing corner/fillet rejection-sampling pattern) against
every ship already placed that reset, rejecting anything within
MIN_SHIP_SEPARATION (4.5m, matching the arena spawn-marker spacing) of one.
2026-08-05 09:16:35 +01:00