--- title: "Squash 2" id: 71304 type: "computer_media" slug: "squash-2" url: "http://localhost/computer_media/squash-2/" markdown_url: "http://localhost/computer_media/squash-2.md" published_at: "2026-09-02T07:06:50+00:00" modified_at: "2026-09-02T07:06:51+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/Squash-2b.png" excerpt: "A two-player squash game with hardware port-scanned paddles, turn-based hitting rules, and a race to 21 points — all in pure BASIC." 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 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/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Squash%202%20(198x)(-)(TS2068)(US)(Program).zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/Squash-2b.png" - url: "http://localhost/wp-content/uploads/2026/09/Squash-2a-scaled.png" media_type_tags: "Game" --- # Squash 2 Squash 2 is a two-player squash simulation in which each player controls a paddle using keyboard ports read via the IN command — port 63486 for player one (keys 1 and 2) and port 61438 for player two (keys 9 and 0). The ball travels diagonally across the screen, bouncing off the top wall and the side walls, and each player must hit it only on their own turn, tracked by variable p. Paddles are rendered as underscore characters on rows 18 and 19, and the ball as a period character; the game uses BEEP calls to signal bounces and hits. The first player to reach 21 points wins, with score display and a flashing “GAME OVER” message implemented using PAPER and FLASH attributes. *** ### Program Structure The program is divided into clearly separated regions: 1. Lines 1–8: Title screen and instructions, waiting for any key via `INPUT a$`. 2. Lines 9–10: Initialization of scores, paddle positions, and game state variables. 3. Lines 15–95: Main game loop — ball launch, movement, collision detection, and scoring. 4. Lines 100–130: Subroutine for reading keyboard ports and updating paddle positions. 5. Lines 1000–1010: End-of-game handling, replay, and quit logic. 6. Line 9000: `SAVE` with auto-start. ### Ball Movement and Physics The ball’s position is stored in `x` (row) and `y` (column), with direction components `ud` (up/down, ±1) and `lr` (left/right, ±1). On each frame the ball is erased at its current position (line 85), then redrawn at the new position (line 40). Bounces off the top wall (row 0) invert `ud` (line 55); bounces off the side walls (columns 0 and 31) invert `lr` (line 60). If the ball reaches row 21 without being hit, a point is awarded and the ball is relaunched (line 90). Line 20 ensures `lr` is never zero (horizontal-only movement is excluded), preventing the ball from traveling in a purely vertical line and getting stuck. ### Turn-Based Hit Detection The variable `p` tracks whose turn it is (1 or 2). Player one’s paddle is at row 18, player two’s at row 19, corresponding to positions `17+p` for the active player. Lines 70 and 75 detect a hit: line 70 handles glancing blows where the ball is one column off-center (`ABS(ny-b(p))=1`), deflecting `lr` accordingly; line 75 handles a direct center hit. After a successful hit, `p` is incremented (with wrap-around from 2 back to 1), passing the turn. The guard condition `ud=-1 OR nx<18` on line 65 prevents hit detection while the ball is moving away from the paddles. ### Keyboard Port Reading Paddle movement uses direct hardware port reads rather than `INKEY$`, allowing both players to move simultaneously. Port `63486` covers the key row containing 1 and 2 (player one); port `61438` covers the row containing 9 and 0 (player two). The IN values `29` and `30` correspond to the specific bit patterns for those keys being pressed. Movement is computed as a conditional expression: - `b(2) + (IN 61438=30 AND b(2)<31) - (IN 61438=29 AND b(2)>0)` — adds 1 to move right, subtracts 1 to move left, with boundary clamping. A quit key check (`INKEY$="q"`, line 107) is inserted between the two port reads, branching to `STOP` at line 1010. ### Display and Audio Feedback The flag variable `w` is set to 1 on wall bounces (lines 55 and 60) and cleared after a `BEEP .01,30` sound is played on the next iteration of line 40. Paddle hits produce a higher-pitched `BEEP .01,50`. A miss (ball reaching row 21) triggers `BEEP .3,0` before relaunching. The score and active player are displayed at row 21 on every frame via line 30. Lines 35 use `OUT 63486,255` and `OUT 61438,255` to initialize the keyboard port state before each read cycle. ### Scoring and Game Over Scores are stored in array `s(2)`. On each ball launch (line 15), `s(p)` is incremented for the serving player. Line 30 checks whether either score has reached 21 and branches to line 1000 if so. The game over screen (line 1000) displays a flashing, white-paper banner. Line 1005 polls `INKEY$` for `"r"` to restart with `RUN`, while `"q"` during play or any other input at game over leads to `STOP`. ### Notable Anomalies - Line 15 increments `p` and sets the ball in motion, but this means the *serving* player is awarded a point at the start of each rally rather than after winning one. This is an unconventional scoring mechanic. - `BORDER 7:PAPER 6:INK 9` sets yellow paper with “bright” ink (color 9 is a non-standard value; on some systems this may map to bright black or be ignored). - The hit detection at lines 70–75 only tests `nx=17+p`, meaning only the active player’s paddle can legally return the ball; the inactive player’s paddle is purely cosmetic during the opponent’s turn. - Line 9000 uses `SAVE "SQUASH" LINE 0`, targeting line 0 which does not exist; this causes execution to begin at the first available line upon loading. ## Source Code ``` 1 PRINT AT 0,13;"SQUASH"; TAB 0;" "; TAB 0;"1. USE KEYS 1 & 2 FOR LEFT AND RIGHT CONTROL OF ONE PLAYER, USEKEYS 9 & 0 FOR CONTROL OF THE OTHER PLAYER." 2 PRINT AT 7,0;"2. A PLAYER MAY ONLY HIT THE BALL ON HIS TURN." 3 PRINT AT 10,0;"3. FIRST PLAYER TO SCORE 21 POINTS IS THE WINNER." 4 PRINT AT 13,0;"PRESS ANY KEY TO PLAY!" 8 INPUT a$ 9 BORDER 7:PAPER 6:INK 9:CLS 10 DIM s(2):DIM b(2):DIM n(2):LET w=0:LET b(1)=13:LET b(2)=17:LET s(1)=-1:LET p=0 15 LET x=0:LET y= INT (RND*31):LET ud=1:LET p=p+1:IF p=3 THEN LET p=1 20 LET lr= INT (RND*3)-1:IF NOT lr THEN GO TO 20 25 LET s(p)=s(p)+1 30 PRINT AT 21,0;"TO PLAY:";p;" SCORES: 1=";s(1); TAB 26;"2=";s(2):IF s(1)=21 OR s(2)=21 THEN GO TO 1000 35 OUT 63486,255:OUT 61438,255 40 PRINT AT x,y;".":IF w THEN BEEP .01,30:LET w=0 45 GO SUB 100 50 LET nx=x+ud 55 IF nx=0 THEN LET ud=-ud:LET w=1 60 LET ny=y+lr:IF ny=0 OR ny=31 THEN LET lr=-lr:LET w=1 65 IF ud=-1 OR nx<18 THEN GO TO 85 70 IF nx=17+p AND ABS (ny-b(p))=1 THEN LET ud=-ud:LET lr=ny-b(p):BEEP .01,50:LET p=p+1:IF p=3 THEN LET p=1 75 IF nx=17+p AND ny=b(p) THEN LET ud=-ud:BEEP .01,50:LET p=p+1:IF p=3 THEN LET p=1 80 PRINT AT 21,8;p 85 PRINT AT x,y; CHR$ 32:LET x=nx:LET y=ny 90 IF x=21 THEN BEEP .3,0:GO TO 15 95 GO TO 40 100 PRINT AT 18,b(1); CHR$ 95; AT 19,b(2); CHR$ 95 105 LET n(2)=b(2)+(IN 61438=30 AND b(2)<31)-(IN 61438=29 AND b(2)>0) 107 IF INKEY$="q" THEN GO TO 1010 110 LET n(1)=b(1)+(IN 63486=29 AND b(1)<31)-(IN 63486=30 AND b(1)>0) 115 IF n(1)=b(1) THEN GO TO 125 120 PRINT AT 18,n(1); CHR$ 95; AT 18,b(1); CHR$ 32:LET b(1)=n(1) 125 IF n(2)=b(2) THEN RETURN 130 PRINT AT 19,n(2); CHR$ 95; AT 19,b(2); CHR$ 32:LET b(2)=n(2):RETURN 1000 PRINT AT 5,1; PAPER 7; FLASH 1;"GAME OVER : Press R for replay" 1005 IF INKEY$="r" THEN RUN 1010 STOP 9000 SAVE "SQUASH" LINE 0 ```