THE ATOM MAGIC BOOK

Contents

Page   Page  
2 Breakout 30 HexPawn
5 3D Maze 33 Drive
9 Letters 35 Biorythm
11 Matches 36 Sums Tester
12 Russian Roulette 38 Scramble
13 Compart 40 Designs
14 Talkback 41 Hunt the Wampus
16 MoonLander 44 Simon
17 Bouncing Ball 45 Screens
18 Patchwork 48 Hangman
19 Bugrace 50 Programming Tips
20 Space Battle 57 Other BASICs
22 Hammurabi 67 Tape Recording
24 Higher/Lower 70 The 6522 Versatile Interface
Adapter chip
25 Buzz-Word 74 The 8255 Programmable Peripheral
Interface Chip
26 Othello 75 Block 0 RAM
28 Number Guessing A 77 ROM Routines
29 Number Guessing B 79 VDU codes

The programs and other information given in this book have
been thoroughly checked and are believed to be accurate,
but should you find any error then please let us have full
details so that it may be corrected to help other readers.


© 1981 TIMEDATA Ltd. 57 Swallowdale,Basildon,Essex

Edition 1 ; Feb 1981
2 ; June 1981
3 ; October 1981

Breakout 

Text; 2K
VDU ½K
Integer

A noisy and fast moving version of the popular computer game, Breakout starts with a wall 5 bricks thick across the top of the screen and a small star passing from side to side across the bottom of the screen.

Pressing either of the SHIFT keys will make the star shoot up diagonally towards the wall. If it hits a brick then that brick will either fall out of the wall, or - if it is held up by another brick - will turn grey and fall as soon as it is no longer supported.

Points are scored by sending the star off the top of the screen through a gap in the wall. An arrow then appears at the point of exit and your score is increased by one. But be careful; if you accidentally hit an arrow it will fall and you lose that point !

You have a limited time in which to score as many points as possible. A count-down display of the time remaining is shown at the top left of the screen. When the game has finished, a new one may be started by pressing any key.

     1 REM- BREAKOUT
     2 REM- WRITTEM 22-10-80
     3 REM- BY D.DINI
     4 GOSUBy
     5 CLEAR0;Y=#B001;F=0;A=4000
     6 D=256*5
    10 S=#8020;E=#80BF
    15 V=1;G=0;Q=1
    20 FORT=S TO E;?T=#7F;NEXTT
    25 W=0;J=#81C0
    27 P.$30,A,F
    30 FORX=G TO(31-G) STEPQ
    32 M=X?J;N=X+J
    34 IFJ<S;GOTOe
    36 IFM=#1E;F=F-1
    37 IFM<>#40;O=X;X=(31-G);GOTOx
    40 ?N=#2A;IFW=0;WAIT;WAIT
    50 IFW=-32;B=60;GOS.s
    55 ?N=#40
    56 IF?Y&#80<>0;V=1
    57 IFV=0;GOTOa
    60 IF?Y&#80=0;W=-32
    61 IF?Y&1=0;W=-32
    70aJ=J+W
    80 A=A-1;IFA=0;GOTOf
   210 N.;X=X-Q
   215 G=X;Q=(G+1)/(-G+1)
   220 IF?#B001&#80=0;V=0
   230 G.25
   490eZ=X
   500 X=31-G;NEXT
   510 F=F+1
   515 Z=Z-Q;J=J-W
   520 Z?J=#1E
   525 FORI=1TO4;B=40;D=256*#22;GOS.s;N.;D=256*5
   530 GOTO25
  1000fP.$30''''''''''''"      ***GAME OVER***"
  1005 P.$30,A,F
  1006 D=#22*256;B=100;FORI=1TO12;GOS.s;N.
  1007 X=31-G;N.
  1010 LINK#FFE3;RUN
  2000xIFO?(J-W)<>#40;O?J=#FF;B=20;GOS.s;G.210
  2002 IFO?J=#1E;D=256*#22;B=#C0;F.I=1TO4;GOS.s;N.;D=256*5
  2005 B=20
  2010 O?J=#40;J=J-W
  2020 IFJ>#8200;LINKNN1;G.u
  2030 O?J=#FF
  2035 B=B+5;GOS.s
  2040 GOTO2010
  2050uJ=J+W
  2060 IFO?J=#40;G.u
  2070 IFO?J=#FF;G.x
  2080 G.210
  5000yDIML(2),NN(10),WW(5)
  5005 DIMP(-1)
  5010 C=#B002
  5015 P.$21
  5020[
  5025 \ RANDOM NOISE GENERATOR(SEE MANUAL)
  5030:NN1LDY@#B0
  5040:NN0
  5050 LDAL;AND@#F7;STAC;LDAL
  5060 AND@#48;ADC@#38
  5070 ASLA;ASLA
  5080 ROLL+2;ROLL+1;ROLL
  5085 LDA@#C0;DEX;BNEP-1
  5090 DEY;BNENN0;RTS
  5100 \ TONE GENERATOR (SEE "HARPSICHORD"
PROGRAM IN MANUAL)
  5110:WW0STA#80;LDA@0
  5120:WW2LDX#80
  5130:WW1DEX;NOP;NOP;BNEWW1
  5140 EOR@4;STA#B002
  5150 DEY;BNEWW2;RTS
  5160]
  5170 P.$6
  6000 RET.
  7000sC=A;R=Y;A=B;Y=D/A
  7010 LINKWW0;A=C;Y=R;RET.

Program Notes:

The program uses two machine language routines (lines 5020 to 5160) to generate various sound effects.

The program draws on the screen by storing appropriate values (e.g. #2A for a *) in the VDU screen memory locations 8000-81FF. Thus line 20 draws the initial 5 rows of bricks, line 40 plots a *, and line 55 deletes the old *.

The main program loop is from lines 30 to 210, which moves the star across the screen; line 32 branching to e if you have scored a point, line 36 reducing your score if you have hit an arrow. If you hit anything, line 37 branches to the routine at line 2000. Lines 40-55 shift the image of the star - using subroutine s to provide sound effects if it is moving upwards. Lines 56-60 set W to -32 when the SHIFT key has been pressed.

Lines 490-530 increment your score, PLOT an arrow in the place where you broke through the wall, using the subroutine s to generate the winning sound.

Line 2000 is reached if the star hits anything, and returns to the main loop at line 210 if a solid brick is below the one hit. Line 2002 is executed if you have hit an arrow. Lines 2005-2040 make the falling brick images and sounds. Lines 2050-2070 repeat the process if any grey blocks are left unsupported.

Line 1010 is reached at the end of the program; it waits for any key to be pressed, then starts a new game.

3D Maze 

Text; 5K
VDU; 1K
Integer

This program generates a random maze of specified dimensions, then plots it in 3D as though you were actually inside it. You then have to find your way out by moving forward (key F), or by turning right (R) or left (L). Pressing key H (for HELP!!!) will give you your co-ordinates and the direction in which you are pointing.

The exit is represented by two vertical poles;


EXIT

The maximum size of maze allowed is 19 x 18.

     1 P.$12'''"LABYRINTH:"''"MAZES IN 3D..."'''
     3 REM-BY D.DINI 6/10/80
     5P.$21
    10 DIMVV1
    15 P=#2800
    20[
    30:VV0 JSR#FFE3;STA#80;RTS;]
    40 P.$6
   100 P."MAZE SIZE"'
   110 INPUT"WIDTH"I,"HEIGHT"H
   120 DIMA(I*H-1),B(I*H-1)
   130 FORX=0TO(I*H-1);A?X=9;NEXT
   135 CLEAR0
   140 Y=ABSRND%H;L=0;X=-1;M=Y;D=1;E=D
   145 MOVE(X*2+2),(Y*2)
   150 R=0;IF ABSRND%2;GOTOa
   160 D=ABSRND%4
   165aV=0;W=0
   170 GOTO(180+D)
   180 W=1;G.b
   181 V=1;G.b
   182 W=-1;G.b
   183 V=-1
  
   190bIFX+V>I-1 ORX+V<0ORY+W>H-1 ORY+W<0;R=R+1;GOTOt
   200 IFA?((X+V)*H+Y+W)<>9;R=R+1;GOTOt
   210 X=X+V;Y=Y+W
   220 A?(X*H+Y)=D;GOSUBu
   225 DRAW(X*2+2),(Y*2)
   230 GOTO150
   240tIFR>3;GOTOe
   250 IFR>2;P=D;GOTOc
   260 IFR>1;K=D;P=9;GOTOc
   270 J=D;K=9;P=9
   280cDO D=ABSRND%4
   290 UNTIL D<>J AND D<>K AND D<>P
   300 GOTOa
   400eD=A?(X*H+Y);D=D+4;A?(X*H+Y)=D
   405 GOSUB3000
   410 D=D-4
   420 V=0;W=0
   430 GOTO(440+D)
   440 W=-1;G.h
   441 V=-1;G.h
   442 W=1;G.h
   443 V=1
   450hX=X+V;Y=Y+W;IFX=L;IFY=M;GOTOx
   455 PLOT14,(X*2+2),(Y*2);WAIT;WAIT;WAIT
   456 PLOT14,(X*2+2),(Y*2)
   460 IFA?((X+1)*H+Y)=9;IFX+1<I;D=1;GOTOj
   470 IFA?((X-1)*H+Y)=9;IFX-1>-1;D=3;GOTOj
   480 IFA?(X*H+Y+1)=9;IFY+1<H;D=0;GOTOj
   490 IFA?(X*H+Y-1)=9;IFY-1>-1;D=2;GOTOj
   500 D=A?(X*H+Y);GOTO 420
   510jMOVE(X*2+2),(Y*2)
   520 F=B?(X*H+Y)
   530 IFD=0;F=F&#E;G.i
   540 IFD=1;F=F&#D;G.i
   550 IFD=2;F=F&#B;G.i
   560 IFD=3;F=F&#7
   570iB?(X*H+Y)=F
   580 E=D;GOTOa
   600xX=I-1
   610 FORY=0TO H-1
   620 IF A?(X*H+Y)>3;GOTOq
   630 NEXTY
   640 Y=ABSRND%H
   645qMOVE(X*2+2),(Y*2)
   650 DRAW((X+1)*2+2),(Y*2)
   660 N=X;O=Y
   670 B?(N*H+O)=B?(N*H+O)&#D
   690 P.$30"MAZE COMPLETE"'
   700 P."PRESS ANY KEY TO ENTER MAZE";LINK#FFE3
   705 B?(L*H+M)=B?(L*H+M)|8
   720 Q=1;Y=M;X=L
   726 CLEAR1;G=0
   730 S=0;GOSUB4050
   770 MOVE34,0;DRAW34,63;MOVE94,0;DRAW94,63
   810 IFF&1<>0;MOVE34,0;DRAW94,0;MOVE34,63;
DRAW94,63;G=1;GOTOz
   815 REM--DEPTH 2
   820 MOVE46,12;DRAW46,51;MOVE82,12;DRAW82,51
   830 GOSUBl
   835 IFS=1;G.z
   840 IFF&8<>0;MOVE46,12;DRAW34,0;MOVE46,51;DRAW34,63;GOTO860
   850 MOVE46,12;DRAW34,12;MOVE46,51;DRAW34,51
   860 IFF&2<>0;MOVE82,12;DRAW94,0;MOVE82,51;DRAW94,63;GOTO880
   870 MOVE82,12;DRAW94,12;MOVE82,51;DRAW94,51
   880 IFF&1<>0;MOVE46,12;DRAW82,12;MOVE46,51;DRAW82,51;GOTOz
   890 REM-DEPTH3
   900 MOVE54,20;DRAW54,43;MOVE74,20;DRAW74,43
   910 GOSUBl
   915 IFS=1;GOTOz
   920 IFF&8<>0;MOVE54,20;DRAW46,12;MOVE54,43;DRAW46,51;GOTO940
   930 MOVE54,43;DRAW46,43;MOVE54,20;DRAW46,20
   940 IFF&2<>0;MOVE74,20;DRAW82,12;MOVE74,43;DRAW82,51;GOTO960
   950 MOVE74,20;DRAW82,20;MOVE74,43;DRAW82,43
   960 IFF&1<>0;MOVE54,20;DRAW74,20;MOVE54,43;DRAW74,43;GOTOz
   970 REM-DEPTH4
   980 MOVE58,24;DRAW58,39;MOVE70,24;DRAW70,39
   990 GOSUBl
   995 IFS=1;GOTOz
  1000 IFF&8<>0;MOVE58,24;DRAW54,20;MOVE58,39;DRAW54,43;GOTO1020
  1010 MOVE58,39;DRAW54,39;MOVE58,24;DRAW54,24
  1020 IFF&2<>0;MOVE70,24;DRAW74,20;MOVE70,39;DRAW74,43;GOTO1040
  1030 MOVE70,39;DRAW74,39;MOVE70,24;DRAW74,24
  1040 IFF&1<>0;MOVE58,24;DRAW70,24;MOVE58,39;DRAW70,39;GOTOz
  1050 MOVE61,27;DRAW61,36;MOVE67,27;DRAW67,36
  1060 GOSUBl
  1065 IFS=1;G.z
  1070 IFF&8<>0;MOVE61,27;DRAW58,24;MOVE61,36;DRAW58,39;GOTO1090
  1080 MOVE61,27;DRAW58,27;MOVE61,36;DRAW58,36
  1090 IFF&2<>0;MOVE67,27;DRAW70,24;MOVE67,36;DRAW70,39;GOTO1110
  1100 MOVE67,27;DRAW70,27;MOVE67,36;DRAW70,36
  1110 IFF&1<>0;MOVE61,36;DRAW67,36;MOVE61,27;DRAW67,27
  1120zLINKVV0;Z=?#80
  1122 IFZ<>CH"H";GOTO1130
  1123 P.$12"YOU ARE AT "X","Y
  1124 P.'"FACING "
  1125 IFQ=0;P."DUE NORTH"'
  1126 IFQ=1;P."DUE EAST"'
  1127 IFQ=2;P."DUE SOUTH"'
  1128 IFQ=3;P."DUE WEST"'
  1129 P."PRESS ANY KEY TO CONTINUE";LINK#FFE3;GOTOp
  1130 IFZ<>CH"R";G.1140
  1135 Q=Q+1;IFQ=4;Q=0
  1136 G.p
  1140 IFZ<>CH"L";GOTO1150
  1145 Q=Q-1;IFQ=-1;Q=3
  1146 G.p
  1150 IFZ=CH"F"ANDG=0;GOTOf
  1155 P.$7;GOTOz
  1160fGOTO(1170+Q)
  1170 Y=Y+1;GOTOp
  1171 X=X+1;GOTOp
  1172 Y=Y-1;GOTOp
  1173 X=X-1
  1175pL=X;M=Y;IFL>N;IFO=M;P.$12"WELL DONE!"';RUN
  1190 CLEAR1;G=0;GOTO730
  2000uIFD/2*2=D;B?(X*H+Y)=#A;GOTO2020
  2010 B?(X*H+Y)=#5
  2020 IFD=E;RET.
  2030 IFE=0IFD=1;F=9;GOTOw
  2040 IFE=3IFD=2;F=9;GOTOw
  2050 IFE=0IFD=3;F=3;GOTOw
  2060 IFE=1IFD=2;F=3;GOTOw
  2070 IFE=2IFD=3;F=6;GOTOw
  2080 IFE=1IFD=0;F=6;GOTOw
  2090 IFE=3IFD=0;F=#C;GOTOw
  2100 IFE=2IFD=1;F=#C;GOTOw
  2110wB?((X-V)*H+Y-W)=F;E=D;RET.
  2999 REM-BLOCK OFF DEAD END
  3000 F=B?(X*H+Y)
  3010 IFD=4;F=F|1;GOTOs
  3020 IFD=5;F=F|2;GOTOs
  3030 IFD=6;F=F|4;GOTOs
  3040 F=F|8
  3060sB?(X*H+Y)=F;RET.
  4000lV=0;W=0;S=0
  4010 GOTO(4020+Q)
  4020 W=1;GOTOk
  4021 V=1;GOTOk
  4022 W=-1;GOTOk
  4023 V=-1;GOTOk

  4040kL=L+V;M=M+W
  4045 IFL=N+1ANDM=0;F=10;S=1;RET.
  4050 F=B?(L*H+M)
  4055 U=Q;T=F
  4060mC=F
  4070 IFU=0;R.
  4080 F=F/2;IFC&1<>0;F=F+8
  4100 U=U-1;GOTOm

Letters 

Text; 2K
VDU; ½K
Integer

This program plots a number of letters on the screen. You then have to erase them all by moving the cursor over each letter in turn. If you hit the edge of the screen or donut erase the letters in alphabetic order then the game finishes and you lose.

Once the game has started the cursor is continually moving. To change it's direction press one of the keys 4,5,6 or 7; which make it, go down, ups left or right respectively.

As it moves, the cursor leaves a trail that can cause great confusion if you have to retrace your steps, as you are then unable to see exactly where you are.

The difficulty of the game can be varied by specifying a different number of letters (1 to 26) to be erased, or by varying the speed of movement to 10) in response to questions asked when the game is started. You are also asked for a 'course number'. This is used to seed the random number generator used to position the letters, so that you may run exactly the same game again by specifying the same course number.

When the game has finished - either because you have made a mistake or because, you have successfully erased all of the letters, then another game is automatically started.

     1 REM-LETTERS BY D.DINI WRITTEN 1/8/80
     9 P.$21;@=0
    10 DIM VV(2);P=#2802
    15 FOR Q=1 TO 2
    19 REM-ASSEMBLE ROUTINE TO READ KEYS 4-7
    20[
    30:VV0 LDX@6
    40:VV1 STX#B000;LDA#B001;AND@4
    50 BEQ VV2
    60 INX;CPX@10;BNE VV1
    70:VV2 STX#80;RTS
    75]
    80 NEXT Q
    90 P.$6
   100 INPUT"NO OF LETTERS"L
   105 IF L>26;GOTO 100
   110 INPUT"SPEED"S
   114 REM-SEED RANDOM NUMBER GENERATOR
   115 ?12=0;INPUT"COURSE"C;!8=C
   120 CLEAR 0;MOVE 0,0;U=1
   130 DRAW 63,0;DRAW 63,47;DRAW 0,47;DRAW 0,0
   134 REM-PLOT LETTERS ON SCREEN
   135 FOR A=1 TO L
   140 X=ABSRND%30+1;Y=ABSRND%14+1;P=#8000+32*Y+X
;IF?P<>64;GOTO140
   150 ?P=A;NEXT A
   160 X=2;Y=45;R=1
   165 REM-WAIT TILL KEY PRESSED
   170 GOSUB k;IF O=10 THEN GOTO 170
   180mPLOT 13,X,Y;GOSUB k;U=U+1;GOTO (K-6+181)
   181 X=X+1;GOTO z
   182 X=X-1;GOTO z
   183 Y=Y+1;GOTO z
   184 Y=Y-1
   185z ?#B000=0
   186 IF R>L THEN GOTO s
   189 REM-CHECK IF BORDER HIT
   190 IF X<1 OR X>62 OR Y<1 OR Y>46 THEN GOTO e
   195 REM-CHECK IF LETTER HIT
   200 V=X/2;W=15-Y/3;P=#8000+32*W+V
   205 REM-CHECK IF RIGHT LETTER
   210 IF ?P>26 THEN GOTO m
   220 IF ?P=R R=R+1;?P=64;GOTO m
   230 GOTO e
   240sP.$30"WELL DONE,TOOK "U" MOVES"';RUN
   250e?P=42;P.$30$7"SHAME!"';RUN
   489 REM-GET KEY & WAIT
   490kFORT=10TO S STEP-1
   500 LINK VV0;O=?#80;IF O<10 K=O
   510 WAIT;NEXT;RETURN

Program Notes;

By leaving out the REM lines and abbreviating the other lines, 'letters' can be made to fit into 1K text RAM space.

A machine language routine (lines 20-75) is used to scan the keyboard by directly manipulating the 8255 I/O chip ports. Line 9 prevents the assembly listing from appearing on the screen when the program is executed. Line 90 subsequently re- enables the display.

Since the random number seed occupies 5 bytes of RAM, (locations 8 to 12), while an integer variable takes only 4 bytes, pre-setting the seed to the 'course' number (C; line 115) involves setting RAM location 12 to zero as well as storing the value of C in the other four bytes.

Matches 

Text; 1K
VDU ½K
Integer

Matches is a simplified form of NIM. Starting with a row of from 21 to 32 matches, the player and the computer take turns to remove 1, 2 or 3 matches. The player left with the last match loses.

    10 REM MATCHES
    20 @=0
   100 M=ABSRND%12+21;GOSUB 900
   110 PRINT"WE TAKE TURNS TO REMOVE"'
   120 PRINT"1,2 OR 3 MATCHES."''
   130 PRINT"THE ONE LEFT WITH THE LAST"'
   140 PRINT"MATCH LOSES."''
   300 PRINT M" MATCHES, YOUR TURN"'
   310 IF M=1 GOTO 510
   320 INPUT"HOW MANY WILL YOU TAKE "T
   330 IF T=M GOTO 500
   340 IF T>3 OR T<1 OR T>M GOTO 320
   400 M=M-T;IF M=1 GOTO 600
   410 R=M%4;C=(R+3)%4
   420 IF R=1 C=1+ABSRND%3
   430 M=M-C;IF M=0 GOTO 600
   440 GOSUB 900
   450 PRINT"YOU TOOK  ",T'
   460 PRINT"SO I TOOK ",C''
   470 GOTO 300
   500 PRINT $12
   510 PRINT"I WON !!!";END
   600 PRINT $12,"*** YOU WON ***"
   610 FOR I=1 TO 10;PRINT $7;NEXT;END
   900 PRINT $12;CLEAR 0;FOR K=1 TO M
   910 MOVE (2*K),0;DRAW (2*K),10
   920 NEXT;RETURN

Program Notes;

Line 100 establishes the starting number of matches and displays them by calling subroutine 900. Lines 110 to 140 then present the instructions above the displayed row of matches.

Lines 300-340 get the player's choice and check that it is valid, lines 400-470 then calculate the computer's move. If neither side has won then the current state of the game is displayed and the next move played.

Russian Roulette 

Text; 1K
VDU; ½K
Integer

Russian Roulette is a game for two or more players who take turns to place a loaded revolver to their heads and pull the trigger. Five of the revolver's chambers are empty, the sixth contains a live round. The game is over when a player refuses to take his turn, or when the revolver fires.

In response to the question 'DO YOU WANT TO PULL THE TRIGGER', enter either Y or N, then press the Return key.

     1 REM RUSSIAN ROULETTE
    10 DIM A(64)
    20 X=#B002;PRINT $12
   110 PRINT"YOU HAVE A REVOLVER"'
   120 PRINT"WITH 5 EMPTY CHAMBERS"'
   130 PRINT"AND ONE LOADED ONE."''
   140 PRINT"IT IS POINTED AT YOUR HEAD !"''
   200 INPUT"DO YOU WANT TO PULL THE TRIGGER"$A
   210 PRINT $12
   220 IF CH$A=CH"N" THEN GOTO 500
   230 FOR I=1 TO 30;WAIT;NEXT
   240 IF ABSRND%6=5 THEN GOTO 400
   300 ?X=?X:4;?X=?X:4
   310 PRINT"LUCKY !"''''''';GOTO 200
   400 CLEAR 0;MOVE 18,30
   410 PLOT 5,16,30;PLOT 5,16,6
   420 PLOT 5,56,6;PLOT 5,56,12
   430 PLOT 5,50,12;PLOT 5,50,6
   440 MOVE 40,24;PLOT 5,40,6
   450 PLOT 13,53,13
   460 PRINT''"!!! YOU ARE DEAD !!!"
   470 END
   500 PRINT"*** CHICKEN ***"
   510 FOR I=1 TO 20;?X=?X:4;WAIT;NEXT;END

Program Notes;

The two PRINT $12 statements (lines 20 & 210) clear the VDU screen and position the cursor at the top left corner.

Line 230 gives a half-second pause to heighten the tension. Line 300 generates a 'click' sound; line 510 makes a suitable 'raspberry' noise.

Lines 400-450 may be improved by artistically minded programmers.

Compart 

Text; 1K
VDU; 1K
Integer

This program draws a sequence of five abstract pictures in either black and white, or black, grey and white.

     1 REM COMPART BY D. DINI AUG.'80
     5 DIM A(7);!A=#10204080;A!4=#1020408
    10 P.$12
    20 P."    computer art"''
    25 IN."DO YOU WANT SINGLE(1) OR DOUBLE(2) SHADE DRAWINGS"I
    30 P."PRESS ANY KEY TO START"
    35 LINK #FFE3
    37 FOR D=1 TO 5
    40 CLEAR 1;IF I=2 THEN ?#B000=#10
    44 MOVE 1,1;X=126;Y=62
    45 DRAW 1,Y;DRAW X,Y;DRAW X,1;DRAW 1,1
    50 P=ABSRND%123+2;Q=ABSRND%59+2
    60 GOSUBd
    70 FOR Z=1 TO 10000;NEXT Z
    80 NEXT D
    90 RUN
  1000dX=RND%2;Y=RND%2
  1010 V=X+P;W=Y+Q;GOSUBt
  1020 IFC GOTOn
  1030 T=0
  1040 P=P+X;Q=Q+Y
  1050 PLOT 13,P,Q
  1060 GOTO 1010
  1070nT=T+1
  1080 IF T<100 GOTOd
  1090 RETURN
  2000tB=V/8+(63-W)*16+#8000
  2010 C=(?B&(A?(V&7))<>0);RETURN

Program Notes:

If double shade drawings are selected, then I=2 and line 40 sets the VDU controller to mode 1a.

Line 70 gives a short pause at the end of each drawing for you to admire it before the computer begins its next opus.

Talkback 

Text; 2K
VDU; 2-6K
Integer

While this program does not answer Man's dream of a talking computer, it does allow you to record a few seconds of speech in ATOM's memory, then play it back on demand.

The speech is converted to digital form then stored in the VDU RAM area (above the text screen area), each 1K byte giving one second of recording time. In any digital speech recording system a compromise must be made between quality of reproduction and the amount of storage needed - in this case the choice has been to extend the recording time as much as possible and accept a pretty dreadful quality for the reproduced signal) although a noticeable improvement can be made by careful choice of the recording-level and by turning any amplifier 'treble' control to minimum.

Recording is done from a microphone connected via a suitable amplifier to ATOM's 'CASS IN' port. The level needed by ATOM is about the same as when loading programs from tape, so the cassette recorder amplifier will probably be suitable. Playback is through ATOM's built-in loudspeaker.

When the program is run, it asks if you want to Record or Play-back If you choose to record then the screen will be covered by 'snow' for a few seconds while the program initialises the VDU RAM area. You are then asked to press any key to start the recording process. While recording, the screen will again be sprinkled with white lines as the data is stored.

    10 REM TALKBACK
    20 DIM YY(6),ZZ(7),A(10)
    30 P.$12;P=P&#FF00+#100
   100 P.$21;GOSUBa;GOSUBa;P.$6$12
   110 DO INPUT"RECORD (R) OR PLAYBACK (P) "$A
   120 UNTIL ?A=CH"P" OR ?A=CH"R"
   130 IF ?A=CH"P" LINK ZZ0;GOTO 100
   200 P.'"ONE MOMENT PLEASE"'
   210 C=#1010101
   220 FOR X=#8200 TO #97FF STEP 4
   230 !X=C;NEXT X
   240 P.$12"PRESS ANY KEY TO START RECORDING"
   250 LINK #FFE3;LINK YY0
   270 P.$12"** END **"''$7;GOTO 100
  1000a REM RECORD ROUTINE
  1005 DIM P(-1)
  1010[
  1020:YY0 LDX @0;LDY @#82
  1030:YY1 LDA @10
  1040:YY2 SEC;NOP;SBC @1;BNE YY2
  1050 LDA #B002;ROL A;ROL A;ROL A
  1060:YY3 ROL #8200,X;BCC YY5
  1070 INX;BNE YY6
  1080 INY;STY YY3+2;CPY @#98
  1090:YY4 BNE YY1;RTS
  1100:YY5 LDA @#FF;NOP
  1110:YY6 NOP;NOP;BNE YY4
  1120]
  1500 REM PLAYBACK ROUTINE
  1510[
  1520:ZZ0 LDX @0;LDY @#82
  1530:ZZ1 LDA @8;STA ZZ7
  1540:ZZ2 LDA #8200,X
  1550:ZZ3 ASL A;PHA;PHP;LDA @10
  1560:ZZ4 SEC;SBC @1;BNE ZZ4;NOP
  1570 PLP;LDA @4;ADC @0;STA #B003
  1580 PLA;DEC ZZ7;BNE ZZ6;INX;BNE ZZ5
  1590 INY;STY ZZ2+2;CPY @#98;BNE ZZ1;RTS
  1600:ZZ5 PHA;PLA;NOP;JMP ZZ1
  1610:ZZ6 ASL #FF00,X;ASL #FF00,X;ASL #FF00,X;JMP ZZ3
  1620:ZZ7 NOP
  1630];RETURN

Program Notes:

As given, the program expects the full 6K bytes of VDU RAM. If less RAM is available, the CPY @#98 instructions in lines 1080 and 1590 should be changed to;

CPY @#94 for 5K bytes VDU RAM
#90 4 " "
#8C 3 " "
#88 2 " "

The main work is done by the two machine language routines at lines 1000-1120 and 1500-1630. When recording, the voltage on the CASS IN port is examined every 125 µS, and one bit of the memory is set to either '1' or '0' depending on whether the signal was positive or negative. When playing back, a single bit is taken from the memory every 125 µS and the state of the loudspeaker drive line set high or low accordingly. A large part of the machine language routines (notably lines 1040, 1100, 1110, 1560, 1600 & 1610) consists of 'time wasting' instructions inserted so that the over-all loop time is always 125 uS.

Note that lines 210-230 preset the RAM before recording so that each byte has bits 1-7 =0 and bit 0 = 1.

Moon Lander 

Text; 2K
VDU; 1K
Integer

You are piloting a rocket landing on the Moon; the **!!**!!** computer has failed again (and the engine sounds rough). At the start of the simulation you are 450 metres up, travelling horizontally at 300 metres per second, and starting to fall from orbit. You should aim to land within the Lunar Landing Area (the small white rectangle on the Moon's surface) with a vertical velocity of less than 50 m/s and a horizontal velocity of less than 20.

Your controls are the keys F, R and U, which apply forward, reverse or upward thrust respectively but only one at a time. Instrument readings of height, velocities and fuel remaining are given on the right of the screen. Happy landings.

    10 REM MOONLANDER
    20 DIM P(-1);P.$21
    30[;JSR #FE71;STY #80;RTS;];P.$6
   100 J=#1B8020;K=#1B8080;L=#1B80E0
   110 M=#1B8140;N=#B002;O=#DE
   120 D=0;A=45000;V=0;H=300;F=1250
   130 T=1000;Y=A/T+2;X=D/T
   140 CLEAR 0;@=5;MOVE 0,0;DRAW 63,0;MOVE 0,1
   150 DRAW 63,1;MOVE 31,2;DRAW 33,2
   160 !O=#1D8000;P."ALT"
   170 !O=#1D8060;P."H-V"
   180 !O=#1D80C0;P."V-V"
   190 !O=#1C8120;P."FUEL"
   200a FOR U=1 TO 5;IF A<1 A=0;G.c
   210 WAIT;PLOT15,X,Y;X=D/T;Y=A/T+2
   220 WAIT;PLOT13,X,Y;?N=#D3
   230 LINK TOP;R=?#80;IF F=1 F=0;G.b
   240 IF R=53 V=V-5;F=F-5;?N=#D7
   250 IF R=50 H=H-3;F=F-3;?N=#D7
   260 IF R=38 H=H+3;F=F-3;?N=#D7
   270b A=A-V;D=D+H;V=V+2;N.
   280c !O=J;P.A/100;!O=K;P.H;!O=L;P.V;!O=M;P.F
   290 IF A>0 G.a
   300 IF ABSV<50 IF ABSH<20 G.d
   310 FOR I=1 TO 4;MOVE(X-6),4
   320 PLOT5,X,0;?N=?N:4;PLOT1,6,4;?N=?N:4;WAIT
   330 PLOT7,X,0;?N=?N:4;PLOT3,(-6),4;?N=?N:4
   340 NEXT;MOVE X,0;PLOT 3,0,3
   350 !O=#8080;P."ANOTHER CRATER "
   360 IF ABSV<100 G.e
   370 !O=#80C0;P."WHERE WAS THE PILOT ?";G.e
   400d !O=#8080;S=ABS(H*V)
   410 IF S<300 P."SMOOTH - -"
   420 IF S>299 P."BUMPY ! ! "
   430 !O=#80C0;@=0;X=ABS(X-32)
   440 IF X>1 P."BUT "X" KM FROM BASE"
   450 IF X>5 P."   walk"
   460 IF X>1 OR S>200 G.e
   470 P."HELLO BUCK ROGERS "
   499e ?#E1=#80;GOTO 514

Program Notes:

A small machine language routine (line 30) is used to scan the keyboard and put the number of any key pressed into RAM location 80. Lines 100-190 set up the constants J-O which are used for speed in the main program loop, the starting values and position, and prepare the screen. Note lines 160-190 (and 280) which move the print cursor by storing a four-byte word in locations #DE-E1.

The main body of the program is lines 200 to 290 which continually plot the latest position of your craft (lines 210, 220), scan the keyboard and adjust the velocities and fuel level accordingly (lines 230-260) and update your position (line 270). Every five iterations, line 280 updates the instrument readings.

When you have touched ground, lines 300-370 draw an explosion and make suitable comments if you landed too fast. If you have survived, lines 400-499 pass comment on your prowess as a pilot.

Bouncing Ball 

Text; ½K
VDU.; ½K
Integer

A simple demonstration of a moving display) this program shows a ball bouncing endlessly between the walls of an enclosure. Use ESC to stop the program.

     1 REM BOUNCING BALL
    10 CLEAR 0;X=1;Y=24;H=-1;V=1
    20 MOVE 0,0
    30 PLOT 1,63,0;PLOT 1,0,47
    40 PLOT 1,-63,0;PLOT 1,0,-47
    50aWAIT;IF X=1 OR X=62 WAIT;H=-H
    60 WAIT;IF Y=1 OR Y=46 WAIT;V=-V
    70 WAIT;PLOT 15,X,Y
    80 WAIT;X=X+H;Y=Y+V
    90 WAIT;PLOT 13,X,Y;GOTO a

Program Notes:

Line 10 sets up the 48 x 64 graphics mode and the starting position (X,Y) and velocity (H,V) of the ball. Lines 25-40 then DRAW the four walls.

The main body of the program is the loop covering lines 50-90. Lines 50 and 60 reverse the direction of travel if the ball touches one of the walls; line 70 deletes the old image of the ball from the screen, and lines 80 and 90 calculate the new position and plot it.

Patchwork 

Text; ½K
VDU; ½K
Integer

Patchwork displays a very long sequence of 'kaleidoscope' patterns. Other sequences may be obtained by changing line 140.

    10 REM PATCHWORK
   100 CLEAR 0
   110 FOR A=1 TO 100
   120 FOR B=1 TO 31
   130 FOR C=0 TO 31
   140 E=(C*5/(B+A+1)+B)%2*2+13
   145 D=B+C
   146 F=B*23/31;G=D*23/31;H=63-D;I=63-B;J=47-F;K=47-G
   150 WAIT;PLOT E,D,F
   160 PLOT E,H,F
   170 WAIT;PLOT E,D,J
   180 PLOT E,H,J
   190 WAIT;PLOT E,B,G
   200 PLOT E,I,G
   210 WAIT;PLOT E,B,K
   220 PLOT E,I,K
   230 NEXT;NEXT;NEXT;END

Bug Race 

Text; 1K
VDU; 1K
Integer

Another simple moving display program, Bug race shows two specks skittering down a racetrack. The program stops when one bug reaches the end of the course - then after a short pause it runs another race.

     1 CLEAR 0
     3 INPUT"HIT RETURN TO START BUGRACE"$TOP
     5 CLEAR 1;A=0;B=15;C=0;D=47
    10 DO WAIT
    20  PLOT 15,A,B;PLOT 15,C,D
    30  A=A+ABSRND%2;B=B+RND%3
    40  C=C+ABSRND%2;D=D+RND%3
    50  IF B<1 B=1
    55  IF B>30 B=30
    60  IF D<33 D=33
    65  IF D>62 D=62
    70  WAIT
    80  PLOT 13,A,B;PLOT 13,C,D
    90 UNTIL (A=127) OR (C=127)
   100 FOR X=1 TO 100;WAIT;NEXT X
   110 GOTO 1

Program Notes:

Line 5 sets up the 64 x 128 graphics mode and the starting points (A,B for the first bug, C,D for the second).

The main body of the program is the loop through lines 10-90. Line 20 erases the previous images; line 80 plots the new positions of the racers. The WAIT statements in lines 10 and 70 ensure that the VDU RAM is only accessed during the display blanking periods (and also slow the competitors down to a decent pace). Lines 30,40 calculate the new positions, and lines 50-65 make sure that the racers do not stray out of their lanes.

Space Battle 

Text; 2K
VDU; 1K
Integer

You are engaged in a fast moving battle against alien spaceships that must be zapped before they can destroy you and go on to conquer Cambridge. Before the fight started, you had a chance to choose the number of enemy ships and the general level of skill needed to survive. Now' the battle is under way, the screen shows you the relative position of the nearest alien. To kill him you just have to steer your ship until his image comes within the inner aiming rectangle on your screen, then press the firing key. But be quick about it - he is liable to shoot back. New recruits to the Atomic Space Service are advised to gain experience in fights at skill level 1 before tackling trickier opponents.

     1 REM SPACE BATTLE - BY T. MABBS
    10 P.$12"*** SPACE BATTLE ***"''
    15 P."KEY 'B' TO GO RIGHT"'
    20 P."    'C'       LEFT"'
    25 P."    'D'       DOWN"'
    30 P."    'E'       UP"'
    35 P."    'F' TO FIRE"''
    50 INPUT"NUMBER OF ALIEN SHIPS (1-20)"A;IF A<1 OR A>20 GOTO 50
    60 INPUT"LEVEL OF SKILL (1-6)"L;IF L<1 OR L>6 GOTO 60
    70 O=56+L;P=72-L;Q=24+L;R=40-L;U=1;V=1;S=0
    80 P."PRESS ANY KEY TO START";LINK #FFE3
   100 GOSUB d
   200e PLOT 14,X,Y;F=X;G=Y;GOSUB b
   210 IF ABSRND%100&lt;L GOSUB 500
   220 IF ?#80=0 GOSUB 300
   230 IF ?#81=0 Y=Y-3
   250 IF ?#82=0 Y=Y+3
   260 IF ?#83=0 X=X+3
   270 IF ?#84=0 X=X-3
   280 X=(X+U)&127;Y=(Y+V)&63
   290 PLOT 14,F,G;GOTO e
   300 S=S+1;FOR C=1 TO 6;?#B002=?#B002:4;NEXT
   320 MOVE 32,0;PLOT 6,64,32;PLOT 6,96,0
   330 MOVE 32,0;PLOT 6,64,32;PLOT 6,96,0
   340 IF X>O IF X<P IF Y>Q IF Y<R GOTO 400
   350 RETURN
   400 MOVE (X-3),(Y-3);PLOT 5,(X+3),(Y+3)
   410 MOVE (X+3),(Y-3);PLOT 5,(X-3),(Y+3)
   420 FOR C=1 TO 90;?#B002=?#B002&RND:4;NEXT
   430 A=A-1;IF A=0 GOTO 1000
   440 GOSUB d;PLOT 14,X,Y;RETURN
   500 MOVE X,Y;C=64+RND%8;D=32+RND%5;PLOT 6,C,D
   510 Z=#B002;FOR K=1 TO 8;?Z=?Z:4;N.
   520 MOVE X,Y;PLOT 6,C,D
   530 U=-U;IF RND%2=0 V=-V
   540 IF C<>64 OR D<>32 RETURN
   560 @=0;P.$12"BAD LUCK!"'"YOU WERE HIT BY ENEMY FIRE"'
   570 P."AND YOUR SHIELDS FAILED."'"YOU USED "S" SHOTS"'
   580 P."BUT "A" ALIEN REMAINED"';GOTO 1100
   800dX=ABSRND%128;Y=ABSRND%64;F=X;G=Y
   810aCLEAR 1;MOVE 64,0;DRAW 64,Q;MOVE 64,R;DRAW 64,64
   820 MOVE 0,32;DRAW O,32;MOVE P,32;DRAW 128,32
   830 MOVE O,Q;DRAW O,R;DRAW P,R;DRAW P,Q;DRAW O,Q
   840 MOVE 32,16;DRAW 32,48;DRAW96,48;DRAW 96,16;DRAW 32,16;R.
   900bFOR B=1 TO 5;?#B000=?#B000&#F0+B
   910 B?#7F=?#B001&8;NEXT;RETURN
  1000 P.$12"WELL DONE!!"'"YOU DESTOYED THE ENEMY"'
  1010 @=0;P."WITH "S" SHOT";IF S>1 P."S"
  1100 P.'';INPUT"AGAIN "$TOP;IF ?TOP=CH"Y" RUN
  1110 END

Program Notes:

Lines 10-80 display the instructions at the start of the game, get the number of aliens (A) and skill level (L), then calculate the size of the aiming window (O, P, Q, R). U and V are the horizontal and vertical velocities of the alien ship, S is the number of shots fired.

The main body of the program is the loop through lines 200-280, which plots the latest position of the alien ship (line 200), then scans the keyboard (subroutine b) and acts accordingly.

Line 2l0 sometimes calls the subroutine at line 500 to give the enemy a chance to fire at you or change direction.

Lines 300-350 are the 'your shot' subroutine; line 300 makes a suitable noise, line 320 draws the shot lines and line 330 erases them. If the alien ship was within the aiming rectangle the program jumps to line 400 to draw a brief explosion with sound effects provided by line 420. If you have destroyed all of the enemy ships the program then goes to line 1000, otherwise line 440 draws a new screen with the next alien.

Lines 500-580 are executed when the alien fires at you. Lines 500 and 520 show the enemy fire and make a suitably frightening noise, line 530 changes his direction of travel. If you have suffered a direct hit (C=64, D=32) then the game ends via lines 560 to 580.

Lines 900-910 scan the keys B-F by direct manipulation of the I/O ports at B000 and B001, and put a '1' in one or the RAM locations 80-84 if the corresponding key was pressed.

Hammurabi 

Text; 2K
VDU; ½K
Integer

Hammurabi was possibly the first 'world simulation' computer game to be written. You play the part of Hammurabi; King of ancient Sumaria. Each year your faithful servant - Atom - tells you how big your kingdom is, how many subjects you have, and how much grain is left from the harvest and from previous years. You then have to decide whether to trade land for grain with neighbouring kingdoms, how much to allocate as food for the coming year, and how much grain is to be used as seed.

Your subjects will die of starvation if you don't allocate enough food for the coming year (about 15 bushels each), but if you give them too much the surplus is wasted. Each year's harvest depends on the amount of seed used, but planting more than two bushels per acre is wasteful as is allocating more than 25 bushels of seed to each of your subjects. The harvest is also subject to a large random factor (the weather). Rats can devastate your grain stores, and your kingdom is subject to plagues about every seventh year.

    10 REM HAMMURABI
    20 H=100;S=3000;A=1000;Y=0;@=0;P.$12
   100 P.'"O HAMMURABI, KING OF SUMARIA,"'
   120 P."YOUR SUBJECTS NOW NUMBER "H","'
   130 P."YOUR KINGDOM COVERS "A" ACRES,"'
   140 P."YOU HAVE "S" BUSHELS OF GRAIN."''
   200 L=20+RND%5;P."LAND IS "L" BUSHELS PER ACRE,"'
   210 INPUT"HOW MANY ACRES DO YOU BUY "E;IF E*L>S GOSUB a;G.210
   220 IF E>0 GOTO 260
   230 GOSUB a
   240 INPUT"HOW MANY ACRES DO YOU SELL"E;E=-E
   250 IF (-E)>A GOSUB a;GOTO 240
   260 A=A+E;S=S-L*E
   270 INPUT"HOW MANY BUSHELS FOR FOOD "F;IF F>S GOSUB a;GOTO 270
   280 S=S-F
   290 INPUT"HOW MANY BUSHELS FOR SEED "P;IF P>S GOSUBa;GOTO290
   300 S=S-P;IF P>2*A P=2*A
   310 IF P>25*H P=25*H
   320 R=ABSRND%(1+S/2);C=P/4+ABSRND%(1+P*4);S=S+C-R;D=H-F/15
   330 D=H-F/15;IF D<1 D=0
   340 H=H-D;N=H/20+ABSRND%(1+H/20);H=H+N
   350 Z=0;IF RND%4=3 Z=H/3+RND%(1+H/4)
   360 H=H-Z;Y=Y+1
   400 P.$12;FOR I=1 TO 50;WAIT;NEXT I
   410 P."O KING,I BEG TO REPORT THAT"'
   420 P."IN YEAR "Y" OF YOUR REIGN"'
   430 P."YOU HARVESTED "C" BUSHELS"'
   440 IF R>0 P."BUT RATS ATE "R" BUSHELS"'
   450 P.D" PEOPLE STARVED, "N" WERE BORN"'
   480 IF Z>0 P.Z" DIED OF PLAGUE"'
   490 IF H>0 GOTO 100
   500 P.''"AS YOU HAVE NO SUBJECTS LEFT,"'
   510 P."THIS IS THE END OF YOUR REIGN"'';END
  1000aP.$11$13"                                "$13$11;R.

Program Notes:

Line 20 sets up the initial values of H (population), S (grain in store), A (acres of land) and Y (year).

The main body of the program is lines 100 to 490, which are executed once for each year of your reign. Lines 100-140 report on the extent of your kingdom, lines 200-290 then ask for your decisions about the amounts of grain to be used for food and seed, each answer being quietly checked for validity and diplomatically ignored if you ask for the impossible (subroutine a being used to delete an erroneous entry from the screen and re-position the cursor; note that there should be exactly 32 spaces, between the quotation marks in line 1000). Lines 300-360 calculate the results for the year, in terms of R (bushels of grain eaten by rats), 0 (deaths from starvation), Z (deaths from plague) and N (births). If you have any subjects left after another year of misrule, the program then loops back to line 100.

Higher/Lower 

Text; 1K
VDU; ½K
Integer

Higher/Lower is played by one person against the computer. For each play the computer picks two numbers between 1 and 99, displays the first, then asks the player to bet on whether the second number is higher or lower than the first. Starting with a stake of £100, a really successful player can break the bank by amassing £10,000 or more. The game will also end if the player has no money left.

    10 REM HIGHER/LOWER
    20 @=0;P=100
   100 M=1+ABSRND%99;N=ABSRND%100;IF N=M GOTO 100
   110 P.$12"I HAVE CHOSEN TWO NUMBERS (0-99)"'
   120 P."THE FIRST IS "M''"IS THE SECOND NUMBER"'
   130 INPUT"HIGHER (H) OR LOWER (L) "$TOP
   140 IF CH$TOP<>CH"H" AND CH$TOP<>CH"L" GOTO 130
   150 P."YOU HAVE GOT "P" POUNDS,"'
   160 INPUT"HOW MUCH DO YOU BET "B;IF B>P OR B<0 GOTO 160
   200 P=P+B
   210 IF CH$TOP=CH"H" AND N<M P=P-2*B
   220 IF CH$TOP=CH"L" AND N>M P=P-2*B
   230 P.'"IT WAS "N'"YOU NOW HAVE "P" POUNDS"''
   240 IF P=0 P."*SORRY & GODBYE*"';END
   250 IF P>9999 P."CONGRATULATIONS - YOU'VE BROKEN THE BANK"';END
   300 INPUT"ANOTHER BET (Y/N) "$TOP;IF CH$TOP=CH"Y" GOTO 100
   310 END

Buzz-Word 

Text; 1K
VDU; ½K
Integer

An aid for the busy executive, Buzz-Word generates impressive sounding phrases for use in reports to higher management.

    10 PRINT$12"*** BUZZ-WORDS ***"''
    20 DIM A(10);N=5;D=#D
   100 X=?18*256
   110 PRINT'"YOUR PHRASE IS;"''
   120 Y=CH"a";GOSUB 500
   130 Y=CH"b";GOSUB 500
   140 Y=CH"c";GOSUB 500
   150 PRINT''"ANOTHER "
   160 INPUT $A
   170 IF ?A=CH"Y" GOTO 100
   180 END
   500 DO DO X=X+1;U.?X=D;U.X?3=Y
   510 X=X+3;Y=CH"*"
   520 FOR P=1 TO 1+ABSRND%N
   530  DO X=X+1;IF ?X=D X=X+3
   540  UNTIL ?X=Y
   550 NEXT P
   600 DO X=X+1;PRINT $?X
   610 UNTIL X?1=Y OR X?1=D
   620 PRINT" ";RETURN
  1000a*GLOBAL*PARALLEL*FEASIBLE
  1010 *LATERAL*STRUCTURED
  1100b*TOP-DOWN*INTEGRATED
  1110 *SILICON*PRAGMATIC*MODULAR
  1200c*CONCEPT*SCENARIO
  1210 *PROJECTION*EVENT*PHASE

Program Notes:

3 lists, each containing 5 words, are stored at the end of the program listing. Each list starts with a label (a, b or c), each word or phrase starts with a *. The program displays one word or phrase - chosen at random - from each list.

Othello 

Text; 3K
VDU; ½K
Integer

Othello is played between the computer (C) and its human opponent (H) on an 8 x 8 board. At the start of the game, each player has two pieces in the centre of the board.

H and C take turns to place a new piece in one of the vacant squares so as to 'capture' one or more opponent's pieces. Pieces are captured if they lie on a horizontal, vertical or diagonal line terminated at one end by the piece just placed, and at the other end by an existing piece belonging to the player making the move. Pieces captured change type to that of the player capturing them.

Each move must capture at least one piece, or else the player forfeits that move. The game ends when all 64 squares have been filled or when neither player can move. The winner is then the player with the most pieces.

The program displays the current scores and the state of the board after each move. The human player should enter his move as the row (1-8) and column (A-H) of the selected square (e.g. 8A), or he may forfeit his move by just pressing the Return key. The program will not accept invalid moves.

The algorithm used to calculate the computer's move is a fairly simple one, which allows the human player a reasonable chance of winning.

    10 REM OTHELLO
   100 M=1;H=8;C=3;DIM A(99),NN(7),B(9)
   110 NN(0)=11;NN(1)=10;NN(2)=9;NN(3)=1
   120 NN(4)=-1;NN(5)=-9;NN(6)=-10;NN(7)=-11
   130 P.$12;?#E1=0;P."        A B C D E F G H"'
   140 @=7;FOR I=1 TO 8;P.I" * * * * * * * *"';NEXT
   150 FOR I=0 TO 99;A?I=0;NEXT
   160 T=C;P=44;GOSUB a;P=55;GOSUB a
   170 T=H;P=45;GOSUB a;P=54;GOSUB a
   200 REM YOUR MOVE
   210 GOSUB b;IF ($B="" AND M=0) OR Y+Z=64 GOTO 900
   230 INPUT"YOUR TURN (E.G. 3D) "$B;IF $B="" GOTO 300
   240 IF ?B<CH"1" OR ?B>CH"8" OR B?1<CH"A" OR B?1>CH"H" GOTO 260
   250 P=(?B-CH"0")*10+B?1-CH"A"+1;T=H;F=0;GOSUB c;IF S>0 GOTO 270
   260 P.$11;GOSUB g;GOTO 230
   270 F=1;GOSUB c
   300 REM COMPUTER'S MOVE
   310 GOSUB b;IF ($B="" AND M=0) OR Y+Z=64 GOTO 900
   320 M=0;D=0;F=0;T=C;P."LET ME THINK ...."
   330 FOR U=1 TO 8;FOR V=1 TO 8;P=U+10*V;GOSUB c;IF S=0 GOTO 365
   340 IF U=1 OR V=8 S=S*2
   345 IF V=1 OR V=8 S=S*2
   350 IF U=2 OR U=7 OR V=2 OR V=7 S=S/2
   355 IF S=D D=D-ABSRND%2
   360 IF S>D D=S;M=P
   365 NEXT V;NEXT U
   370 GOSUB g;IF M>0 F=1;P=M;GOSUB c
   380 IF M=0 P."I CNA'T MOVE";FOR I=1 TO 25;WAIT;NEXT
   390 GOTO 200
   900 REM WRAP IT UP
   910 IF Y>Z P."YOU WON - CONGRATULATIONS"'
   920 IF Y=Z P."** A DRAW **"'
   930 IF Y<Z P."I WON - OF COURSE"'
   940 ?#E1=#80;END
  1000a REM PLACE PIECE
  1010 X=2*(P%10)+32*(P/10);X?#8006=128+X?#8006
  1020 FOR I=1 TO 30;WAIT;NEXT
  1030 A?P=T;X?#8006=T;RETURN
  2000b REM ADD SCORES
  2010 Y=0;Z=0
  2020 FOR I=11 TO 88
  2030 IF A?I=H Y=Y+1
  2040 IF A?I=C Z=Z+1
  2050 NEXT
  2060 P.$30;FOR I=1 TO 10;P.$10;NEXT
  2070 FOR I=1 TO 3;GOSUB g;P.$10;NEXT
  2080 FOR I=1 TO 3;P.$11;NEXT
  2090 @=0;P."YOU HAVE "Y", I HAVE "Z'';RETURN
  3000c REM EXAMINE POSITION & MOVE IF F=1
  3010 R=P;S=0;IF A?P<>0 RETURN
  3015 IF F=1 GOSUB a
  3020 FOR J=0 TO 7;Q=R;P=R;K=0
  3030d Q=Q+NN(J);IF A?Q=0 GOTO f
  3040 IF A?Q=T GOTO e
  3050 K=K+1;GOTO d
  3060e S=S+K;IF F=0 OR K<1 GOTO f
  3070 FOR L=1 TO K;P=P+NN(J);GOSUB a;NEXT
  3080f NEXT J;RETURN
  4000g REM CLEAR LINE
  4010 P.$13"                                "$11;RETURN

Program Notes:

There should be exactly 32 spaces between the quotation marks in line 4010.

By cutting out the REM statements and abbreviating wherever possible, Othello can be made to run in 2K of text RAM.

The 10 x 10 byte array A(99) is used to hold the current state of the board; each byte being either 0 (free square), H or C. A 10 x 10 array is used because by considering it to represent the 8 x 8 board plus an empty surrounding border no special treatment is needed for squares on the edge of the playing board when looking for possible moves. The variable P is used to represent the position being examined, and the array NN holds the 8 possible movements from P.

Lines 100-170 set the starting values and DRAW the board at the start of play.

Lines 200-270 get your move, check that it is valid, then update the displayed board image and the array A().

The computer calculates its best move in lines 300-390 by examining every possible position, then choosing that with the highest score S. Line 355 introduces a random element if two positions have equal scores. The algorithm used does not do any form of 'look-ahead' but just sums the number of enemy pieces that could be captured, then increases the score if the square being examined is on the edge of the board, or decreases the score if it is just one row or column away from the edge.

Number Guessing A 

Text; ½K
VDU; ½K
Integer

In this simple game, the computer picks a random number from 1 to 9, the player then has 5 chances to guess it. Unless the player has considerable ESP talent, he should only be able to win about half of the games played.

    10 REM NUMBER GUESSING A
    20 N=1+ABS(RND%9);@=0
    30 PRINT $12,"I AM THINKING OF"'
    40 PRINT "A NUMBER FROM 1 TO 9"'
    50 PRINT"YOU HAVE 5 GUESSES"''
   100 FOR G=1 TO 5;INPUT X
   110 IF X=N THEN GOTO 200
   120 PRINT $11,X," IS WRONG"'
   130 NEXT G
   140 PRINT'"IT WAS "N';END
   200 PRINT $7;WAIT;PRINT $7
   210 PRINT'"*** CORRECT ***"';END

Number Guessing B 

Text; ½K
VDU; ½K
Integer

This number guessing game gives the player 7 chances to guess a number from 1 to 99, but tells the player whether each guess was too high or too-low - which is enough information to allow the correct number to be deduced in every game.

    10 REM NUMBER GUESSING B
    20 N=1+ABS(RND%99);@=0
    30 PRINT $12,"I AM THINKING OF "'
    40 PRINT "A NUMBER FROM 1 TO 99"'
    50 PRINT "YOU HAVE 7 GUESSES."''
   100 FOR G=1 TO 7
   110 INPUT X;IF X=N THEN GOTO 200
   120 IF X<N THEN PRINT $11,X," IS TOO SMALL"'
   130 IF X>N THEN PRINT $11,X," IS TOO BIG"'
   140 NEXT G
   150 PRINT'"IT WAS ",N';END
   200 PRINT $7;WAIT;PRINT $7
   210 PRINT'"*** CORRECT ***"';END

Program Notes:

Line 20 chooses the number (N) and sets the print field width to zero for a neater display.

The PRINT $11 statements in lines 120 and 130 move the cursor back one line so that the comment 'IS TOO SMALL' or 'IS TOO BIG' appears on the same line as the entered value.

Line 200 generates the sound of success.

Hex Pawn 

Text; 3K
VDU; 1/2K
Integer

Hexpawn is a simple game played between the computer (C) and its human opponent (H) on a 3 x 3 board. It is interesting to the computer programmer as it has the right level of complexity to useful for experiments in computer 'learning' techniques. In the program given here, the computer remembers each board position (or pattern) that it encounters, and over the course of many games it learns the best move to make from each position. Given enough practice it can become very good.

As the player will soon notice, the program does not attempt to work out the best move to make from any new position, but just selects the first legal move that it can find. However, if that move results in the computer losing, then it will not play the move again if confronted by the same position in another game.

At the start of each game each player has three pieces; the computer's being along the top row of the board, the human player's being along the bottom row. The pieces are similar to chess pawns and may be moved straightforward to an empty square, or may be moved diagonally forward to take an opponent's piece. A player loses when he cannot move any of his pieces. The program assumes that its opponent knows how to play properly, and the computer will surrender if it finds itself in a position that it has learnt will always lead to defeat.

At the end of each game the computer will ask if you want to another. Note that if the program is actually stopped at any time by ESC, BREAK or by refusing the invitation to play another game, then re-starting it by typing RUN will make the computer forget all it has learned. Type GOTO 100 to avoid this.

    10 REM HEXPAWN
    20 DIM A(8),S(200),I(10);C=1;H=2
    30 FOR L=0 TO 200;S?L=0;NEXT L
   100 FOR R=1 TO 54321;P.$12;?#E1=0
   110 A?0=C;A?1=0;A?2=H;A?3=C;A?4=0;A?5=H;A?6=C;A?7=0;A?8=H
   120 P."        C C C      1 4 7"''
   130 P."        * * *      2 5 8"''
   140 P."        H H H      3 6 9"''''
   200 REM YOUR MOVE
   210 T=H;FOR M=10 TO 87
   220 IF M%10<9 GOSUB b;IF E=0 GOTO 240
   230 NEXT M;GOTO 800
   240 GOSUB a;INPUT"YOUR MOVE (FROM TO) "$I
   250 IF ?I<CH"1" OR ?I>CH"9" GOTO 240
   260 IF I?1<CH"1" OR I?1>CH"9" GOTO 240
   270 M=(?I-CH"1")*10+I?1-CH"1"
   280 GOSUB b;IF E>0 GOTO 240
   290 GOSUB c
   300 REM COMPUTERS MOVE; FIRST LOOK THROUGH S()
   310 GOSUB a;T=C;U=0;P."MY MOVE ..."'
   320 X=A?0+4*(A?1)+16*(A?2)+64
   330 Y=A?3+4*(A?4)+16*(A?5)+64
   340 Z=A?6+4*(A?7)+16*(A?8)+64
   350 V=S
   355e IF ?V>128 GOTO f
   360 IF ?V=0 GOTO 400
   370 IF ?V=X IF V?1=Y IF V?2=Z GOTO 500
   380 IF ?V=Z IF V?1=Y IF V?2=X U=1;GOTO 500
   385 V=V+2
   390f IF V<S+200 V=V+1;GOTO e
   395 P.'''"S() TOO SMALL";END
   400 REM ADD NEW ENTRY TO S()
   410 ?V=X;V?1=Y;V?2=Z;W=V+3;?W=0
   420 FOR M=1 TO 78;IF M%10<9 GOSUB b
   430 IF E=0 W?0=M+128;W?1=0;W=W+1
   440 NEXT M
   500 REM SELECT MOVE IF POSSIBLE
   510 V=V+3;IF ?V<128 GOTO 700
   520 M=?V-128; IF U=0 GOTO 600
   530 IF M/10<3 M=M+60
   540 IF M/10>5 M=M-60
   550 IF M%10<3 M=M+6
   560 IF M%10>5 M=M-6
   600 REM DO COMPUTER'S MOVE
   610 GOSUB c;L=V;GOTO 200
   700 REM DELETE LOSING MOVE & QUIT
   710 FOR V=L TO S+199;?V=V?1;NEXT V
   720 P.'"OK - YOU WIN"'';GOTO 900
   800 P."YOU CAN'T MOVE - I WIN"''
   900 INPUT"ANOTHER GAME "$I;IF ?I=CH"N" THEN ?#E1=#80;END
   910 NEXT R
  1000a REM CLEAR LINE
  1010 P.$11"                                "$11;RETURN
  2000 REM CHECK MOVE, E=0 IF OK
  2010b E=1;F=M/10;G=M%10;IF A?F<>T OR A?G=T RETURN
  2020 IF A?G>0 GOTO g
  2030 IF G=F-2*T+3 IF G/3=F/3 E=0
  2040 RETURN
  2050g IF G-F=4*T-6 IF G/3<>F/3 E=0;RETURN
  2060 IF G-F=12-8*T IF F<>2 IF F<>6 E=0
  2070 RETURN
  3000 REM MOVE PIECE
  3010c P=M/10;GOSUB d;?P=#2A
  3020 P=M%10;GOSUB d;?P=5*T-2
  3030 A?(M/10)=0;A?(M%10)=T;RETURN
  3100d P=#8008+P/3*2+P%3*64
  3110 ?P=?P+#80
  3120 FOR K=1 TO 30;WAIT;NEXT K;RETURN

Program Notes:

There should be exactly 32 spaces between the quotation marks in line 1010.

The current state of the board is held in the 9 byte vector A(), each byte being 0 (empty square), 1 (computer's piece) or 2 (human player's piece).

The 201-byte vector S() is used to hold previously encountered board positions and the possible moves which did not lead to disaster. Each board position is represented by three bytes, which give the states of the three columns of the board, each coded to have a value of 64 to 127 (as X, Y & Z in lines 320-340). These are followed by single byte representations of the possible moves (if any) from that position coded as values from 128 to 255 (see lines 430 & 520). The end of the list is signalled by a zero byte. When the computer finds itself in a losing position, it removes the move that lead to defeat from the list (line 710).

The learning process is simplified by allowing the computer to recognise 'reflections' of board positions - thus when searching the list to see if it has played from that position before line 380 sets U=1 if it finds the mirror image position, and lines 520 to 560 subsequently invert the move selected.

When a new position is encountered, it is added to the list by line 410, then the program examines all possible from that position and adds legal ones to the list (lines 420-440).

Drive! 

Text; 1K
VDU; ½K
Integer

Drive is a game in which you have to steer a rapidly moving object through a course that is gradually filled with white and grey squares. The grey squares represent the enemy targets; if you hit one it is destroyed and you gain a point. The white squares, however, are dangerous if you hit one it will explode, killing you and scattering potentially lethal debris. You can survive 3 'deaths' before the game ends - and gain an extra 'life' for every 10 grey blocks hit.

The REPT and SHIFT keys are used for steering, moving you up and down the screen respectively. When the game ends (because you have run out of 'lives') press the space bar to play another. While the game is in progress three numbers across the top of the screen show (from left to right) your current score of grey blocks zapped, the number of lives you have left, and the best score to date in previous games.

     1 REM- DRIVE 18-11-80
     2 REM- BY D. DINI
     4 G=0
     5 A=0;N=#8000;Z=32;M=3
    10 CLEAR 0
    15 DIM H(5);!H=#4081020;H!4=#102
    20 MOVE 0,2;DRAW 64,2;MOVE 0,42;DRAW 64,42
    25 PRINT $30,A,M,G
    30 Y=24;O=0;U=24
    40 FOR X=0 TO 63
    50 GOSUB p
    60 IF Q=0 THEN GOTO c
    70 IF ?P=#FF THEN ?P=#40;A=A+1;IF A%10=0 THEN M=M+1
    72 IF ?P=#40 THEN GOTO c
    75 GOTO e
    80cIF RND%5<>0 THEN GOTO j
    82 L=ABSRND%13+2
    85 S=N+L*Z+ABSRND%22+8
    88 IF (15-L)=Y/3 THEN GOTO j
    90 ?S=#FF;IF ABSRND%2=0 THEN ?S=#7F
   100jPLOT 15,O,U;PLOT 13,X,Y;O=X;U=Y
   102 IF ?#B001&#80=0THEN Y=Y-1
   104 IF ?#B002&#40=0 THEN Y=Y+1
   110 NEXT
   120 PLOT 15,O,U
   130 PRINT $30,A,M,G
   999 GOTO 30
  1000pP=X/2+(47-Y)/3*Z+N
  1010 Q=(?P&(H?(X&1+(47-Y)%3*2))<>0)
  1020 RETURN
  2000eMOVE X,Y;PLOT 0,-3,0;PLOT 2,6,0;PLOT 0,-3,3;PLOT 2,0,-6
  2010 PLOT 0,3,0;PLOT 2,-6,6;PLOT 0,6,0;PLOT 2,-6,-6
  2011 M=M-1;IF M<>0 THEN X=64;N.;G.25
  2015 IF A>G THEN G=A
  2020 PRINT $30,A,M,G
  2040 LINK #FFE3
  2045 X=64;NEXT
  2050 GOTO 5

Program Notes:

Abbreviations have been used wherever possible to fit the program into 1K text RAM.

Line 20 draws the top and bottom boundaries of the course.

The main body of the program is within the loop between lines 30 and 999. An inner loop (lines 40-110) moves the object across the screen, using subroutine p to check for collision with a white square, and line 70 to see if you have destroyed a grey one. The program branches to see if you are killed; to PLOT the debris from the explosion and to see if you have any lives left. If you are still alive, line 100 plots your new position, and lines 102,104 test the state of the SHIFT and REPT keys.

Biorythm 

Text; 2K
VDU; ½K
Integer

This program plots graphs of your physical (P), emotional (E) and intellectual (I) cycles for a four-week period.

As well as showing the ups and downs of your biological cycles, the graphs also warn of those critical days when a cycle is crossing through the centre line. For a finale, the program calculates how many days you have lived.

   100 P.$12"* ATOMIC BIORYTHM CALCULATER *"
   110 P.''"ENTER YOUR DATE OF BIRTH"''
   120 E=0;GOSUB 500;E=-E
   130 P.'"NOW ENTER TODAY'S DATE"''
   150 GOSUB 500;E=E-14
   200 P.$12;FOR I=1 TO 6;P.';NEXT;P." "
   210 FOR I=1 TO 4;P."!......";NEXT;P."!"'
   220 FOR I=1 TO 7;P.';NEXT
   230 P." PREV 2 WKS  TODAY  NEXT 2 WKS"'
   250 FOR I=0 TO 12;X=32*I+#800F;?X=#21;NEXT
   300 P=#10;C=23;GOSUB 600
   310 P=#5;C=28;GOSUB 600
   320 P=#9;C=33;GOSUB 600
   400 @=0;P."     YOU ARE "E+14" DAYS OLD"
   410 END
   500 REM GET # OF DAYS
   510 INPUT"YEAR "Y,"MONTH (1-12) "M,"DAY (1-31) "D
   515 E=E+D
   520 IF M>1 E=E+31;IF M>2 E=E+28
   525 IF M>3 E=E+31;IF M>4 E=E+30
   530 IF M>5 E=E+31;IF M>6 E=E+30
   535 IF M>7 E=E+31;IF M>8 E=E+31
   540 IF M>9 E=E+30;IF M>10 E=E+31
   545 IF M>11 E=E+30
   550 IF M>2 IF Y%4=0 IF Y%100<>0 E=E+1
   560 Y=Y-1800
   570 FOR I=0 TO Y-1;E=E+365
   580 IF I%4=0 IF I%100<>0 E=E+1
   590 NEXT;RETURN
   600 REM PLOT A CURVE
   610 FOR I=0 TO 28
   620 X=%(6.5*SIN(2*PI*(E+I)/C))
   630 X=#80C1-32*X+I;?X=P
   640 NEXT;RETURN

Program Notes:

The program is based on the assumption that your cycles follow sine-wave patterns with periods of 23, 28 and 33 days, starting from your date of birth.

Sums Tester 

Text; 2K
VDU; ½K
Integer

And now to prove that the computer has an educational value. Sums Tester provides an exercise in simple mental arithmetic by posing 10 questions to be answered in 60 seconds. The questions involve simple addition and subtraction of numbers from 1 to 99 (no negative answers), and multiplication and division using factors up to 12, and are chosen at random by the program.

If you don't finish within the time allowed, the test ends; in any case your score and the total time taken to answer are shown at the end of the test.

    10 REM SUMS TESTER
   100 DIM B(8),I(-1);S=0;T=60
   110 GOSUB a;!#80=-(T*60)
   120 $B="GOTO 700";?16=B;?17=B/256
   130 P.$12"YOU HAVE 10 QUESTIONS"'
   140 @=0;P."TO ANSWER IN "T" SECONDS"''
   200 FOR Q=1 TO 10;P."QUESTION "Q" IS ;"''
   300 GOSUB (1000+ABSRND%4*100)
   400 INPUT $I;IF $I="" P.$7;GOTO 400
   410 Z=0
   420 FOR P=0 TO LEN(I)-1
   430 IF I?P<CH"0" OR I?P>CH"9" P.$7;GOTO 400
   440 Z=I?P-CH"0"+10*Z
   450 NEXT P
   500 IF Z=R P.'"THAT'S RIGHT !";S=S+1;GOTO 520
   510 P.'"SORRY, BUT IT WOULD BE "R
   520 FOR A=1 TO 60;WAIT;NEXT
   530 P.$12;@=0
   540 NEXT Q
   600 P."YOUR SCORE WAS"'S" OUT OF 10"''
   610 E=T+(!#80)/60;P."IN "E" SECONDS"''
   620 IF S>8 P."CONGRATULATIONS ARE DUE"'
   630 IF S*T/E>10 P."WELL DONE"'
   640 ?#20A=?#A0;?#20B=?#A1;END
   700 P.&7$12;@=0;P."* NO MORE TIME *"'
   710 !#80=0;GOTO 600
  1000 X=2+ABSRND%98;Y=2+ABSRND%98
  1010 R=X+Y;P."WHAT IS "X" + "Y" ";RETURN
  1100 X=2+ABSRND%98;Y=2+ABSRND%98
  1110 IF Y+2>X GOTO 1100
  1120 R=X-Y;P."WHAT IS "X" - "Y" ";RETURN
  1200 X=2+ABSRND%11;X=2+ABSRND%11
  1210 R=X*Y;P."WHAT IS "X" TIMES "Y" ";RETURN
  1300 X=2+ABSRND%11;R=2+ABSRND%11
  1310 Y=X*R;P."WHAT IS "Y" DEVIDED BY "X" ";RETURN
  9000a P.$21;P=#84
  9010[ PHP;CLD;STX #E4;STY #E5
  9020 BIT #B002;BVC #94;JSR #21C;BCC #8A
  9030 JSR #FB8A;JSR #21C;BCS #97;JMP #FEA7;]
  9040 P=#21C
  9050[ JSR #FE66;INC #80;BNE #228
  9060 INC #81;BNE #228;BRK;JMP #FE71;]
  9070 ?#A0=?#20A;?#A1=?#20B
  9080 11/05/2019?#20A=#84;?#20B=0;P.$6;RETURN

Program Notes:

The program loops between lines 200 and 540 ten times; each time line 300 decides whether the question is to involve addition, subtraction, multiplication or division, and calls one of the subroutines starting at lines 1000, 1100, 1200 and 1300.

Lines 9000-9080 are two machine language routines similar, to those in the 'Keyboard Timeout' program given elsewhere in this book, which increment a counter (locations #80,#81) every 1/60th of a second while the program is waiting for an answer. The counter is preset to (-T) seconds at the start of the program by line 110. If the counter times out (by reaching zero), the machine-language routine executes a BRK instruction which - because of line 120 - makes the program jump immediately to line 700.

Lines 400-450 get the answer to each question as a string and convert that to a number if possible. If the input cannot be a number then the program goes back to line 400 to ask again. This approach is used in preference to a simple 'INPUT Z' because it prevents the program crashing if the user gives a non-numeric response (such as just pressing the Return key), and it also stops him cheating by for example answering "WHAT IS 63+38" by "63+38".

Scramble 

Text; 2K
VDU; ½K
Integer

Scramble is a computer version of the old sliding letter square puzzle, in which you have to re-arrange 24 letters in a 5 x5 board by moving one letter at a time into the empty square.

When the program is run, it first shows you the board with the letters in order. It then scrambles them according to the degree of difficulty you have chosen for the game. You then have to restore the board to its original ordered form in less than 100,000 moves.

    10 REM SCRAMBLE
   100 REM SET UP BOARD
   110 DIM DD(3),A(-1)
   120 DD(0)=-32;DD(1)=-1;DD(2)=1;DD(3)=32
   130 P.$12;X=#800D
   140 FOR I=1 TO 24;?X=I;X=X+1
   150 IF I%5=0 X=X+27
   160 NEXT;?X=#20
   200 REM INSTRUCTIONS
   210 FOR I=1 TO 6;P.$10;NEXT
   220 P."THIS PATTERN WILL BE SCRAMBLED."'
   230 P."YOU HAVE TO PUT IT BACK IN ORDER"
   240 P."BY MOVING ONE LETTER AT A TIME"'
   250 P."INTO A BLANK SQUARE."'
   260 P."YOU CAN ONLY MOVE A LETTER WHICH"
   270 P."IS VERTICALLY OR HORIZONTALLY"'
   280 P."NEXT TO THE BLANK SQUARE."''
   300 REM SCRAMBLE BOARD
   310 INPUT"DIFFICULTY (1-9) "D
   320 GOSUB a;P=0
   330 FOR R=1 TO D*5
   340 DO J=X+DD(ABSRND%4)
   350 UNTIL ?J<25 AND J<>P
   360 WAIT;?X=?J;?J=#20;P=X;X=J
   370 NEXT R
   400 REM GET MOVE
   410 FOR M=1 TO 9999
   420 DO P.$11"WHICH LETTER WILL YOU MOVE    "$8$8
   430 INPUT $A;B=?A-#40;P=0
   440 FOR I=0 TO 3;IF X?DD(I)=B P=X+DD(I)
   450 NEXT
   460 UNTIL P>0 AND B>0 AND B<26
   470 ?P=?P+#80
   475 FOR I=1 TO 30;WAIT;NEXT
   480 ?P=#20;?X=B+#80
   485 FOR I=1 TO 30;WAIT;NEXT
   490 ?X=B;X=P
   500 REM GAME OVER ?
   510 B=#800C
   520 FOR I=1 TO 24;IF B?I<>I GOTO 600
   530 IF I%5=0 B=B+27
   540 NEXT I
   550 GOSUB a;@=0
   560 P."AT LAST; YOU MADE IT"'
   570 P."IN "M" MOVES"'
   580 END
   600 NEXT M
   900a REM CLEAR BOTTOM OF SCREEN
   905 P.$30;B=#20202020
   920 FOR I=#80A0 TO #81FC STEP 4;!I=B;NEXT
   930 FOR I=1 TO 7;P.$10;NEXT;RETURN

Program Notes:

The letters are stored directly in the appropriate VDU RAM locations, lines 130-160 set up the initial (ordered) board with the letters A-X and a blank position.

Lines 300-370 then 'scramble' the board by making 5xD moves (D being the degree of difficulty chosen for the game); the array DD(3) being used to hold the four possible movements from any position J. Line 350 checks that the computer does not attempt to move outside of the playing area, and that it does not attempt to move the same piece two times running when scrambling the board.

Lines 420-460 get your move and check that it is legal. Lines 470-490 then make your move on the screen, highlighting the positions you are moving between, then lines 500-540 see if you have put the board back into its correct order. If not, the program branches to line 600 and so back for your next move.

Lines 900-930 form a subroutine which is used to clear the bottom part of the screen and re-position the text cursor ready for the next move.

Designs 

Text; 1k
VDU; 6K
Integer

Three short programs that use the highest resolution graphics mode to generate attractive moiré patterns each program can produce a number of different designs, a fresh one being drawn each time a key is pressed.

    10 REM DESIGN #1
   100 CLEAR 4;Z=6;S=2+ABSRND%4
   110 A=127+RND%100;B=95+RND%75
   120 FOR X=1 TO 255 STEP S
   130 PLOT 4,X,0;PLOT Z,A,B;PLOT Z,(255-X),191
   140 NEXT
   150 FOR Y=1 TO 191 STEP S
   160 PLOT 4,255,Y;PLOT Z,A,B;PLOT Z,0,(191-Y)
   170 NEXT
   180 LINK #FFE3;RUN

    10 REM DESIGN #2
   100 CLEAR 4;Z=6;S=1+ABSRND%4
   110 FOR Y=0 TO 191 STEP S;MOVE 0,Y
   120 PLOT Z,127,0;PLOT Z,255,Y;NEXT
   125 S=1+ABSRND%4
   130 S=1+ABSRND%4
   140 FOR X=0 TO 127 STEP S;MOVE X,191
   150 PLOT Z,127,0;PLOT Z,(255-X),191;NEXT
   160 LINK #FFE3;RUN

    10 REM DESIGN #3
   100 CLEAR4;Z=6;S=1+ABSRND%15
   110 FOR Y=0 TO 191 STEP S
   120 MOVE 0,0;PLOT Z,255,Y
   130 MOVE 255,0;PLOT Z,0,Y;NEXT
   140 S=2+ABSRND%15
   150 FOR X=0 TO ABSRND%5*32+127 STEP S
   160 MOVE 0,0;PLOT Z,(255-X),191
   170 MOVE 255,0;PLOT Z,X,191;NEXT
   180 LINK #FFE3;RUN

Hunt the Wampus 

Text; 4K
VDU ½K
Integer

This is a game for the brave and adventurous. You are hunting the dread Wampus, in the pitch-black depths of his cave kingdom, armed only with a bow and five arrows. Super strong bats also inhabit the caves, and though they will not harm you directly, they may make you lose the trail by carrying you off to another cave - and that might be the one with the bottomless pit! Good hunting, and don't run out of arrows.

     1 REM WAMPUS. BY T.MABBS
     5 P.$15
    10 P.$12"hunt the wampus"''"YOU ARE IN A NETWORK OF 20 CAVES"'
    20 P."THE WAMPUS IS IN ONE CAVE, YOU"'
    30 P."HAVE 5 ARROWS TO SHOOT AT HIM,"'
    35 P."YOU MAY THROUGH 1 OR 2"'"CAVES PER SHOT."''
    40 P."ALSO IN THE CAVES ARE A COLONY"'
    45 P."OF SUPERBATS, AND A BOTTOMLESS  PIT!!"''
    50 P."any key to continue";LINK #FFE3;P.$12
    55 P."IF THE SUPERBATS GET YOU, THEY"'
    60 P."TAKE YOU TO ANOTHER CAVE."''
    65 P."IF YOU FALL INTO A PIT, YOU LOSE"''
    70 P."IF YOU MEET THE WAMPUS, HE MAY"'
    72 P."MOVE TO THE NEXT CAVE, OR HE"'"MAY EAT YOU."''
    75 P."any key to continue";LINK #FFE3;P.$12
    77 P."""I SMELL THE WAMPUS"" MEANS THE"'
    78 P."WAMPUS IS IN THE NEXT CAVE."''
    79 P."""I FEEL A DRAFT"" MEANS A"'"BOTTOMLESS PIT."''
    80 P."""I HEAR WINGFLAPS"" MEANS"'"SUPERBATS."''
    85 P."GOOD LUCK!!!!"''"press any key to start";LINK #FFE3
    90 DIM AA(6),BB(20),Q(5);D=5
   100 X=ABSRND%19+1;Y=ABSRND%19+1;Z=ABSRND%19+1;P.$12;@=0;F=5
   105 IF X=Y OR X=Z X=ABSRND%19+1;G.105
   106 IF Y=Z Y=ABSRND%19+1;G.106
   110 W=ABSRND%19+1
   120 FOR T=1 TO 32;P."-";N.;P."YOU ARE IN CAVE "W'
   125 GOS.130;G.230
   130 S=W-1;IF S=0 S=20
   140 U=W+1;IF U=21 U=1
   150 V=W+10;IF V>20 V=V-20
   225 R.
   230 P."YOU CAN MOVE INTO CAVES"'S", "U", OR "V'
   231 P."SHOOT(1) OR MOVE(2)"'
   235 ?#B000=2;IF ?#B001=#FD THEN T=1;G.250
   240 ?#B000=1;IF ?#B001=#FD THEN T=2;G.250
   245 G.235
   250 IF T=1 P."shoot"';G.600
   260 P."move"'
   270 IN."MOVE TO"T;IF T<>S IF T<>U IF T<>V G.270
   280 W=T;GOS.130
   290 IF X=S OR X=U OR X=V P."I SMELL A WAMPUS!!"'
   300 IF Y=S OR Y=U OR Y=V P."I HEAR WINGFLAPS!!"'
   310 IF Z=S OR Z=U OR Z=V P."I FEEL A DRAFT!!"'
   320 IF Z=W P.$12"AAAAHHHHHHHH!!"';FOR T=1 TO 100;WAIT;N.;G.5000
   330 IF Y=W G.340
   335 G.400
   340 T=ABSRND%5+15;P.$12;?#E1=0;?#8000=#20
   345 FOR P=1 TO T
   350 L=ABSRND%#1FF+#8000;?#DE=L;?#DF=(L/255)
   351 BB(P)=L;N=0
   352 FOR M=1 TO 8;IF ?(BB(P)+M)<>#20 M=8;N.;N.;N=1;G.354
   353 N.
   354 P."FLAP!!";WAIT;WAIT;WAIT;WAIT;WAIT;WAIT;WAIT
   355 IF N=1 G.360
   356 N.
   360 F.T=1 TO 100;WAIT;N.;P.$12;F.T=1 TO 6;P.$10;N.;W=ABSRND%8+1
   370 ?#E1=#80;P."        SUPERBATSNATCHED!!"';G.110
   400 IF X<>W G.120
   410 P."YOU HAVE DISTURBED THE WAMPUS!!"';T=ABSRND%10
   420 IF T=1 OR T=4 X=S;IF X=Y OR X=Z X=X+1;G.500
   430 IF T=2 OR T=5 X=U;IF X=Y OR X=Z X=X+1;G.500
   440 IF T=3 OR T=6 X=V;IF X=Y OR X=Z X=X+1;G.500
   445 IF T<>5 G.120
   450 P.$12"THE WAMPUS HAS EATEN YOU!!";FOR T=1 TO 100;WAIT;N.
   460 G.5000
   500 G.120
   600 IN."THROUGH HOW MANY CAVES"C;IFC<1ORC>2P."MUSCLES"';G.600
   601 E=W
   602 F.T=1 TO C;P."SHOOTING THROUGH CAVE"'S", "U" OR "V
   603 IN.G;AA(T)=G
   605 IFAA(T)<>U IFAA(T)<>V IFAA(T)<>S P."I'M NOT BIONIC!"';G.603
   607 W=G;GOS.130
   618 N.
   619 W=E
   620 FOR T=1 TO C;G=AA(T)
   630 IF X=G THEN T=11;N.;G.700
   640 IF W=G THEN T=11;N.;G.800
   650 P."********BOIIIING!!*****"';N.;D=D-1;IF D=0 G.900
   660 G.120
   700 P.$12"YOU GOT THE WAMPUS,"'
   710 P."BUT THE WAMPUS'LL GETCHA NEXT"'"TIME!!!!!!!!"';G.5030
   800 P.$12"UUNNNNNGGGHH!!!!"'"YOU SHOT YOURSELF!!";F.T=1 TO 100
   810 WAIT;N.;G.5000
   900 P.$12"YOU EXHAUSTED YOUR SUPPLIES"'"OF ARROWS!!!!"'
   910 FOR T=1 TO 100;WAIT;N.;G.5000
  5000 P.$12"YOU LOST!"';IN."AGAIN(YES OR NO)"$Q
  5010 IF $Q="NO" OR $Q="N" E.
  5020 IF $Q="YES" OR $Q="Y" G.5040
  5030 IN."AGAIN(YES OR NO)"$Q;G.5010
  5040 IN."SAME SETUP(YES OR NO)"$Q
  5045 IF $Q="YES" OR $Q="Y" P.$12;G.110
  5050 IF $Q="NO" OR $Q="N" G.100
  5060 G.5040

Program Notes:

The body of the program is the loop from lines 120 to 400. Lines 120-230 show which cave you are in (W), and which you can move to (S,U,V). Lines 231,245 directly examine the keyboard keys 1 and 2 to see if you want to shoot or move to another cave. If you decide to move, lines 260-270 find out which cave you want to move to and check that this is possible.

Having moved you, the program then uses lines 290-310 to warn you of any dangers lurking in adjacent caves (X is the cave occupied by the Wampus, Y that infested by superbats, and Z is that without a floor). If you had entered the cave of the bottomless pit, line 320 drops you in it. Lines 340-370 activate the bats when you intrude upon them. If the Wampus is next door, lines 410-450 decide whether he will eat you or merely move away.

When you decide to shoot, lines 600-618 find out which caves you will shoot through - and note them in AA(). Lines 619-910 then tell you what - if any - effect your shot has had.

Simon 

Text; 1k
VDU; ½K
Integer

The Simon of legend said "Do what I do". In this musically accompanied game, ATOM says "Remember the sequence of letters I flash onto the screen, then press the same sequence of keys". If you do well, ATOM will gradually increase the number of letters displayed each time, but if you consistently fail to remember, then ATOM will give up in disgust.

    10 REM SIMON
   100 DIM S(10),R(-1)
   110 N=5;B=0;P=#81;;P.$21
   120[;LDA #B002;LDY @#FF;LDX #80;DEX;BNE P-1
   130 EOR @4;STA #B002;DEY;BNE P-11;RTS
   140];P.$6
   200 DO;P.$12;@=0;?#E1=0
   210 P."THIS TIME, SIMON GIVES YOU "N
   215 P.'"LETTERS TO REMEMBER ;"''
   220 FOR L=0 TO N-1;T=65+ABSRND%26
   230 S?L=T;?#806C=T-64;?#80=160-L*8;LINK#81
   240 FOR I=1 TO 30;WAIT;N.;?#806C=#40
   250 FOR I=1 TO 30;WAIT;N.;N.L;S?N=13
   300 IN.'"THEY WERE ; "$R;IF $R=$S G.340
   310 P."NO - THEY WERE ; "
   320 FOR L=0 TO N-1;P.$S?L;?#80=?#80+8
   330 LINK#81;WAIT;N.;B=B-1;G.350
   340 P."CORRECT !"';LINK#81;WAIT;LINK#81;B=B+1
   350 IF B=2;N=N+1;B=0
   360 IF B=-2;N=N-1;B=0
   370 IF N=2 P.''"ABYSMAL !!!"';G.500
   380 INPUT''"ANOTHER "$R;IF ?R=CH"N" G.500
   390 UNTIL N=10
   400 P."WELL DONE, I GIVE UP"'
   500 ?#E1=#80;END

Program Notes:

A small machine language routine (lines 120-140) is used to provide the musical accompaniment by generating a short note of a pitch determined by the value put into the RAM location 80.

The main body of the program is the loop through lines 200 to 390, an inner loop (lines 220-250) chooses and displays the sequence of N letters, saving them as the string $S. If the player answers incorrectly, lines 320-330 show him what he should have entered.

Screens 

Text; 2K
VDU; 2-6K
Integer

This program is useful as a lecture aid, as an advertising gimmick, or as an auto-banner for Computer Lib demonstrations, as it allows you to create a number of text 'screens' in RAM, to edit them as required, and to play them through at any rate. It will also save the screens to a tape file, and subsequently load them back into RAM.

The number of screens that can be used is limited by the amount of VDU RAM available; the minimum useable amount of 2K bytes gives 3 screens - while an ATOM fitted with the full 6K bytes of VDU RAM can handle 11 screens.

When the program is first run the screens are cleared, then a 'menu' is presented. You may then enter;

    10 REM SCREENS
    50 DIMG8,Z-1;GOS.9000
   100 S=-1;X=#8000;C=#20202020;W=0
   110 DOX?512=#AA;X?513=#55
   120 F.I=0TO511STEP4;X!I=C;N.
   130 X=X+512;S=S+1
   140 U.?X<>#AAORX?1<>#55
   200 P.$12;@=2;P."ENTER ;"''
   210 P."1-"S" TO EDIT SCREENS"'
   220 P." P   TO PLAY SCREENS"'
   230 P." S   TO SAVE ON TAPE'"'
   240 P." L   TO LOAD FROM TAPE"'
   250 P." E   TO END"''
   260 IN.$Z
   265 IF$Z="P"G.2000
   270 IF$Z="S"G.3000
   275 IF$Z="L"G.4000
   280 IF$Z="E"E.
   285 GOS.6000
   288 IFT>0AND T<(S+1)G.1000
   290 P.$11;G.260
  1000 D=512*T;W=1
  1010 F.I=#8000TO#81FFSTEP4;!I=I!D;N.
  1020 !#DE=#80008000;?#8000=(?#8000+#80)&#FF
  1030aLI.#FFE6;G.a
  2000 IN."SCREENS 1-"$Z;GOS.6000
  2010 IFT<1ORT>S P.$11$11;G.2000
  2020 E=T
  2030 IN."TIME FOR EACH (SECONDS) "$Z
  2040 GOS.6000
  2050 K=T
  2060 IN."NUMBER OF CYCLES "$Z
  2070 GOS.6000
  2100 F.L=1TO T
  2110 F.F=1TO E;D=512*F
  2120 F.I=#8000TO#81FFSTEP4;!I=I!D;N.
  2130 F.H=0TO60*K;WAIT;N.
  2140 N.F
  2150 N.L;G.200
  3000 IN.'"SCREENS 1-"$Z;GOS.6000
  3010 IFT<1ORT>S P.$11$11;G.3000
  3020 IN."FILENAME "$Z
  3030 T=#8200+512*T;X=#A0
  3040 !X=Z;X!2=#8200;X!6=#8200
  3050 X?8=T;X?9=T/256
  3060 LI.#FFDD;G.200
  4000 IN."FILENAME "$Z
  4010 T=#8200+512*T;X=#A0;!X=Z;X!2=#8200
  4020 LI.#FFE0;G.200
  6000 T=0;J=0
  6010bIFZ?J<CH"0"ORZ?J>CH"9"R.
  6020 T=10*T+Z?J-CH"0";J=J+1;G.b
  8000 D=?#DE+?#DF*256+?#E0;?D=(?D+#80)&#FF
  8020 D=512*T
  8030 F.I=#8000TO#81FFSTEP4;I!D=!I;N.
  8040 W=0;G.200
  9000 P=#80;P.$21
  9010[;LDA@0;STA#B000;JSR#FE94
  9020 PHA;LDA@#A;STA#B000;PLA
  9030 CMP@#1B;BEQP+3;RTS;BRK
  9040]
  9050 P.$6;?#20A=#80;?#20B=0
  9060 $G="GOTO8000";?16=G&#FF;?17=G&#FFFF/256
  9070 R.

Program Notes:

When the program is started it calls the subroutine at line 9000 which modifies ATOM's normal keyboard read and BRK routines so that pressing the ESC key does not stop the program, but makes it jump to line 8000 instead

The screens are stored in the VDU RAM space above 81FF, this area being otherwise unused when the VDU is in text mode. Lines 100-140 fill this area with the VDU 'space' code and also count the number (S) of 512 byte blocks available for use as screens.

Lines 200-295 present the menu - and refuse to accept anything except a valid response from the user. If a screen number is entered the program jumps to line 1000 with T equal to the number of the selected screen. This screen is then copied into the visible area of the VDU RAM space (8000 - 81FF) by lines 1000, 1010 and the cursor positioned at the top left corner by line

1020. Line 1030 allows you to type onto the screen by repeatedly calling the (now modified) Operating System OSECHO routine.

Lines 2000-2150 are executed if you have chosen to Play through the screens; line 2120 being used to bring the appropriate screen into the viewing area.

Lines 3000-3060 save selected screens as a file on tape by using the Operating System OSSAVE routine - after getting the new file's name and setting up the appropriate data for the OSSAVE routine (lines 3020-3050). Lines 4000-4020 similarly use the OSLOAD routine to load a tape rile of screens into RAM.

Lines 6000-6020 are a subroutine which is used to convert an input string $Z to a number Z; if $Z cannot be interpreted as a number then the subroutine returns T as 0.

When the ESC key is pressed the program jumps to lines 8000-8030 which remove the cursor (line 8000), then if the program had been in Edit mode, the screen is saved in the appropriate area of RAM before branching back to line 200 to display the menu.

Hangman 

Text; 2K
VDU; ½K
Integer

This is a computerised version of the word guessing game; Hangman. The computer picks a word, shows you how many letters it has, and then you try to guess the letters one at a time. If the letter you choose is in the word, the computer shows you where, but it you are wrong then the computer starts to hang you. For each mistake, the computer fills in part of a drawing of you dangling from a gallows. The ninth mistake is fatal.

     1 REM HANGMAN
    10 DIM W(20),R(1);N=10
    20 CLEAR 0;GOTO 100
    50a*CAMBRIDGE*ATOM*FIEND*SLAYS
    51 *FOREIGN*MICRO*DURING*PIZZA
    52 *EATING*COMPETITION
   100 X=?18*256;D=#D;Y=CH"a"
   110 DO DO X=X+1;UNTIL ?X=D;UNTIL X?3=Y
   120 X=X+3;Y=CH"*"
   130 FOR P=1 TO ABSRND%N
   140 DO X=X+1;IF ?X=D X=X+3
   150 UNTIL ?X=Y;X=X+1
   160 NEXT P;Z=0
   170 DO W?Z=X?Z;Z=Z+1
   180 UNTIL X?Z=D OR X?Z=Y OR X?Z=CH" "
   190 W?Z=D
   200 FOR X=1 TO LEN(W);X?#80F0=#2E;NEXT
   210 MOVE 0,9;DRAW 24,9
   220 E=0
   300 DO !#DE=#81C0
   310 P."LETTER     "$8$8$8;INPUT $R
   320 UNTIL ?R>CH"@" AND ?R<CH"["
   400 X=1
   410 IF X?#80F0=#2E IF ?R=W?(X-1) GOTO 600
   420 IF X<LEN(W) X=X+1;GOTO 410
   430 GOSUB (1000+100*E);E=E+1
   440 IF E<10 GOTO 300
   500 !#DE=#8111;P.$W
   510 !#DE=#81C0;P."<** YOU ARE dead !!! **"
   520 ?#E1=#80;END
   530 END
   600 X?#80F0=?R-#40;C=0
   610 FOR X=1 TO LEN(W)
   620 IF X?#80F0=#2E C=1
   630 NEXT X;IF C=1 GOTO 300
   700 CLEAR 0;MOVE 16,40
   710 GOSUB 1400;GOSUB 1500;GOSUB 1600
   720 GOSUB 1700;GOSUB 1800
   730 MOVE 16,32;DRAW 24,40
   740 MOVE 0,8;DRAW 63,8
   750 !#DE=#80F1;P.$W
   760 !#DE=#81C0;P."<** A REPRIEVE !! ** "
   770 ?#E1=#80;END
  1000 MOVE 0,6;DRAW 0,47;RETURN
  1100 MOVE 0,38;DRAW 9,47;RETURN
  1200 MOVE 0,47;DRAW 16,47;RETURN
  1300 DRAW 16,40;RETURN
  1400 DRAW 14,40;DRAW 14,36;DRAW 18,36
  1410 DRAW 18,40;DRAW 16,40;RETURN
  1500 MOVE 16,36;DRAW 16,24;RETURN
  1600 DRAW 8,10;RETURN
  1700 MOVE 16,24;DRAW 24,10;RETURN
  1800 MOVE 16,32;DRAW 8,40;RETURN
  1900 MOVE 3,9;PLOT 7,24,9
  1910 MOVE 8,10;PLOT 6,16,24;PLOT 6,24,10
  1920 MOVE 14,8;DRAW 16,24;MOVE 18,8;DRAW 16,24
  1930 MOVE 8,40;PLOT 6,16,32;DRAW 13,22
  1940 MOVE 16,32;DRAW 19,22;RETURN

Program Notes:

The list of words used is stored in lines 50-52, and may be changed as long as each word is preceded by a *, and N (line 10) is made equal to the number of words in the list.

When the program is run, lines 100-120 look through the text area for the * immediately following the label a. Lines 130-160 then search for the start of a randomly chosen word, and lines 170-190 copy it as a string into the byte vector W. Lines 200-220 put a line of dots onto the screen, corresponding to the number of letters in the word, and draw the stage of the gallows.

The body of the program is the loop through lines 300-440, which gets the letter you have chosen, then sees if it is in the word (lines 400-420). If it isn't, then lines 430,440 draw the next stage of your execution and - if you are still alive - go back to line 300 for your next guess. After the ninth mistake, lines 500-530 declare you dead. Note line 300, which sets the text cursor position to the start of the 14th line and turns the cursor off.

If you have guessed a letter correctly, lines 600-630 display it and see if you have completed the word. If so, your reprieve is granted via lines 700-770, if not then back to line 300.

Lines 1000-1940 are a series of subroutines used to draw various parts.

Programming Tips 

Unlisting

In some circumstances you may wish to allow people to run your program, but not to list it - to hide your programming technique or to protect a password or other sensitive data within the program. Unfortunately a determined programmer can break any software safeguards if he has total control of the machine - as with ATOM - but it is possible to make it difficult enough to discourage the merely curious, or those with little time to spare.

The basic technique is to insert those ASCII codes that turn off the printer and VDU into REM statements so that they have no effect when the program is run, but prevent the later lines from being shown when the LIST command is given. Thus, if you have a completed, tested program ready for added protection type;

     1 REM CTRL-L CTRL-U CTRL-C RETURN

(do it carefully, the screen will not show anything after the REM statement).

Then press BREAK, and enter OLD to restore the VDU to normal use. You should now be able to run the program as before, but not list it out on the VDU or printer.

Machine Language to BASIC

Although it is easy enough to call a machine language routine from a BASIC program by using the LINK command, there are occasions when it would be useful if a short BASIC routine could be called from a machine language program - for example to generate a random number with BASIC's RND function. It can be done if the RAM locations 5 & 6 are loaded with the address of the start of the BASIC routine (low byte in 5, high byte in 6), then a JSR #C2F2 is executed. At the end of the BASIC routine, a suitable LINK instruction will return control to the remainder of the machine language routine.

Autostart

If a BASIC program is saved on tape by using the COS command

*SAVE "FILENAME" START END CE86

Where START is the text space start address (2900 or 8200), and END is the (hex) address of the end of the program (obtained by typing P.&TOP), then you will subsequently be able to LOAD the program, and RUN it as normally, but the command

*RUN "FILENAME"

will fetch the program from tape, and run it automatically as soon as it has loaded.

Chaining

It is possible for a BASIC program to load and run another program from tape - the original program being deleted from RAM in the process - if the second program is saved as an 'autostart' program.

Thus, in the example given below, two programs are entered and saved on tape, the second in autostart mode, then the first one is loaded and run. Program 1 then automatically loads and runs the second program.

    10 REM PROG 1
    20 PRINT "THIS IS PROGRAM 1"'
    30 *RUN "PROG 2"
  >
  >P.&TOP
      293F>
  >*SAVE "PROG 1" 2900 293F CE86
  RECORD TAPE
  >
  >NEW
  >10 REM PROG 2
  >20 PRINT "THIS IS PROGRAM 2"'
  >30 END
  >
  >P.&TOP
      2935>
  >*SAVE "PROG 2" 2900 2935 CE86
  RECORD TAPE
  >*RUN "PROG 1"
  PLAY TAPE
  THIS IS PROGRAM 1
  PLAY TAPE
  THIS IS PROGRAM 2
  >

FOR - - NEXT/ DO - - UNTIL CRASHES

Repeatedly branching out of a FOR ... NEXT loop (or a DO ... UNTIL loop) can cause a program to 'crash', giving error code 18 or 111. For example, the two programs given below should both print out indefinitely, but they both crash after 11 *'s.

    10 REM
    20 X=1
    30 DO
    40 X=X+1
    50 IF X=5 GOTO 70
    60 UNTIL X=0
    70 PRINT '*'
    80 GOTO 10
  RUN
  ERROR 18 LINE   30
    10 REM START
    20 FOR I-1 TO 10
    30 IF I=5 GOTO 50
    40 NEXT I
    50  PRINT '*'
    60 GOTO 10
  >RUN
  ***********
  ERROR 111 LINE  20

The reason is that on entering a FOR ... NEXT loop (or a DO UNTIL loop), ATOM BASIC puts details of the loop onto a stack, and pulls them from the stack when it finally exits via the NEXT or UNTIL statement. However, jumping out of the middle of the loop leaves the data still on the stack, which can eventually fill up and cause the program to crash.

In the case of the DO … UNTIL loop, there is no way around the problem, so programs should avoid having to branch out of DO UNTIL loops. FOR … NEXT loops, however, will not cause a crash if an outer FOR ... NEXT loop (which is not jumped out of) can be included so that the NEXT of the outer loop is reached before the stack has filled. Thus in the example given below, the addition of the loop involving lines 10 and 60 prevents the overall program from crashing. The reason for this recovery is that the data relating to the outer loop is put onto the stack first, so on encountering the outer NEXT statement in line 60, ATOM BASIC cleans-up the stack, removing the irrelevant data left from the inner loop. For a practical example, see the program "SCRAMBLE", where lines 410,600 prevent the inner loop between lines 520 and 540 from crashing the program after several moves.

    10 FOR K=1 TO 30
    20 FOR 1=1 TO 10
    30 IF 1=5 GOTO 50
    40 NEXT I
    50 PRINT '*'
    60 NEXT K
    70 END
  >RUN
  ******************************>

Reading a Single Keystroke

In some cases it would be convenient if the program could read a single keystroke, without the user having to press the Return key. The following example program does this by using a machine language routine to wait for a keystroke then place the appropriate ASCII code in location 80 before returning to the BASIC program which then displays the ASCII code.

     1 REM KEYPRESS DEMO
    10 DIM P(-1)
    20[JSR #FFE6;STA #80;RTS;]
   100 PRINT"PRESS A KEY; "'
   110 LINK TOP
   120 PRINT" CODE =    "?#80
   130 GOTO 100

As it stands, the routine will display the character corresponding to the key pressed. To prevent this 'echo' change line 20 to;

    20[JSR #FFE3;STA #80;RTS;]

Preventing Escapes

Atomic Theory and Practice suggests that to prevent operation of the ESC key from halting a program, you use ?#B000=10. This is because, when the program is running, the low four bits of the 8255 port B000 are normally set to 0 to allow the BASIC interpreter to examine the state of the ESC key by simply looking at bit 5 of B001; setting B000 to 10 means that B001 bit 5 no longer is connected to any of the keys.

Unfortunately, if the program requires an INPUT from the user, then each time a character is read from the keyboard, the keyboard scan routine resets the low four bits of B000 to zero. To overcome this, and so provide a more foolproof method of disabling the ESC Key, we should also modify the OSRDCH routine so that B000 is set to 10 after each character has been read. This can be done by placing a routine such as that listed below at the start of the program;

    10 P=#80;P.$21
    20[LDA @0; STA#B000;JSR #FE94
    30 CMP @#1B;BNE P+4;LDA @#20
    40 PHA;LDA @10;STA #B000;PLA;RTS;]
    50 P.$6;?#20A=#80;?#20B=0;?#B000=10

Lines 20-40 are a machine language routine which is substituted for OSRDCH by changing the vector at 20A & 20B. Line 20 reads a character from the keyboard, using the (undocumented) COS routine at FE94, line 30 then checks to see if it is ESC, and if

so changes the code to that for 'space', line 40 resets B000 to 10. As well as changing the vector, line 50 also sets B000 to 10 before anything else happens. Note that certain control codes (e.g. that generated by PRINT $6) or a CLEAR will reset the low four bits of B000 to zero.

Packing

If you have to store a lot of alphanumeric data in RAM or on tape, and if you can do without the inverse (lower case) characters and the control codes, then it is possible to increase the number of characters that can be stored in a given area by converting each ASCII character to a 6-bit code, then packing 4 characters into 3 bytes.

The demonstration program below use lines 100-180 to pack the 16-character string $A into the 12 byte vector P(), then lines 400-480 reverse the process to restore the original form of $A.

    10 REM PACKING DEMO
    20 DIM A(16),P(11)
    30 $A="ABCDEF0123156789"
   100 Y=A
   110 FOR X=P TO (P+11) STEP 3
   120 Z=0
   130 FOR Q=0 TO 3;Z=Z*#40+Y?Q-#20
   140 NEXT Q
   150 FOR Q=0 TO 2;X?Q=Z%256;Z=Z/256
   160 NEXT Q
   170 Y=Y+4
   180 NEXT X
   200 @=0;P.$12$A''"PACKS TO (HEX)"'
   210 FOR X=P TO P+11;P.&?X" ";NEXT X
   300 $A = " ";REM DESTROY THE EVIDENCE
   400 Y=A
   410 FOR X=P TO (P+11) STEP 5
   420 Z=0
   430 FOR Q=2 TO 0 STEP -1;Z=Z*256+X?Q
   410 NEXT P
   450 FOR Q=3 TO 0 STEP 1;Y?Q=Z%#40+#20;Z=Z/#40
   460 NEXT Q
   470 Y=Y+4
   480 NEXT X
   500 P.''"AND UNPACKS TO; "''
   510 END

If a control code such as CR is essential, then it could be substituted for one of the less-used alphanumerics such as ASCII codes 5B-5F.

A similar technique can he used to pack two BCD digits into a single byte for data storage applications.

Keyboard Time-out

In some applications (as for example the "Sums Tester" program given elsewhere in this book), the computer should be able to keep track of how long it has waited for a response from the keyboard, and take alternative action if it has waited too long.

This can be done by modifying ATOM's normal keyboard input routine so that a counter is incremented at regular intervals when it is waiting for a key to be pressed, and abandoning the wait via a BRK instruction when the counter has reached a pre-determined number.

An example of such a routine is given below.

    10 REM KB TIMEOUT EXAMPLE
   100 P=#B4
   102[\ NEW KEYIN ROUTINE
   104 PHP
   106 CLD
   108 STX #E4
   110 STY #E5
   112 BIT #B002
   114 BVC #94   REPT?
   116 JSR #210  SCAN KB
   118 BCC #8A   BR IF KEYPRESS
   120 JSR #FB8A CHECK SHFT,CTRL
   122 JSR #21C  WAIT FOR
   124 BCS #97   KEYPRESS
   126 JMP #FEA7 TO OP SYSTEM
   129]
   130 P=#21C
   132[\ SCAN & COUNT SUBROUTINE
   134 JSR #FE66   WAIT FOR FLYBACK
   136 INC #80     INCREMENT
   138 BNE #228
   140 INC #81
   142 BNE #228    TIMER
   144 BRK
   146 JMP #FE71   SCAN KB & RTS
   148]
   200 REM LINK IN NEW ROUTINE
   210 ?#20A=#84;?#20B=0
   300 REM TEST ROUTINE
   310 !#80=-600
   320 INPUT STOP
   330 PRINT !#80
   340 GOTO 310

Lines 100-128 assemble to give a machine language routine in the free RAM locations 80-9E, which is used to replace the first part of ATOM's normal input routine. It waits until all keys except

perhaps the SHIFT, CTRL or REPT keys) have been released (lines 114,118), then waits for a new key to be pressed (lines 122,124) before jumping to the second part of ATOM's normal keyboard input routine at FEA7. While waiting, it uses a subroutine (lines 132, 146) which assembles into the free RAM locations 21C-22A to increment the contents of locations 80,81 and scan the keyboard every 1/60 second. Locations 80,81 are to be preset to a negative number at the start of a program, and the routine times out by executing the BRK instruction when the count reaches zero. Note that locations 82 & 83 are left free so that the counter can be preset with a normal ATOM BASIC 4-byte word. The longest timeout that can be obtained is 18 minutes, obtained by pre-setting the count to -65535.

As an example of using the timeout facility, lines 300-340 are a simple loop which first presets the count to -600 (10 seconds), then waits for an input. If the Return key is pressed to signal the end of the input before the 10 seconds has elapsed, the program will display the remaining count then loop back for another input. If the time limit is exceeded, the program simply crashes;- in practice it would be better to add a BRK error handler as described in sections 18.8 and 23.10 of 'Atomic Theory and Practice', or as in the 'Sums Tester' program in this book.

It should be noted that the ATOM Operating System routines used by this program are not documented by Acorn, and so may not be valid if they introduce an updated ROM.

ASSEMBLER LISTING OF MACHINE CODE ROUTINES

   102 0084            \ NEW KEYIN ROUTINE
   104 0084 08         PHP
   106 0085 D8         CLD
   108 0086 86 E4      STX #E4
   110 0088 84 E5      STY #E5
   112 008A 2C 02 B0   BIT #B002
   114 008D 50 05      BVC #94     REPT?
   116 008F 20 1C 02   JSR #21C    SCAN KB
   118 0092 90 F6      BCC #8A     BR IF KEYPRESS
   120 0094 20 8A FB   JSR #FB8A   CHECK SHIFT,CTRL
   122 0097 20 10 02   JSR #21C    WAIT FOR
   124 009A B0 FB      BCS #97     KEYPRESS
   126 009C 4C A7 FE   JMP #FEA7   TO OP SYSTEM
   132 021C            \ SCAN & COUNT SUBROUTINE
   134 021C 20 66 FE   JSR #FE66   WAIT FOR FLYBACK
   136 021F E6 80      INC #80     INCREMENT
   138 0221 D0 05      BNE #228
   140 0223 E6 81      INC #81
   142 0225 D0 01      BNE #228    TIMER
   144 0227 00         BRK
   146 0228 4C 71 FE   JMP #FE71   SCAN KB & RTS

Other BASICs 

A wealth of programs written in BASIC can be found in other books and computing magazines, but there are many versions of BASIC, and it is unlikely that a program written to run on another computer will work on the ATOM without some changes. The extent and nature of the alterations needed will depend on the structure of the program, and how it handles data, as well as the particular dialect of BASIC used, so you should understand how the original program works before attempting to convert it to ATOM BASIC, and be prepared to alter the program and data structures if necessary.

The following paragraphs list the differences between ATOM BASIC and the major dialects found on other machines.

Multiple-statement lines

Some BASICs don't allow more than one statement on a line, thus

    10 LET B=B+C
    15 PRINT B

could be written for the ATOM as;

    10 LET B=B+C;PRINT B

but take care that the 'deleted' line (line 15 in this example) is not the target of a GOTO or GOSUB.

More importantly, those versions of BASIC which do allow multiple statements on a line usually use ':' or '\' to separate the statements, rather than the ';' used by the ATOM. Thus;

    10 A=2:B=3

would become;

    10 A=2;B=3

Note that most other BASICs use the semi-colon in a PRINT statement to indicate that the items on either side of it are to be printed without intervening spaces, thus;

    10 PRINT "ABCD";"EFGH"

will usually give a print-out of;

  ABCDEFGH

whereas ATOM BASIC would misinterpret this line as two statements;

    10 PRINT "ABCD"
  and "EFGH"

See the notes on PRINT statements for ways of replacing the ';' in these circumstances.

Numeric Variables

Many BASICs allow floating point decimal numbers (generally called 'real' numbers) such as 9.73 or -27.456. If your ATOM is not fitted with the Floating-Point extension ROM, then depending on the program it may be possible to 'scale' the values - by multiplying by say 10 or 1000 for the calculations so that a reasonable accuracy is obtained. The large range of values allowed by ATOM (approximately -2000 million to +2000 million) make this task relatively straightforward.

BASICs that allow real numbers usually do all operations in floating point mode, and only give integer results when specifically instructed to do so by a function such as INT (X); which gives the integer value of the real variable or expression X (e.g. INT (6.67) gives 6). This is different to the approach used by ATOM BASIC, which has separate commands for integer and floating point working (when the Floating Point ROM is fitted) e.g. PRINT and FPRINT, IF and FIF, and must be watched carefully when translating.

Some floating point BASICs allow the use of integer variables by giving them special names in much the same way as ATOM BASIC has different types of names for integer and real variables. Unfortunately, this can cause some confusion as opposite conventions are used, thus typically;

A is a floating point variable equivalent to ATOM's %A

%A or A% is an integer variable equivalent to ATOM's A

Many versions of BASIC allow you to use variable names longer than one character, such as A1, A2% or COUNTUP.

Single letter names will have to be allocated for ATOM.

Numeric Arrays

In most versions of BASIC, an array variable is distinguished from an ordinary variable only by the presence of the parentheses () after the name. For example A(7) is element 7 of the array A() and may be an integer or a floating point number depending on the type of BASIC, space for the array being reserved by a previous statement such as DIM A(99). ATOM BASIC, of course, uses the double letter form AA() for an integer array element, and %M() for a floating point array element - with space reserved by a DIM AA(99) or FDIM %AA(99).

Note that the expression DIM A(n) is used by ATOM BASIC to reserve space for n+1 bytes, which may then be used to hold a string variable or for byte or word vectors, and is therefore not equivalent to DIM A(n) In other BASICs (which don't allow for byte or word

vectors). Also, note that in most BASICs the array variable A() and the ordinary variable A have no relation and may be used independently within a program. This differs from ATOM BASIC which uses the variable A to hold the RAM address of the first byte in the vector defined by a DIM A() statement.

As byte and word vectors are a unique ATOM BASIC feature, it may be worthwhile seeing if a program being translated can be simplified by their use.

Many versions of BASIC allow multi-dimensional arrays, such as DIM A(4,4,4) , which declares a three dimensioned array having a total of 125 (5x5x5) elements. Page 50 of 'Atomic Theory and Practice' shows how to convert multi-dimensional arrays so that the ATOM can handle them.

Note that in some BASICs the first element of an array has the subscript (1), rather than (0).

String variables

String variables are represented in most versions of BASIC by a variable name followed by the '$' sign, thus A$ is a string variable. Usually A and A$ are unrelated.

In ATOM BASIC, however, strings are handled as byte vectors, by using a DIM statement to set up a variable (say A) to point to the first RAM location where the string is to be stored. The string is then accessed by putting the string operator '$' in front of the variable name. Thus '$A' refers to a string starting at RAM location A.

Many versions of BASIC allow string variables of less than a certain length (for example 10 characters) to be used without having to specifically reserve space with a DIM statement. This is not allowed in ATOM BASIC.

When the length of a string has to be declared to reserve memory space, the various versions of BASIC differ in the details of how this is done, but the most common scheme is to use a statement of the form DIM A$(20) or DIM A$[20] to reserve space for a 20-character string. The latter form is most used by BASICs which allow arrays of strings; such that DIM A$(10)[20] declares a 10 (or 11) element string array, each string being up to 20 characters. Pages 62,63 of 'Atomic Theory and Practice' show how string arrays can be handled by the ATOM.

GOTO, GOSUB

Some BASICs do not allow a computed GOTO or GOSUB such as GOTO (A+100). It may therefore be possible to simplify a program

by taking advantage of this ATOM BASIC facility.

Remember also that the use of a label associated with a line number is another ATOM BASIC feature that can be useful to speed up the execution of GOTO and GOSUB statements.

ON … GOTO

Sometimes found in other BASICs, these statements make the program GOTO (or GOSUB) one of a number of lines depending on the value of a variable. For example;

    10 ON I GOTO 100,105,50

will jump to line 100 if I=1, 105 if I=2, or 50 if I=3.

Depending on the particular application, ON..GOTO or ON..GOSUB may be replaced by a 'computed' GOTO or GOSUB, or by a combination of IF- - GOTO lines.

IF … THEN

Most other versions of BASIC require that the 'THEN' is always included; a few memory bytes can usually be saved by leaving it out when translating to ATOM BASIC.

Some BASICs don't allow anything except a GOTO after the THEN. Programs written in these dialects may sometimes be simplified by taking advantage of ATOM's ability to have any statement or statements after a THEN. Thus;

    10 IF X>0 THEN GOTO 40
    20 PRINT "TOO LOW"
    30 END
    40 ...

could be re-written as;

    10 IF X<11 PRINT "TOO LOW"; END
    40 ...

Note that BASICs differ in their interpretation of a value as being 'true' or 'false'. Thus;

    10 IF A THEN PRINT "TRUE"

will print TRUE in ATOM BASIC if A is non-zero, whereas other versions of BASIC may use - for example - negative values to represent the Boolean value 'false' and zero or positive values for 'true'.

FOR TO STEP

ATOM BASIC's FOR ... NEXT loop function is similar to other BASICs, so usually no alteration will be needed when translating except - perhaps - to note that in some circumstances it may be better to take advantage of ATOM's DO . .UNTIL loop control function.

Be careful, however, if the program jumps out of a FOR . . NEXT loop. Some BASICs are able to do this repeatedly without harm, but as discussed in the section 'Programming Tips', ATOM BASIC may object.

INPUT

Some forms of BASIC don't allow a 'prompt' string to be included in the INPUT statement, so programs written in these dialects may be simplified slightly for use on the ATOM. For example;

    10 PRINT "MONTH "
    20 INPUT M

could be translated to;

    10 INPUT "MONTH "M

PRINT

Print statements will often have to be amended to make best use of the ATOM's screen format. It should also be noted that in most versions of BASIC, items in a PRINT list must be separated by a comma (,) or a semicolon (;). The comma causes the next expression to be printed out in the next tabulation field - as in ATOM BASIC -the semicolon causes the next expression to be printed immediately following the previous one without any intervening spaces, and is equivalent to an ATOM BASIC PRINT statement with just a space between expressions. For example;

    10 PRINT A,B;C;D

translates to the ATOM BASIC

    10 PRINT A,B C D

Most versions of BASIC output a carriage return/line feed automatically at the end of a PRINT list, unless the last character in the list is a semicolon, and if an additional line feed is needed it has to be generated by another PRINT statement. ATOM

BASIC on the other hand, only outputs carriage return/line feed when specifically instructed by an apostrophe (') in the PRINT list. Thus;

    10 PRINT "ABC";
    20 PRINT "DEF"
    30 PRINT "l23"
    40 PRINT
    50 PRINT "456"

will cause most BASICs to print out

  ABCDEF
  123

  456

and is equivalent to the ATOM's

    10 PRINT "ABC" "DEF" '"123"' '"456"'

TAB

In most BASIC dialects, TAB(X) is used in a PRINT statement to cause the next character to be printed at position number X in the line. Thus PRINT TAB(25);"A" will print the letter A in the 25th column.

ATOM BASIC does not have the TAB() function, but does have a function COUNT which gives the number of characters already printed on that line, thus the example given above could be re-written as; DO PRINT " ";UNTIL COUNT=24; PRINT "A".

Programs written in other BASICs sometimes use the TAB function to simple graphs; in these cases it may be possible to produce the same result by use of ATOM's PLOT or DRAW statements.

PEEK, POKE, USR

PEEK and POKE statements are used in some BASICs to look at, and change, the values of specific memory locations. Equivalents of these are given in page 15 of 'Atomic Theory and Practice'.

USR(X) is a function which calls a machine language routine starting at memory location X - and sometimes it returns a value in a way that depends on the version of BASIC being used. As ATOM BASIC allows you to insert a section of machine code within a BASIC program, to pass values freely between the BASIC and machine code routines, and to run the machine code routine by using the LINK statement, it allows you to do all that USR() can, and more.

In any case, the effect of PEEK, POKE and USR(X) depends entirely an the particular computer being used, therefore to convert a program containing any of these to run on the ATOM, you must find out exactly what the command was intended to do, then write ATOM code to perform a similar function.

DATA, READ, RESTORE

DATA and READ statements are often used to handle a list of fixed numeric or string values. Thus if the lines;

   100 DATA 7,2,5
   110 DATA 12,13

appear in a program, then

   200 FOR I=1 TO 5
   210 READ A(I)
   220 NEXT I

will load the values 7,2,5,12,13 into the array variables A(1) to A(5); each READ statement executed taking the next value from the list. RESTORE sets the list 'pointer' back to the first item in the first DATA statement in the program.

Pages 63,64 of 'Atomic Theory and Practice' show how to perform similar functions in ATOM BASIC, and see the program "Buzz-Word" in this bock for an example with strings.

DEF, FN

A statement of the form

    10 DEF FNA(X) = X+X*X

is acceptable to most BASICs, and defines a function FNA(X) which returns the value of X+X*X and can be called up with different parameters during the program, e.g.

    20 LET A=3*FNA(2)

would give A the value 18.

Usually up to 26 functions; FNA() to FNZ(), are allowed.

ATOM BASIC does not allow functions to be defined in this way, so the expression would have to be written out in full each time it is used, thus the above example would require line 20 to be;

    20 A=3*(2+2*2)

Arithmetic functions

The following functions are not available in the Integer form of ATOM BASIC, and if they occur in a program you wish to translate then some other way of calculating the required value must be found;

  ATN(X) ; Arctangent of X
  COS(X) ; Cosine of X
  EXP(X) ; e raised to the Xth power
  LOG(X) ; Logarithm of X to the base e
  SGN(X) ; Returns -1,0 or +1 depending on whether X is negative, zero or positive.
  SIN(X) ; Sine of X
  SQR(X) ; Square root of X
  TAN(X) ; Tangent of X

Trigonometric functions are usually expressed in radians. The Floating Point extension to ATOM BASIC uses the symbol ^ to mean 'raise to the power of' (e.g. 3^2 = 9). Some BASICs use the symbols up-arrow or ** instead.

RND

In most Integer BASICs, the expression RND(X) returns a random positive integer between 0 and X, and is equivalent to ATOM BASIC's ABSRND%(X+1).

In most Floating Point BASICs, RND(X) returns a random decimal fraction between 0 and 1, regardless of the value of X.

Joining strings

Most BASICs will let you join two strings to form a third ('concatenation' is the official word for this operation), thus;

    10 LET AS = "ABC"
    20 LET S$ = "DEF"
    30 LET C$ = A$ & B$

gives C$ the value "ABCDEF". "+" or "!" symbols may sometimes be used instead of "&". ATOM's equivalent for this example is;

    10 $A = "ABC"
    20 $B = "DEF"
    30 $C = $A; $C+LEN(A)=$B

LEFT$, MID$, RIGHT$

These functions occur in many versions of BASIC. They operate on a string (e.g. X$) to return a string which is a part of X$.

LEFT$(X$,Y) gives the first Y characters in X$. The statement;

    10 LET X$ = LEFT$(X$,3)

translates to;

    10 $X+3

and the ATOM BASIC equivalent of

    10 LET A$ = LEFT$(X$,J)

is;

    10 $A = $X ; $A+J = ""

RIGHT$(X$,Y) gives the last Y characters from X$ and is equivalent to ATOM BASIC's $X+Y

MID$(X$,Y,Z) gives 7 characters from X$, starting at the Yth character, thus;

    10 LET B$ = "ABCDEF"
    20 LET A$ = MID$(B$,3,2)

will give A$ the value "CD". To perform a similar function in ATOM BASIC, a routine such as that given below is required;

    10 $B = "ABCDEF"
    20 $A = $B+3; $A+2  = ""

Page 61 of 'Atomic Theory and Practice' gives further explanation of these techniques.

ASC CHR$

ASC(X$) gives the decimal value of the ASCII code for the first character in the string X$, the ATOM BASIC's equivalent is the function CH. Thus

    10 LET B = ASC(C$)

translates to;

    10 B = CH$C

CHR$(X) returns a string of one character corresponding to the

ASCII code X. Thus;

    10 LET B$ = CHR$(65)

gives B$ the value "A". To perform this function on the Atom, we first put the value of X in the first byte of the memory space reserved for the target string, then put the value 13 ('Return') in the second byte. Thus the example given above becomes;

    10 B?0 = 65; B?1 = 13

Alternatively, if the CHR$() function is being used in a PRINT statement (usually to output a special control code or a graphics character), the $ operator may be used. Thus;

    10 PRINT CHR$(12)

could be translated to run on the Atom as;

    10 PRINT $12

as long as the value following the $ is between 0 and 255.

VAL

VAL(X$)gives the numeric value of the string (of digits) X$. Thus;

    10 LET A = VAL("12.34")

gives A the value 12.34

The function is available in the floating Point extension to Atom BASIC, but not in the integer form, where a special routine would have to be written to convert the string to it's equivalent numeric form, for example;

    10 A = 0
    20 FOR I = 1 TO LEN(X)
    30 A = 10*A+X?I-CH"0"
    40 NEXT I

STR$

In most versions of BASIC, the function STR$(X) gives a string of digits equal to the value X. Thus LET A$ = STR$(123) give A$ the value "123". The function is available in the Floating Point Extension to Atom BASIC, although in a slightly different form (see page 163 of 'Atomic Theory and Practice'), but not in integer BASIC.

Tape Recording 

To avoid future aggravation, it is worth investing in a few hours to find the best settings for your tape recorder controls, and possibly the brand of tape used, so you can be confident of being able to retrieve whatever valuable information you commit to tape.

The simplest test is that given in chapter 1 of 'Atomic Theory and Practice', and this should be used first. For a more stringent test, we need to record and retrieve data in blocks, as the Atom normally does. This can easily be done by saving the contents of the 4K BASIC ROM;

  *SAVE "TEST TAPE" C000 D000

which gives a tape lasting about 4 minutes. A catalogue of the tape should then show 16 consecutive blocks, as below, if the Atom can successfully read the block headers.

  TEST TAPE   C000 C000 0000 FF
  TEST TAPE   C100 C000 0001 FF
  TEST TAPE   C200 C000 0002 FF
  TEST TAPE   C300 C000 0003 FF
  TEST TAPE   C400 C000 0004 FF
  TEST TAPE   C500 C000 0005 FF
  TEST TAPE   C600 C000 0006 FF
  TEST TAPE   C700 C000 0007 FF
  TEST TAPE   C800 C000 0008 FF
  TEST TAPE   C900 C000 0009 FF
  TEST TAPE   CA00 C000 000A FF
  TEST TAPE   CB00 C000 000B FF
  TEST TAPE   CC00 C000 000C FF
  TEST TAPE   CD00 C000 000D FF
  TEST TAPE   CE00 C000 000E FF
  TEST TAPE   CF00 C000 000F FF

If all is well, we can then check the Atom can read all the tape, including the actual data, by;

  *LOAD "TEST TAPE"

This makes the Atom try to read data from the tape and write it to the BASIC Read Only Memory, which is of course impossible, but the Atom will check that the data there matches the data it tried to write. If the data are read without error, the cursor will re-appear about four minutes later.

Problems and Cures

If you are unable to save and load programs successfully despite careful adjustment of your recorder's level and tone controls, then;

As supplied, the recorder interface of the Atom is optimised for use with the 'Aux' or 'Amp' recorder sockets which expect a signal level of around 300 to 500 mV at an impedance of 1 to 10k. If you are feeding into the 'Mic' socket, then the level expected is usually 5 mV, and the resulting overload can have some very odd effects, especially if the recorder has automatic level control.

In this case, the Atom's 'CAS OUT' level should be reduced drastically; either by increasing R29 to between 100k and 1M, or by adding an external voltage divider as Fig. 1. The latter is preferable as it avoids tampering with the Atom's PCB, and can easily be changed for different recorders by fitting miniature resistors in the recorder connectors.

If the recorder output level is not enough to drive the Atom's interface properly when reading tapes, then the gain of the input amplifier IC46 can be increased by increasing R34 to 100k or 200k. Alternatively, a 3k3 to 10k resistor can be added in parallel with R37.

Some cheap cassette recorders produce a lot of high-frequency noise on playback. This may not be noticed if the loudspeaker has a poor high-frequency response, but can upset the Atom. If you think this may be the problem, a simple low-pass filter (Fig. 2) may help.

The 6522 Versatile Interface Adapter chip  

The 6522 VIA chip can be added to the Atom to provide printer or other parallel I/O. It is a very clever chip which can handle many parallel or serial I/O functions. A full description would occupy many pages and be beyond the scope of this book, but the following paragraphs show the simpler functions satisfactory for most applications.

Within the VIA are two 8-bit bi-directional I/O ports connected to the I/O lines PA0-7 and PB0-7, two 16-bit counter/timers, an 8-bit serial shift register, and some control circuitry associated with the four lines CA1-2, CB1-2. It appears as 16 registers;

Base Offset Function
B800    
  +00 Port B. Will float high when inputs.
  +01 Port A
  +02 Port B data direction
  +03 Port A data direction
  +04 Timer 1 low counter/latch
  +05 Timer 1 high counter
  +06 Timer 1 low latch
  +07 Timer 1 high latch
  +08 Timer 2 low counter/latch
  +09 Timer 2 high counter
  +0A Shift register
  +0B Auxiliary control
  +0C Peripheral control
  +0D Interrupt flags
  +0E Interrupt enables
  +0F Port A (like B801, but does not affect interrupt flag)

Each bit of ports A and B can be made an input by writing '0' to the corresponding bit of the direction register ('1' = output). Once the bit direction has been programmed, the port registers (B800 and B801) may be read or written as any other memory location. reading output bits will just return the value last written to them. Writing to an input bit does nothing.

PA0-7 and PB0-7 presents one TTL load as an input, and can drive one TTL load as an output. PB0-7 outputs can source 3mA at 1V5 when high, useful for driving NPN transistors.

Bits 0 and 1 of B80B should normally be zero. Setting either to 1 invokes a complex latching arrangement for data input to ports A and B.

The 16-bit timer 1 counts down at 1MHz, and has two associated 8-bit latches. Writing to B804 latches the low count data byte. Reading B804 returns the low 8 bits of the counter. Reading B805 returns the high 8 bits of the counter. You can read and write the two latches at B806 and B807 without affecting the counter.

If bit 6 of the auxiliary control register (B80B) is '0', the counter will decrement continually at 1MHz, and set the interrupt flag the first time it reaches zero. This is the 'one-shot' timing mode. If B80B bit 6 is '1', the counter will decrement at 1MHz, but will reload from the two latches as well as setting the T1 interrupt flag. This is the 'free-running' mode, and PB7 toggles each time the counter reaches zero.

The 16-bit timer 2 is similar but there are some differences. Writing to B808 stores the data in an 8-bit latch, reading B808 returns the low byte of the counter. Writing to B809 directly loads the high byte of the counter then loads the low-byte of the counter with the data from the latch. Reading B809 returns the high 8 bits of the counter.

Timer 2 can be clocked from either of two sources; if bit 5 of B808 is '0', the counter decrements at 1MHz. If bit 5 is '1', the counter is decremented by each falling edge applied to PB6. In all cases the timer operates in the 'one-shot' mode; the counter is started by writing to B809, and on reaching zero the T2 interrupt flag becomes '1' and the counter continues to decrement.

The 8-bit shift register uses CB2 for serial input or output, and CB1 for clock pulse input or output. Its operation is controlled by B80B bits 2, 3 and 4.

000 Shift register disabled
001 Shift in controlled by timer 2, clock pulses output on CB1
010 Shift in at 1MHz, clock pulses output on CB1
011 Shift in on falling edge clock pulses input on CB1
100 Shift out repeatedly, controlled by timer 2
101 Shift out 8 bits, controlled by timer 2
110 Shift out at 1MHz, clock pulses output on CB1
111 Shift out on falling edge clock pulses input on CB1

In the timer '2' modes, only the low byte of the timer is used. In all cases data are clocked on the rising edge of the internal or external clock pulse on CB1, and - except for the 'repetitive' mode - shifting (and clock pulses supplied to CB1) stops after 8 bits have been shifted in or out. The shift register interrupt flag then becomes '1'. This flag is made '0' by reading or writing of the shift register.

The function of the four control lines are (except when CB1 or CB2 are used by timer 2 or the shift register) determined by the Peripheral Control register at B80C. Most modes are intended for complex interrupt/handshake operations. CA2 and CB2 can be used as simple I/O lines via bits 0 and 5 respectively of B80C if all other bits of B80C are set to '1'.

The interrupt flag register (B80D) has 7 bits which are set to '1'' by particular events inside the VIA chip, and set to '0' by reading or writing particular registers.

Bit Set to '1' by Set to '0' by:
0 Transition on CA2 Read/write B801
1 Transition on CA1 Read/write B801
2 8th shift in/out Read/write shift reg.
3 Transition on CB2 Read/write B800
4 Transition on CB1 Read/write B800
5 Timer 2 = zero Read B808, write B809
6 Timer 1 = zero Read B804, write B807
7 Any other bit '1'  

The Interrupt enable register at B80E has 6 interrupt enable bits corresponding to the six bits in the Interrupt flag register. Most applications will not use interrupts, so 00 should be written to B80E. This will not affect the setting of bits in B80D, but will prevent them interrupting the processor.

The 8255 Programmable Peripheral Interface Chip 

The following paragraphs summarise the main features of the 8255, which should be enough for most applications. More complex applications require the full data sheet.

The 8255 has three 8-bit ports (A, B and C) which may be used in three modes. Modes 2 and 3 use certain port C lines for handshaking. Mode 0 is easy to use for most applications.

The 8255 appears as four registers

Address Offset Function
B000 +00 Port A
  +01 Port B
  +02 Port C
  +03 Control

In mode 0, ports A and B may be set up as 8 input lines or 8 output lines.
Port C is divided into upper and lower 4-bit sections, each of which may be set up for input or output.

B003 7 6 5 4 3 2 1 0 Bit function
                0 Port C lower = output
                1 Port C lower = input
              0   Port B = output
              1   Port B = input
            0     Mode 0
            1     Mode 1
          0       Port C upper = output
          1       Port C upper = input
        0         Port A = output
        1         Port A = input
    0 0           Mode 0: Basic input/output
    0 1           Mode 1: Strobed Input/output
    1 x           Mode 2: Bi-directional Bus
  0               Mode select flag = inactive
  1               Mode select flag = active

Thus to set port A for output, port B for input, port C lower for output and port C upper for input (the normal conditions in the Atom), we have to write 10001010 binary (8A hex) to B003. We can then read the data on port B at B001.

Port C lines can also be changed individually (if set for output) by writing to the control register a value equal to 2*BitNumber +Q where Q is the value of the output.

When set for output, the 24 I/O lines can each drive one TTL load, sinking 1.7 mA at 0.4V, sourcing 200mA at 2.4V. As inputs, they present a high impedance to the driving source, recognising voltages below 0.8V as '0' and voltages between 2.0V and 5V as '1'

Block 0 RAM 

Advanced programmers may find the following table useful as it shows the contents of important block zero RAM locations used by BASIC or the Cassette Operating System. Locations marked as miscellaneous working space tend to have multiple uses. For example, B0 to DB are used by COS for different purposes at different times, and 16 to 59 are usually but not always used as 4-byte integer arithmetic registers.

Note that many of these explanations are not formally supported by Acorn, so they may change in future ROMs. If this happens, we at Timedata would be interested to hear about it.

Page 0 RAM

Address  
00 Error number
01-02 Current Line number (binary)
03 Pointer to character being investigated in statement being interpreted.
04 Temp. for X
05-06 Address of start of statement being interpreted
07 Print Column counter
08-0C Random number seed
0D 0E Top (binary)
10 11 Address of BASIC error handler, normally C9E7,
12 Text space pointer; normally 82 or 89
16-59 Misc. BASIC working space
5A 5B X ordinate for point plot routine
5C 5D Y ordinate for point plot routine
5E Data for point plot routine. 1=set, 2=invert, else clear
5F 60 Point plot routine workspace
61 6F Misc. BASIC working space
70 7F FP. BASIC working space
80 AF Free
B0 DB Misc. COS working space
DC Tape read/write checksum
DD Fload flag; bit 7 = 1 to ignore block numbers
DE DF VDU RAM address of start of line containing the cursor
DE should be 00, 20, 40 ... E0, DF should be 80 or 81
E0 Cursor position in VDU line; 00 to 3F (or is that 1F?)
E1 0=cursor off, 1 = cursor on
E2 E5 Misc. Workspace
E6 Number of lines remaining (1-16) if VDU in page mode,
bit 7 = 1 if not in page mode.
E7 Bits 5,6,= 1 for shift lock, else 0
E8 E9 Misc. Workspace
EA 'Nomon' if not zero
EB FD Misc. Workspace for COS
FE Character not sent to printer (normally 0A = Line Feed)

Page 1 RAM

100 13F Input line buffer
140 17F String processing area
180 1FF Stack

Page 2 and 3 RAM

200 201 Ptr. to NMI routine; not set by COS or BASIC
202 203 Ptr. to BRK routine; normally C9D8
204 205 Ptr. to IRQ routine; normally A000 (Utility ROM)
206 207 Ptr. to Command Line Interpreter, normally F8EF
208 209 Ptr. to Write Char. routine, normally FE52
20A 20B Ptr. to Read Char. routine, normally FE94
20C 20D Ptr. to Load File routine, normally FE6E
20E 20E Ptr. to Save File routine, normally FAE5
210 211 Ptr. to RDRVEC routine, normally
212 213 Ptr. to STRVEC routine, normally
214 215 Ptr. to GetTapeByte routine, normally
216 217 Ptr. to PutTapeByte routine, normally
218 219 Ptr. to PrintTapeMessage routine, normally
21A 21B Ptr. to Shut file routine, normally
21C 23F Free
240 2EA Misc. Workspace for BASIC
2EB 320 Pointers to arrays: 2EB,306 = AA; 2EC,307 = BB etc.
321 Integer Variable
322 33C Low byte of variables A-Z
33E 357 2nd byte of variables A-Z
359 371 3rd byte of variables A-Z
373 38C High byte of variables A-Z
38D 3C0 Labels; 38D, 38E is RAM address of label a,
38F, 340 is RAM address of label b, etc.
3C1 3FD Misc. Workspace for BASIC
3FE 3FF Ptr. to point plot routine F6E2 for mode 0,
F73B for mode 1,
F754 for mode 2,
F76D for mode 3,
F7AA for mode 4,

ROM Routines 

The following addresses (except for C2F2, C8E6, FFFA, FFFC and FFFE) are the entry points for some useful routines in BASIC and COS. Note that most are not documented by Acorn, and so may change in future ROMs.

Address  
C2F2 Entry point for BASIC interpreter; locations 5 and 6
should point to the start of the BASIC program
C278 File Shut - just RTS
C589 Print4-byte binary integer from #16,#25,#34, #43 (MSB)
C8E6 Auto start address for routine loaded from tape.
C9D8 BRK service routine; retrieves PC from stack, stores it in 0,
then goes to BASIC routine pointed to by 10,11 (normally C9E7)
F6E2 Plot mode 0
F73B Plot mode 1
F754 Plot mode 2
F76D Plot mode 3
F7AA Plot mode 4. See block zero RAM
F7D1 Output ASCII string from the calling routine following 'JSR F7D1'.
Returns calling routine at first byte with bit 7 = 1. Uses A,X,Y.
F802 Print A as two hex digits. A destroyed.
F87E Convert ASCII hex char in A to binary. A destroyed.
Returns C=1 if char was not ASCII '0' to '9'
F89E Converts ASCII hex string at 0100,Y to 16 bit binary in 0,X and 1,X. Uses 2,X. Destroys A.
Returns with Y pointing to first non-hex character,
Z=1 if first character is not ASCII '0' to '9'
F8EF Interpret string starting at 0100 as an Operating System command. Uses all registers. Legal commands are: 'CAT', 'LOAD', 'SAVE', 'RUN', 'MON', 'NOMON', 'FLOAD' and 'DOS'. The latter causes a jump to E000
F96E Load cassette file.
Enter with X pointing to the first of five data bytes in zero page RAM;
0,X and 1,X pointing to the file name string,
2,X and 3,X pointing to the first byte to be loaded.
4,X bit 7 should be 0 to use the file's start address
FAE5 Save cassette file.
Enter with X pointing to the first of 10 data bytes in zero page RAM;
0,X and 1,X pointing to the file name string,
2,X and 3,X pointing to the reload address
4,X and 5,X pointing to the execution address
6,X and 7,X pointing to the first byte to be saved
8,X and 9,X pointing to the last byte to be saved plus one
FB83 Wait X/60 seconds. Returns with X=0. Other registers preserved
FBEE Get byte from tape, return with it in A. X and Y preserved
Byte added to checksum at 00DC
FC38 Prints 'PLAY TAPE' if flag C=1, or 'RECORD TAPE' if C=0.
Then waits for a key press before returning.
Returns with A=13, X and Y destroyed.
FC40 Prints 'REWIND TAPE', then waits for a key press
before returning with A=13. X and Y destroyed.
FC7C Put byte to tape. All registers preserved. Byte added to checksum at 00DC.
FD1A Bleep. All registers destroyed.
FD44 Invert character at current cursor position.
See page zero RAM locations DE to E0. A and Y destroyed.
FE52 Write ASCII character in A to printer and VDU (if enabled).
Control characters recognised and acted upon. All registers preserved.
FE55 As FE52 but does not write to printer.
FE66 Wait for start of VDU fly-back (blanking) period. All registers preserved.
FE71 Scan key (except for CTRL, SHIFT, RPT and BRK).
Returns with flag C-1 if no key pressed,
else C=0 and Y = key number. All registers destroyed.
FE94 Wait for key press then return with its ASCII code in A. X and Y preserved.
FEFB Write ASCII character in A to printer (if enabled).
If A=02 (STX), enable printer.
If A=03 (ETX), disable printer.
All registers preserved.
FFCB OSSHUT; normally calls C278 (RTS)
FFCE OSFIND; normally calls FC38
FFD1 OSBPUT; normally calls FC7C
FFD4 OSBGET; normally calls FBEE
FFDD OSSAVE; normally calls FAE5
FFE0 OSLOAD; normally calls F96E
FFE3 OSRDCH; normally calls FE94
FFE6 OSECHO; normally calls FE94 then FE52
FFE9 OSASCI; normally calls FE52
FFED OSCRLF; normally calls FE52 to print CR/LF
FFF7 OSCLI; normally calls F8EF
FFFA NMI vector; normally contains FFC7
FFFC Reset vector; normally contains FF3F
FFFE IRQ/BRK vector; normally contains FFB2

Note: #C014 input routine in #100. Y register must be zero.

VDU Codes; #00–#7F 

00 @ 01 A 02 B 03 C 04 D 05 E 06 F 07 G
08 H 09 I 0A J 0B K 0C L 0D M 0E N 0F O
10 P 11 Q 12 R 13 S 14 T 15 U 16 V 17 W
18 X 19 Y 1A Z 1B [ 1C \ 1D ] 1E ^ 1F `
20 21 ! 22 " 23 # 24 $ 25 % 26 & 27 '
28 ( 29 ) 2A * 2B + 2C , 2D - 2E . 2F /
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3A : 3B ; 3C < 3D = 3E > 3F ?
40   41 42 43 44 45 46 47
48 49 4A 4B 4C 4D 4E 4F
50 51 52 53 54 55 56 57
58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67
68 69 6A 6B 6C 6D 6E 6F
70 71 72 73 74 75 76 77
78 79 7A 7B 7C 7D 7E 7F

VDU Codes; #80–#FF 

80 @ 81 A 82 B 83 C 84 D 85 E 86 F 87 G
88 H 89 I 8A J 8B K 8C L 8D M 8E N 8F O
90 P 91 Q 92 R 93 S 94 T 95 U 96 V 97 W
98 X 99 Y 9A Z 9B [ 9C \ 9D ] 9E ^ 9F `
A0 A1 ! A2 " A3 # A4 $ A5 % A6 & A7 '
A8 ( A9 ) AA * AB + AC , AD - AE . AF /
B0 0 B1 1 B2 2 B3 3 B4 4 B5 5 B6 6 B7 7
B8 8 B9 9 BA : BB ; BC < BD = BE > BF ?
C0   C1 C2 C3 C4 C5 C6 C7
C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7
D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7
E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7
F8 F9 FA FB FC FD FE FF

Electronic Remastering Revision History 

Original scans, OCR, quick proof reading and initial separate HTML pages by Keith Howell

Markup & layout tidying, additional content, images and thorough proof reading by Phil Mainwaring

All source code added from tested versions in AtomMMC library by Phil Mainwaring

AtomMMC versions entered and edited by David Banks and the other good peeps over at the StarDot forums