Squash 2

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

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.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

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

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

People

No people associated with this content.

Scroll to Top