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 XEY 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.