43

On many arcade machines when running in attract mode, they often show a demo gameplay. I wondered how they did this?
I guess those are not pre-recorded movies, so I think that they probably ran the game engine with some pre-defined input. On some machines one can see that this demo is not always the same, so there is some randomness there as well.

4
  • 15
    Welcome to Retrocomputing! I do not understand why someone else has flagged this question as off-topic. We have had plenty of previous questions about vintage games, including how various features were implemented. So this question is on-topic here.
    – DrSheldon
    May 11 at 16:05
  • 2
    @DrSheldon Well, I did flag it, because it's not about any specific game and/or historic implementation, but a generic programming question targeted to solve a design decision for a modern development. As such it would only collect random opinions.
    – Raffzahn
    May 11 at 23:59
  • 24
    "How was it done" is appropriate. "How could it be done" is gamedev.stackexchange.com .
    – fadden
    May 12 at 1:04
  • 3
    Tangentially related: In SM64, the demo inputter makes a mistake May 12 at 12:47
36

Most of the time, game coders are not going to program an A.I. just to show the demo so the moves are pre-recorded, and generally the demo ends quickly with the main character dying/exploding (maybe not to show too much of the level)

To record the moves, the programmers probably added some piece of code to log all player input along with the exact frame where it occurs and save it in memory. In the end, the memory is dumped and the moves are integrated as game data. (and recording code is then probably removed from the final release).

Part of the disassembly of Bombjack arcade game proves that there was a recording of some input (fake player input)

; play mode ?
ld     a,($8070)       ; 038C 3A 70 80
or     a               ; 038F B7
jp     nz,$0398        ; 0390 C2 98 03

; no (demo), A = fake input
ld     a,($807a)       ; 0393 3A 7A 80
jr     $03a2           ; 0396 18 0A

; yes (play), A = player pinout
ld     a,($b000)       ; 0398 3A 00 B0
bit    0,b             ; 039B CB 40
jr     z,$03a2         ; 039D 28 03

Sometimes there are several moves or levels recorded just for variety too. Introducing randomness in the player moves would be risky and would bear poor results. Just recording 2 or 3 different games is better.

About the randomness, well, most games have randomness in them (enemy moves/shots). So if you record moves with some random setting, and replay them with another, then the game will be different.

If this causes too much problems, I suppose that they can fix the random seed of the demo so it matches the random seed of the time when they recorded it.

A "modern" example of this is the fact that you can record input in a lot of emulators. MAME for instance. Of course, you have to record the moves from the machine bootup. Replaying moves of a game on another game without rebooting the machine will give another (failed) sequence because of randomness not being the same. This technique is also used (along with state save) for tool assisted speedruns.

Okay, but...

Just to contradict myself, I checked Mrs PacMan source code derived from PacMan source, and commented by the person who reverse engineered it) and this comment directly contradicts the above... Duh.

controls pac-man AI during demo. pacman will avoid pink ghost, or chase it when red ghost is edible

The A.I. is simple in that case, but it's very unlikely that an A.I is used in platformers/shooters or a racing game. A complex A.I needs time to make it right, and takes more room on released program ROM (so a fighting game could totally use its own opponent A.I. for the main character during a demo)

So the right answer is probably "it depends", depending on the ability to auto-play during a few seconds without the main character moves looking dumb.

Let's not forget that the demo mode is vital to attract players, so if the demo game play is dumb A.I. that doesn't demonstrate the game possibilities, that's not going to work to cut it.

12
  • 4
    @Devolus they could easily have used efficent approaches, like new status of user inputs and delay how many frames until next user input is set - basically RLE compression, user input X is repeated for Y frames.
    – Justme
    May 11 at 16:31
  • 3
    or press/release signals. We're talking about a few moves. It probably takes less than 500 bytes to record all this. And it can use bits, so no need to compress it. And I'm not saying that all games were using the same approach. Maybe some weren't recording their games, just put values and played until it was right. May 11 at 16:32
  • 3
    I question the reasoning in the last paragraph. I myself have been attracted to play a game by noticing how poorly the demo “player” does and thinking, “At least I can do a lot better than the demo!” In other words, poorly played demos helped me feel better about my playing by comparison. May 12 at 6:09
  • 3
    Regarding recorded versus programmed gameplay for demos, based on my many hours of watching demos in the 80s (when you run out of quarters and don’t care about roller skating, it’s your best source of entertainment), my memory suggests different games used one or the other strategy. Some demos clearly followed the exact same moves every time, others did not. May 12 at 6:14
  • 6
    @ToddWilcox Many modern game demos seem to intentionally play on that emotion (of being able to do better than the demo) - showing deliberately bad gameplay of a trivially easy game in an attempt to make people download it to prove how good they are...
    – Steve
    May 12 at 9:59
17

For space invaders what happens is the game has short list of movements (11 in ROM but only 10 are used) left and right or stay still.

If there is no bullet in flight the player fires, each time the bullet fires the next direction action is pulled from the list and the player starts moving in that direction. The time of flight of the bullet acts as a timer, either it hits an alien, base or goes of the top of screen and then the player fires again.

The position in the movement list only gets reset as part of the power on (IIRC) so the movement feels fairly random.

If you use mame there are some oddities around the way the two screen scan interrupts work which mean that performing a mame reset is slightly different from starting mame and you get different sequences.

In psuedo code it looks something like this:

IsrRoutine60Hz()
{
  CheckForPlayerFiresBullet();
  MovePlayer();
  // Draw Screen / Invaders etc....
}

CheckForPlayerFiresBullet()
{
   if (no_bullet_in_motion) 
   {
     if (demo_mode )
     { 
       FireBullet();
       demoPlayerDirection=moveList[nextDemoCommand++];
       if (nextDemoCommand>=moveList.Length)
          nextDemoCommand=0;
     } 
     else 
     {
       if (fireButtonDown) FireBullet();
     }
   }
}

MovePlayer()
{
   if (demo_mode)
     command=demoPlayerDirection;
   else
     command=GetDirectionFromButton();
   // Move left,right or stay still based on command
}
5
  • Only 11? Do you know how often the game queries the controller? Because if it runs at 25FPs this would mean that it would run though the set twice per second, which doesn't make sense, so the fake input seems to be differently treated than regular input. Assuming that the update loop would also query the input, which may or may not be true.
    – Devolus
    May 11 at 21:14
  • 3
    It never really queries the controller, the players moves in the direction constantly and always fires. There is only allowed to one player bullet in flight at a time so this acts as timer (short if the player is under a base, long if it misses entirely). When the bullet explodes the player fires again and starts moving in the new direction. The players base moves 1 pixel every video frame left or right.
    – PeterI
    May 11 at 21:25
  • 2
    IIRC the delay between shots was always so that only one shot was on the screen at the time - for all types of players. Was always hairpullingly frustrating to miss the entire stack - took forever to fire again! May 12 at 12:09
  • @StianYttervik, I remember that too, and how frustrating it was to have to wait until the missile was available again. Made you take better aim for the next shot. :)
    – Devolus
    May 12 at 12:52
  • I built a version in C# with WPF before I started implementing a race the beam implementation with a cheap STM8 part I bought to get free delivery on an electronics order a while ago, to check I could fit everything into ROM / RAM (not yet written) getting the demo to match mame was a bit a of a challenge, but most of this is from recent(ish) memory.
    – PeterI
    May 12 at 17:17
13

In Battlezone, the code for the play loop is shared between "play" and "attract" modes. At various points, a flag is tested to see if the game is "played" by the player or a demo. A counter is used to cycle between showing the logo, showing high scores, and driving around.

The self-driving logic is in the UpdatePlayer code. It steers toward the enemy position, alternating forward and reverse movement every 64 frames. Other bits of code check play_flag to change enemy behavior, omit display of the copyright string, unmute the engine sound, etc.

It's not very sophisticated -- it doesn't really show you what playing the game looks like -- but it was enough to get one's attention back in 1980.

Update: a couple more...

In Missile Command, the game actually plays the first wave, which is randomized. It targets missiles in the order in which they appear, moving the crosshairs to a point the missile will reach in 16 frames. When it reaches the coordinates, it fires an ABM from the closest launcher. There are some limitations, like not having more than two ABMs in flight at once, that slow the pace of the demo.

There's a little bit of "am I playing or attracting" code elsewhere, to suppress sounds and scoring and so on, but most of the work happens in a replacement for the controller read routine.

In Asteroids, the game just plays without a player. Saucers appear and occasionally shoot asteroids; when they're all gone, the wave resets. Not really a play demo; more like everyone left but somebody forgot to turn off the lights.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.