--- title: "Squash – Basic" id: 57446 type: "computer_media" slug: "squash-basic" url: "http://localhost/computer_media/squash-basic/" markdown_url: "http://localhost/computer_media/squash-basic.md" published_at: "2024-10-05T13:53:26+00:00" modified_at: "2026-04-03T07:58:28+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/247_Squa.png" excerpt: "A bouncing-ball Squash game where you control a bat with two keys, racing the computer to score 10 points — built entirely in BASIC with block-graphic court walls." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56736 title: "Timex Sinclair Public Domain Library Tape 1005" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1005/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/247_Squa.png" media_type_tags: "Game" --- # Squash – Basic This program implements a single-player Squash game in which a ball bounces around an enclosed court and the player controls a bat at the bottom using the P and Q keys. The court walls are drawn using inverse-video characters for the sides and block graphics (▄) for the top, while the bat is rendered with a block graphic character. Ball movement is tracked with direction variables L and M, and the collision logic at line 130 uses a chained comparison idiom to detect wall bounces. Scores are tracked separately for the Sinclair (computer) and the player, with the first to reach 10 winning the match. *** ## Program Analysis ### Program Structure The program is divided into four logical sections: 1. **Initialisation (lines 2–9):** Sets up all game variables and calls the title/intro subroutine at line 1000. 2. **Court drawing (lines 15–75):** Draws the side walls, top wall, and score labels using `PRINT AT`. 3. **Main game loop (lines 80–210):** Handles bat movement, ball movement, ball rendering, and collision detection in a tight `GOTO 80` loop. 4. **Subroutines (lines 1000–3110):** Intro screen (1000), Sinclair scores a point (2000), player scores a point (3050). ### Variable Usage | Variable | Purpose | | --- | --- | | `C` | Sinclair (computer) score | | `F` | Player score | | `X`, `Y` | Ball column and row offset within court | | `L`, `M` | Ball horizontal and vertical direction (±1) | | `H` | Bat horizontal position (column 8–17) | ### Court Rendering The side walls (lines 15–35) are drawn using the inverse-video space character `"% "` (inverse space), producing solid vertical bars. The top wall (lines 40–60) uses the block graphic `\".."` (▄, lower-half block) to form a horizontal ceiling. The bat at line 80 is rendered with `"\ '' "` (a combination of block graphic characters), giving it a two-cell wide appearance. ### Main Game Loop Mechanics The loop begins at line 80, where the bat position `H` is updated using a single-line Boolean arithmetic expression — a classic Sinclair BASIC idiom. `INKEY$="P"` and `INKEY$="Q"` evaluate to 1 (true) or 0 (false), allowing movement in either direction without branching: `LET H=H+(INKEY$="P" AND H<17)-(INKEY$="Q" AND H>8)` This both reads input and constrains the bat within the court boundaries (columns 8–17) in a single statement. ### Ball Movement and Wall Bouncing The previous ball position is erased at line 120 by printing a space, then new coordinates are computed and the ball is redrawn at line 170. Horizontal bouncing (line 130) uses a chained comparison expression: `IF L+X>9<=L+X<0 THEN LET L=-L` This is an idiomatic ZX81/TS1000 BASIC technique exploiting left-to-right Boolean chaining: the expression fires if the new X would be out of bounds in either direction. Vertical bouncing (line 140) uses a more conventional `OR` check. ### Collision Detection Lines 190 and 200 check whether the ball has reached the bottom row (`Y=8`). If `ABS(H-X)>=9`, the ball has missed the bat entirely and the Sinclair scores (subroutine 2000). If `ABS(H-X)=8`, the ball is touching or just beside the bat and the player scores (subroutine 3050). The boundary of 8 here corresponds to the bat’s position relative to the court origin. ### Scoring Subroutines Both scoring subroutines (2000 and 3050) follow the same pattern: increment the relevant counter, print it at the correct screen position, check if the score has reached 10, and either return to the game loop or end the game with a congratulatory/commiserating message and `STOP`. The player’s score label reads “YOUR SCORE IS” and the Sinclair’s label reads “SINCLAIR SCORE”, updated in-place using `PRINT AT`. ### Notable Techniques and Anomalies - Boolean arithmetic for bat movement and boundary clamping in a single `LET` statement (line 90) — avoids multiple `IF` branches. - Chained comparison in the horizontal bounce condition (line 130) — a compact but non-obvious idiom. - The intro loop at line 1140 uses `IF INKEY$<>"P" THEN GOTO 1140`, a standard busy-wait for a key press. - Lines 3110–3130 (`CLEAR`, `SAVE`, `RUN`) are unreachable dead code following `STOP` at line 3100; they would only execute if somehow reached by fall-through, which cannot happen. - There is no mechanism for the ball to actually “bounce” off the bat — the player scoring subroutine only awards a point without reversing the ball’s vertical direction, meaning a successful return is not simulated; the ball always travels in one direction vertically until it reaches the bottom. - The REM statements at lines 10, 65, and 180 use inverse-video characters to display readable labels when the program is listed, a common ZX81 documentation technique. ## Source Code ``` 2 LET C=0 3 LET X=0 4 LET Y=0 5 LET M=1 6 LET L=1 7 LET H=10 8 LET F=0 9 GOSUB 1000 10 REM %B%U%I%L%D% %C%O%U%R%T 15 FOR A=6 TO 14 20 PRINT AT A,8;"% " 30 PRINT AT A,19;"% " 35 NEXT A 40 FOR B=8 TO 19 50 PRINT AT 5,B;".." 60 NEXT B 65 REM %S%C%O%R%E% %A%N%D% %B%A%T% %C%O%N%T%R%O%L 70 PRINT AT 3,0;"SINCLAIR SCORE..0" 75 PRINT AT 1,0;"YOUR SCORE IS...0" 80 PRINT AT 15,H;" '' " 90 LET H=H+(INKEY$="P" AND H<17)-(INKEY$="Q" AND H>8) 120 PRINT AT 6+Y,9+X;" " 130 IF L+X>9<=L+X<0 THEN LET L=-L 140 IF M+Y>8 OR M+Y<0 THEN LET M=-M 150 LET X=X+L 160 LET Y=Y+M 170 PRINT AT 6+Y,9+X;"O" 180 REM %C%H%E%C%K%S% %B%A%L%L% %P%O%S%I%T%I%O%N 190 IF Y=8 AND ABS (H-X)>=9 THEN GOSUB 2000 200 IF Y=8 AND ABS (H-X)=8 THEN GOSUB 3050 210 GOTO 80 1000 PRINT "*********** SQUASH ***********" 1060 PRINT "*** FIRST TO SCORE 10 WINS ***" 1100 PRINT 1110 PRINT "*USE P AND Q KEYS TO MOVE BAT*" 1120 PRINT 1130 PRINT "***PRESS .P. KEY TO PLAY.***" 1140 IF INKEY$<>"P" THEN GOTO 1140 1150 CLS 1160 RETURN 2000 LET C=C+1 2050 PRINT AT 3,16;C 2060 IF C<10 THEN RETURN 2070 CLS 2080 PRINT AT 10,1;"***** COME ON TRY AGAIN *****" 2090 STOP 3050 LET F=F+1 3060 PRINT AT 1,16;F 3070 IF F<10 THEN RETURN 3080 CLS 3090 PRINT AT 10,1;"* I WILL BEAT YOU NEXT TIME *" 3100 STOP 3110 CLEAR 3120 SAVE "1024%7" 3130 RUN ```