Jerry Wright and Lloyd Ollman, Jr.

The graphics potential of the Atari personal computer is a powerful educational tool. It can be used to transform the chores of learning into the fun of learning.

A growing number of companies now produce educational software for the Atari computer, but the quality of this software varies widely. A good children's educational program draws children to play with it, and allows learning to happen along with the fun.

When you think back to your school days (assuming you're not still there), what did you find to be the worst part of the learning process? For us it was drill and practice. Here's a children's educational program that makes addition practice enjoyable using an interesting type of animation.

The program is called Animath, for animated math program, and it uses a modified character set to create a sauntering gorilla. Player/missile graphics are also used to spice up the game.

There are several commercial programs which can be used to create modified character sets. Perhaps the best-known of these is Fontedit, from Iridis #2. We used a program similar to this to write a "gorilla" font to disk. The original version of this program called the font from disk and loaded it into memory. The Atari character set is a part of ROM, so the font must be moved to RAM, where it can be modified by the appropriate POKEs into memory.

We knew that many Atari owners utilize cassette storage, so we wrote a little utility to save the font as data statements at the end of the program. There are 24 modified characters, represented as 24 data statements. Because the characters are set up in 8 x 8 blocks, each of the eight numbers in the individual data statements is one 8-bit word, or byte.

After the gorilla is POKEd into RAM, he can be animated by the POSITION command. By changing the positions of his arms and legs, we simulate motion, and the gorilla is able to run down the screen to the first problem.

Thanks to Basic A+ from Optimized Systems Software, we were able to get an accurate list of variables. The first list we generated contained several variables we couldn't find. After listing the program to disk and entering it back in the computer, we came up with an accurate variable table, without all the variables that had been eliminated in earlier incarnations of the program. It's always wise to LIST, then ENTER programs when they are finished, to clear the Atari variable table of all but the variables actually being used.

Variable Table

NU$--String holding answer input by player

TN$--String holding randomly generated top number

BN$--String holding randomly generated bottom number

A$--String to hold player input to questions

P--Horizontal position of individual number input by player as an answer

START--Beginning location of character set in the operating system

NOW--Variable loop pointing to next character in the character set

CH--ATASCII number of character set

Q--Location of RAMTOP (PEEK (106))

I--Location of PLAYER/MISSILE Base Address

T--Variable for top end of volume in motion sounds

L--Number of problems completed

X--Horizontal position variable

WAL--Gorilla movement subroutine

PR--Number of problems chosen

W--Number of problems successfully completed

TN--Actual top number of problem

BN--Actual bottom number of problem

D--Decreasing pitch used in booming sound

E--Timing loop variable

A--Vertical position of gorilla or erase pattern

K--ATASCII number input from keyboard

N--Actual number input from keyboard

AMT--Answer: total of answer numbers in the ones, tens, and hundreds columns

J--Sum of top number (TN) and bottom number (BN)

C--Number of times gorilla goes through movement routine

B--Volume of motion sound routine ending in variable T, also wait routine

F--Flag set to 0: input character set. Flag set to 1; jump directly to main body of program

WT--Wait routine

The Program

Lines 0 through 4 introduce our authors, and set up our new character set. Line 2 DIMensions the various strings we will need, and makes sure that the string to hold the answer is empty.

In line 3 we find the top of our available memory by PEEKing RAMTOP, which is location (106) in memory. Then we fool the operating system into believing that the available memory is five pages smaller than it actually is, so we won't accidentally load our program on top of the changes we are going to make.

We then get an even number above our new RAMTOP (by adding 1) and multiply this number by 256. This new value of Q gives us the starting location of our new character set.

We use the number 256 because the Atari 6502 microprocessor divides memory into 256-byte "pages," and we must start the new character set at the beginning of an even page mark.

Line 4 begins the river sound and jumps to the introduction and instructions.

The subroutine at 6100 prints out the name of the program, and the authors. Then there is a pause at line 6120, so the title can be read, followed by a jump to the section asking for the number of problems desired--line 6000.

If this is the first time the program has been run, the F flag is set at 0 and a message asks the player to wait while the character set is set up. The program then returns to line 5.

The Atari character set can't actually be changed, because it is permanently embedded in ROM starting at address 57344. So we must move it into RAM. We do this in line 3 by PEEKing the character set and then POKEing it into the space we have set aside above RAMTOP.

Line 6 reads the DATA defining the new characters and POKEs it into our new locations. In line 11 we POKE the location of our new character set into location (756), just above RAMTOP in the Character Base Register.

There is a stream in our graphics jungle. In line 8 we create this by turning on two Players and setting their location just below RAMTOP then POKEing this into the Player/Missile Base address 52479.

Jumping to line 15, the horizontal position of Player 0 is POKEd into 53248, Player 1 into 53249. POKEs (704) and (705) set the color, POKEs (53261) and (53262) set up the shape and POKEs (53256) and (53257) set up Player size.

We keep track of the number of times the Gorilla finds a problem with the variable L, and use the variable X as the X coordinate of our gorilla's location. Atari Basic accepts names as well as line numbers in GOTOs and GOSUBs, so we give the movement subroutine a name, WAL.

Line 40 sets the starting location of the animal by using a position statement in X/Y coordinate form. Line 55 then randomly selects a top number which is placed in TN$ and a bottom number, placed in BN$.

Line 56 places the number of problems successfully answered next to the number of problems tried, and line 57 gets more numbers for the number strings. Line 58 gets the value of the strings and places them into variables TN and BN.

Line 60 places the numbers in their proper positions at the bottom of the screen.

In line 60 we jump to the gorilla animation section. This time WAL=500 so in line 500 we find the vertical positions for the gorilla in a FOR/NEXT loop and jump to the actual movement subroutine at line 2000.

Lines 2000 through 2009 draw the gorilla and move his arms and legs, while making the movement sound. Then the subroutine jumps back to line 501 where it gets a new position from the variable A in the FOR/NEXT loop. It then goes back to the movement routine until it reaches vertical position 17 on the screen. Next we jump back to line 100 for a sound routine and then jump to line 600.

This is the keyboard routine--where we PEEK location (764) to find the internal code of the last key pressed. The computer runs through a series of IF/ THEN statements to determine which key has been pressed by the player, and compares it to a list of valid inputs. The first number input goes into the ones column, the second into the tens column, the third into the hundreds column, and the fourth into the thousands column.

This is done by setting up a number holding string (NU$). The position of the number in the string is determined by line 700, which starts with P=4, so the first number is placed in the fourth position of NU$, the second number in the third position and so on. Line 705 prints the NU$ on the screen and then the Atari loops around to line 120 and back through the keyboard routine until Return is pressed at line 660.

Line 670 allows you to recover if a mistake is made. All you have to do is press Delete/Backspace or the Space Bar, the NU is cleared, and you start back at the ones column. You then repeat the procedure until you have what you feel is the correct answer.

Pressing Return takes you out of the loop at line 660 where this time the value of the numbers in NU$ is transferred to the variable AMT. We then jump to 800 to find out if the answer is correct.

Line 810 clears NU$ and resets location (764) by POKEing in 255.

Lines 820 and 830 blank out the standing gorilla, then 835 determines if the answer is right. If it is, the gorilla walking routine (WAL) jumps back to line 500, adds 1 to the amount answered correctly, and jumps to line 1000.

If AMT doesn't equal J, then the gorilla movement subroutine is set to 900, the horizontal position (X) is moved over 8 places, and the gorilla runs through the subroutine at line 400 which forces him into the river. A reverse FOR/NEXT loop carries him downstream in subroutine 3000. Then the program jumps back to line 55 where the new value of X swims him upstream with the subroutine at line 900, and gives him a new addition problem to answer.

If the question was answered correctly, the program jumps to the subroutine at 2000 through 2009, where the gorilla jumps up and down with joy. The routine then sets the sound volume variable T to 20 and the horizontal position variable X to 1 and then jumps back to the main program loop at line 55.

When the number of problems chosen (PR) equals the number actually done (L), the program goes to line 7000 where it displays a score and offers a chance to play again.

We hope this program and accompanying explanation have given you an idea of some of the things that can be achieved with the Atari Personal Computer. We enjoy this system thoroughly, and hope that many more people will soon see the Atari as a computer with truly incredible possibilities.


After the program is loaded and the player has chosen the number of problems, the gorilla will come on the screen and run down to the first problem. The answer should be typed in with the first number in the ones column, the second in the tens column, and the third in the hundreds.

If you make a mistake, just press the space bar. When you have the correct answer, press the return key. The gorilla will tell you if you are right.

In the listing that follows, several characters are in square brackets. These should be typed in as inverse characters. The Epson MX-80 prints a "1 "instead of a clear sign, so when you see that symbol type Escape, then Control and Clear together.

2 DIM NU$(5),TN$(3),BN$(3),A$(1):NU$="     ":P=4:POKE 764,255
3 Q=PEEK(106):Q=Q-5:POKE 106,Q:Q=Q+1:Q=Q*256
4 SOUND 0,8,8,4:GOSUB 6100
8 I=PEEK(106)-8:POKE 54279,I
11 GRAPHICS 17:POKE 756,Q/256:SETCOLOR 4,1,2
12 T=20:SETCOLOR 2,0,0
15 POKE 53248,95:POKE 53249,127:POKE 704,117:POKE 705,117:POKE 53261,255:POKE 53262,255:POKE 53256,3:POKE 53257,3
35 L=-1:X=1:WAL=500
40 POSITION X+1,2:? #6;"[AB]";:POSITION X+1,3:? #6;"[CD]";:POSITION X+1,4:? #6;"[EF]";
55 TN$(2,2)=STR$(INT(RND(1)*10)):BN$(2,2)=STR$(INT(RND(1)*10)):L=L+1:IF L=PR THEN GOTO 7000
56 POSITION 2,0:? #6;W;"/";L;
57 TN$(1,1)=STR$(INT(RND(1)*10)):BN$(1,1)=STR$(INT(RND(1)*10))
60 POSITION X+1,20:? #6;TN$;:POSITION X,21:? #6;"+";BN$;:POSITION X,22:? #6;"___";
70 POSITION X,23:? #6;"   ";:GOSUB WAL
100 SOUND 0,8,8,4
120 IF RND(1)>0.95 THEN FOR D=10 TO 5 STEP -1:SOUND 1,D,10,INT(RND(1)*10):NEXT D:SOUND 1,0,0,0
140 GOSUB 600
180 IF RND(1)>0.95 THEN FOR D=10 TO 5 STEP -1:SOUND 1,D,10,8:NEXT D:SOUND 1,0,0,0
184 GOSUB 600
185 IF RND(1)>0.95 THEN FOR D=15 TO 0 STEP -1:SOUND 1,100,8,D:FOR E=1 TO 20:NEXT E:NEXT D:SOUND 1,0,0,0
195 GOSUB 600
200 GOTO 120
500 FOR A=2 TO 17
501 GOSUB 2000
535 NEXT A
600 TRAP 840:K=PEEK(764)
610 IF K=31 THEN N=1:GOTO 700
615 IF K=30 THEN N=2:GOTO 700
620 IF K=26 THEN N=3:GOTO 700
625 IF K=24 THEN N=4:GOTO 700
630 IF K=29 THEN N=5:GOTO 700
635 IF K=27 THEN N=6:GOTO 700
640 IF K=51 THEN N=7:GOTO 700
645 IF K=53 THEN N=8:GOTO 700
650 IF K=48 THEN N=9:GOTO 700
655 IF K=50 THEN N=0:GOTO 700
660 IF K=12 THEN AMT=VAL(NU$):GOTO 800
670 IF K=33 THEN NU$="     ":P=4:GOTO 705
700 P=P-1:IF P<1 THEN K=33:GOTO 670
701 NU$(P,P)=STR$(N):POKE 764,255
800 J=TN+BN
810 NU$="     ":P=4:POKE 764,255:POSITION X,23:? #6;NU$
820 POSITION X+1,2:? #6;"  ";:POSITION X+1,3:? #6;"    ";:POSITION X+1,4:? #6;"  ";
830 POSITION X+1,8:? #6;"  ";:POSITION X,8+1:? #6;"      ";:POSITION X,8+2:? #6;"   ";
835 IF AMT=J THEN WAL=500:W=W+1:GOTO 1000
840 POKE 764,255:X=8:WAL=900:GOSUB 1010:GOTO 4000
900 T=30:FOR A=2 TO 17:GOSUB 3000:NEXT A:T=20:RETURN
1000 IF X=8 THEN 5000
1005 X=1:T=10:A=17:FOR C=1 TO 20:GOSUB 2000:NEXT C:T=20:FOR B=1 TO 200:NEXT B:GOSUB 1010:GOTO 55
1010 FOR A=17 TO 23:POSITION 0,A:? #6;"             ";:NEXT A:RETURN
2000 POSITION X+1,A-1:? #6;"    ";
2005 POSITION X+1,A:? #6;"[NO]";:POSITION X+1,A+1:? #6;"[PQ]";:POSITION X+1,A+2:? #6;"[RS]";
2006 FOR B=1 TO T:SOUND 3,200,8,B:NEXT B
2007 POSITION X+1,A:? #6;"[TU]";:POSITION X+1,A+1:? #6;"[YV]";:POSITION X+1,A+2:? #6;"[WX]";
2008 FOR B=1 TO T:SOUND 3,200,8,B:NEXT B
2009 POSITION X+1,A:? #6;"[AB]";:POSITION X+1,A+1:? #6;"[CD]";:POSITION X+1,A+2:? #6;"[EF]";:SOUND 3,0,0,0:RETURN
3000 POSITION X+1,A-1:? #6;"  ";
3001 POSITION X+1,A:? #6;"NO";:POSITION X+1,A+1:? #6;"PQ";
3002 FOR B=1 TO T:SOUND 3,170,8,B:NEXT B
3003 POSITION X+1,A:? #6;"TU";:POSITION X+1,A+1:? #6;"YV";
3004 FOR B=1 TO T:SOUND 3,170,8,B:NEXT B
3005 POSITION X+1,A:? #6;"AB";:POSITION X+1,A+1:? #6;"CD";:SOUND 3,0,0,0:RETURN
4000 T=10:FOR A=17 TO 2 STEP -1:GOSUB 3000:POSITION 8,A+1:? #6;"   ";:NEXT A:T=20:GOTO 55
5000 GOSUB 1010:T=20:X=1:GOTO 55
6005 IF F=1 THEN 11
6100 GRAPHICS 1:SETCOLOR 2,0,0:POSITION 6,4:? #6;"[animath]":POKE 752,1:? "         A MATH PROGRAM BY"
6120 FOR WT=1 TO 1000:NEXT WT:? "}":GOSUB 6000:RETURN
7000 GRAPHICS 0:POKE 704,0:POKE 705,0:POKE 710,0
7020 IF A$<>"Y" THEN END
7030 W=0:L=0:F=1:GOTO 6000
10000 DATA 0,0,0,0,1,3,6,52
10010 DATA 0,0,0,0,128,192,96,44
10020 DATA 124,254,255,239,239,231,231,199
10030 DATA 62,127,255,247,247,231,231,227
10040 DATA 71,83,115,6,6,4,2,14
10050 DATA 226,202,206,96,96,32,64,112
10060 DATA 255,255,255,255,255,255,255,255
10070 DATA 15,15,15,15,15,15,15,15
10080 DATA 240,240,240,240,240,240,240,240
10090 DATA 1,1,1,1,1,1,1,1
10100 DATA 128,128,128,128,128,128,128,128
10110 DATA 3,3,3,3,3,3,3,3
10120 DATA 192,192,192,192,192,192,192,192
10130 DATA 0,0,0,0,1,3,6,4
10140 DATA 0,0,0,0,128,198,110,63
10150 DATA 28,126,255,239,239,255,59,3
10160 DATA 63,127,255,227,227,227,231,238
10170 DATA 199,239,126,60,24,0,0,0
10180 DATA 224,224,112,48,48,60,60,0
10190 DATA 0,0,0,0,1,99,118,252
10200 DATA 0,0,0,0,128,192,96,32
10210 DATA 56,126,255,247,247,255,220,192
10220 DATA 7,7,14,12,12,124,124,0
10230 DATA 227,247,62,60,24,0,0,0
10240 DATA 252,254,255,199,199,199,231,119
20000 DATA 62,0,0,0,0,0,1,3
20010 DATA 6,52,0,0,0,0,128,192
20020 DATA 99,44,124,254,255,239,239,231
20030 DATA 231,199.62,127,255,247,247,231
20040 DATA 231,227,71,83,115,6,6,4
20050 DATA 2,14,226,202,206,96,96,32
20060 DATA 64,112,255,255,255,255,255,255
20070 DATA 255,255,15,15,15,15,15,15
20080 DATA 15,15,240,240,240,240,240,240
20090 DATA 240,240,1,1,1,1,1,1
20100 DATA 1,1,128,128,128,128,128,128
20110 DATA 128,128,3,3,3,3,3,3
20120 DATA 3,3,192,192,192,192,192,192
20130 DATA 192,192,0,0,0,0,1,3
20140 DATA 6,4,0,0,0,0,128,198
20150 DATA 110,63,28,126,255,239,239,255
20160 DATA 59,3,63,127,255,227,227,227
20170 DATA 231,238,199,239,126,60,24,0
20180 DATA 0,0,224,224,112,48,48,60
20190 DATA 60,0,0,0,0,0,1,99
20200 DATA 118,252,0,0,0,0,128,192
20210 DATA 96,32,56,126,255,247,247,255
20220 DATA 220,192,7,7,14,12,12,124
20230 DATA 124,0,227,247,62,60,24,0
20240 DATA 0,0,252,254,255,199,199,199

Jerry Wright, 18812 116 Ave., SE, Renton, WA 98055.

Table of Contents
Previous Section: Player-Missile Design Aid
Next Section: Greater Graphics Control