A downloadable game

A DAY AT THE ANIMAL RACES


BASIC 10 Liner video game for the Sinclair ZX Spectrum

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

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

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

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

Download/play: online https://retrobits.itch.io/animalrace10l

Gameplay video:

A Day At The Animal Races is a BASIC 10 liner version for the Sinclair ZX Spectrum 48K computer of the VIP Animal Race gambling videogame.

The original game was programmed by Brian Astle for the CHIP-8 interpreter running on the COSMAC VIP computer and published in the RCA COSMAC VIP Game Manual in 1978.

In this video (

), you can see it in action on the Sinclair ZX Spectrum Next, running in my CHIP-8 virtual machine.


How to play

Five different animals race against one another and you have the chance to test your expertise at picking the winner.

Wait until the animals are ready to start, then select an animal by pressing a number 1 through 5 and then Enter. 

Decide how much you want to bet (up to a limit of $9), then press that key, followed by Enter. 

You can change the selected animal by inputting an invalid bet.

The selected animal and the corresponding number will be highlighted in cyan to remind you of your choice and the race will start.

After the race is over, your winnings or losses will be computed and the new total displayed. Press Enter to start the the next race.

You can win the game by accumulating $256 or more.

Hints for expert players: all animals move at approximately the same speed, but they start from different positions.

The odds for each animal are related to the starting position but include a random element.

Some races favor the player and you should bet up to the limit on these.

Some races are unfavorable and you should bet carefully on these.


PROGRAM DESCRIPTION

The program uses user-defined graphic characters (UDGs) to print and animate the animals.

All UDGs available on the ZX Spectrum 16/48K (graphic characters "A" to "U") are used. 

In the 128K models, the last 2 UDG characters have been reserved for the "SPECTRUM" and "PLAY" keywords, so the game will not display correctly on these machines.


Variables

m Your money.

b Your bet.

s The selected animal.

r Race result (0: race is not over; -1: you lost the race; 1: you won the race).

c(5) Array storing the horizontal position (column) of each animal.

a Animal iterator.

i Loop iterator; frame counter.

s$ String storing the user-defined graphic characters (UDGs) for the animals animations.

For each animal, there are 5 characters; the first is used when the animal is still; the remaining 4 (3 for the elephant) define the sequence of characters printed when the animal is running.

f$ For each animal, stores how many user-defined graphic characters (UDGs) are used for the running animation (3 for the elephant and 4 for other animals): "43444". Data is encoded as string for compactness.

t$ Animals user-defined graphics data definitions, encoded as string.

u$ Temporary string used for building t$.

m$, n$ User messages.

u, v Indices to access messages stored in n$.


Program listing

Please note that this program listing is formatted in order to be used with the bas2tap utility, which converts a BASIC listing in an ASCII text file to a .TAP emulator tape image. In particular, "{XX}" represents the character with code XX (hexadecimal).

1 LET t$="&%%%1---&%%%1--'&%%%1--4#bbb{60}HHG#bbb{60}HHK#bbb{60}HGe#bbb{60}HH7#&)17I####&)a'&##"

2 LET t$=t$+"#&)a')###&)a+/###.AaEE###.AaEC###.AaEd###.AaE%###.AaE7#":READ u$:LET t$=t$+u$

3 BORDER 1:PAPER 1:INK 7:DIM c(5):FOR i=1 TO LEN t$:POKE USR"A"+i-1,CODE t$(i)-35:NEXT i:LET f$="43444":LET m$="You have $"

4 RESTORE 9:LET m=10:LET s$="{90}{91}{90}{92}{90}{93}{94}{95}{96} {97}{98}{99}{9A}{97}{9B}{9C}{9D}{9E}{9F}{A0}{A1}{A2}{A3}{A4}":LET n$="Race againYou win  !You lose !"

5 CLS:FOR a=1TO5:LET c(a)=5*RND:PRINT AT a*2,0;a;AT a*2,INT c(a)+2;s$(1+5*(a-1)):NEXT a:PLOT 245,84:DRAW 0,80:LET i=0

6 LET a=1:INPUT (m$);(m);". Animal? ";s;" Bet? ";b:RANDOMIZE:GO TO 6+(s>0)*(s<6)*(b>0)*(b<=m)*(b<10)

7 LET c(a)=c(a)+RND:GO SUB 10:LET r=(c(a)>=28)*((a=s)-(a<>s)):LET i=i+(a=5):LET a=(a<5)*a+1:GO TO 7+(r<>0)

8 LET m=m+b*r:LET u=11+10*(r=-1):LET v=1+10*(m>254)+20*(m<1):PRINT AT21,0;n$(u TO u+8);"$";b,m$;m

9 INPUT(n$(v TO v+9));LINE t$:GO TO 4+(m>0)*(m<255):DATA "##%6A55##%6A5E####%6A54###%6A5-###%6A57#"

10 PRINT INK 7-2*(a=s);AT a*2,0;a;AT a*2,INT c(a)+1;" "+s$(2+5*(a-1)+(i-INT(i/VAL f$(a))*VAL f$(a))):RETURN


Source code explained

Program initialization

Line 1 and 2 are used to build the t$ string, which stores data used for the animals user-defined graphics definition. 

Since the length of the whole string exceeded two lines, the last part of the string is stored as DATA in line 9.

Compared to a list of numeric data values, the string made up of the corresponding characters (the code is incremented by 35 in order to use printable characters only) offers a more compact representation.

Line 3 sets up the colours (blue border and white ink on blue paper), allocates the animals horizontal positions array c, defines the graphic animal characters using data stored in t$ by means of a loop and initializes the string f$, telling how many characters are using for animating each animal, and the message m$, used to inform the player about the total money available.


Game initialization

Line 4 contains statements used for both program initialization and game initialization. This is not a good programming practice, but in 10 liners you have to deal with program and lines length, so this might happen!

The RESTORE statements resets the start of DATA to line 9. This is not necessary for normal game operation, but avoids crashes in case the player breaks the game and then runs it again. The array storing the animals graphic characters s$ is initialized, as well as the string n$, which contains multiple user messages.

The initial available money m is set to $10.

Hacking tip: you start the game with more money by changing the value used to initialize the variable m.

Line 5 clears the screen, computes the starting position c(a) of each animal, prints the still animals and draws the finishing line. The i variable, used to compute the index of the animal animation characters that must be printed at each iteration of the game loop, is initialized to 0.

Line 6 initializes the animal iterator a to the first animal and asks the player to select an animal and the bet amount. If the selected animal and the bet are valid, the program can continue to line 7. After the animal number and bet have been input, the random number generator is also reinitialized.


Race game loop

In line 7, current animal horizontal position c(a) is advanced by a random value and the animal is reprinted on the screen by executing the subroutine at line 10.

The race status flag r is updated according to current animal position: if the animal has not yet reached the finishing line (at column 28), the race is not over and r is set to 0. Otherwise, if the winner is the animal s chosen by the player, r is set to 1; conversely, if the winner is not the player's animal, r is set to -1.

If the loop is over, i.e. all five animals have advanced (current animal a = 5), i is incremented for the next iteration and a is reset to 1; otherwise, i is left unchanged and a is incremented, so that the next animal will be updated. The last statement goes back to line 7 if the race is not over, otherwise the program continues to line 8.

Line 8 updates the total money amount by adding or subtracting the bet depending on the race result r and then determines the indices used for building the messages to inform the player about the outcome. The "You win $" or "You lose $" message follow by the bet and the updated total money are printed at line 21.

Line 9 prints the following messages based on the game status:

"You win!" if the game is over because you accumulated more than $255;

"You lose!" if you lost all your money;

"Race again" if the game is not over.

Then, it waits for you to press the Enter key (actually input a string) to either jump to line 4 to start a new game if the game is over or jump to line 5 and start a new race if the game is not over.

The last part of the line contains part of the DATA used to build the t$ string.

Update animal on screen subroutine

The routine at line 10 updates animal a on the screen. The blank space deletes the old animal picture and the new is printed afterwards. The character to print in the s$ string is determined by the remainder of i divided by the number of "frames" f$(a) making the animation.


Program lines length proof

By replacing each bas2tap escape sequence and each BASIC token with a single character and by removing redundant blank spaces, each line in the resulting source code does not exceed the 80 characters limit:

Therefore, A Day At The Animal Races is a suitable entry for the PUR-80 category of the BASIC 10 Liner Contest.

1lt$="&%%%1---&%%%1--'&%%%1--4#bbb£HHG#bbb£HHK#bbb£HGe#bbb£HH7#&)17I####&)a'&##"
2lt$=t$+"#&)a')###&)a+/###.AaEE###.AaEC###.AaEd###.AaE%###.AaE7#":Au$:lt$=t$+u$
3b1:C1:X7:dc(5):fi=1 FKt$:oL"A"+i-1,It$(i)-35:ni:lf$="43444":lm$="You have $"
4S9:lm=10:ls$="ABACADEFG HIJKHLMNOPQRSTU":ln$="Race againYou win  !You lose !"
5v:fa=1F5:lc(a)=5*T:pIa*2,0;a;Ia*2,Rc(a)+2;s$(1+5*(a-1)):na:q245,84:w0,80:li=0
6la=1:i(m$);(m);". Animal? ";s;" Bet? ";b:t:g6+(s>0)*(s<6)*(b>0)*(b<=m)*(b<10)
7lc(a)=c(a)+T:h10:lr=(c(a)>=28)*((a=s)-(a<>s)):li=i+(a=5):la=(a<5)*a+1:g7+(r<>0)
8lm=m+b*r:lu=11+10*(r=-1):lv=1+10*(m>254)+20*(m<1):pI21,0;n$(u Fu+8);"$";b,m$;m
9i(n$(v Fv+9));Lt$:g4+(m>0)*(m<255):D"##%6A55##%6A5E####%6A54###%6A5-###%6A57#"
10pX7-2*(a=s);Ia*2,0;a;Ia*2,Rc(a)+1;" "+s$(2+5*(a-1)+(i-R(i/Jf$(a))*Jf$(a))):y



LINKS, REFERENCE AND CREDITS

VIP Animal Race, COSMAC VIP and CHIP-8 related:

* The RCA COSMAC VIP Game Manual with the description and CHIP-8 source code of VIP Animal Race by Brian Astle. The A Day At The Animal Races description has been adapted from the original game description.

* The EMMA 02 emulator, which has many CHIP-8 games bundled (including the original VIP Animal Race by Brian Astle and YAS - Yet Another Snake, coded by myself)

* CHIP-OTTO and WEB-OTTO, my own CHIP-8 interpreters

Tools used for A Day At The Animal Races development:

* Notepad++

* bas2tap

* Visual Studio Code and its git plugin

* Fuse - the Free Unix Spectrum Emulator and Fuse-utils

* BasinC's great UDG editor and import utility

* This online CSV rows to columns converter: https://onlinecsvtools.com/convert-csv-rows-to-columns and Microsoft Excel helped to encode UDG characters data to a string

* paint.net

* ImageMagick

* Typora for writing this manual

The A Day At The Races album by Queen - I didn't yet watch the comedy with the Marx Brothers from which the album inherited the name

Love animals!

Download

Download
ADayAtTheAnimalRaces.bas 1 kB
Download
ADayAtTheAnimalRaces.pdf 277 kB
Download
ADayAtTheAnimalRaces.tap 1.1 kB
Download
ADayAtTheAnimalRaces.txt 12 kB

Install instructions

LOADING INSTRUCTIONS

A Day At The Animal Races is provided in TAP tape image format, which can be easily loaded in most ZX Spectrum emulators and on the real machines, either equipped with devices such as the DivMMC or by playing it through the MIC port using tools like PlayTZX or WinTZX.

Fuse emulator

The following instructions apply to the Fuse open source emulator, which is available for Unix, Linux, Windows, macOS and many other platforms.

For other emulators or devices, please refer to their specific documentation for loading TAP files.

Start the Fuse emulator and select the Spectrum 48K model in "Machine" -> "Select..."

Make sure that automatic loading of tape image files is enabled, by checking the corresponding options in "Options" -> "Media..."

Open the ADayAtTheAnimalRaces.tap file, either by selecting it in "File"->"Open..." or by dragging and dropping it on the emulator window.

To see the program listing, BREAK the program by pressing SHIFT + SPACE (the CAPS SHIFT ZX Spectrum key is usually mapped to SHIFT) in the middle of a race.

The "L BREAK into program" message will be displayed.

Then press the K key, followed by ENTER. Now you will see the first page of the program listing; to scroll to the next page, press any key except SPACE.

If your emulator of choice does not support automatic tape loading, after mounting the tape image you must manually issue the tape loading command, by pressing the J key, followed by CTRL + P twice (the SYMBOL SHIFT ZX Spectrum key is usually mapped to CTRL) and then by ENTER.

You may have to press PLAY on the virtual tape emulator.

JSSpeccy

Alternatively, if your web browser supports Javascript, you can play directly in your browser (powered by JSSpeccy - A ZX Spectrum emulator in Javascript).

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

Mobile devices are not currently supported.

Leave a comment

Log in with itch.io to leave a comment.