--- title: "Squash 1" id: 71302 type: "computer_media" slug: "squash-1" url: "http://localhost/computer_media/squash-1/" markdown_url: "http://localhost/computer_media/squash-1.md" published_at: "2026-09-02T07:07:13+00:00" modified_at: "2026-09-02T07:07:13+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/Squash-1.png" excerpt: "Guide your paddle with keys 5 and 8 to keep a bouncing ball in play in this minimalist one-player squash game written entirely in 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%201%20(198x)(-)(TS2068)(US)(Program).zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/Squash-1.png" media_type_tags: "Game" --- # Squash 1 Squash 1 is a single-player squash/paddle game in which a ball bounces around the screen and the player moves a bat (displayed as CHR$ 95, the underscore character) along a fixed horizontal row using keys 5 and 8. The ball is represented by a period character and travels diagonally, reflecting off the top edge and side walls, with a BEEP sounded on each bounce. The bat is positioned at row 20 and the ball is lost when it reaches row 22 without being intercepted, triggering a new serve via GO TO 20. A subroutine at line 100 handles both reading the bat position from INKEY$ and redrawing the bat on every iteration of the main loop, giving responsive but polling-based control. The SAVE line stores the program with an auto-run directive at LINE 0. *** ### Program Structure The program is organized into a tight main loop and a single subroutine: - **Lines 5–15:** Initialization — screen attributes and starting values for bat position (`a=20`, `b=15`), and a “wall-hit” flag `w`. - **Line 20:** New-serve setup — ball position (`x`, `y`), vertical direction (`ud=1`), and random horizontal direction (`lr` set to ±1). - **Lines 25–70:** Main game loop — draws the ball, calls the bat subroutine, computes next position, checks wall/bat collisions, and redraws. - **Lines 100–115:** Bat subroutine — reads INKEY$, moves and redraws the bat. ### Ball Movement and Collision Logic The ball moves one cell per loop iteration in both axes. Direction variables `ud` (up/down, ±1) and `lr` (left/right, ±1) are negated on wall hits. The top edge reflection is detected when `nx=0` (line 40); side wall reflections trigger when `ny=0 OR ny=31` (line 50). Bat contact is checked at line 55: if the ball’s next row equals `a` (row 20) and its column equals `b`, vertical direction is reversed and a higher-pitched BEEP is played. No reflection is performed for the bat’s horizontal position — only an exact column match triggers a return. A wall-hit flag `w` is set to 1 whenever the ball reflects off a wall, causing a BEEP at line 25 on the following iteration. This deferred sound avoids sound calls inside position update logic and separates audio from movement cleanly. ### Bat Subroutine (Lines 100–115) The subroutine at line 100 is called twice per loop: once before computing the next position (line 30) and once more at line 45, giving the player two opportunities per frame to move the bat. This is a straightforward way to improve responsiveness without restructuring the loop. The bat movement expression on line 100 uses a Boolean arithmetic idiom common in Sinclair BASIC: `LET n=b+(INKEY$="8" AND b<31)-(INKEY$="5" AND b>0)` The relational expressions evaluate to 1 (true) or 0 (false), so `n` is incremented when “8” is pressed and decremented when “5” is pressed, with boundary clamping built in. The bat is only redrawn if its position actually changed (line 105), reducing flicker. ### Screen and Display Techniques The ball is erased by printing CHR$ 32 (space) at its old position before moving (line 60). The bat is drawn as CHR$ 95 (underscore), which visually resembles a horizontal paddle. There is no use of graphics characters or pixel-level drawing; everything is character-cell based. PAPER 4 sets a green background and INK 9 selects bright default ink, giving a colored court effect. BRIGHT 1 applies globally at initialization. ### Loss Condition and Restart If the ball reaches row 22 (`x=22`, line 65), a low BEEP is played and the program jumps back to line 20 for a new serve. There is no score tracking — the game loops indefinitely with no win condition. ### Bugs and Anomalies - The bat collision check (line 55) only tests for an exact column match (`ny=b`). The bat visually occupies only one character cell, so this is consistent, but it makes the target very small. - The ball is not erased at line 25 before the subroutine call — the print at line 25 draws the ball dot, then at line 60 it is erased. This ordering means the ball is visible during the subroutine call delay, which is the intended display behavior. - When the ball’s next position matches the bat (line 55), only `ud` is reversed; `w` is not set, so no wall-bounce BEEP fires — but a separate higher-pitched BEEP (note 50) is played instead, correctly distinguishing bat hits from wall hits. - There is no check preventing the ball from passing through the bat if it approaches from below row 20, though the ball starts moving downward (`ud=1`) and the loss condition triggers at row 22, so this situation cannot arise in normal play. ## Source Code ``` 5 BORDER 4:PAPER 4:BRIGHT 1:INK 9 10 CLS 15 LET a=20:LET b=15:LET w=0 20 LET x=0:LET y= INT (RND*31):LET ud=1:LET lr= INT (RND*2):IF lr=0 THEN LET lr=-1 25 PRINT AT x,y;".":IF w THEN BEEP .01,30:LET w=0 30 GO SUB 100 35 LET nx=x+ud 40 IF nx=0 THEN LET ud=-ud:LET w=1 45 GO SUB 100 50 LET ny=y+lr:IF ny=0 OR ny=31 THEN LET lr=-lr:LET w=1 55 IF nx=a AND ny=b THEN LET ud=-ud:BEEP .01,50 60 PRINT AT x,y; CHR$ 32:LET x=nx:LET y=ny 65 IF x=22 THEN BEEP .3,0:GO TO 20 70 GO TO 25 100 LET n=b+(INKEY$="8" AND b<31)-(INKEY$="5" AND b>0) 105 IF n <>b THEN PRINT AT a,b; CHR$ 32:LET b=n 110 PRINT AT a,b; CHR$ 95 115 RETURN 9000 SAVE "PRACTICE"\{16}\{3}\{16}\{3} LINE 0 ```