Pobtastic / Rampage / Random Number

Created Wed, 06 Mar 2024 22:02:27 +0000 Modified Thu, 12 Dec 2024 14:35:47 +0000

What Does It Do?

In his book “It’s Behind You”1, Bob Pape talks a little about Rampage and how it was developed. He describes it as his “first real computer game” which is an astounding achievement! Especially considering that they received none of the original code and had to recreate the game by playing the arcade machine and taking notes on how it looked/ played, armed only with a portable audio recorder!

Anyways, in the book Bob talks about how, nearing the end of the development cycle, he went to implement the monster AI - and couldn’t believe his eyes when it was already working 🤣

Here’s an excerpt from the book:

The monster AI is something that even today I find a bit frightening, and was one of the last routines to be written.

I had a byte for each Monster that showed if it was under player or computer control and sometime that Friday morning at Southampton, even though I hadn’t written the AI routines yet, I set the byte to computer control just to see if the rest of my code would recognize it. Not only did it recognize it but the monsters started moving around the screen, climbing buildings and punching holes in them! I couldn’t believe how this was possible so I stopped everything and checked the code and there, right in the middle of things, were some basic AI routines.

I must have written the AI code sometime Thursday, but was so stressed and tired that I’d just blanked the whole thing out of my mind and forgotten I’d done it. Again lack of time meant that the finished routines weren’t as good as I’d have liked them to be but I didn’t have a choice, so after a bit of tweaking I had to go with what I had.

Most of the AI centers around a very simple routine, and it’s incredible that it works so well! If you leave the monsters to their own devices they will complete the level for you. It’s just incredible that this randomness allows for it!

Obviously there is more to it than this simple function but it is all based on what’s returned from here.

Subroutine: Get Random Number

; Random Number
;
; Output:A = Random number
@label=RandomNumber
c$DA28 LD DE,($D21A) ; Fetch the *Game_Clock and store it in DE.
 $DA2C INC DE        ; Increment DE by one.
; The max value is $2800 so test the higher order byte to check if this limit
; has been hit.
 $DA2D LD A,D        ; {If D is equal to $28 then jump to ResetSeed.
 $DA2E CP $28        ;
 $DA30 JR Z,$DA38    ; }
; Update the "clock" value.
@label=WriteSeed
*$DA32 LD ($D21A),DE ; Write DE back to *Game_Clock.
; The "random number" is actually a byte from the Spectrum ROM. The "clock" is
; used as a pointer to return a value from between memory locations $0000-$27FF.
 $DA36 LD A,(DE)     ; Fetch a byte from *DE and store it in A for the response.
 $DA37 RET           ; Return.

; Reset the "game clock" back to $0000.
@label=ResetSeed
*$DA38 LD D,$00      ; D=$00. (E is already $00 at this point)
 $DA3A JP $DA32      ; Jump to WriteSeed.

How Does It Work?

Hopefully the comments in the code already make the flow of the code pretty clear. It very simply has a 16 bit store of a number we’re going to call “game clock” - this is a counter, and the routine increments it - and also ensures that the number never goes higher than 10240/ $2800. This number is then used as a pointer to the ZX Spectrum ROM (!) and the random number returned is a byte from that memory location.

Here’s a diagram which should make it even easier to understand.

---
title: "Subroutine: Get Random Number"
---
flowchart TD;

    DE["DE=*53786 (fetch the game clock)"]-->INC["Increment DE by one"];
    INC-->D["Is DE equal to 40?"];
    D--Yes-->ResetSeed["Set DE back to 0000"]
    D-->WriteSeed["Update the game clock value stored at *53786"]
    WriteSeed-->A["A=Fetch a byte from the ZX Spectrum ROM using DE as a pointer"]
    A-->Ret
    ResetSeed-->WriteSeed
    Ret[Return]

Rampage Disassembly