mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
feat(*): Exempt the floor from the wall-contact penalty, add a tilt penalty for non-upright flight, and double velocity-to-ball shaping
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
[node name="Match" type="Node3D"]
|
||||
script = ExtResource("1_m")
|
||||
bot_model_path = "res://bots/rookie.json"
|
||||
bot_model_path = "res://bots/run03.json"
|
||||
|
||||
[node name="Arena" parent="." instance=ExtResource("2_m")]
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
[node name="Spectate" type="Node3D"]
|
||||
script = ExtResource("1_s")
|
||||
bot_a_model_path = "res://bots/run02.json"
|
||||
bot_b_model_path = "res://bots/run01.json"
|
||||
bot_a_model_path = "res://bots/run03.json"
|
||||
bot_b_model_path = "res://bots/run03.json"
|
||||
|
||||
[node name="Arena" parent="." instance=ExtResource("2_s")]
|
||||
|
||||
|
||||
@@ -16,13 +16,22 @@ extends AIController3D
|
||||
# per sim-second); event terms fire once. Exported so tuning needs no code
|
||||
# edits. Goal rewards are added by TrainingMode, which owns goal events.
|
||||
@export var ball_touch_reward := 0.25
|
||||
@export var velocity_to_ball_weight := 0.001
|
||||
@export var velocity_to_ball_weight := 0.002
|
||||
@export var ball_velocity_to_goal_weight := 0.004
|
||||
# Per-tick penalty while touching the arena enclosure (walls/floor/ceiling).
|
||||
# At 60 ticks/sim-second this is -0.3/s: a ship parked on a wall for a full
|
||||
# 30 s episode loses ~9 — comparable to conceding — while a brief graze
|
||||
# costs almost nothing.
|
||||
# Per-tick penalty while pressed against a side wall, end wall, or the
|
||||
# ceiling — NOT the floor (run03 lesson: taxing floor contact punishes the
|
||||
# ship's natural low flight and drowns every other signal). At 60 ticks per
|
||||
# sim-second this is -0.3/s: parked on a wall for a full 30 s episode loses
|
||||
# ~9 — comparable to conceding — while a brief graze costs almost nothing.
|
||||
@export var wall_contact_penalty := 0.005
|
||||
# Per-tick penalty for not being upright, scaled by tilt: 0 when flat, full
|
||||
# value (-0.12/s) when inverted. A penalty rather than an upright bonus so a
|
||||
# flat, idle ship farms nothing.
|
||||
@export var tilt_penalty := 0.002
|
||||
|
||||
# A ship (1x1x4 box) touching a wall has its centre within ~2.05 of it;
|
||||
# 2.5 adds slack for contact jitter without misreading mid-field contact.
|
||||
const WALL_PROXIMITY_MARGIN := 2.5
|
||||
|
||||
var ship: Ship
|
||||
var rl_controller: RLShipController
|
||||
@@ -89,14 +98,32 @@ func _physics_process(delta):
|
||||
var ball_progress := ball.linear_velocity.dot(ball_to_goal.normalized())
|
||||
reward += ball_velocity_to_goal_weight * ball_progress / ShipObservations.BALL_SPEED_SCALE
|
||||
|
||||
# Dense penalty: every tick spent in contact with the arena enclosure
|
||||
# Dense penalty: every tick spent pressed against a wall or the ceiling
|
||||
# (contact monitoring is already on for the ball-touch reward). Ships
|
||||
# bumping each other or the ball is fine — only the boundary counts.
|
||||
if wall_contact_penalty > 0.0:
|
||||
for body in ship.get_colliding_bodies():
|
||||
if body is ArenaBoundary:
|
||||
reward -= wall_contact_penalty
|
||||
break
|
||||
# bumping each other, the ball, or the floor is fine. The boundary is one
|
||||
# body, so position tells us which surface the contact is.
|
||||
if wall_contact_penalty > 0.0 and _touching_boundary() and _near_wall_or_ceiling():
|
||||
reward -= wall_contact_penalty
|
||||
|
||||
# Dense penalty: tilt away from upright (0 flat, max when inverted) —
|
||||
# discourages ending up on a side or roof without rewarding idleness.
|
||||
if tilt_penalty > 0.0:
|
||||
var uprightness: float = ship.global_transform.basis.y.dot(Vector3.UP)
|
||||
reward -= tilt_penalty * (1.0 - uprightness) * 0.5
|
||||
|
||||
|
||||
func _touching_boundary() -> bool:
|
||||
for body in ship.get_colliding_bodies():
|
||||
if body is ArenaBoundary:
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _near_wall_or_ceiling() -> bool:
|
||||
var p := ship.global_position
|
||||
return absf(p.x) > ArenaBoundary.INNER_HALF_X - WALL_PROXIMITY_MARGIN \
|
||||
or absf(p.z) > ArenaBoundary.INNER_HALF_Z - WALL_PROXIMITY_MARGIN \
|
||||
or p.y > ArenaBoundary.INNER_HEIGHT - WALL_PROXIMITY_MARGIN
|
||||
|
||||
|
||||
func _on_ship_body_entered(body: Node) -> void:
|
||||
|
||||
Reference in New Issue
Block a user