Compare commits

...

7 Commits

Author SHA1 Message Date
Josh Creek 8c15c466ef fix(*): apply the locomotion mask during in-game/eval inference, not just training
AIShipController (eval + real gameplay) ran the raw policy output unmasked
regardless of allow_vertical/allow_pitch_roll, while ShipAIController
(training) correctly discarded those axes for grounded curriculum stages.
A grounded-trained model's untrained vertical/pitch-roll output reached the
ship as noise during eval, understating it against models that were never
handicapped this way.
2026-07-21 22:23:09 +01:00
CosmicClash Training Bot dd2b3c570b chore(training): curriculum progress after curric-s3-no_draws 2026-07-21 21:46:34 +01:00
CosmicClash Training Bot bc644e0305 chore(training): Add curric-s3-no_draws checkpoints, logs, and exported policy 2026-07-21 21:44:51 +01:00
CosmicClash Training Bot 44b1384a97 chore(training): curriculum progress after curric-s2-defend 2026-07-21 19:19:44 +01:00
CosmicClash Training Bot ffa9017cbd chore(training): Add curric-s2-defend checkpoints, logs, and exported policy 2026-07-21 19:17:32 +01:00
CosmicClash Training Bot 7e67998a23 chore(training): curriculum progress after curric-s1-score 2026-07-21 16:52:20 +01:00
CosmicClash Training Bot 523a26aa60 chore(training): Add curric-s1-score checkpoints, logs, and exported policy 2026-07-21 16:50:08 +01:00
616 changed files with 166 additions and 8 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+13 -3
View File
@@ -17,6 +17,16 @@ extends ShipController
# Uniform noise magnitude added to each action axis (0 = play at full skill). # Uniform noise magnitude added to each action axis (0 = play at full skill).
@export_range(0.0, 1.0) var action_noise: float = 0.0 @export_range(0.0, 1.0) var action_noise: float = 0.0
# Must mirror whatever the model was actually trained with (see
# ShipAIController's identical exports on the training side, curriculum
# stages 1-2 in TRAINING.md). A model trained grounded (mask on) never got a
# reward gradient on these axes, so its raw output there is untrained noise —
# leaving this true for such a model doesn't make it fly well, it just lets
# that noise reach the ship instead of being discarded like it was in
# training. Set false to match a grounded-trained model's actual behaviour.
@export var allow_vertical := true
@export var allow_pitch_roll := true
var _policy: PolicyNetwork var _policy: PolicyNetwork
var _action := ShipAction.new() var _action := ShipAction.new()
var _ticks_until_decision := 0 var _ticks_until_decision := 0
@@ -53,13 +63,13 @@ func _decide() -> void:
# gymnasium orders by SORTED key name — rotation xyz, thrust xyz, turbo # gymnasium orders by SORTED key name — rotation xyz, thrust xyz, turbo
# (> 0 means on) — NOT ShipAction's thrust-first declaration order. # (> 0 means on) — NOT ShipAction's thrust-first declaration order.
_action.rotation = Vector3( _action.rotation = Vector3(
_axis(out[0]), _axis(out[0]) if allow_pitch_roll else 0.0,
_axis(out[1]), _axis(out[1]),
_axis(out[2]) _axis(out[2]) if allow_pitch_roll else 0.0
) )
_action.thrust = Vector3( _action.thrust = Vector3(
_axis(out[3]), _axis(out[3]),
_axis(out[4]), _axis(out[4]) if allow_vertical else 0.0,
_axis(out[5]) _axis(out[5])
) )
_action.turbo = out[6] > 0.0 _action.turbo = out[6] > 0.0
+12
View File
@@ -91,6 +91,12 @@ var _agents: Array[ShipAIController] = []
# Eval mode state (see header comment) # Eval mode state (see header comment)
var _eval := false var _eval := false
var _eval_models: Array[String] = ["", ""] var _eval_models: Array[String] = ["", ""]
# Per-model locomotion mask — must match how each model was actually trained
# (see AIShipController's identical exports), so a stage 1/2 (grounded)
# candidate isn't unfairly penalized by untrained aerial noise during eval
# that its training environment never had.
var _eval_allow_vertical: Array[bool] = [true, true]
var _eval_allow_pitch_roll: Array[bool] = [true, true]
var _eval_episodes := 20 var _eval_episodes := 20
var _eval_goals := {0: 0, 1: 0} var _eval_goals := {0: 0, 1: 0}
var _eval_draws := 0 var _eval_draws := 0
@@ -123,6 +129,8 @@ func _start() -> void:
for team in [0, 1]: for team in [0, 1]:
var bot := AIShipController.new() var bot := AIShipController.new()
bot.model_path = _eval_models[team] bot.model_path = _eval_models[team]
bot.allow_vertical = _eval_allow_vertical[team]
bot.allow_pitch_roll = _eval_allow_pitch_roll[team]
spawn_ship(team, 0, bot) spawn_ship(team, 0, bot)
return return
@@ -161,6 +169,10 @@ func _parse_eval_args() -> void:
_eval_models[0] = args["eval_model_a"] _eval_models[0] = args["eval_model_a"]
_eval_models[1] = args["eval_model_b"] _eval_models[1] = args["eval_model_b"]
_eval_episodes = int(args.get("eval_episodes", str(_eval_episodes))) _eval_episodes = int(args.get("eval_episodes", str(_eval_episodes)))
_eval_allow_vertical[0] = _typed_like(args.get("eval_allow_vertical_a", "true"), true)
_eval_allow_vertical[1] = _typed_like(args.get("eval_allow_vertical_b", "true"), true)
_eval_allow_pitch_roll[0] = _typed_like(args.get("eval_allow_pitch_roll_a", "true"), true)
_eval_allow_pitch_roll[1] = _typed_like(args.get("eval_allow_pitch_roll_b", "true"), true)
# TrainingMode @export names a curriculum run may override from the cmdline. # TrainingMode @export names a curriculum run may override from the cmdline.
+7
View File
@@ -122,6 +122,13 @@ appends to `training/eval_history.json` — the long-term progress record.
Evaluate each new candidate against the previous promoted bot and a fixed Evaluate each new candidate against the previous promoted bot and a fixed
early reference to see absolute progress over time. early reference to see absolute progress over time.
If a model was trained with the locomotion mask on (curriculum stages 1-2 —
see below), pass `--grounded-a`/`--grounded-b` for whichever side it's on.
The eval otherwise runs `AIShipController` fully unmasked regardless of how a
model was trained, so a grounded model's untrained vertical/pitch-roll output
reaches the ship as noise it never had to contend with during training —
this understates it, not a neutral comparison.
## Difficulty tiers ## Difficulty tiers
A bot is `(model, reaction_ticks, action_noise)` — configured on the Match A bot is `(model, reaction_ticks, action_noise)` — configured on the Match
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More