Your Computer, March, 1983, page 68
|
Ralph Hilton get his
teeth into Forth Games. Have an Ace munch. |
WITH FORTH now available for home
computers and the release of the Jupiter Ace,
users suddenly have a machine and a language
ideally structured to games that are fast,
involved and without the relative complexity
of machine code. Forth's compact programming means one can develop and test each of
the elements of the whole program as one
builds it up.
The disadvantage of not being able to code
from the top down, as in Basic, is overcome
easily by either flowcharting the proposed
program or doing a simple logical list of its
component parts.
The Jupiter Ace I used for this program has
an actual memory availability for user Forth
words of less than 1K. This may seem very
little but it gives one sufficient space to create
versions of popular arcade games that contain
the main features of the originals and run very
close to their speeds. In fact, I found that
Pac-Man written in Forth actually runs faster
than the game played at the local amusement
centre. As it is one of the more popular games
and contains many of the building blocks one
would use in other games I chose it as the
example for this article.
I have included all the main points of the
arcade version, except for the power pills
which would take up an extra 500 bytes at a
rough estimate.
I have assumed that you understand the
basic words used in the Ace but include an
explanation of the specific techniques
involved. To conserve memory the variables
and words used have short names but I
comment on each separately.The sequence for the game is as follows.
First, the graphics used for the man, ghosts,
dots and wall are defined and the screen
created. Next the variables are initialised and
the man and ghosts placed in their starting
positions.
The way the man moves is broken down
into the following steps. First, a check to see if
an appropriate key has been pressed, and the
program continues with this sequence if it has.
The Inkey function on the Ace returns to
the stack the ASCII value of the key pressed.
This has to be converted into a number giving
the change in position in the display file. The
Ace display file is laid out in 24 rows of 32
columns, each at addresses 9216 to 9984. An
up or down movement changes the memory
location by 32 and a left or right movement
changes it by 1. I have used these numbers to
give the new location of the man.
Next the program checks to make sure the
man does not bump into a wall and continues
only if there is no risk of this.
Then a space is put in the man's last
position, and the new position is checked to
see whether or not it contains a dot. If it does,
the score is incremented. If this score means
that all the available dots have been eaten, the
screen is refilled.
Now the man is moved to his new position
which is stored in the appropriate variable.
The ghost-moving section comes next. I found
that this was most easily done by having a
separate variable for each ghost's position
which is put into the variable used by the
subroutine as each ghost is moved.
|
The sequence for each ghost starts by
checking whether the ghost should move up or
down or neither according to the relative
position of the man, and then makes sure that
it does not hit a wall. A random generator is
used to allow the ghost only limited movement
- the game would be impossible if the ghost
was always correct, and boring if its movement
were fully predictable. When a ghost moves,
the space it leaves is replaced with a space or
dot as appropriate. This is done by a method
which is explained fully in the actual coding.
The same procedure is used for left and right
movement of the ghost. If the man now
occupies the same position as one of the ghosts
the game ends.
Obviously all these procedures need
additional subroutines to generate the random
numbers and refill the screen with dots when
required.
The game is loaded in three sections to make
full use of the memory but no reloading is
necessary to replay.
First, the graphics section is prepared. I
have assigned user graphics for the wall and
dots as this makes it far easier to type in the
screen itself. The graphics are placed into a
section of RAM which is calculated as starting
at 11264 plus the ASCII code of the character
one is defining multiplied by 8. As typing in a
list of binary digits is tedious I have converted
all the values to decimal. Here is the listing for the graphics section:
: NM 36 126 219 90 126 255 126 36 ; This word puts the values used for the ghost
on to the stack. It is a separate word because it
is needed several times.
: GR 8 * 11263 +DUP 8 + DO i C! -1 +LOOP ; This word takes nine numbers from the stack;
the first eight define the character and the
ninth is the ASCII value of the character. It
makes a loop, using as its limits the sections of
memory at the beginning and end of the space
we want to fill. It then puts each of the
numbers into its appropriate place. It is taken
from the Ace manual. : A 85 170 85 170 85 170 85 170 1 GR Wall 0 0 0 24 24 0 0 0 2 GR Dot 28 20 8 127 8 20 34 65 3 GR Man NM 5 GR NM 35 GR ; When you have typed this in, A will run the
routine and store the characters appropriately.
This section should then be saved on tape by
starting the tape player then entering
SAVE GRAPHICS |
The maze display snappers and gulpers thrive in this sort of environment
Your Computer, March, 1983, page 69
|
You can then verify it as explained in the
manual and delete it from memory using
FORGET NM to leave space for the next section, the game
itself.
For this section first enter the variables, -
0 variable A The score. 0 variable X The man's position. 0 variable W Used for the position of the ghost being moved. Y and Z are moved to W as needed. 0 variable Y The positions of the two 0 variable Z ghosts.
Only two ghosts have been used - a third
would fit in the memory but with the speed at
which the program runs would make it almost
impossible to win.
0 variable SD This holds the random number.
0 variable K This sets the difficulty level.
The subroutines used by the main words need
to go in next so that the compiler recognises
them when called from the upper words.
: B This fills the screen with dots wherever there is no wall and is used whenever the dots are all eaten. 9856 9216 DO Sets a loop to go over the whole screen. i c@ 1 = 0 = Checks that the space does not contain a wall. IF 2 i c! Puts a dot there if it does not. THEN LOOP 5 Y @ c! 5 Z @ c! Puts the ghosts back on the screen. Y @ Z @ = IF 8 Y @ c! THEN When a ghost leaves a position then 3 is
subtracted from the ASCII value of the
character so that it is left as it was; dots use 2
and spaces 32 so the ghost is given values 5
and 35, and 3 is added to the ASCII when the
ghost is moved there. Here if the two ghosts
are in the same place when all the dots are
eaten then 2 + 3 + 3 has to go in that space
giving a dot when they both leave.
K @ DUP 2 > IF 1- THEN K ! Increases the difficulty level if it is not at maximum; : RND This is taken from the Ace manual and covered there. SD @ 75 u* 75 0 D + OVER OVER u< - - 1- DUP SD! u* SWAP DROP ; : CPS
This is used to add 3 to the position that the
ghost moves into and add 253 when it leaves.
Adding 253 achieves the same as taking away 3
as one is using a single byte.
SWAP OVER c@ + SWAP c! ;
Next the main routines are typed in. M is the
routine for moving the man complete with
associated checks and score changing. The
comments could be typed into the machine
but would take up valuable memory and so
should be omitted.
: M INKEY DUP DUP 52 >SWAP 57 <AND This checks that the key is one of the cursor control keys 5 to 8; these have ASCII values 53 through 56. IF 52 - DUP Puts the number into the range 1 to 4 4 MOD 1 > 31 * 1 + MOD gives the remainder after dividing by the preceding number so cursor keys 6 and 7 will leave 32 on the stack while keys 5 and 8 leave 1 on the stack. SWAP 3 < -2 * 1 + * This multiplies the 32 or 1 obtained by -1 if keys 5 or 6 were pressed. X @ + DUP c@ DUP Leaves on the stack the new value of X and two copies of what X currently contains. 1 = 0 = IF Continue only if one will not collide with a wall. 32 X @ c! Put a space in the old position of the man. 2 = IF Check if the man is eating a dot. A @ 1+ DUP DUP A ! 21 O AT . 326 MOD 0= IF B THEN Add 1 to the score; print the score; check whether all the dots have been eaten and refill screen if more left. THEN |
3 OVER c! X ! Put the man in the new position and store the value of X. 99 40 BEEP ELSE DROP DROP Removes unused numbers from stack. THEN ELSE DROP THEN ;
The routines G and H are used together. H
used twice by G to actually move the ghost. l
should be typed in before G.
: G W @ DUP X @ 16 - <32 * Compares the values of X and W to see whether or not the ghost should move down. It puts 32 on the stack if it should. SWAP X @ 16 + > - 32 * + H puts - 32 on the stack if the ghost should move up, and then uses H to move it appropriately. W @ 32 MOD X @32 MOD > - 2 * 1 + H Puts 1 or -1 on the stack after comparing the horizontal positions of X and W to move ghost left or right. : H W @ + DUP c@ Finds the new position of the ghost. 1 = 0 = Makes sure that it is not in a wall K @ RND 0= AND Uses the difficulty variable K and RND to limit the probability of the ghost's movement IF 253 W @ CPS Puts a space or dot where the ghost was. 3 OVER CPS Puts the ghost on the screen. W ! Stores the new position of the ghost ELSE DROP THEN ;
The routines are now linked together by the
program word which is Run.
: RUN FAST 9249 X ! 9339 Y ! 9479 Z ! Sets initial positions of man and ghosts. 0 A ! Zeros score. 6 K ! Sets initial difficulty. B Fills the screen with dots. 39249 c! Puts the man on the screen. B ;B puts on the ghosts. BEGIN The main control loop. M Move man. Z @ W ! G W @ Z ! Moves the ghost Z by putting its value into W which is used by H. Y @ W ! G W @ Y ! Does the same for Y. X @ DUP Y @ = SWAP Z @ = OR UNTIL Compares X to Z and Y. If either equal X then the procedure ends otherwise it goes back to Begin. SLOW 999 999 BEEP ; The game is stored entering
SAVE RUN The screen is created and, then saved as a
series of bytes. Enter
: Z INVIS CLS."
leaving enough space between the CLS and ."
so that there is only one space left at the end of
the line. Use Shift 9 to put the Ace in graphics
mode then, using A for the wall and B for the
dots, type in the 20 lines of screen per the
attached diagram. On the next line type " 5 -
Entering Z will now give you the screen in
the correct position and it can be saved on to
tape by entering
8192 768 BSAVE screen Start the tape and press enter.
Clear the memory with
FORGET Z The program is now loaded with LOAD GRAPHICS A FORGET NM Enter these three together and then start the
tape. Stop the tape when you see the cursor.
INVIS LOAD RUN 0 0 BLOAD SCREEN
Enter this and then restart the tape. Stop it
when the screen is full. You can now play the
game by entering Run.
If you have queries about the program I can
answer them. Write to me with stamped,
addressed envelope at xx Grimston Avenue,
Folkestone, Kent.
|