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

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
 1000 FOR I=1 TO 8
 1010 PRINT AT 10+I,Y;A$(I);AT 10+I,Z;B$(I)
 1012 NEXT I
 1030 REM %M%O%V%E%M%E%N%T
 1040 IF INKEY$="X" THEN LET Y=Y+1
 1045 IF INKEY$="Z" THEN LET Y=Y-1
 1050 IF INKEY$="M" THEN LET Z=Z+1
 1055 IF INKEY$="N" THEN LET Z=Z-1
 1100 REM %M%O%V%E%M%E%N%T% %C%H%E%C%K
 1200 IF Y<1 THEN LET Y=1
 1220 IF Y>19 THEN LET Y=19
 1240 IF Y=Z-6 THEN GOSUB 2000
 1250 IF Z<1 THEN LET Z=1
 1260 IF Z>24 THEN LET Z=24
 1300 GOTO 1000
 1900 REM %A%T%T%A%C%K% %S%T%A%R%T
 2000 FOR I=1 TO 6
 2010 PRINT AT 10+I,Y;C$(I);AT 10+I,Z;D$(I)
 2020 NEXT I
 2021 REM %S%E%E% %I%F% %H%I%T
 2022 LET K=INT ((RND*10)+1)
 2023 IF K>5 THEN LET V=V-1
 2024 PRINT AT 2,10;V
 2026 IF V=0 THEN GOTO 5000
 2100 LET N=INT ((RND*10)+1)
 2109 IF N>5 THEN LET J=J-1
 2110 PRINT AT 2,26;J
 2120 IF J=0 THEN GOTO 3000
 2500 GOTO 1030
 3000 REM %P%L%A%Y%E%R% %2% %D%I%E%S
 3094 FOR I=1 TO 8
 3960 PRINT AT 10+I,Z;E$(I);AT 10+I,Y;G$(I)
 3980 NEXT I
 3985 FOR N=1 TO 40
 3990 PRINT AT 20,2;"  PLAYER 1 HAS KILLED YOU  "
 3994 PRINT AT 20,2;"  %P%L%A%Y%E%R% %1% %H%A%S% %K%I%L%L%E%D% %Y%O%U    "
 3998 NEXT N
 4000 GOTO 8000
 4999 REM %P%L%A%Y%E%R% %1% %D%I%E%S
 5000 FOR I=1 TO 8
 5010 PRINT AT 10+I,Y;F$(I);AT 10+I,Z;H$(I)
 5030 NEXT I
 5040 FOR N=1 TO 40
 5050 PRINT AT 20,2;"  PLAYER 2 HAS KILLED YOU   "
 5060 PRINT AT 20,2;"  %P%L%A%Y%E%R% %2% %H%A%S% %K%I%L%L%E%D% %Y%O%U    "
 5070 NEXT N
 5100 GOTO 8000
 7000 LET Z=20
 7002 LET Y=6
 7004 LET V=9
 7006 LET J=9
 7009 REM %D%I%M% %A%L%L% %A%R%R%A%Y%S
 7010 DIM A$(8,6)
 7012 LET A$(1)="  :    "
 7014 LET A$(2)="  :    "
 7016 LET A$(3)=" ':'    "
 7018 LET A$(4)=" :  ::   "
 7020 LET A$(5)="  '%  .  "
 7022 LET A$(6)="  %K''  "
 7024 LET A$(7)="  :'':  "
 7026 LET A$(8)=" :''  ''  "
 7030 DIM B$(8,6)
 7032 LET B$(1)="    :  "
 7034 LET B$(2)="    :  "
 7036 LET B$(3)="    ':' "
 7038 LET B$(4)="   ::  : "
 7040 LET B$(5)="  . % '  "
 7042 LET B$(6)="  ''%L  "
 7044 LET B$(7)="  :'':  "
 7046 LET B$(8)="  ''  '': "
 7050 DIM C$(6,6)
 7056 LET C$(4)="   %   "
 7058 LET C$(5)="  ':: .  "
 7060 LET C$(6)="   ::'~~~~"
 7070 DIM D$(6,6)
 7072 LET D$(4)="  %   "
 7074 LET D$(5)=" .  ::' "
 7076 LET D$(6)="~~~~'::  "
 7080 REM %D%E%A%T%H% %M%O%V%E%S
 7090 DIM E$(8,6)
 7095 LET E$(4)="% .   "
 7097 LET E$(5)=" '%   "
 7098 LET E$(6)=" '%   "
 7100 LET E$(7)="  ::  "
 7102 LET E$(8)="  '  "
 7120 DIM F$(8,6)
 7122 LET F$(4)="     .% "
 7124 LET F$(5)="    % ' "
 7126 LET F$(6)="    % ' "
 7128 LET F$(7)="    ::  "
 7130 LET F$(8)="    '  "
 7140 REM %H%E%R%O% %M%O%V%E%S
 7150 DIM G$(8,6)
 7152 LET G$(1)="     : "
 7154 LET G$(2)="     : "
 7156 LET G$(3)="   . ':' "
 7158 LET G$(4)="  : %  : "
 7160 LET G$(5)="   '%.'  "
 7162 LET G$(6)="   .%..  "
 7164 LET G$(7)="   : :  "
 7166 LET G$(8)="  '' '  "
 7170 DIM H$(8,6)
 7172 LET H$(1)=" :     "
 7174 LET H$(2)=" :     "
 7176 LET H$(3)=" ':'    "
 7178 LET H$(4)=" : %" :  "
 7180 LET H$(5)="  '%$'   "
 7182 LET H$(6)="  .##.   "
 7184 LET H$(7)="  : :   "
 7186 LET H$(8)="  ' ''  "
 8000 FOR N=1 TO 22
 8010 SCROLL 
 8020 NEXT N
 8025 FAST 
 8030 PRINT AT 0,0;"% % ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;% % "
 8040 PRINT AT 1,0;"% % ########################################################% % "
 8050 FOR N=1 TO 18
 8060 PRINT "% ############################################################% "
 8070 NEXT N
 8080 PRINT AT 20,0;"% % ########################################################% % "
 8090 PRINT AT 21,0;"% % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!% % "
 8100 SLOW 
 8110 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*"
 8120 PRINT AT 7,2;"THIS IS A GRAPHICAL GAME OF ";AT 8,2;"     COMBAT BETWEEN TWO     "
 8130 PRINT AT 9,2;"GLADIATORS IT CAN BE PLAYED ";AT 10,2;"IN TWO DIFFERENT WAYS EITHER"
 8140 PRINT AT 11,2;"1) YOU AGAINST THE COMPUTER ";AT 12,2;"2) YOU AGAINST A FRIEND     "
 8150 PRINT AT 13,2;"NOTE YOU CAN CHANGE SIDES AT";AT 14,2;"AT ANY TIME                 "
 8160 PRINT AT 15,2;"TO MOVE GLADIATOR ""K"" USE   ";AT 16,2;"KEYS (Z)-(X)                "
 8170 PRINT AT 17,2;"TO MOVE GLADIATOR ""L"" USE   "
 8180 PRINT AT 18,2;"KEYS (N)-(M)                "
 8190 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%."
 9192 IF INKEY$="" THEN GOTO 9192
 9195 GOTO 3
 9200 CLEAR 
 9210 SAVE "1028%4"
 9220 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