River Raid is a great early vertical shooter where you fly a plane down a river and fire missiles to blow up helicopters, jets, ships and bridges. Due to engineering constraints, the plane stocks unlimited missiles -- but only 35 seconds worth of fuel -- so you have to fly over fuel depots to stay in the air. The constantly changing river terrain and the need to balance blowing stuff up with keeping an eye on the gas tank are credited for the game's memorable play. It's also one of the first successful video games programmed by a woman, Carol Shaw.
Difficulty increases with each bridge section, maxing out at level 48. Higher difficulty means more enemies, and fewer homes & fuel. The difference is dramatic, with approximately 24% of objects being fuel on level 1 and only 6% at level 48. Getting 100,000 points seemed like the ideal goal as it reaches the maximum difficulty level for 9 sections and results in a watchable 8 minute movie.
The game does have an ending when one reaches 1,000,000 points, at which point the plane explodes and the score is replaced by !'s. I'd very much like to see a full run, but at 80 minutes it would be extremely repetitive to watch (about 500 bridge sections beyond the end of this movie at the same difficulty level!), not to mention to make. I'm contemplating whether it'd be easier to write a bot for such a run using Lua (in the emulator) or Java (simulating the game logic, without video or sound). I think it'd be fairly easy to do an ok job, but very difficult to do a good job of it. We'll see.
At about 20k points I create an artificial fuel crisis for entertainment's sake by shooting every fuel in sight for a while without using it. Arranging the two cases where I was a few frames from dying when I reached the fuel depot required slowing down to use one depot I could have just shot at a near-term cost of about 10 frames. It's unclear if this affects the overall time though due to enemy movement manipulation.
I try to be as entertaining as possible with near-crashes, steering bullets around and in between enemies and killing stuff in unexpected orders. Also, I take the final shot a few frames late while still ending input as early as possible, so the plane runs out of fuel exactly as the bullet hits.
For fun, I created a Lua script
to do a kill-count; some may find it more fun to watch with the running total included:
I'll have to redo this vid since I noticed I'd forgotten to reset the Lua script at the start, but here are the real final #'s:
Manipulating these is key - most often this is done to move enemies out of nooks where they'd otherwise be inaccessible. The game tracks 5 enemies in front of the plane; every 16 frames it attempts to start one of these moving. Enemies 1-3 (closest to the player) are twice as likely to start moving as enemies 4-5. Every time the plane advances 32 pixels, each enemy shifts down a slot. So if you need enemy #2 to move on frame x, you can try slowing down a bit so the same enemy is in slot 1 on frame x - there's a 1 in 3 chance it will move.
In many cases there's flexibility on when to take the slow-down, so I can 'double-dip' and slow down while flying over fuel. Other times it needs to be very precise, i.e. there's 2 helis in front of me, and I need one to start moving before the slot shift, and the other 16 frames later after the slot shift.
The 'Point Stream'
For reference, the point values for each object: ship (30), helicopter (60), fuel (80), jet (100), bridge (500). I apparently played this game so much as a kid that I still remembered these values. :D
The 'score points as quickly as possible goal' was interesting conceptually in figuring out what sort of time vs points trade-offs were worth it. If you're contemplating give up 10 frames to nab a helicopter in section 5, you have to weigh whether that's worth it based on your expected rate of point accumulation at the end of the run, not the current section. There's no way to know exactly what that rate will be, so I used 3.3-3.5 points/frame based on early testing. This worked out well since the rate ended up being 3.41 overall, and approximately 3.52 in later sections; hence it's worth losing up to 17 frames to get a helicopter, and up to 28 for a jet, but only 8 for a ship.
The matter gets more complicated around level 30, when fuel rapidly becomes more scarce. At this point, one has to consider whether it's worth it point-wise to slow down to obtain extra fuel. Losing 1 frame in time to get 1 extra frame of refueling worked pretty well as a rule of thumb. Many times when I slow down over fuel tanks, I'm actually slowing down to manipulate a later enemy and just taking the slow-down over a fuel depot to reduce the impact of the slow-down.
Finally, one can squeeze a few more frames of refueling out a fuel depot by not blowing it up. But since depots are worth a lot of points it's more economical to slow down to eke the extra frames and still blow it up -- except in special circumstances as noted in the next section.
For my first version of this run, destroying the final bridge gave me 100,270 points, though I didn't have enough fuel so I had to artificially poke some extra in to reach that point. Having the final kill be a bridge (500 points) let me choose to lose some points earlier in the run either for fuel or time. Since I needed almost 2 entire fuel tanks' more fuel, I elected to forgo killing 3 fuel tanks (240 points) making up about half the fuel deficit. Fortunately, I found another place around 30k points where I'd skipped a refuel just to snag a ship; reversing this lost 30 points but gave me enough fuel to finish, and brought the final total to a very satisfying 100,000 even.
Unlike vertical acceleration, where speeding up and slowing down occur quite gradually, it takes a while to reach full horizontal speed (1 px/frame), but as soon as you let go of the stick you stop instantly. In a nice quirk of physics, though, one can change directions while maintaining horizontal speed. That's why the plane's movement is so twitchy at times - it's important to have good horizontal speed to reach as many enemies as possible. The occasions where I drop horizontal momentum are usually to optimize going around a corner or reaching an enemy by 1 additional horizontal pixel.
Shooting Enemies in Walls
Bullets stop the first frame they spend overlapping a wall. However, for that 1 frame they still have their full movement and hit-box. By timing shots carefully, it's possible to hit jets embedded as many as 6 pixels into a wall.
Jets are worth the most points apart from bridges, but their presence in a level makes things MUCH more difficult. Jets move horizontally at the plane's max horizontal speed. In practical terms, this means that once a jet gets ahead of you (moving away), there's no way to catch up to it. As a result, it's often necessary to either miss a jet or lose some time to hit a particular jet. With the terrain, some are actually not possible to hit at all.
- A commented disassembly by Thomas Jentzsch was helpful in figuring out how to manipulate enemy movements. Not sure why, but the memory addresses in the source don't match what's used in the emulator.
- An full-of-awesomeness 1982 commercial for River Raid:
: Here are some considerations before my verdict;
If you haven’t played the original game back in the day it was released, you may find it hard to be entertained by any Atari 2600 game. But this game still has his charm, and is not too different from modern shooters. The River of no Return was and I dare to say it still is an entertaining game for the casual player. The entertainment of this run was stated in most of the comments so far, so I’m more than confident when I say that this game meets the requirement of being an entertaining game.
It may be just a nostalgic mistake, but along with Enduro, Pitfall, Frostbite and a few other titles what other game was so popular in the golden days of the Atari 2600? Game choice is a strong factor for the Moons tier and this game meets this requirement.
The chosen goal here is not only to complete the game as fast as possible, or glitch the game to an extent no one could recognize or even enjoy the original feeling of the game. Instead, the author made a wise decision to stop the game as soon as the maximum difficulty level was achieved preventing the game to keep rolling with no more input. Another requirement met.
Show skills beyond a human playing in real time are a requirement for the Moons tier. Although Atari games are so simple in their designs to allow one to easily do that, the author managed to show off things a human would not be able to achieve; enemy manipulation, daring near misses, out of order killings and an end of input with a precise score.
Well, the requirements may be out of order the way I put them, sorry about that, but this run meets all of them with enough technique, so here’s my verdict; accepted for publication in Moons
: Thanks to feos for dump.