A downloadable game


BASIC 10-Liner videogame for the Sinclair ZX81

by Marco's Retrobits: https://retrobits.itch.io

English language blog: https://retrobits.altervista.org

Italian language blog: https://somebitsofme.altervista.org

YouTube channel: https://youtube.com/@marcosretrobits

Play Online/Download: https://retrobits.itch.io/squashtrainer

Gameplay video:

Squash Trainer is an action game for the Sinclair ZX81 8-bit home computer.

It is my (first?) entry to the 12th edition (2023) of the BASIC 10 Liner Contest, PUR-80 category.

The game has been entirely coded in BASIC language and the program is 10 lines long.

Since the ZX81 BASIC allows only one statement per line, the program consists of only 10 statements.

You love playing squash, but let's face it, you're not so good at it. [1] But don't worry, with the right training you'll become an ace!

So... let's start!

Move your racket by tapping "O" (left) or "P" (right).

Every time you hit the ball, it will bounce with a random direction (I told you you are not so good at Squash!) and you will score one point.

If you score 99 points, your training is over.

If the ball falls beyond your racket, the game is over and you can start again by pressing "R" (RUN) and then "Enter".

Your current score is displayed in the top-left corner of the screen.

[1]: I'm just kidding, I'm sure you're a great player; I just needed something for the game introduction.

Program description

Squash Trainer is my entry to the PUR-80 category of the BASIC 10 Liner Contest; this means the program is 10 lines long and each line is made up of 80 characters to the upmost.

Since the Sinclair ZX81 BASIC allows only one statement per line, the program consists of only 10 statements. 

The program uses a string (M$) to encode multiple variables; with this technique, it is possible to alter their values with just one statement.

At each game tick, the ball moves either horizontally and vertically by 2 character positions, so horizontal and vertical velocities values can be either -2 or 2. 

Since velocities are encoded as characters in a string (the variable value is the character code), they cannot assume negative values, so their values are displaced by adding 2.

The ball coordinates and the horizontal position of the left end of the bat are stored as characters as well, while the score is stored as the string representation of the numeric value.

The movements are a bit jerky (if played on an emulator, by increasing the speed the game becomes more enjoyable). Rather than an actual videogame, Squash Trainer can be seen as a proof of concept that a 1 player PONG-like game can be coded in BASIC with just 10 statements.


M$(1): Ball vertical position y

M$(2): Ball horizontal position x

M$(3): Key pressed

M$(4): Ball vertical velocity

M$(5): Ball horizontal velocity

M$(6 TO 7): Score

M$(8): Racket X (horizontal position of the left end of the racket)

C: Collision flag


The following listing can be used with the ZXText2P tool to make a ".P" file suitable for loading into ZX81 emulators.

Block graphic characters have been replaced with the corresponding escape sequences.

1LET M$="?(X "+CHR$(4*(RND<.5))+"0 ?"
2LET C=(M$(1)="$")*(M$(2)>=M$(8))*(CODE M$(2)-CODE M$(8)<3)
3IF C THEN LET M$(4 TO 7)=" "+CHR$((RND<.5)*4)+STR$(1+VAL M$(6 TO 7))
4LET M$(4)=CHR$((M$(1)>"\''")*CODE M$(4)+4*(M$(1)="\''"))
5LET M$(5)=CHR$((M$(2)>" ")*(M$(2)<"0")*CODE M$(5)+4*(M$(2)=" "))
6PRINT AT CODE M$(1),CODE M$(2);" ";AT14,CODE M$(8);"   "
7LET M$(TO3)=CHR$(CODE M$(1)+CODE M$(4)-2)+CHR$(CODE M$(2)+CODE M$(5)-2)+INKEY$
8LET M$(8)=CHR$(CODE M$(8)+3*(M$(3)="P")*(M$(8)<".")-3*(M$(3)="O")*(M$(8)>" "))
9PRINT AT0,0;M$(6TO7);AT CODE M$(1),CODE M$(2);"\::";AT14,CODE M$(8);"\~~\~~\~~"
10GOTO 2*(M$(1)<"?")+20*((M$(1)="?")+(M$(6TO7)="99")>0)

Source code explained line by line

1. Initialize all variables in M$: ball y M$(1) = 15 ("?"), ball x M$(2) = 16 ("("); currently pressed key M$(3) = "X", ball velocity y M$(4) = 0 - UP, ball velocity x M$(5) = either 0 - LEFT or 4 - RIGHT randomly, score M$(6 to 7) = 0 ("00"), racket x M$(8) = 15 ("?").

2. Begin of the game loop. Collision detection: set flag C if the racket hits the ball, i.e. if the ball is above the racket (ball y M$(1) = 13) and ball x M$(2) >= racket x M$(8) and ball x M$(2) < racket x M$(8) + 3.

3. If the collision flag C is set, set the ball y velocity M$(4) to UP and x velocity M$(5) to LEFT or RIGHT randomly; increment the score by one.

4. Update ball vertical velocity: if the ball hits the top wall (ball y = 3), set ball vertical velocity M$(4) to 4 - DOWN.

5. Update ball horizontal velocity: if the ball hits the right wall (ball x = 0), set ball horizontal velocity M$(5) to RIGHT; if the ball hits the right wall (ball x M$(2) = 28), set ball horizontal velocity M$(5) to LEFT.

6. Erase ball and racket, by printing space characters.

7. Update ball y M$(1) and x M$(2) by adding vertical and horizontal velocities subtracted by 2 (since velocities values are displaced by 2); save the character corresponding to currently pressed key in M$(3).

8. Update racket x M$(8) by adding 3 (thus moving right) if the "P" key is pressed and by subtracting 3 (thus moving left) if the "O" key is pressed.

9. Print the score in the top left corner of the screen; print the ball at line M$(1), column M$(2) and then print the racket at line 14, starting at column M$(8).

10. If the ball is still within the playing field (ball y < 15), jump to line 2 and continue the game. 

    Otherwise, if either the ball passed the racket without being hit (ball y = 15) or the training is over (score = 99), the game is over. End the game by jumping to non-existing line 20.


PIXELGLIDER (Dr. Beep's entry to the 2022 edition of the contest) has been the source of inspiration on how to use a single string to encode several variables.


Squash Trainer picture adapted from the Squash Man Clip Art from clker.com: http://www.clker.com/clipart-squash-man-.html


SquashTrainer.bas 657 bytes
SquashTrainer.p 1 kB
SquashTrainer.pdf 283 kB
SquashTrainer.txt 7 kB

Install instructions


Squash Trainer requires a real or emulated ZX81 with a 2k (or bigger) RAM Pack expansion.

EightyOne emulator (Windows):

The following instructions apply to the EightyOne emulator: https://sourceforge.net/projects/eightyone-sinclair-emulator/

Go to "Options" -> "Hardware..." and make sure that ZX81 with 2k RAM Pack is selected.

Open "Tools" -> "Tape Manager..." and ensure that automatic loading options are selected.

Select “Open Tape…” from the “File” menu to locate and load the "SquashTrainer.p" file. 

In the next seconds, if the emulator is configured in order to automatically load tape images, you should see something happening on the screen and finally a white screen with only the "0/0" message on the bottom. 

If nothing happens, you must manually start tape image loading, by tapping the "J" key followed by "SHIFT" + "P" twice. You should see the “LOAD ""” message followed by a a black cursor. Press "ENTER" to start loading.

To run the program, tap the "R" key. You should see "RUN" followed by a black cursor on the bottom of the screen. Finally, press "ENTER".

To list the program, tap the "K" key. You should see "LIST" followed by a black cursor on the bottom of the screen. Finally, press "ENTER".

The program listing exceeds the room available on the screen, so to list the last lines, you must issue the "LIST 9" command.

You might also want to try EightyOne's "Tools" -> "BASIC Listing..." functionality.

JtyOne Online ZX81 Emulator:

Alternatively, if your web browser supports Javascript, you can play directly in your browser (powered by JtyOne Online ZX81 Emulator). 

Just surf to: https://retrobits.itch.io/squashtrainer.

Mobile devices are not supported.

Leave a comment

Log in with itch.io to leave a comment.