BBC BASIC Code Golfing Tips
Code Golf
|>
|
|
|
o O
Golf is played for the lowest number of strokes. Code golfing is trying to make a program with as few characters as possible while still maintaining its functionality.
I’ve been playing recently with the twitter bot @bbcmicrobot which runs a tweet sent to it as if it was a program for the BBC Micro (see my other blog post about this).
Code golfing is what we need to do to fit an interesting program into the size of a tweet for @bbcmicrobot.
There are a number of features of BBC BASIC that can help with reducing a BASIC program size.
Hopefully this will be useful if you are trying to cut down the size of a program for the bot or trying to decipher someone else’s cryptic code.
Abbreviated Keywords
BBC BASIC allows some keywords to be abbreviated. e.g. LIST can be written L.
See this full list of abbreviations.
The abbreviations save time when typing in the program (and save space in the listing on Twitter). Once typed in, the keywords are stored in the listing as tokens. This means you can immediately get the expanded (and slightly more readable) version of an abbreviated program by pasting the listing into an emulator and LISTing the program.
>1D.0,4,6,2,3,1
>2MO.2:Z=RND(-2):C%=1:Y=1:F.I%=0TO1000:IFZ>0G.4
>3GC.1,0:X=Y:Y=RND(99)-49:Z=.2
>4U=X/Z:V=Y/Z:IFU*U+V*V>=6E5 G.3
>5DR.640+U,512+V:GC.0,C%:C%=1+(C%MOD15):Z=Z-.005:N.I%:O%=0:REP.F.I%=0TO5:READC%:V.19,(O%+I%)MOD15+1,C%;0;:N.I%:O%=O%+1:RES.:U.FA.
L.
1DATA0,4,6,2,3,1
2MODE2:Z=RND(-2):C%=1:Y=1:FORI%=0TO1000:IFZ>0GOTO4
3GCOL1,0:X=Y:Y=RND(99)-49:Z=.2
4U=X/Z:V=Y/Z:IFU*U+V*V>=6E5 GOTO3
5DRAW640+U,512+V:GCOL0,C%:C%=1+(C%MOD15):Z=Z-.005:NEXTI%:O%=0:REPEATFORI%=0TO5:READC%:VDU19,(O%+I%)MOD15+1,C%;0;:NEXTI%:O%=O%+1:RESTORE:UNTILFALSE
>
Removing Unnecessary Spaces
The BASIC interpreter will greedily find a keyword as soon as it matches. Often spaces between keywords or commands and parameters are not required.
>REPEATUNTILFALSE
16 bit Word Parameters for VDU Command
The VDU command used for various display options can take parameters that are 8 bit bytes or 16 bit (little endian) words.
In BASIC we differentiate the byte and word parameters by following 16 bit word parameters with a semicolon (rather than a comma). We can take advantage of this to reduce the program size. If we have a byte parameter followed by another byte parameter that is zero we can remove the second parameter “,0” and replace it with “;”
e.g. if changing the palette for colour 7 to be red
VDU 19,7,1,0,0,0
we can change two of the parameters to be words so it can be written
VDU 19,7,1;0;
The VDU parameters are added to a queue. As both the above commands above still generate the same sequence of bytes, the result is the same.
Chaining Parameters
Some commands will act as if you called them multiple times if you provide a list of parameters separated by commas.
e.g.
10 DIM A(3):DIM B(5)
can be written
10 DIM A(3),B(5)
similarly
10 FOR I=1 TO 3:FOR J=1 TO 3:PRINT I,J:NEXT J:NEXT I
can be written
10 FOR I=1 TO 3:FOR J=1 TO 3:PRINT I,J:NEXT J,I
and the VDU command adds its parameters to a queue so
VDU 22,2 : VDU 25,4,1280;1024; : VDU 7
can be written
VDU 22,2,25,4,1280;1024;7
Removing NEXT Variables
If the variable is omitted from a NEXT command, the program will loop to the last FOR statement encountered
10 FOR I=0 TO 10:PRINT I:NEXT N
can be written
10 FOR I=0 TO 10:PRINT I:NEXT
combining this with the chaining parameters we can iterate several NEXT loops by just specifying a comma
e.g.
10 FOR I=1 TO 3:FOR J=1 TO 3:PRINT I,J:NEXT J,I
can become
10 FOR I=1 TO 3:FOR J=1 TO 3:PRINT I,J:NEXT,
Exponential Values
BBC BASIC lets us specify values with exponential notation.
This notation looks like X
EY
where X
and Y
are numbers.
And the final value is equivalent to evaluating X*10^Y
e.g.
>PRINT 1E5
100000
>PRINT 2.5E4
25000
>PRINT 2.5*10^4
25000
>PRINT 2.5E-1
0.25
Writing very big or very small values in a program in this way can often save space over writing the number out in full.
Memory Access
BBC BASIC has very terse commands for reading and writing from memory.
?900=10
Will set the byte in memory at address 900 to the value 10
?900
will return the contents of address 900. These are the equivalent of PEEK and POKE in other BASIC dialects.
>?900=10
>PRINT ?900
10
>_
Reading from and writing to memory with these can sometimes save space over using an array.
These operations can also be used to index into memory from a base address. e.g.
>M=900
>M?3=10
>PRINT M?3
10
>_
Sets the contents of address (900 + 3) to 10 and then prints the contents of this address.
String Addressing
BBC BASIC allows you to read and write strings directly to memory.
$900="Hi"
will write the bytes 72 (‘H’), 105 (‘i’) and a terminating 13 to memory, starting from address 900.
We can assign a string from values in memory similarly.
>$900="HELLO THERE"
>PRINT $900
HELLO THERE
>_
This can be useful to setup data for the program to use in a succinct way.
10 M=900
20 $M="MY DATA"
30 FOR I=0 TO LEN($M)
40 E=M?I
50 PRINT CHR$(E)
60 NEXT I
RUN
M
Y
D
A
T
A
>_
Note, this is using $M to write string data to a memory address, this is different to M$ which would be a string variable.
Turning off the Cursor
In graphics modes you can hide the flashing cursor with
VDU 23;8202;0;0;0;
Often the same can be achieved with just
VDU 5
This can also be combined with an existing VDU call.
…
Now we know some of the basic BBC Micro graphics commands, how to do colour cycling and some tricks we might use to reduce the size of a BBC BASIC program, next time we can finally have a look at what is going on in some @bbcmicrobot programs.