--- title: "Twists" id: 72412 type: "computer_media" slug: "twists" url: "http://localhost/computer_media/twists/" markdown_url: "http://localhost/computer_media/twists.md" published_at: "2026-10-23T07:47:08+00:00" modified_at: "2026-10-23T07:47:08+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/10/twists-1.png" excerpt: "Restore a scrambled four-by-four board of coloured tiles by twisting its rows and columns, racing the clock, with machine code painting the tiles." post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Paul Clansey" slug: "paul-clansey" taxonomy: "indiv" url: "http://localhost/indiv/paul-clansey/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" programmers: - name: "Paul Clansey" slug: "paul-clansey" taxonomy: "indiv" url: "http://localhost/indiv/paul-clansey/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Twists%20%281984%29%28Clansey%2C%20Paul%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "Twists (1984)(Clansey, Paul)(TS2068)(US)(Program)/Twists (1984)(Clansey, Paul)(TS2068)(US)(Program).tap" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2026/10/twists-1.png" - url: "http://localhost/wp-content/uploads/2026/10/twists-2.png" - url: "http://localhost/wp-content/uploads/2026/10/twists-3.png" related_content: - id: 10285 title: "ZX Computing" type: "periodical" url: "http://localhost/periodical/zx-computing/" - id: 72713 title: "SNUG-ISTUG Public Domain Library" type: "computer_media" url: "http://localhost/computer_media/snug-istug-public-domain-library/" media_type_tags: "Game" license: false --- # Twists A sliding-tile puzzle against the clock. The board is a four-by-four grid in four colour blocks: red, yellow, green and blue quarters. Thirty random twists scramble it. Keys `a`–`d` shift a column up, `i`–`l` shift a column down, `e`–`h` shift a row left and `m`–`p` shift a row right; each shift wraps the end tile round to the other side. The keys are labelled with arrows round the board. Press `Q` when you think you are done: a solved board shows your time in seconds, and an unsolved one says INCOMPLETE and the game starts over. A REM credits Paul Clansey and *ZX Computing*, February/March 1984. ## Program Analysis ### Structure - Lines 1–2: a REM holding the machine code, and a loop that POKEs the 44 code bytes from DATA lines 6–8 to 26715. - Lines 20–55: set up the target board in `a(4,4)`, define four arrow UDGs and draw the frame. - Lines 65–73: the scramble and the key loop. `GO TO (CODE INKEY$)+3` sends keys `a`–`p` to lines 100–115, which set the row or column and jump to one of four shift routines at lines 82–85. - Lines 116–125: redraw the board. Lines 75–81: stop the clock and check the board. ### Machine code The routine at 26715 fills a four-by-four block of attribute cells with one colour. Line 120 POKEs the colour and the block’s column and row into the code and calls it with `USR 26715` for each of the sixteen tiles. 26715 is where the text of the first REM line sits on the TS2068 (it is 23760 on a Spectrum), so this listing is a 2068 version. ## Notable Techniques - Key dispatch by computed `GO TO` on the key code. - The timer reads the three-byte `FRAMES` counter (23672–23674) and divides by 60. - DATA lines 11–12 use the variable `Z` as an item, which takes whatever value was last `READ` into `z`. ## Potential Issues - The scramble picks a line with `GO TO INT (RND*16+97)`. Lines 97–99 do not exist, so those three values fall through to line 100, and the first column is shifted far more often than the others. This program came from an Oliger (JLO SAFE) disk, a copy of the SNUG library disk 17/18, and was converted to load from tape. The disk copy started at line 10, which skipped the machine code loader in line 2 and the `DIM` in line 5 and stopped with “2 Variable not found”; the tape version starts at line 1. It was tested in ZEsarUX, scrambling the board and twisting a column. ## Source Code ``` 1 REM >@! OUT W MERGE A# MOVE B RESTORE HCw# LLIST MERGE MOVE A<>xxxxxxxxxxx 2 FOR n=26715 TO 26758: READ a: POKE n,a: NEXT n 3 REM >> TWISTS << * ZX COMPUTING, Feb/Mar 1984 by Paul Clansey 5 RANDOMIZE : DIM a(4,4) 6 DATA 62,64,1,0,0,17,4,4,33,223,87,213,17,32,0,4,25,16,253 7 DATA 65,4,35,16,253,209,66,229,72,67,119,35,16,252,225,213 8 DATA 17,32,0,25,209,65,16,239,201 10 DATA 16,16,48,48,16,16,48,48,32,32,8,8,32,32,8,8 11 DATA 0,8,28,42,8,Z,0,Z,Z,Z,8,Z,42,28,8,0 12 DATA 0,16,32,124,32,16,0,Z,Z,8,4,62,4,8,0,Z 20 RESTORE 10: FOR y=1 TO 4: FOR x=1 TO 4: READ z: LET a(x,y)=z: NEXT x: NEXT y 21 FOR f=0 TO 31: READ z: POKE USR "a"+f,z: NEXT f 25 BORDER 0: PAPER 5: CLS 26 PRINT AT 2,9;"aa ba ca da ";AT 19,9;"lb kb jb ib" 27 PRINT AT 4,7;"p";AT 4,24;"e";AT 8,7;"o";AT 8,24;"f" 28 FOR n=5 TO 17 STEP 4: PRINT AT n,7;"c";AT n,24;"d": NEXT n 29 PRINT AT 12,7;"n";AT 12,24;"g" 30 PRINT AT 16,7;"m";AT 16,24;"h" 31 FOR n=3 TO 10: PRINT PAPER 2;AT n,8;" "; PAPER 6;" ": NEXT n: FOR n=11 TO 18: PRINT PAPER 4;AT n,8;" "; PAPER 1;" ": NEXT n 45 FOR n=64 TO 216 STEP 32: PLOT n,24: DRAW 0,127: PLOT 64,n-40: DRAW 127,0: NEXT n 55 PRINT AT 10,28; PAPER 2;" "; PAPER 6;" ";AT 11,28; PAPER 4;" "; PAPER 1;" " 61 PRINT AT 0,0;" PRESS ANY KEY TO PLAY." 62 IF INKEY$<>"" THEN GO TO 62 63 IF INKEY$="" THEN GO TO 63 64 PRINT AT 0,0,,: LET fg=30 65 LET fg=fg-1: GO TO INT (RND*16+97) 70 IF INKEY$="" THEN GO TO 70 71 IF INKEY$="q" THEN GO TO 75 72 IF CODE INKEY$<97 OR CODE INKEY$>112 THEN GO TO 70 73 GO TO ((CODE INKEY$)+3) 75 RESTORE 10: LET t=(256*256*PEEK 23674+256*PEEK 23673+PEEK 23672)/60-t 76 FOR y=1 TO 4: FOR x=1 TO 4: READ z: IF z<>a(x,y) THEN GO TO 80 77 NEXT x: NEXT y 78 PRINT AT 21,0,, FLASH 1;AT 21,10;"TIME: ";t: GO TO 61 80 PRINT AT 21,0,,: PRINT AT 21,10;"INCOMPLETE" 81 FOR n=1 TO 500: NEXT n: RESTORE 10: GO TO 20 82 LET v=a(ar,1): FOR n=1 TO 3: LET a(ar,n)=a(ar,n+1): NEXT n: LET a(ar,n)=v: GO TO 116 83 LET v=a(4,ar): FOR n=4 TO 2 STEP -1: LET a(n,ar)=a(n-1,ar): NEXT n: LET a(n,ar)=v: GO TO 116 84 LET v=a(ar,4): FOR n=4 TO 2 STEP -1: LET a(ar,n)=a(ar,n-1): NEXT n: LET a(ar,n)=v: GO TO 116 85 LET v=a(1,ar): FOR n=1 TO 3: LET a(n,ar)=a(n+1,ar): NEXT n: LET a(n,ar)=v: GO TO 116 100 LET ar=1: GO TO 82 101 LET ar=2: GO TO 82 102 LET ar=3: GO TO 82 103 LET ar=4: GO TO 82 104 LET ar=1: GO TO 83 105 LET ar=2: GO TO 83 106 LET ar=3: GO TO 83 107 LET ar=4: GO TO 83 108 LET ar=4: GO TO 84 109 LET ar=3: GO TO 84 110 LET ar=2: GO TO 84 111 LET ar=1: GO TO 84 112 LET ar=4: GO TO 85 113 LET ar=3: GO TO 85 114 LET ar=2: GO TO 85 115 LET ar=1: GO TO 85 116 IF fg=0 THEN GO TO 120 117 IF fg>1 THEN GO TO 65 118 LET fg=0: PRINT AT 21,0;" Press 'Q' to stop clock.": LET t=VAL "(256*256*PEEK 23674+256*PEEK 23673+PEEK 23672)/60" 120 FOR y=1 TO 4: FOR x=1 TO 4: POKE 26716,a(x,y): POKE 26718,8+4*(x-1): POKE 26719,3+4*(y-1): LET q=USR 26715: NEXT x: NEXT y 125 GO TO 70 ```