Spinner

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

This program implements a 4×4 sliding-tile puzzle called “SPINNER T.M.” where sixteen tiles are arranged in a grid and the player rotates groups of four tiles in a cycle using keyboard keys. The array A$(16,1) stores the current symbol in each of the 16 tile positions, with each cell holding one of four inverse-video characters (X, colon, O, or space) indicating the tile type. The 16 move subroutines (lines 1000–1269) each perform a four-way cyclic rotation among four specific array indices, using a temporary variable B$ for the swap. The display loop redraws the board frame using inverse-video border characters and then plots the current tile symbols into the grid at lines 500–550; PAUSE 60000 inside the loop effectively halts until a keypress is detected in the next iteration. The program auto-saves itself with an auto-run flag via the SAVE command at line 1280.


Program Analysis

Program Structure

The program is divided into four functional regions:

  1. Initialisation (lines 5–60): Populates a 16-element string array with the starting tile symbols.
  2. Main game loop (lines 70–570): Scans 16 keys, redraws the board frame and tile grid, then pauses before repeating.
  3. Move subroutines (lines 1000–1269): One subroutine per key, each performing a four-element cyclic rotation in the tile array.
  4. Save/restart (lines 1270–1290): Clears memory, saves the program with an auto-run flag, and restarts.

Data Representation

The board is modelled as A$(16,1), a 16-row string array where each row holds exactly one character. The four tile types are initialised in lines 10–60:

Array indicesCharacterMeaning
1–4%X (inverse X)Top row tiles
5–8%: (inverse colon/block)Second row tiles
9–12%O (inverse O)Third row tiles
13–16% (inverse space)Bottom row tiles

The solved state therefore has all tiles of the same type in their respective row, providing a clear visual goal.

Board Layout and Display

The frame is drawn unconditionally on every loop iteration (lines 400–430) using inverse-video border characters including %=, %S, %P etc. to form decorative text and box-drawing lines. The tile symbols are then overlaid in lines 500–550 using PRINT AT 6,(9+2*A) and similar expressions, placing tiles in every other column to give visual spacing. The PAUSE 60000 at line 560 acts as a long delay that is effectively interrupted by the INKEY$ polling on the next loop iteration — since PAUSE does not exit early on keypress in this context, the game relies on the outer FOR T=1 TO 60000 loop cycling rapidly through the INKEY$ checks before reaching the PAUSE.

Move Subroutines and the Rotation Mechanic

Each of the 16 keys (1–4, Q–R, A–F, Z–V) calls a dedicated subroutine that rotates four specific array indices in a cycle. The canonical pattern uses a temporary string B$:

  1. Save the first element into B$.
  2. Copy element 2 → position 1, element 3 → position 2, element 4 → position 3.
  3. Restore B$ into position 4.

This is a standard four-element left-rotation. The indices chosen for each subroutine define which “spinner” on the board is activated, linking adjacent or diagonal cells in a pattern consistent with the game’s name.

Key-to-Subroutine Mapping

KeySubroutineIndices rotated
110002→13→4→5→2
211203→14→1→6→3
311304→15→2→7→4
411401→16→3→8→1
Q11506→1→8→9→6
W11607→2→5→10→7
E11708→3→6→11→8
R11805→4→7→12→5
A119010→5→12→13→10
S120011→6→9→14→11
D121012→7→10→15→12
F12209→8→11→16→9
Z123014→9→16→1→14
X124015→10→13→2→15
C125016→11→10→3→16
V126013→12→15→4→13

Notable Techniques

  • Single-character string array: DIM A$(16,1) exploits the ZX81’s fixed-length string array rows to store exactly one character per tile, making indexing straightforward with A$(N) notation.
  • Inline INKEY$ polling: Each key check is a separate IF INKEY$="x" THEN GOSUB line rather than using a variable, avoiding the overhead of storing the key value but requiring 16 consecutive INKEY$ reads per frame, which can miss fast keypresses.
  • Symmetric keyboard layout: The keys 1–4 occupy a physical row, Q–R the next, A–F the next, and Z–V the bottom — matching the four columns and four rows of the spinner grid in a spatially intuitive way.
  • Auto-run save: Line 1280 uses an inverse-video digit in the filename to set the auto-run flag, so the program restarts automatically when loaded.

Anomalies and Notes

  • Line 1250 rotates indices 16→11→10→3→16. The middle step goes 11→10 rather than 11→14 as would be expected for a clean 2×2 spinner — this may be an intentional asymmetric move or a transcription error in the original.
  • The subroutine numbering is inconsistent: the first subroutine is at 1000 while subsequent ones skip to 1120, leaving a gap of 120 lines that could have accommodated the earlier subroutine’s lines more naturally at 1100.
  • PAUSE 60000 inside the main loop means the screen freezes for a very long time if no key is pressed during the INKEY$ checks at the top of each iteration; the effective frame rate depends entirely on how quickly lines 75–260 are scanned.

Content

Appears On

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

Related Products

Related Articles

Related Content

Image Gallery

Spinner

Source Code

   5 DIM A$(16,1)
  10 FOR B=1 TO 4
  20 LET A$(B)="%X"
  30 LET A$(4+B)="%:"
  40 LET A$(8+B)="%O"
  50 LET A$(12+B)="% "
  60 NEXT B
  70 FOR T=1 TO 60000
  75 IF INKEY$="1" THEN GOSUB 1000
 120 IF INKEY$="2" THEN GOSUB 1120
 130 IF INKEY$="3" THEN GOSUB 1130
 140 IF INKEY$="4" THEN GOSUB 1140
 150 IF INKEY$="Q" THEN GOSUB 1150
 160 IF INKEY$="W" THEN GOSUB 1160
 170 IF INKEY$="E" THEN GOSUB 1170
 180 IF INKEY$="R" THEN GOSUB 1180
 190 IF INKEY$="A" THEN GOSUB 1190
 200 IF INKEY$="S" THEN GOSUB 1200
 210 IF INKEY$="D" THEN GOSUB 1210
 220 IF INKEY$="F" THEN GOSUB 1220
 230 IF INKEY$="Z" THEN GOSUB 1230
 240 IF INKEY$="X" THEN GOSUB 1240
 250 IF INKEY$="C" THEN GOSUB 1250
 260 IF INKEY$="V" THEN GOSUB 1260
 400 PRINT AT 2,7;"%=%=%=%=%=%=%=%=%=%=%=%=%=%=%=%="
 405 PRINT AT 3,7;"%    %S%P%I%N%N%E%R   % T.M."
 410 PRINT AT 4,7;"%  %=%=%=%=%=%=%=%=%=%=%= % "
 411 PRINT AT 5,7;"%  %          %  % " 
 412 PRINT AT 6,7;"% %X%          % %X% "
 413 PRINT AT 7,7;"%  %          %  % "
 414 PRINT AT 8,7;"% %:%          % %:% "
 415 PRINT AT 9,7;"%  %          %  % "
 416 PRINT AT 10,7;"% %O%          % %O% "
 417 PRINT AT 11,7;"%  %          %  % "
 418 PRINT AT 12,7;"%=%=%=         %=%=%="
 419 PRINT AT 13,7;"%  %          %  % "
 423 PRINT AT 14,7;"%  % %*%*%*%*%*%*%*%*%*%  % "
 425 PRINT AT 15,7;"%              % "
 430 PRINT AT 16,7;"%=%=%=%=%=%=%=%=%=%=%=%=%=%=%="
 500 FOR A=1 TO 4
 510 PRINT AT 6,(9+2*A);A$(A);" "
 520 PRINT AT 8,(9+2*A);A$(4+A);" "
 530 PRINT AT 10,(9+2*A);A$(8+A);" "
 540 PRINT AT 12,(9+2*A);A$(12+A);" "
 550 NEXT A
 560 PAUSE 60000
 570 NEXT T
\n1000 LET B$=A$(2)
\n1010 LET A$(2)=A$(13)
\n1020 LET A$(13)=A$(4)
\n1030 LET A$(4)=A$(5)
\n1040 LET A$(5)=B$
\n1050 RETURN 
\n1120 LET B$=A$(3)
\n1122 LET A$(3)=A$(14)
\n1124 LET A$(14)=A$(1)
\n1126 LET A$(1)=A$(6)
\n1128 LET A$(6)=B$
\n1129 RETURN 
\n1130 LET B$=A$(4)
\n1132 LET A$(4)=A$(15)
\n1134 LET A$(15)=A$(2)
\n1136 LET A$(2)=A$(7)
\n1138 LET A$(7)=B$
\n1139 RETURN 
\n1140 LET B$=A$(1)
\n1142 LET A$(1)=A$(16)
\n1144 LET A$(16)=A$(3)
\n1146 LET A$(3)=A$(8)
\n1148 LET A$(8)=B$
\n1149 RETURN 
\n1150 LET B$=A$(6)
\n1152 LET A$(6)=A$(1)
\n1154 LET A$(1)=A$(8)
\n1156 LET A$(8)=A$(9)
\n1158 LET A$(9)=B$
\n1159 RETURN 
\n1160 LET B$=A$(7)
\n1162 LET A$(7)=A$(2)
\n1164 LET A$(2)=A$(5)
\n1166 LET A$(5)=A$(10)
\n1168 LET A$(10)=B$
\n1169 RETURN 
\n1170 LET B$=A$(8)
\n1172 LET A$(8)=A$(3)
\n1174 LET A$(3)=A$(6)
\n1176 LET A$(6)=A$(11)
\n1178 LET A$(11)=B$
\n1179 RETURN 
\n1180 LET B$=A$(5)
\n1182 LET A$(5)=A$(4)
\n1184 LET A$(4)=A$(7)
\n1186 LET A$(7)=A$(12)
\n1188 LET A$(12)=B$
\n1189 RETURN 
\n1190 LET B$=A$(10)
\n1192 LET A$(10)=A$(5)
\n1194 LET A$(5)=A$(12)
\n1196 LET A$(12)=A$(13)
\n1198 LET A$(13)=B$
\n1199 RETURN 
\n1200 LET B$=A$(11)
\n1202 LET A$(11)=A$(6)
\n1204 LET A$(6)=A$(9)
\n1206 LET A$(9)=A$(14)
\n1208 LET A$(14)=B$
\n1209 RETURN 
\n1210 LET B$=A$(12)
\n1212 LET A$(12)=A$(7)
\n1214 LET A$(7)=A$(10)
\n1216 LET A$(10)=A$(15)
\n1218 LET A$(15)=B$
\n1219 RETURN 
\n1220 LET B$=A$(9)
\n1222 LET A$(9)=A$(8)
\n1224 LET A$(8)=A$(11)
\n1226 LET A$(11)=A$(16)
\n1228 LET A$(16)=B$
\n1229 RETURN 
\n1230 LET B$=A$(14)
\n1232 LET A$(14)=A$(9)
\n1234 LET A$(9)=A$(16)
\n1236 LET A$(16)=A$(1)
\n1238 LET A$(1)=B$
\n1239 RETURN 
\n1240 LET B$=A$(15)
\n1242 LET A$(15)=A$(10)
\n1244 LET A$(10)=A$(13)
\n1246 LET A$(13)=A$(2)
\n1248 LET A$(2)=B$
\n1249 RETURN 
\n1250 LET B$=A$(16)
\n1252 LET A$(16)=A$(11)
\n1254 LET A$(11)=A$(10)
\n1256 LET A$(10)=A$(3)
\n1258 LET A$(3)=B$
\n1259 RETURN 
\n1260 LET B$=A$(13)
\n1262 LET A$(13)=A$(12)
\n1264 LET A$(12)=A$(15)
\n1266 LET A$(15)=A$(4)
\n1268 LET A$(4)=B$
\n1269 RETURN 
\n1270 CLEAR 
\n1280 SAVE "1026%8"
\n1290 RUN 

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

People

No people associated with this content.

Scroll to Top