THE REVERSING BALLET
====================
A truck parking game for the Commodore 64 (PAL), 2026

Reverse an articulated truck into a loading bay without touching a wall - then
try it with two trailers, and then with three. The trailers swing the opposite
way, and learning to dance with them is the whole game.

Free. Runs on a real C64 or in an emulator such as VICE. 12 levels, joystick or
paddle.


IN THIS ZIP
-----------
  reversing_ballet.d64            the game on a 1541 disk image
  reversing_ballet_gameplay.mp4   3:00 gameplay video (recorded in VICE, with
                                  sound): the title screen, a demo, the help
                                  page, level 7 and the expert levels 9-12,
                                  the final score and the credits
  readme.txt                      this file


WHAT IT IS
----------
The Reversing Ballet is a parking game. Each level is a walled yard seen from
above, with a yellow bay at the end of it. Drive the truck in, reversing, and
stop with the cab facing out. Hitting a wall or a parked truck costs damage;
ten damage ends the game. The faster you park, the bigger the time bonus.
Score = 500 + time bonus - damage.

It's built on a real piece of 8-bit history. The truck - its outline, its
steering and above all the way its trailer swings - comes from Juggernaut, a
1985 ZX Spectrum game written by Pete Cooke and published by CRL. We took the
Spectrum program apart, ported its truck to the C64 exactly, and built a new
game around the part that was always the most fun: getting that trailer to go
where you want it.


WHY MAKE IT
-----------
Reversing a trailer is a genuinely hard, genuinely satisfying skill: to send
the trailer left you steer right, and every correction you make shows up a
moment later, a bit bigger than you wanted. Juggernaut modelled that properly
in 1985, on a 3.5 MHz machine. The idea behind this project was to give that
physics a game of its own, on the C64, running smoothly - and then to keep
raising the bar with longer trains.

It's also an experiment in how far a human and an AI can take a retro project
together: the idea, game and level design and the testing by grue; the
disassembly, porting and all the 6502 code by Claude, an AI by Anthropic.


HOW TO PLAY
-----------
Reverse into the yellow bay and stop, cab facing out. Driving in forwards
doesn't count - the game tells you to turn round.

Joystick, port 2
  left / right      steer (the wheel returns to the middle when you let go)
  up / down         accelerate / brake
  fire or SPACE     gear 1 <-> 2; when stopped, forward <-> reverse; start the
                    level

Paddle, port 2
  knob              the steering wheel - it follows the knob
  button held       accelerate; let go and the truck brakes gently
  SPACE             gear, forward/reverse, start

Keys
  P                 title: joystick or paddle
  F1                help page (the game pauses)
  F3                title: start at the expert levels (9-12)
  F5                title: credits
  F7                title: training - no score, no game over, + skips a level
  RETURN            restart the level
  RUN/STOP          quit to the title screen
  (15 s)            title left alone: a demo drives one level, the next one
                    each time; any key or fire ends it

The screen: the status line at the top (level, score, time bonus, damage,
speed, gear), a message line under it, the yard, and on the right a steering
wheel and a gear selector (1, 2, R).

The levels
  Levels 1-8 use one trailer and add tighter bays, gaps between parked trucks,
  narrow alleys and oil. On oil the tyres barely grip and the truck slides;
  level 8's whole yard is oily, with a gate of parked trucks. Levels 9-11 hitch
  a second trailer, level 12 a third. Level 9 starts off the dock's line, so
  the trailers have to be brought round while reversing; in level 11 the train
  starts facing the dock and has to make a U-turn first - steer too hard and
  the trailers fold. More trailers are heavier - speed changes far more slowly,
  both speeding up and braking - and they get a bigger time bonus.


LOADING
-------
In VICE: drag the .d64 onto the VICE window, or start it with
  x64sc -autostart reversing_ballet.d64
Give it a joystick in control port 2. For the paddle, set control port 2 to
Paddles and press P on the title screen; the mouse turns the knob.

On a C64: write the image to a floppy, or use an SD2IEC, a 1541 Ultimate or
similar, then
  LOAD"*",8,1
  RUN

PAL machine recommended (the speed is tuned for 50 Hz). Loading the 94 blocks
takes about a minute on a stock 1541 and about 10 seconds with JiffyDOS - the
disk is laid out (sector interleave 6) for JiffyDOS, measured in VICE. The game
then unpacks itself in about a second. The disk's directory shows the game, a
steering wheel and a note, drawn with PETSCII.


HOW IT WAS MADE - AND WHAT HURT
-------------------------------
The project started as a straight port of Juggernaut and turned into a game of
its own. These are the main steps, with the problems that cost the most time.

1. Taking the Spectrum game apart
   The tape image was unpacked into its loader and the 40 KB game block, then
   disassembled into a labelled Z80 source with SkoolKit. Which bytes are code
   and which are data was worked out from emulator traces of the title, the
   town map and driving. The rebuilt source reassembles byte for byte into the
   original.
   Pain: about 7.7 KB of code mixed with tables, jump tables and graphics.
   Without traces, a disassembler happily "decodes" data as instructions.

2. A bit-exact truck on the 6502
   The truck's physics - an articulated tractor and trailer in fixed point -
   was rewritten in 6502 and checked against the original Z80 code running in
   an emulator. After every update the two must agree on every byte of the
   state: heading, trailer angle, position, speed.
   Pain: the Z80's 16-bit arithmetic and the Spectrum's rounding had to be
   copied exactly. "Close" isn't good enough, because the trailer amplifies
   every difference.

3. Drawing a rotating truck in sprites
   The Spectrum draws the truck as software graphics. On the C64 its outline
   is drawn line by line into a 48x42 block of four hardware sprites,
   double-buffered so you never see half a picture. The drawing code is
   generated per angle - long runs of plain stores, no loops - and a finished
   image is reused while the angles don't change.
   Pain: a turning truck still costs up to ~27,000 CPU cycles to draw, more
   than a whole frame. That decided the update rate.

4. A game around the truck
   Walled bays you have to reverse into, damage, a time bonus, oil, a title
   page and a help page, a steering wheel and a gear selector, SID engine
   sound, a training mode and credits. Levels are checked with an automatic
   driver: a feedback "player" that steers the real game code in a 6502
   emulator until the truck is parked, so a level is known to be solvable
   before anyone plays it. Those proven drives, packed to a byte per step, are
   also the demos the title screen plays after 15 seconds.
   Pain: the original's 22.5 degree steering lock made reversing hopeless - a
   bent trailer swings faster than the cab can follow. It became 45 degrees,
   with a self-centring wheel. And very slow turns used to vanish entirely,
   because the original's division dropped the remainder each update;
   carrying it over fixed "the truck goes straight back no matter what I do".
   Pain: the demos replayed perfectly in the emulator used for testing, yet in
   the real game a level sometimes drove differently. A few physics counters
   (the trailers' mass timing, the oil grip) were never reset, so a level
   played slightly differently depending on how the one before ended. Now
   every level starts from the same state.

5. Two trailers, then three
   The extra trailers can't be drawn at run time - there's no time left - so
   every one of their 128 angles is precalculated as a pair of sprites placed
   wherever they fit best. At run time a trailer only needs a 128-byte copy,
   and only when its angle step changes. The third trailer reuses the second
   one's pictures.
   Pain: the C64 has eight sprites. The truck takes four, two trailers four
   more, and the oil patches and the steering wheel wanted some too. The wheel
   and gear selector first shared one sprite via a raster split, and in the
   end became characters, which freed the last two sprites for the third
   trailer. Oil stays off the trailer levels.

6. Making it feel right
   A jackknife between trailers is now a solid bump that stops the truck,
   instead of a clamp that dragged a trailer sideways ("it slips!"). Trailers
   have mass: speed changes only every 6th update with two of them, every 10th
   with three. The first, gentler settings were "hardly felt".
   Pain: what looks like a big change on paper can be invisible at 25 updates
   per second. Tuning took real play, in VICE, by a human.


MAKING IT RUN AS WELL AS IT DOES
--------------------------------
  8 -> 25       updates per second: the Spectrum's pace vs. the C64 version
  35K           CPU cycles in the slowest update with three trailers, of a
                ~38K budget
  50 -> 23 KB   game packed for loading, unpacks in about 1 second
  0             late updates in a VICE stress run with three trailers turning
                hard

- Cache on. The bug that only a real C64 had. At start-up the game never
  cleared its zero-page variables. In the test emulator memory starts at zero,
  but on a real C64 one of them sat on top of BASIC's own code - so the "don't
  reuse images" flag was always set and the image cache never worked. Found by
  measuring in VICE instead of trusting the tests.
- 2 frames. Checking collisions one picture later. Hardware sprite collisions
  are only known after a picture has been on screen. Before, every update
  waited a whole frame for that. Now each double buffer remembers what was
  drawn into it, and an update checks the previous picture while the new one
  is shown, so drawing gets two full frames. A bump is noticed 1/25 s later -
  nobody can tell.
- 16 KB. Precalculated trailers. All 128 angles of the extra trailers are
  prepared on the PC: two sprites per angle, positioned per angle, 16 KB under
  the BASIC ROM. Turning a trailer at run time is just a copy.
- -0.7K x2. An unrolled copy. With three trailers both trailer pictures can
  change in the same update. The 128-byte copy was rewritten without the
  pointer loop: about 1.4K cycles instead of 2K per trailer - the headroom to
  keep 25 updates/s.
- -1 IRQ. A wheel made of characters. The steering wheel and gear selector are
  3x3 blocks of characters, rewritten only when they change. That freed a
  sprite and removed the mid-screen interrupt.
- C64C. No flicker on newer machines. Writing a colour register while that
  colour is on screen makes grey dots on the C64C's newer video chip, so the
  game never changes the border colour mid-frame.
- 1.0 s. A packer built for unpacking speed. The release is packed with
  c64pack, a self-extracting packer whose byte-aligned format unpacks the
  50 KB game in about a second (23.7 KB on disk).


THE DEMO RUNS - HOW THEY WERE MADE, AND HOW HARD IT WAS
-------------------------------------------------------
(Written by Claude, who made them. grue asked for an honest account.)

What a demo is. Leave the title screen alone for 15 seconds and the game
drives one level by itself, the next level each time, all 12 in turn. Nobody
played these drives. Each one is a list of joystick inputs, one per update
(25 a second), found by programs on the PC that drive the real game code in a
6502 emulator (py65) until the truck is parked. The game replays the list, so
a demo is exactly as good as the search that found it. Packed one byte per
run of equal inputs (count in the high nibble, input code in the low one), the
12 demos take 3,966 bytes, squeezed into three free corners of memory with
about 330 bytes to spare.

You can tell they're machine-made: the steering taps left, centre, right
almost every update - it's a feedback controller, not a person. The routes
are often not the ones a human would choose.

How it went. When grue moved the start positions of several levels and added
oil to two more, nine of the twelve stored drives no longer worked (two of
them had been broken for a while already). The automatic driver can only back
into a bay from roughly in line with it, so for each level I wrote a search:
random forward routes (a few waypoints for the truck to drive through), each
followed by the reversing driver, about 4,000 tries per level spread over 44
processor cores. Levels 1, 4, 5, 7 and 9 fell out of that within minutes;
level 6 (a narrow alley) needed a rough route sketched by hand that the search
then varied.

Level 8 (the oily yard) needed a hand-drawn route - over the top of a parked
truck and back through the gate - which the search then fine-tuned. Level 3
has its gap between the parked trucks completely blocked, which leaves a 40
pixel corridor in front of the bay; the reversing driver can't start from
there at all. I added a scripted full-lock "swing" before the driver takes
over and searched its length, speed and starting point.

Mistakes I made along the way:
- The driver only checked for collisions, not for the damage counter. So three
  of my first "solutions" (levels 3, 6, 7) quietly took a jackknife damage
  point. I first assumed the real game and the test emulator disagreed and
  spent a long time comparing memory dumps between them - including one trace
  comparison that was off by a step, which sent me looking for a difference
  that wasn't there. In the end both emulators agreed perfectly; my driver was
  simply accepting a damaged run. Now any damage fails a run, and every demo
  parks with 0 damage.
- That hunt did find real game bugs, though: two counters (the trailers' mass
  timing and the oil grip) were not reset when a level started, so a level
  drove slightly differently depending on how the previous one ended, and the
  trailer's cached sine/cosine also came from the previous level for the first
  step. All three are now reset.

Level 12 - the hard one, in detail. Level 12 pulls three trailers. The whole
train is 78 pixels long, the bay is 88 pixels deep, and the new start puts the
train 32 pixels above the bay's line, already over the bay and facing away
from it. So the train has to be driven forward out to the left, brought down
32 pixels, and reversed back in dead straight.

- First, the automatic driver had no idea about a third trailer: it controls
  the second trailer's tail through the cab, and with three the last trailer
  just wanders. I wrote a third control loop (lateral error behind trailer
  three -> wanted angle of trailer three -> wanted angle between trailers two
  and three -> and on down to the steering).
- 4,000 random routes: none parked.
- Second idea: an S-bend forward, then reverse with the wheel straight - the
  way the old level 12 was solved. It fails because forward driving
  straightens a three-trailer train only slowly. The bend can't start until the
  last trailer has cleared the bay's top-left corner, and by the time the cab
  reaches the left wall the trailers still lie at an angle. The yard is not
  long enough.
- Third: an evolutionary search over the route and all eleven control gains at
  once. After twelve generations it reported success - and the replay failed.
  That was my error: in the scoring, any negative value counted as "parked",
  and the truck overshooting its target point also gave a negative value.
  It had never parked. I removed that route and fixed the scoring.
- With honest scoring the search stalled (best score around 100 where 0 means
  parked) for both one-pass routes and routes with "shunting" (driving forward
  again part way to straighten the train, like a real driver). Watching the
  best failures showed why: every forward bend left the trailers pointing down
  and to the left, so reversing carried the whole train up and to the right,
  away from the bay line, every time.
- The fix was to let the routes overshoot: drive down well past the bay line,
  so that reversing brings the train back up onto it. With that allowed, the
  search found a drive in three generations: an S-bend that overshoots, then
  two shunts, then the final reverse. It parks with 0 damage after 1,284
  updates - about 51 seconds, by far the longest demo.

To be honest about what that is: the level-12 demo proves the level can be
done, but it isn't a model of how to do it. Its control gains were tuned by
the search for this one start position, the drive is fussy and very long, and
any later change to the physics would almost certainly break it. A human will
probably find a cleaner way - or decide the start should sit a little lower.

Checking. Every demo was then replayed in VICE, all twelve in a row the way
the title screen plays them, and each one parked with 0 damage before the
cycle wrapped round to level 1 again. The test suite (373 checks, including
"each level's stored solution parks") passes. The gameplay video in this zip
uses the same drives: a special build of the game presses the keys around the
levels and lets the demo drives do the driving.


CREDITS
-------
Based on Juggernaut (ZX Spectrum), program by Pete Cooke, (c) CRL 1985 - the
truck, its outline graphics and its trailer physics come from the original.
Thank you!

C64 programming: Claude, an AI by Anthropic.
Idea, game and level design, production, testing: grue.
