Gladiators

This file is part of and Timex Sinclair Public Domain Library Tape 1006. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Game

Gladiator is a two-player combat game in which two sprite characters fight each other on a bordered arena screen, each controlled by a pair of keys (Z/X for Player 1, N/M for Player 2). The program uses eight-row by six-column string arrays (A$–H$) to store multiple sprite frames for each gladiator: standing poses, attacking poses, and death animations, all drawn using ZX81 block graphics characters. Collision detection is handled by checking whether the two players’ column positions differ by exactly six (line 1240), which triggers the attack subroutine at line 2000. Hit resolution is randomised with a 50% probability (RND*10 > 5), reducing each player’s hit counter from 9 to 0, and when either reaches zero the corresponding death animation and scrolling victory message are displayed.


Program Analysis

Program Structure

The program is organised into clearly separated regions, navigated primarily by GOTO rather than structured subroutines:

  1. Lines 1–2: REM header and immediate GOTO 7000 to bypass all game code on first run.
  2. Lines 450–999: Screen setup routine — draws the arena border, score display, and title graphic using block graphics strings.
  3. Lines 1000–1300: Main game loop — renders both gladiator sprites at their current column positions, reads keypresses, enforces boundary limits, and checks for combat range.
  4. Lines 2000–2500: Attack subroutine — draws attack-pose sprites for both fighters, applies random hit logic, updates scores, and checks for death conditions.
  5. Lines 3000–4000 / 5000–5100: Death sequences for Player 2 and Player 1 respectively, showing a flashing kill message before jumping to the end screen.
  6. Lines 7000–7186: Initialisation — sets starting positions and scores, then DIMs and populates all eight sprite arrays.
  7. Lines 8000–9220: End/title screen — scrolls the display clear, draws a decorated title panel, shows instructions, and waits for a keypress before restarting.

Sprite System

All character graphics are stored as fixed-length string arrays, each row being six characters wide and eight rows tall, using ZX81 block graphic characters embedded directly in string literals. Eight separate arrays cover the different animation states:

ArrayPurposeRows used
A$(8,6)Player 1 standing1–8
B$(8,6)Player 2 standing1–8
C$(6,6)Player 1 attacking4–6
D$(6,6)Player 2 attacking4–6
E$(8,6)Player 2 dying4–8
F$(8,6)Player 1 dying4–8
G$(8,6)Player 1 victory1–8
H$(8,6)Player 2 victory1–8

Only a subset of rows in the attack and death arrays are explicitly populated; the others remain as spaces (the default after DIM), which effectively erases the upper body when those frames are drawn — a deliberate cropping technique rather than a bug.

Main Game Loop

The loop at lines 1000–1300 is tight and unconditional. It redraws both sprites every iteration regardless of input, then samples INKEY$ four times in sequence (lines 1040–1055) for the four movement keys. Because each IF INKEY$= is a separate statement, only one key can be acted upon per pass, and holding multiple keys will only register one. Boundary clamping follows immediately (lines 1200–1260), and the loop ends with an unconditional GOTO 1000.

Collision and Combat Detection

Combat is triggered exclusively by line 1240: IF Y=Z-6 THEN GOSUB 2000. This means the attack subroutine fires only when Player 1’s column position Y is exactly six less than Player 2’s column Z. There is no symmetric check (i.e. Player 2 moving left into Player 1 does not trigger combat), which means combat can only occur with Player 1 to the left of Player 2 at that precise distance — a significant gameplay asymmetry.

Hit Resolution

Within the attack subroutine, each hit is resolved independently with a 50 % probability:

  • K = INT((RND*10)+1) → if K>5, Player 1 loses a hit point (V).
  • N = INT((RND*10)+1) → if N>5, Player 2 loses a hit point (J).

Both players start with 9 hit points. The subroutine does not return normally to the main loop — after updating scores and checking for death, control falls through to GOTO 1030 (line 2500), bypassing the boundary check at lines 1200–1260 for that iteration.

Death and End-Game Sequences

When a player’s hit counter reaches zero, the program jumps directly to a death animation block. A FOR N=1 TO 40 loop alternates between printing the kill message in normal and inverse video, creating a flashing effect. Both death routines then jump to line 8000, the shared end screen, which uses SCROLL in a loop to wipe the display before showing the title/instructions screen and waiting on IF INKEY$="" THEN GOTO 9192.

Screen Layout

The arena is drawn with a decorative border using block graphic characters ( top, bottom, sides) at lines 500–900. The title graphic at lines 911–915 spells out “GLADIATOR” in inverse characters surrounded by block art. Player scores are printed at fixed positions (AT 2,10 and AT 2,26) and refreshed only when a hit occurs, not every game loop iteration.

Notable Techniques and Idioms

  • The entry point bypass (GOTO 7000 at line 2) ensures initialisation always runs before game code, while keeping the functional game code at lower line numbers for faster lookup.
  • The end screen uses FAST (line 8025) before the heavy block-graphic printing and SLOW (line 8100) before the text display, managing display speed deliberately.
  • Lines 9200–9220 (CLEAR / SAVE / RUN) are utility lines for saving the program with auto-run, not part of normal execution flow.
  • The flashing kill-message technique (alternating normal/inverse strings in a tight loop) is a common ZX81 animation idiom requiring no timing hardware.

Bugs and Anomalies

  • Line 9195 jumps to line 3, which does not exist. This is a deliberate technique — on the ZX81, GOTO to a non-existent line number jumps to the next higher line, which here is line 450 (the screen setup routine), effectively restarting the game without re-initialising scores or positions.
  • The attack-range check (Y=Z-6) is one-directional; if Player 2 moves to within range from the left side, no combat occurs.
  • Line 7178 contains %"\ : — a literal quote character inside the string literal for H$(4), likely a data entry error producing unexpected graphics in that sprite row.
  • Line 7180 contains %$\' and line 7182 contains \## — the $ and ## sequences are not standard zmakebas escapes, suggesting possible corruption or non-standard characters in those sprite rows.
  • The attack subroutine is called with GOSUB 2000 but exits via GOTO 1030 rather than RETURN, making it effectively a jump rather than a true subroutine — the GOSUB stack entry is never cleared, which will cause a stack growth issue over a long game.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10252 – 10293.

Related Products

Related Articles

Related Content

Image Gallery

Gladiators

Source Code

   1 REM %S%E%T% %A%L%L% %V%A%L%U%E%S
   2 GOTO 7000
 450 REM %S%C%R%E%E%N% %S%E%T% %U%P
 500 PRINT AT 0,0;"% \''\''\''\''\''\''\''\''\''\''\''\''\''\''% \''\''\''\''\''\''\''\''\''\''\''\''\''\''\''% "
 510 FOR N=1 TO 20
 520 PRINT "\:                               \ :"
 530 NEXT N
 540 PRINT "% \..\..\..\..\..\..\..\..\..\..\..\..\..\..% \..\..\..\..\..\..\..\..\..\..\..\..\..\..\..% "
 550 PRINT AT 20,1;" KEYS:(Z)-(X) \ :  KEYS:(N)-(M)"
 600 PRINT AT 3,0;"% \..\..\..\..\..\..\..\..\..\..\..\..\..\..% \..\..\..\..\..\..\..\..\..\..\..\..\..\..\..% "
 610 PRINT AT 1,15;"\ :";AT 2,15;"\ :"
 650 PRINT AT 1,4;"%P%L%A%Y%E%R% %1";AT 1,20;"%P%L%A%Y%E%R% %2";AT 2,4;"HITS= ";V;AT 2,20;"HITS= ";J
 900 PRINT AT 19,0;"% \''\''\''\''\''\''\''\''\''\''\''\''\''\''% \''\''\''\''\''\''\''\''\''\''\''\''\''\''\''% "
 911 PRINT AT 5,0;"\:        \..\..% % % % % % % % % % % % % \..\..      \ :"
 912 PRINT AT 6,0;"\:    \..\..% % % % % % %G%L%A%D%I%A%T%O%R% % % % % % \..\..  \ :"
 913 PRINT AT 7,0;"\:.\..% % % % % % % % \''\''\''\''\''\''\''\''\''\''\''\''% % % % % % % % \..\.:"
 914 PRINT AT 8,0;"% % % % % % %                   % % % % % % % "
 915 PRINT AT 9,0;"% \''\''\''                        \''\''\''% "
 999 REM %S%T%A%R%T% %O%F% %G%A%M%E
\n1000 FOR I=1 TO 8
\n1010 PRINT AT 10+I,Y;A$(I);AT 10+I,Z;B$(I)
\n1012 NEXT I
\n1030 REM %M%O%V%E%M%E%N%T
\n1040 IF INKEY$="X" THEN LET Y=Y+1
\n1045 IF INKEY$="Z" THEN LET Y=Y-1
\n1050 IF INKEY$="M" THEN LET Z=Z+1
\n1055 IF INKEY$="N" THEN LET Z=Z-1
\n1100 REM %M%O%V%E%M%E%N%T% %C%H%E%C%K
\n1200 IF Y<1 THEN LET Y=1
\n1220 IF Y>19 THEN LET Y=19
\n1240 IF Y=Z-6 THEN GOSUB 2000
\n1250 IF Z<1 THEN LET Z=1
\n1260 IF Z>24 THEN LET Z=24
\n1300 GOTO 1000
\n1900 REM %A%T%T%A%C%K% %S%T%A%R%T
\n2000 FOR I=1 TO 6
\n2010 PRINT AT 10+I,Y;C$(I);AT 10+I,Z;D$(I)
\n2020 NEXT I
\n2021 REM %S%E%E% %I%F% %H%I%T
\n2022 LET K=INT ((RND*10)+1)
\n2023 IF K>5 THEN LET V=V-1
\n2024 PRINT AT 2,10;V
\n2026 IF V=0 THEN GOTO 5000
\n2100 LET N=INT ((RND*10)+1)
\n2109 IF N>5 THEN LET J=J-1
\n2110 PRINT AT 2,26;J
\n2120 IF J=0 THEN GOTO 3000
\n2500 GOTO 1030
\n3000 REM %P%L%A%Y%E%R% %2% %D%I%E%S
\n3094 FOR I=1 TO 8
\n3960 PRINT AT 10+I,Z;E$(I);AT 10+I,Y;G$(I)
\n3980 NEXT I
\n3985 FOR N=1 TO 40
\n3990 PRINT AT 20,2;"  PLAYER 1 HAS KILLED YOU  "
\n3994 PRINT AT 20,2;"  %P%L%A%Y%E%R% %1% %H%A%S% %K%I%L%L%E%D% %Y%O%U    "
\n3998 NEXT N
\n4000 GOTO 8000
\n4999 REM %P%L%A%Y%E%R% %1% %D%I%E%S
\n5000 FOR I=1 TO 8
\n5010 PRINT AT 10+I,Y;F$(I);AT 10+I,Z;H$(I)
\n5030 NEXT I
\n5040 FOR N=1 TO 40
\n5050 PRINT AT 20,2;"  PLAYER 2 HAS KILLED YOU   "
\n5060 PRINT AT 20,2;"  %P%L%A%Y%E%R% %2% %H%A%S% %K%I%L%L%E%D% %Y%O%U    "
\n5070 NEXT N
\n5100 GOTO 8000
\n7000 LET Z=20
\n7002 LET Y=6
\n7004 LET V=9
\n7006 LET J=9
\n7009 REM %D%I%M% %A%L%L% %A%R%R%A%Y%S
\n7010 DIM A$(8,6)
\n7012 LET A$(1)=" \ :    "
\n7014 LET A$(2)=" \ :    "
\n7016 LET A$(3)=" \':\'    "
\n7018 LET A$(4)=" \: \ :\:   "
\n7020 LET A$(5)=" \ '%  \.  "
\n7022 LET A$(6)="  %K\''  "
\n7024 LET A$(7)="  \:'\':  "
\n7026 LET A$(8)=" \:'\' \ '\'  "
\n7030 DIM B$(8,6)
\n7032 LET B$(1)="    \:  "
\n7034 LET B$(2)="    \:  "
\n7036 LET B$(3)="   \ '\:' "
\n7038 LET B$(4)="  \ :\: \ : "
\n7040 LET B$(5)=" \ . % \'  "
\n7042 LET B$(6)="  \''%L  "
\n7044 LET B$(7)="  \:'\':  "
\n7046 LET B$(8)=" \ '\' \ '\': "
\n7050 DIM C$(6,6)
\n7056 LET C$(4)="   %   "
\n7058 LET C$(5)="  \':\: \.  "
\n7060 LET C$(6)="  \ :\:'\~~\~~"
\n7070 DIM D$(6,6)
\n7072 LET D$(4)="  %   "
\n7074 LET D$(5)=" \. \ :\:' "
\n7076 LET D$(6)="\~~\~~\':\:  "
\n7080 REM %D%E%A%T%H% %M%O%V%E%S
\n7090 DIM E$(8,6)
\n7095 LET E$(4)="% \.   "
\n7097 LET E$(5)="\ '%   "
\n7098 LET E$(6)="\ '%   "
\n7100 LET E$(7)=" \ :\:  "
\n7102 LET E$(8)="  \'  "
\n7120 DIM F$(8,6)
\n7122 LET F$(4)="    \ .% "
\n7124 LET F$(5)="    % \' "
\n7126 LET F$(6)="    % \' "
\n7128 LET F$(7)="   \ :\:  "
\n7130 LET F$(8)="   \ '  "
\n7140 REM %H%E%R%O% %M%O%V%E%S
\n7150 DIM G$(8,6)
\n7152 LET G$(1)="    \ : "
\n7154 LET G$(2)="    \ : "
\n7156 LET G$(3)="  \ . \':\' "
\n7158 LET G$(4)="  \: % \ : "
\n7160 LET G$(5)="  \ '%.\'  "
\n7162 LET G$(6)="  \ .%.\.  "
\n7164 LET G$(7)="  \ : \:  "
\n7166 LET G$(8)="  \'' \'  "
\n7170 DIM H$(8,6)
\n7172 LET H$(1)=" \:     "
\n7174 LET H$(2)=" \:     "
\n7176 LET H$(3)="\ '\:'    "
\n7178 LET H$(4)=" \: %"\ :  "
\n7180 LET H$(5)=" \ '%$\'   "
\n7182 LET H$(6)=" \ .\##\.   "
\n7184 LET H$(7)=" \ : \:   "
\n7186 LET H$(8)=" \ ' \''  "
\n8000 FOR N=1 TO 22
\n8010 SCROLL 
\n8020 NEXT N
\n8025 FAST 
\n8030 PRINT AT 0,0;"% % \;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;% % "
\n8040 PRINT AT 1,0;"% % \##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##% % "
\n8050 FOR N=1 TO 18
\n8060 PRINT "% \##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##% "
\n8070 NEXT N
\n8080 PRINT AT 20,0;"% % \##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##\##% % "
\n8090 PRINT AT 21,0;"% % \!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!% % "
\n8100 SLOW 
\n8110 PRINT AT 3,10;"*%W%E%L%C%O%M%E% %T%O*";AT 5,10;"*%G%L%A%D%I%A%T%O%R%S*"
\n8120 PRINT AT 7,2;"THIS IS A GRAPHICAL GAME OF ";AT 8,2;"     COMBAT BETWEEN TWO     "
\n8130 PRINT AT 9,2;"GLADIATORS IT CAN BE PLAYED ";AT 10,2;"IN TWO DIFFERENT WAYS EITHER"
\n8140 PRINT AT 11,2;"1) YOU AGAINST THE COMPUTER ";AT 12,2;"2) YOU AGAINST A FRIEND     "
\n8150 PRINT AT 13,2;"NOTE YOU CAN CHANGE SIDES AT";AT 14,2;"AT ANY TIME                 "
\n8160 PRINT AT 15,2;"TO MOVE GLADIATOR ""K"" USE   ";AT 16,2;"KEYS (Z)-(X)                "
\n8170 PRINT AT 17,2;"TO MOVE GLADIATOR ""L"" USE   "
\n8180 PRINT AT 18,2;"KEYS (N)-(M)                "
\n8190 PRINT AT 20,3;"%P%R%E%S%S% %A%N%Y% %K%E%Y% %T%O% %C%O%N%T%I%N%U%E%."
\n9192 IF INKEY$="" THEN GOTO 9192
\n9195 GOTO 3
\n9200 CLEAR 
\n9210 SAVE "1028%4"
\n9220 RUN 7000

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top