re-capture: read the ADVANCED CONTROLS tutorial; its moves regress the pilot, so they ship off
tutorial_capture.sh plays a tutorial and photographs what it teaches. ADVANCED
CONTROLS states three mechanics the key-config screen only named:
B + LS Side Roll / 180 Degree Turn / Level Off
B + A together face the target (snap turn)
LT + RT together 'sets your fighter's speed to that of the target ... works
well when you are trying to get behind an enemy. Once
behind an enemy, this also helps you attack them.'
Wired both usable ones in and measured, one run each, everything else equal:
commitment only ............ 101 missiles, 364 fire frames, 9 kills
+ match(4500) + snap-face .... 9 missiles, 28 fire frames, 0 kills
+ match(1200) + snap-face ... 57 missiles, 225 fire frames, 2 kills
So both are a net regression as applied, and both now default to OFF. Matching a
target's speed while still 5 km behind means never closing (the pilot sat at
272 u/s all run) — the tutorial scopes it to being already in the saddle. The
B+A snap turn reorients mid-pursuit and destroys the dwell commitment buys.
The code and thresholds stay so a future session can re-enable and A/B them over
SEVERAL runs; one run per config is inside this stage's spawn variance.
This commit is contained in:
@@ -129,6 +129,37 @@ class Pilot:
|
||||
COMMIT_MAX = 14.0 # s before we are allowed to reconsider anyway
|
||||
COMMIT_DROP = 6000.0 # ...or it gets this far away
|
||||
COMMIT_BEHIND = 2.5 # ...or stays >90 deg off the nose this long
|
||||
# --- moves the ADVANCED CONTROLS tutorial teaches (tutorial_capture.sh) ---
|
||||
# "Target an enemy and pull LT and RT [together]. This sets your fighter's
|
||||
# speed to that of the target. This works well when you are trying to get
|
||||
# behind an enemy. Once behind an enemy, this also helps you attack them."
|
||||
# That is the overshoot problem solved by the game itself: matching speed
|
||||
# holds us in the target's rear hemisphere instead of flying through it,
|
||||
# which is the only way a time-on-target lock ever completes.
|
||||
# Scope matters, and a measured regression proved it: applying the match at
|
||||
# 4500 with a 70 deg cone dropped kills 9 -> 0. Matching a target's speed
|
||||
# while still 5 km behind it means never closing — the pilot sat at 272 u/s
|
||||
# and fired 28 frames all run. The tutorial's own wording scopes it: "when
|
||||
# you are trying to get BEHIND an enemy... ONCE BEHIND an enemy, this also
|
||||
# helps you attack them". So it is station-keeping in the saddle, not an
|
||||
# approach throttle. Only match when we are already there.
|
||||
# MEASURED: both tutorial moves are a NET REGRESSION as applied here, so
|
||||
# both ship DISABLED. One run each, same everything else:
|
||||
# commitment only ............ 101 missiles, 364 fire frames, 9 kills
|
||||
# + match(4500) + snap-face .... 9 missiles, 28 fire frames, 0 kills
|
||||
# + match(1200) + snap-face ... 57 missiles, 225 fire frames, 2 kills
|
||||
# The moves are real and the tutorial is right about them; the loop just
|
||||
# cannot use them yet. Snap-face (B+A) reorients the craft mid-pursuit and
|
||||
# destroys the very dwell that commitment buys, and speed-match needs to be
|
||||
# entered from the saddle rather than commanded at range. Set MATCH_RANGE
|
||||
# and lower FACE_MIN to re-enable, and A/B them over SEVERAL runs — one run
|
||||
# per config is inside this stage's spawn variance.
|
||||
MATCH_RANGE = 0.0 # 1200.0 to re-enable
|
||||
MATCH_CONE = math.radians(25)
|
||||
# "Press B and A together to face [the target]" — a snap turn, far quicker
|
||||
# than winding the PD controller around for a contact behind us.
|
||||
FACE_MIN = math.radians(999) # 50 deg to re-enable the B+A snap turn
|
||||
FACE_PERIOD = 4.0
|
||||
|
||||
def __init__(self, W, pad, dry=False, log=sys.stdout):
|
||||
self.W = W
|
||||
@@ -158,6 +189,10 @@ class Pilot:
|
||||
self.commit_off = None # entity we are committed to
|
||||
self.commit_t = -1e9
|
||||
self.behind_since = None
|
||||
self.matching = False
|
||||
self.face_t = -1e9
|
||||
self.face_down = None
|
||||
self.faces = 0
|
||||
|
||||
def f32(self, off):
|
||||
b = os.pread(self.W.fd, 4, off)
|
||||
@@ -204,13 +239,31 @@ class Pilot:
|
||||
return hull, shield
|
||||
|
||||
def set_throttle(self, want):
|
||||
"""RT / LT are a persistent setting, so only send the change."""
|
||||
"""RT / LT are a persistent setting, so only send the change.
|
||||
|
||||
`want` is +1 accelerate, -1 brake, 0 coast, or the string "match" for
|
||||
the tutorial's both-triggers speed-match onto the current target.
|
||||
"""
|
||||
if want == self.throttle or self.dry:
|
||||
return
|
||||
self.pad.trig("RT", 1.0 if want > 0 else 0.0)
|
||||
self.pad.trig("LT", 1.0 if want < 0 else 0.0)
|
||||
if want == "match":
|
||||
self.pad.trig("RT", 1.0)
|
||||
self.pad.trig("LT", 1.0)
|
||||
else:
|
||||
self.pad.trig("RT", 1.0 if want > 0 else 0.0)
|
||||
self.pad.trig("LT", 1.0 if want < 0 else 0.0)
|
||||
self.throttle = want
|
||||
|
||||
def face_target(self, t):
|
||||
"""B + A: snap the nose onto the selected target."""
|
||||
if self.dry or t - self.face_t < self.FACE_PERIOD:
|
||||
return
|
||||
self.pad.press("B")
|
||||
self.pad.press("A")
|
||||
self.face_down = t
|
||||
self.face_t = t
|
||||
self.faces += 1
|
||||
|
||||
# -------------------------------------------------------------- targets
|
||||
def hostiles(self, ents, me_off):
|
||||
out = []
|
||||
@@ -439,10 +492,10 @@ class Pilot:
|
||||
# than a stall in the middle of a battle; collision avoidance already
|
||||
# keeps a fighter-sized margin.
|
||||
want = norm(tgt[3]) if tgt else fwd
|
||||
if tgt and tgt[4] > 2500.0:
|
||||
if tgt and tgt[4] < self.MATCH_RANGE and ang(tgt[3], fwd) < self.MATCH_CONE:
|
||||
self.set_throttle("match") # sit in its rear hemisphere
|
||||
elif tgt and tgt[4] > 2500.0:
|
||||
self.set_throttle(+1)
|
||||
elif tgt and tgt[4] < 500.0 and speed > 900.0:
|
||||
self.set_throttle(-1)
|
||||
else:
|
||||
self.set_throttle(0)
|
||||
fire = True
|
||||
@@ -503,6 +556,13 @@ class Pilot:
|
||||
if fire != self.firing:
|
||||
(self.pad.press if fire else self.pad.release)("RB")
|
||||
self.firing = fire
|
||||
if self.face_down is not None and t - self.face_down > 0.2:
|
||||
self.pad.release("B")
|
||||
self.pad.release("A")
|
||||
self.face_down = None
|
||||
elif (tgt and self.mode in ("ENGAGE", "DEFEND")
|
||||
and abs(aim[0]) > self.FACE_MIN and pn < 1.2):
|
||||
self.face_target(t)
|
||||
if self.missile_down and t - self.missile_t > 0.15:
|
||||
self.pad.release("Y")
|
||||
self.missile_down = False
|
||||
@@ -514,9 +574,10 @@ class Pilot:
|
||||
self.missiles += 1
|
||||
|
||||
msg = (f"{self.mode:<7} hull={hull:6.0f} shd={shield:6.0f} spd={speed:6.0f} "
|
||||
f"thr={self.throttle:+d} yaw={math.degrees(yaw):+6.1f} "
|
||||
f"thr={str(self.throttle):>5} yaw={math.degrees(yaw):+6.1f} "
|
||||
f"pit={math.degrees(pitch):+6.1f} aim={math.degrees(aim[0]):+6.1f}"
|
||||
f"/{math.degrees(aim[1]):+6.1f} fire={int(fire)} msl={self.missiles}")
|
||||
f"/{math.degrees(aim[1]):+6.1f} fire={int(fire)} msl={self.missiles}"
|
||||
f" fc={self.faces}")
|
||||
if ast is not None:
|
||||
msg += f" ast={a_frac*100:5.1f}%"
|
||||
if a_dmg > self.ASSET_ALERT:
|
||||
|
||||
Reference in New Issue
Block a user