agent-parkour / train.py
anngo-1's picture
Deploy Agent Parkour app
386f43a verified
Raw
History Blame Contribute Delete
29.2 kB
from __future__ import annotations
import argparse
from pathlib import Path
from mapgen import configure_motif_mapgen, install_motif_mapgen
from ppo import parse_curriculum, train
from runtime import configure_threads, make_config
from settings import (
ACTIVE_CHECKPOINT,
DEFAULT_CURRICULUM,
DEFAULT_TRAIN_RUN_NAME,
ENV_DEFAULTS,
MAPGEN_KWARGS,
PHYSICS_DEFAULTS,
TRAIN_DEFAULTS,
)
DEFAULT_RESUME = ACTIVE_CHECKPOINT
def train_default(name: str, fallback: float | int | str) -> float | int | str:
return TRAIN_DEFAULTS.get(name, fallback)
def env_default(name: str, fallback: float | int) -> float | int:
return ENV_DEFAULTS.get(name, fallback)
def map_default(name: str, fallback: float | int) -> float | int:
return MAPGEN_KWARGS.get(name, fallback)
def physics_default(name: str, fallback: float) -> float:
return float(PHYSICS_DEFAULTS.get(name, fallback))
def main() -> None:
parser = argparse.ArgumentParser(description="Train the active attention/direct motif-map parkour runner.")
parser.add_argument("--run-name", default=DEFAULT_TRAIN_RUN_NAME)
parser.add_argument("--device", default="cuda")
parser.add_argument("--cpu-threads", type=int, default=64)
parser.add_argument("--envs", type=int, default=int(train_default("envs", 196608)))
parser.add_argument("--eval-envs", type=int, default=int(train_default("eval_envs", 8192)))
parser.add_argument("--steps", type=int, default=int(train_default("steps", 64)))
parser.add_argument("--epochs", type=int, default=int(train_default("epochs", 1)))
parser.add_argument("--minibatches", type=int, default=int(train_default("minibatches", 48)))
parser.add_argument("--hidden", type=int, default=int(train_default("hidden", 256)))
parser.add_argument("--depth", type=int, default=int(train_default("depth", 3)))
parser.add_argument("--policy-arch", choices=("mlp", "attention"), default=str(train_default("policy_arch", "mlp")))
parser.add_argument("--planner-hidden", type=int, default=128)
parser.add_argument("--planner-depth", type=int, default=2)
parser.add_argument("--planner-mode", choices=("local-beacon", "direct"), default=str(train_default("planner_mode", "direct")))
parser.add_argument("--planner-max-xy", type=float, default=8.0)
parser.add_argument("--planner-max-z", type=float, default=1.2)
parser.add_argument("--planner-blend-bias", type=float, default=-2.0)
parser.add_argument("--reset-planner-head", action="store_true")
parser.add_argument("--capture", type=int, default=int(train_default("capture", 8)))
parser.add_argument("--log-every", type=int, default=int(train_default("log_every", 20)))
parser.add_argument("--min-stage-updates", type=int, default=int(train_default("min_stage_updates", 20)))
parser.add_argument("--lr", type=float, default=float(train_default("lr", 4.0e-5)))
parser.add_argument("--entropy-coef", type=float, default=float(train_default("entropy_coef", 0.008)))
parser.add_argument("--sil-coef", type=float, default=float(train_default("sil_coef", 0.030)))
parser.add_argument("--resume-checkpoint", default=DEFAULT_RESUME)
parser.add_argument("--anchor-checkpoint", default=None)
parser.add_argument("--anchor-bc-coef", type=float, default=0.0)
parser.add_argument("--no-resume", action="store_true")
parser.add_argument("--sensor-mode", choices=("ray", "topk"), default=str(train_default("sensor_mode", "topk")))
parser.add_argument("--sensor-topk", type=int, default=int(train_default("sensor_topk", 16)))
parser.add_argument("--sensor-token-range", type=float, default=float(train_default("sensor_token_range", 9.5)))
parser.add_argument("--sensor-fov-degrees", type=float, default=float(train_default("sensor_fov_degrees", 120.0)))
parser.add_argument("--sensor-token-sort", choices=("index", "distance", "bearing"), default=str(train_default("sensor_token_sort", "distance")))
parser.add_argument("--observe-progress", action=argparse.BooleanOptionalAction, default=bool(int(train_default("observe_progress", 0))))
parser.add_argument("--fragile-platforms", action="store_true")
parser.add_argument("--fragile-delay-steps", type=int, default=14)
parser.add_argument("--launch-pads", action="store_true")
parser.add_argument("--launch-pad-fraction", type=float, default=0.24)
parser.add_argument("--launch-pad-velocity", type=float, default=10.4)
parser.add_argument("--launch-pad-gap-extra", type=float, default=0.0)
parser.add_argument("--moving-platforms", action="store_true")
parser.add_argument("--moving-platform-fraction", type=float, default=0.18)
parser.add_argument("--moving-platform-amplitude", type=float, default=0.72)
parser.add_argument("--moving-platform-period-steps", type=int, default=70)
parser.add_argument("--moving-platform-transport", action="store_true")
parser.add_argument("--moving-platform-force-every", type=int, default=0)
parser.add_argument("--moving-platform-force-offset", type=int, default=3)
parser.add_argument("--moving-platform-transport-span", type=float, default=5.35)
parser.add_argument("--moving-platform-endpoint-gap", type=float, default=1.05)
parser.add_argument("--unlock-platforms", action="store_true")
parser.add_argument("--unlock-gate-count", type=int, default=1)
parser.add_argument("--unlock-lock-span", type=int, default=2)
parser.add_argument("--unlock-hold-steps", type=int, default=1)
parser.add_argument("--unlock-reward", type=float, default=1.5)
parser.add_argument("--map-height-offset", type=float, default=float(env_default("map_height_offset", 2.85)))
parser.add_argument("--map-vertical-scale", type=float, default=float(env_default("map_vertical_scale", 1.35)))
parser.add_argument("--map-max-height", type=float, default=float(env_default("map_max_height", 5.6)))
parser.add_argument("--map-scenic-turn-scale", type=float, default=float(map_default("map_scenic_turn_scale", 0.48)))
parser.add_argument("--map-scenic-island-radius", type=float, default=1.55)
parser.add_argument("--map-scenic-vertical-step", type=float, default=0.46)
parser.add_argument("--map-platform-min-scale", type=float, default=float(map_default("map_platform_min_scale", 0.68)))
parser.add_argument("--map-platform-max-scale", type=float, default=float(map_default("map_platform_max_scale", 1.44)))
parser.add_argument("--map-platform-tiny-fraction", type=float, default=float(map_default("map_platform_tiny_fraction", 0.08)))
parser.add_argument("--map-platform-large-fraction", type=float, default=float(map_default("map_platform_large_fraction", 0.18)))
parser.add_argument("--map-platform-aspect-jitter", type=float, default=float(map_default("map_platform_aspect_jitter", 0.32)))
parser.add_argument("--start-forward-fraction", type=float, default=0.0)
parser.add_argument("--gravity", type=float, default=physics_default("gravity", 30.0))
parser.add_argument("--accel", type=float, default=physics_default("accel", 65.0))
parser.add_argument("--ground-damping", type=float, default=physics_default("ground_damping", 0.55))
parser.add_argument("--air-damping", type=float, default=physics_default("air_damping", 0.91))
parser.add_argument("--air-control", type=float, default=physics_default("air_control", 0.10))
parser.add_argument("--max-speed", type=float, default=physics_default("max_speed", 4.3))
parser.add_argument("--jump-velocity", type=float, default=physics_default("jump_velocity", 7.2))
parser.add_argument("--sprint-speed-mult", type=float, default=physics_default("sprint_speed_mult", 1.35))
parser.add_argument("--sprint-accel-mult", type=float, default=physics_default("sprint_accel_mult", 1.25))
parser.add_argument("--turn-speed", type=float, default=physics_default("turn_speed", 3.2))
parser.add_argument("--landing-pad-scale", type=float, default=physics_default("landing_pad_scale", 0.25))
parser.add_argument("--landing-top-tolerance", type=float, default=physics_default("landing_top_tolerance", 0.03))
parser.add_argument("--landing-prev-slack", type=float, default=physics_default("landing_prev_slack", 0.12))
parser.add_argument("--map-edge-gap-min", type=float, default=float(map_default("map_edge_gap_min", 0.76)))
parser.add_argument("--map-edge-gap-max", type=float, default=float(map_default("map_edge_gap_max", 1.24)))
parser.add_argument("--map-route-gap-scale", type=float, default=float(map_default("map_route_gap_scale", 1.06)))
parser.add_argument("--map-cleanup-iters", type=int, default=48)
parser.add_argument("--map-illegal-decoy-fraction", type=float, default=0.0)
parser.add_argument("--map-route-tiny-fraction", type=float, default=float(map_default("map_route_tiny_fraction", 0.0)))
parser.add_argument("--map-route-tiny-min-scale", type=float, default=0.44)
parser.add_argument("--map-route-tiny-max-scale", type=float, default=0.68)
parser.add_argument("--map-momentum-jump-fraction", type=float, default=0.0)
parser.add_argument("--map-momentum-gap-bias", type=float, default=0.82)
parser.add_argument("--map-redirect-period", type=int, default=0)
parser.add_argument("--map-redirect-angle", type=float, default=1.05)
parser.add_argument("--map-direct-decoy-fraction", type=float, default=float(map_default("map_direct_decoy_fraction", 0.06)))
parser.add_argument("--map-goal-xy-min", type=float, default=float(map_default("map_goal_xy_min", 7.5)))
parser.add_argument("--map-goal-xy-per-jump-min", type=float, default=float(map_default("map_goal_xy_per_jump_min", 0.0)))
parser.add_argument("--map-extra-span-min-frac", type=float, default=float(map_default("map_extra_span_min_frac", 0.05)))
parser.add_argument("--map-extra-span-max-frac", type=float, default=float(map_default("map_extra_span_max_frac", 0.90)))
parser.add_argument("--map-extra-span-end-margin", type=float, default=float(map_default("map_extra_span_end_margin", 1.10)))
parser.add_argument("--map-route-edge-gap-floor", type=float, default=float(map_default("map_route_edge_gap_floor", 0.24)))
parser.add_argument("--map-goal-vertical-bias", type=float, default=float(map_default("map_goal_vertical_bias", 0.0)))
parser.add_argument("--map-goal-vertical-bias-min", type=float, default=float(map_default("map_goal_vertical_bias_min", 0.0)))
parser.add_argument("--map-hairpin-period", type=int, default=int(map_default("map_hairpin_period", 0)))
parser.add_argument("--map-hairpin-angle", type=float, default=float(map_default("map_hairpin_angle", 0.0)))
parser.add_argument("--map-hairpin-depth", type=float, default=float(map_default("map_hairpin_depth", 0.0)))
parser.add_argument("--map-cluster-extra-fraction", type=float, default=float(map_default("map_cluster_extra_fraction", 0.08)))
parser.add_argument("--map-decoy-corridor-fraction", type=float, default=float(map_default("map_decoy_corridor_fraction", 0.06)))
parser.add_argument("--map-unintuitive-depth", type=float, default=float(map_default("map_unintuitive_depth", 0.08)))
parser.add_argument("--map-valley-period", type=int, default=int(map_default("map_valley_period", 0)))
parser.add_argument("--map-valley-depth", type=float, default=float(map_default("map_valley_depth", 0.0)))
parser.add_argument("--map-false-summit-fraction", type=float, default=float(map_default("map_false_summit_fraction", 0.03)))
parser.add_argument("--map-false-branch-fraction", type=float, default=float(map_default("map_false_branch_fraction", 0.04)))
parser.add_argument("--map-false-finish-fraction", type=float, default=float(map_default("map_false_finish_fraction", 0.02)))
parser.add_argument("--map-greedy-trap-fraction", type=float, default=float(map_default("map_greedy_trap_fraction", 0.04)))
parser.add_argument("--map-braid-bridge-fraction", type=float, default=float(map_default("map_braid_bridge_fraction", 0.06)))
parser.add_argument("--map-braid-bridge-span", type=int, default=int(map_default("map_braid_bridge_span", 3)))
parser.add_argument("--map-trap-jump-fraction", type=float, default=float(map_default("map_trap_jump_fraction", 0.10)))
parser.add_argument("--map-trap-jump-drop", type=float, default=float(map_default("map_trap_jump_drop", 0.72)))
parser.add_argument("--map-trap-jump-min-drop", type=float, default=float(map_default("map_trap_jump_min_drop", 0.34)))
parser.add_argument("--map-trap-jump-edge-margin", type=float, default=float(map_default("map_trap_jump_edge_margin", 0.06)))
parser.add_argument("--map-trap-jump-high-fraction", type=float, default=float(map_default("map_trap_jump_high_fraction", 0.04)))
parser.add_argument("--map-trap-jump-high-min-up", type=float, default=float(map_default("map_trap_jump_high_min_up", 0.26)))
parser.add_argument("--map-trap-jump-high-max-up", type=float, default=float(map_default("map_trap_jump_high_max_up", 0.78)))
parser.add_argument("--map-trap-jump-disguise", type=float, default=float(map_default("map_trap_jump_disguise", 0.35)))
parser.add_argument("--map-route-detour-period", type=int, default=int(map_default("map_route_detour_period", 8)))
parser.add_argument("--map-route-detour-depth", type=float, default=float(map_default("map_route_detour_depth", 0.10)))
parser.add_argument("--map-backtrack-period", type=int, default=int(map_default("map_backtrack_period", 0)))
parser.add_argument("--map-backtrack-depth", type=float, default=float(map_default("map_backtrack_depth", 0.0)))
parser.add_argument("--goal-progress-reward-scale", type=float, default=float(env_default("goal_progress_reward_scale", 2.4)))
parser.add_argument("--first-visit-reward", type=float, default=float(env_default("first_visit_reward", 0.10)))
parser.add_argument("--step-cost", type=float, default=float(env_default("step_cost", 0.0005)))
parser.add_argument("--fall-penalty", type=float, default=float(env_default("fall_penalty", 4.0)))
parser.add_argument("--success-time-bonus", type=float, default=float(env_default("success_time_bonus", 0.10)))
parser.add_argument("--stagnation-patience-steps", type=int, default=0)
parser.add_argument("--stagnation-warmup-steps", type=int, default=32)
parser.add_argument("--stagnation-progress-epsilon", type=float, default=0.002)
parser.add_argument("--stagnation-penalty", type=float, default=0.0)
parser.add_argument("--run-dir", default="data/runs")
parser.add_argument("--curriculum", default=DEFAULT_CURRICULUM)
args = parser.parse_args()
threads = configure_threads(int(args.cpu_threads))
mapgen_kwargs = dict(
map_scenic_turn_scale=float(args.map_scenic_turn_scale),
map_scenic_island_radius=float(args.map_scenic_island_radius),
map_scenic_vertical_step=float(args.map_scenic_vertical_step),
map_platform_min_scale=float(args.map_platform_min_scale),
map_platform_max_scale=float(args.map_platform_max_scale),
map_platform_tiny_fraction=float(args.map_platform_tiny_fraction),
map_platform_large_fraction=float(args.map_platform_large_fraction),
map_platform_aspect_jitter=float(args.map_platform_aspect_jitter),
map_edge_gap_min=float(args.map_edge_gap_min),
map_edge_gap_max=float(args.map_edge_gap_max),
map_route_gap_scale=float(args.map_route_gap_scale),
map_route_tiny_fraction=float(args.map_route_tiny_fraction),
map_route_tiny_min_scale=float(args.map_route_tiny_min_scale),
map_route_tiny_max_scale=float(args.map_route_tiny_max_scale),
map_momentum_jump_fraction=float(args.map_momentum_jump_fraction),
map_momentum_gap_bias=float(args.map_momentum_gap_bias),
map_redirect_period=int(args.map_redirect_period),
map_redirect_angle=float(args.map_redirect_angle),
map_direct_decoy_fraction=float(args.map_direct_decoy_fraction),
map_goal_xy_min=float(args.map_goal_xy_min),
map_goal_xy_per_jump_min=float(args.map_goal_xy_per_jump_min),
map_extra_span_min_frac=float(args.map_extra_span_min_frac),
map_extra_span_max_frac=float(args.map_extra_span_max_frac),
map_extra_span_end_margin=float(args.map_extra_span_end_margin),
map_route_edge_gap_floor=float(args.map_route_edge_gap_floor),
map_goal_vertical_bias=float(args.map_goal_vertical_bias),
map_goal_vertical_bias_min=float(args.map_goal_vertical_bias_min),
map_hairpin_period=int(args.map_hairpin_period),
map_hairpin_angle=float(args.map_hairpin_angle),
map_hairpin_depth=float(args.map_hairpin_depth),
map_cluster_extra_fraction=float(args.map_cluster_extra_fraction),
map_decoy_corridor_fraction=float(args.map_decoy_corridor_fraction),
map_unintuitive_depth=float(args.map_unintuitive_depth),
map_valley_period=int(args.map_valley_period),
map_valley_depth=float(args.map_valley_depth),
map_false_summit_fraction=float(args.map_false_summit_fraction),
map_false_branch_fraction=float(args.map_false_branch_fraction),
map_false_finish_fraction=float(args.map_false_finish_fraction),
map_greedy_trap_fraction=float(args.map_greedy_trap_fraction),
map_braid_bridge_fraction=float(args.map_braid_bridge_fraction),
map_braid_bridge_span=int(args.map_braid_bridge_span),
map_trap_jump_fraction=float(args.map_trap_jump_fraction),
map_trap_jump_drop=float(args.map_trap_jump_drop),
map_trap_jump_min_drop=float(args.map_trap_jump_min_drop),
map_trap_jump_edge_margin=float(args.map_trap_jump_edge_margin),
map_trap_jump_high_fraction=float(args.map_trap_jump_high_fraction),
map_trap_jump_high_min_up=float(args.map_trap_jump_high_min_up),
map_trap_jump_high_max_up=float(args.map_trap_jump_high_max_up),
map_trap_jump_disguise=float(args.map_trap_jump_disguise),
map_route_detour_period=int(args.map_route_detour_period),
map_route_detour_depth=float(args.map_route_detour_depth),
map_backtrack_period=int(args.map_backtrack_period),
map_backtrack_depth=float(args.map_backtrack_depth),
)
configure_motif_mapgen(**mapgen_kwargs)
install_motif_mapgen()
resume = None
if not bool(args.no_resume):
candidate = Path(str(args.resume_checkpoint))
if candidate.exists():
resume = str(candidate)
else:
print(f"resume_checkpoint_missing path={candidate}; training from scratch", flush=True)
cfg = make_config(
seed=17,
device=str(args.device),
envs=int(args.envs),
eval_envs=int(args.eval_envs),
ppo_steps=int(args.steps),
ppo_epochs=int(args.epochs),
minibatches=int(args.minibatches),
hidden=int(args.hidden),
lr=float(args.lr),
gamma=0.992,
gae_lambda=0.94,
entropy_coef=float(args.entropy_coef),
value_coef=0.55,
max_steps_factor=24.0,
run_dir=str(args.run_dir),
sensor_mode=str(args.sensor_mode),
sensor_topk=int(args.sensor_topk),
sensor_token_range=float(args.sensor_token_range),
sensor_fov_degrees=float(args.sensor_fov_degrees),
sensor_token_sort=str(args.sensor_token_sort),
observe_progress=bool(args.observe_progress),
start_forward_fraction=float(args.start_forward_fraction),
gravity=float(args.gravity),
accel=float(args.accel),
ground_damping=float(args.ground_damping),
air_damping=float(args.air_damping),
air_control=float(args.air_control),
max_speed=float(args.max_speed),
jump_velocity=float(args.jump_velocity),
sprint_speed_mult=float(args.sprint_speed_mult),
sprint_accel_mult=float(args.sprint_accel_mult),
turn_speed=float(args.turn_speed),
landing_pad_scale=float(args.landing_pad_scale),
landing_top_tolerance=float(args.landing_top_tolerance),
landing_prev_slack=float(args.landing_prev_slack),
fragile_platforms=bool(args.fragile_platforms),
fragile_delay_steps=int(args.fragile_delay_steps),
launch_pads=bool(args.launch_pads),
launch_pad_fraction=float(args.launch_pad_fraction),
launch_pad_velocity=float(args.launch_pad_velocity),
launch_pad_gap_extra=float(args.launch_pad_gap_extra),
moving_platforms=bool(args.moving_platforms),
moving_platform_fraction=float(args.moving_platform_fraction),
moving_platform_amplitude=float(args.moving_platform_amplitude),
moving_platform_period_steps=int(args.moving_platform_period_steps),
moving_platform_transport=bool(args.moving_platform_transport),
moving_platform_force_every=int(args.moving_platform_force_every),
moving_platform_force_offset=int(args.moving_platform_force_offset),
moving_platform_transport_span=float(args.moving_platform_transport_span),
moving_platform_endpoint_gap=float(args.moving_platform_endpoint_gap),
unlock_platforms=bool(args.unlock_platforms),
unlock_gate_count=int(args.unlock_gate_count),
unlock_lock_span=int(args.unlock_lock_span),
unlock_hold_steps=int(args.unlock_hold_steps),
unlock_reward=float(args.unlock_reward),
route_jumps=10,
distractors=8,
pillar_platforms=False,
map_height_offset=float(args.map_height_offset),
map_vertical_scale=float(args.map_vertical_scale),
map_max_height=float(args.map_max_height),
map_overlap_cleanup_iters=int(args.map_cleanup_iters),
map_illegal_decoy_fraction=float(args.map_illegal_decoy_fraction),
map_route_tiny_fraction=float(args.map_route_tiny_fraction),
map_route_tiny_min_scale=float(args.map_route_tiny_min_scale),
map_route_tiny_max_scale=float(args.map_route_tiny_max_scale),
map_momentum_jump_fraction=float(args.map_momentum_jump_fraction),
map_momentum_gap_bias=float(args.map_momentum_gap_bias),
map_redirect_period=int(args.map_redirect_period),
map_redirect_angle=float(args.map_redirect_angle),
map_direct_decoy_fraction=float(args.map_direct_decoy_fraction),
map_goal_xy_min=float(args.map_goal_xy_min),
map_goal_xy_per_jump_min=float(args.map_goal_xy_per_jump_min),
map_extra_span_min_frac=float(args.map_extra_span_min_frac),
map_extra_span_max_frac=float(args.map_extra_span_max_frac),
map_extra_span_end_margin=float(args.map_extra_span_end_margin),
map_route_edge_gap_floor=float(args.map_route_edge_gap_floor),
map_goal_vertical_bias=float(args.map_goal_vertical_bias),
map_goal_vertical_bias_min=float(args.map_goal_vertical_bias_min),
map_hairpin_period=int(args.map_hairpin_period),
map_hairpin_angle=float(args.map_hairpin_angle),
map_hairpin_depth=float(args.map_hairpin_depth),
map_cluster_extra_fraction=float(args.map_cluster_extra_fraction),
map_decoy_corridor_fraction=float(args.map_decoy_corridor_fraction),
map_unintuitive_depth=float(args.map_unintuitive_depth),
map_valley_period=int(args.map_valley_period),
map_valley_depth=float(args.map_valley_depth),
map_false_summit_fraction=float(args.map_false_summit_fraction),
map_false_branch_fraction=float(args.map_false_branch_fraction),
map_false_finish_fraction=float(args.map_false_finish_fraction),
map_greedy_trap_fraction=float(args.map_greedy_trap_fraction),
map_braid_bridge_fraction=float(args.map_braid_bridge_fraction),
map_braid_bridge_span=int(args.map_braid_bridge_span),
map_trap_jump_fraction=float(args.map_trap_jump_fraction),
map_trap_jump_drop=float(args.map_trap_jump_drop),
map_trap_jump_min_drop=float(args.map_trap_jump_min_drop),
map_trap_jump_edge_margin=float(args.map_trap_jump_edge_margin),
map_trap_jump_high_fraction=float(args.map_trap_jump_high_fraction),
map_trap_jump_high_min_up=float(args.map_trap_jump_high_min_up),
map_trap_jump_high_max_up=float(args.map_trap_jump_high_max_up),
map_trap_jump_disguise=float(args.map_trap_jump_disguise),
map_route_detour_period=int(args.map_route_detour_period),
map_route_detour_depth=float(args.map_route_detour_depth),
map_backtrack_period=int(args.map_backtrack_period),
map_backtrack_depth=float(args.map_backtrack_depth),
goal_progress_reward_scale=float(args.goal_progress_reward_scale),
first_visit_reward=float(args.first_visit_reward),
step_cost=float(args.step_cost),
fall_penalty=float(args.fall_penalty),
success_time_bonus=float(args.success_time_bonus),
stagnation_patience_steps=int(args.stagnation_patience_steps),
stagnation_warmup_steps=int(args.stagnation_warmup_steps),
stagnation_progress_epsilon=float(args.stagnation_progress_epsilon),
stagnation_penalty=float(args.stagnation_penalty),
)
print(
f"v37_start arch={args.policy_arch} envs={cfg.envs} eval_envs={cfg.eval_envs} steps={cfg.ppo_steps} "
f"minibatches={cfg.minibatches} cpu_threads={threads} mapgen=motif planner={args.planner_mode} "
f"sensor={args.sensor_mode}:{args.sensor_topk}@{args.sensor_fov_degrees:.0f}deg/{args.sensor_token_sort} "
f"observe_progress={bool(args.observe_progress)} launch={args.launch_pads} moving={args.moving_platforms} "
f"physics=g{args.gravity:.1f}/j{args.jump_velocity:.1f}/v{args.max_speed:.1f}/air{args.air_control:.2f}/turn{args.turn_speed:.1f}/land{args.landing_pad_scale:.2f} "
f"moving_transport={args.moving_platform_transport} unlock={args.unlock_platforms}:{args.unlock_gate_count}x{args.unlock_lock_span} "
f"unlock_hold={args.unlock_hold_steps} momentum={args.map_momentum_jump_fraction:.3f} "
f"start_forward={args.start_forward_fraction:.2f} "
f"tiny_route={args.map_route_tiny_fraction:.3f} redirect_period={args.map_redirect_period} "
f"direct_decoy={args.map_direct_decoy_fraction:.3f} goal_xy={args.map_goal_xy_min:.1f}+{args.map_goal_xy_per_jump_min:.2f}/jump "
f"extra_span={args.map_extra_span_min_frac:.2f}-{args.map_extra_span_max_frac:.2f}@{args.map_extra_span_end_margin:.2f} "
f"vertical_bias={args.map_goal_vertical_bias:.3f} "
f"hairpin={args.map_hairpin_period}:{args.map_hairpin_angle:.2f}:{args.map_hairpin_depth:.2f} "
f"cluster={args.map_cluster_extra_fraction:.3f} corridor={args.map_decoy_corridor_fraction:.3f} "
f"unintuitive={args.map_unintuitive_depth:.2f} valley={args.map_valley_period}:{args.map_valley_depth:.2f} "
f"false_summit={args.map_false_summit_fraction:.3f} false_branch={args.map_false_branch_fraction:.3f} "
f"false_finish={args.map_false_finish_fraction:.3f} "
f"greedy_trap={args.map_greedy_trap_fraction:.3f} braid_bridge={args.map_braid_bridge_fraction:.3f}:{args.map_braid_bridge_span} "
f"trap_jump={args.map_trap_jump_fraction:.3f}:{args.map_trap_jump_min_drop:.2f}-{args.map_trap_jump_drop:.2f}@{args.map_trap_jump_edge_margin:.2f} "
f"trap_high={args.map_trap_jump_high_fraction:.3f}:{args.map_trap_jump_high_min_up:.2f}-{args.map_trap_jump_high_max_up:.2f} "
f"trap_disguise={args.map_trap_jump_disguise:.2f} "
f"route_detour={args.map_route_detour_period}:{args.map_route_detour_depth:.2f} "
f"backtrack={args.map_backtrack_period}:{args.map_backtrack_depth:.2f} "
f"step_cost={args.step_cost:.4f} time_bonus={args.success_time_bonus:.2f} "
f"stagnation={args.stagnation_patience_steps}@{args.stagnation_warmup_steps}/eps{args.stagnation_progress_epsilon:.4f}/pen{args.stagnation_penalty:.2f} "
f"anchor_bc={args.anchor_bc_coef:.4f}:{args.anchor_checkpoint or ''} "
f"resume={resume or 'none'}",
flush=True,
)
result = train(
cfg,
str(args.run_name),
depth=int(args.depth),
policy_arch=str(args.policy_arch),
planner_mode=str(args.planner_mode),
planner_hidden=int(args.planner_hidden),
planner_depth=int(args.planner_depth),
planner_max_xy=float(args.planner_max_xy),
planner_max_z=float(args.planner_max_z),
planner_blend_bias=float(args.planner_blend_bias),
capture=int(args.capture),
log_every=int(args.log_every),
min_stage_updates=int(args.min_stage_updates),
resume_checkpoint=resume,
reset_planner_head=bool(args.reset_planner_head),
curriculum=parse_curriculum(str(args.curriculum)),
sil_coef=float(args.sil_coef),
anchor_checkpoint=str(args.anchor_checkpoint) if args.anchor_checkpoint else None,
anchor_bc_coef=float(args.anchor_bc_coef),
)
print(result, flush=True)
if __name__ == "__main__":
main()