|Previous Page > Listings Index > Forth: Ace for Games listing - Your Computer, March, 1983|
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
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
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
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
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.