# Drift scoring regression (run with NFSU2_FIXED_DT=120, tests/run_suite.sh
# "driftscore"): Quick Race Drift, Stadium Drift 2, 3 AI drifters, Nissan
# 350Z.  Four open-loop handbrake drifts (the outcome of each one depends on
# the exact trajectory, so the checks are cumulative): at least one drift must
# be detected, accrue and bank into the total.  Usually one also ends in the
# wall (style state 4: pending points dropped), but not in every run (the
# trajectory varies with the frames before GO), so a crash loss is counted,
# not required; tools/drift_accrual.py checks the loss rule whenever one
# happens.  Scoring objects: $P = the human racer, [$P+0x1d4] =
# DriftScore (first style: +0x14 state 0 drifting/1 starting/2 idle/3 banked/
# 4 lost, +0x1c multiplier, +0x20 drift count, +0x24 pending, +0x2c total),
# [$P+0x1d8] = DriftCar (+0x15 crash flag, +0x1c level, +0x34 point rate),
# [[$P+0x1d8]+8] = the car (+0x60 position, +0x430 speed).  The style's
# +0x28 is the rate of its last report and +0x34 that report's WorldTimer
# stamp; [0x86518c] is the WorldTimer (1/4000 s) and [0x865154] the frame's
# world step.  The trace runs every frame:
# tests/checks/driftscore.sh checks the scoring rules on it
# (tools/drift_accrual.py: pending += 120 * rate * multiplier * dt, banking,
# crash loss).
0     tapuntil RETURN MC_Background.fng 120 4000
+200  tap RETURN
+0    tapuntil RETURN UI_QRModeSelect.fng 150 3000
+40   tap RIGHT
+40   tap RIGHT
+40   tap RIGHT
+60   dump mode_selected
+0    tapuntil RETURN UI_QRTrackSelect.fng 150 1500
+0    tapuntil RETURN UI_QRModeOptions.fng 150 1500
+0    tapuntil RETURN UI_QRCarSelect.fng 150 1500
+100  tap RIGHT
+30   tap RIGHT
+30   tap RIGHT
+30   tap RIGHT
+30   tap RIGHT
+30   tap RIGHT
+30   tap RIGHT
+90   dump car_350z
+0    tapuntil RETURN PC_Loading.fng 150 1500
+0    waitmem 0x8654a4 6 6000
+0    waitexpr i:[0x890118] == 4 6000            # GRaceStatus: 4 = racing (after the countdown)
+0    wzero now
+0    trace 1 stamp=i:[[$P+0x1d4]]+0x34 wt=i:0x86518c srate=[[$P+0x1d4]]+0x28 dtw=0x865154 v=[[$P+0x1d8]+8]+0x430 st=i:[[$P+0x1d4]]+0x14 mult=[[$P+0x1d4]]+0x1c n=i:[[$P+0x1d4]]+0x20 pend=[[$P+0x1d4]]+0x24 tot=[[$P+0x1d4]]+0x2c rate=[$P+0x1d8]+0x34 lvl=i:[$P+0x1d8]+0x1c crash=b:[$P+0x1d8]+0x15 a0=[[$R0+0x1d4]]+0x2c a1=[[$R1+0x1d4]]+0x2c a2=[[$R2+0x1d4]]+0x2c a3=[[$R3+0x1d4]]+0x2c
+0    expect i:[[$P+0x1d4]]+0x14 == 2              # idle at GO
# counted from here on, every frame: drifts that count (state 0), drifts
# banked (3) and drifts lost to a crash (4)
+0    edge drifts i:[[$P+0x1d4]]+0x14 == 0
+0    edge banked i:[[$P+0x1d4]]+0x14 == 3
+0    edge lost i:[[$P+0x1d4]]+0x14 == 4
+0    down UP
# drift 1: flick left with the handbrake, counter-steer, straighten
3600wms down LEFT
+100wms tap SPACE 8
+300wms up LEFT
+0    down RIGHT
+300wms up RIGHT
+0    down LEFT
+150wms up LEFT
+0    dump drift1
# drift 2: long handbrake slide, usually into the wall
6300wms down RIGHT
+100wms tap SPACE 12
+600wms up RIGHT
+0    down LEFT
+400wms up LEFT
+0    dump drift2
# drifts 3 and 4: the same flicks again wherever the car is now
+1500wms down LEFT
+100wms tap SPACE 10
+400wms up LEFT
+0    down RIGHT
+300wms up RIGHT
+1500wms down RIGHT
+100wms tap SPACE 10
+500wms up RIGHT
+0    down LEFT
+300wms up LEFT
+2000wms dump flicks_end
+0    up UP
# Then the game's own AI drives the player's car for 30 s (career.c
# "autopilot"; the player's AI driver drifts like the AI opponents).  The
# open-loop flicks above do not always count: the trajectory varies with the
# frames before GO, and on the integrated
# branch they counted in 4 of 7 runs.  The AI's drifts make the counted and
# banked checks hold; same car, same DriftScore, same per-frame trace and
# rules checks (tests/checks/driftscore.sh) for the whole run.
# The AI does not drift on every stretch either: from some starting points
# (a car stopped against the wall after the flicks) its first drift came
# after more than 30 s, and the run failed with nothing banked (seen under
# load, where the trajectories spread more).  So after the 30 s it keeps
# driving until a drift has banked, for at most 90 s more of world time
# (10800 frames at the fixed 1/120 s step); the checks below are unchanged.
+0    autopilot on
+30000wms waitexpr @banked >= 1 10800              # 30 s, then until a drift banked
+0    autopilot off
+0    waitexpr [[$P+0x1d4]]+0x24 == 0 2400           # the last drift banked (or lost)
+120  dump end
+0    expect @drifts >= 1                            # a drift was detected and counted
+0    expect @banked >= 1                            # ... and banked
+0    expect [[$P+0x1d4]]+0x2c >= 50                 # into the total (50 is the floor, not a margin: a drift is
#                                                      counted only with >= 50 points, 0x56E920, drift-fidelity.md)
+0    expect @lost >= 0                              # crash losses: logged, not required
+0    expect [[$P+0x1d4]]+0x24 == 0                  # nothing pending now
+0    untrace
+0    quit
