Skip to content
Game 2

Keep score and play again

Count returns and build a complete serve, miss, retry and exit cycle.

A rally now works. Finish the surrounding play cycle so a player can get ready, see how they did and try again without returning to the BASIC editor.

Continue from Make contact matter, stopped at the editor. Enter these changes together:

Replace lines 25, 30, 106, 620, 700. Add lines 15, 710, 720, 730, 740, 750, 800, 810, 820, 830, 840, 900.

15 PRINT AT 5,3;"A up   Z down";AT 7,3;"Q quits. Keep the rally going.";AT 9,3;"S to serve": GO SUB 800: CLS
25 LET p=9: LET score=0
30 PRINT AT 0,1;"VOLLEY   Returns: ";score
106 IF k$="q" THEN GO TO 900
620 LET dx=1: LET nx=4: LET score=score+1: PRINT AT 0,19;score
700 PRINT AT 21,1;"Miss. R retry, Q quit."
710 IF INKEY$<>"" THEN GO TO 710
720 LET k$=INKEY$: IF k$="q" THEN GO TO 900
730 IF k$<>"r" THEN GO TO 720
740 IF INKEY$<>"" THEN GO TO 740
750 GO TO 10
800 IF INKEY$<>"" THEN GO TO 800
810 LET k$=INKEY$: IF k$="q" THEN GO TO 900
820 IF k$<>"s" THEN GO TO 810
830 IF INKEY$<>"" THEN GO TO 830
840 RETURN
900 PRINT AT 21,1;"Finished.                    ": STOP

Count the event, not the frames

score starts at zero. Add one in the successful paddle-contact branch, after the two miss checks have returned. The score counts paddle returns. A wall bounce is not a point, and a ball travelling between walls earns nothing.

The new PRINT updates the counter at row 0, column 19, exactly where its initial zero was printed. The rest of the heading can stay in place. During a rally the number only grows; the next game clears the screen before printing zero again.

Why doesn’t the ball earn several points while leaving the paddle?

Show the explanation

The contact branch changes the candidate column to 4 and direction to right. On the following update the candidate is 5, not 2, so the contact routine is not called again. The point belongs to one approach and return.

Give the player a serve

Line 15 shows the controls and calls the waiting routine at 800. That routine first waits for an empty keyboard reading, then looks for S or Q. The test <> means “not equal”. Thus IF k$<>"s" THEN GO TO 810 keeps asking until the reading is S, unless the earlier Q test takes us to the exit.

After detecting S, line 830 waits for release before returning. The main program then clears the instructions, sets the starting positions and draws the court. Holding S does not keep restarting the game. This waiting phase is deliberate; once the ball is in play, the moving loop polls input without waiting.

There are no calls to INPUT: that command would stop the moving world while waiting for a completed answer. Here we choose explicitly which phases wait.

Retry without carrying old state

After a miss, line 700 offers R or Q. Lines 710–740 use the same sequence: wait for release, recognise a choice, then require release of R. Line 750 goes to 10. That restarts the setup, including the serve screen, rather than continuing from the old ball position.

CLS removes the previous display. Lines 20, 25 and 26 reset position, direction, paddle, score and the miss flag. Retrying must reset the program’s values as well as its picture. Otherwise a fresh-looking court could contain an ended rally or an old score.

The miss routine already returned before we reached this screen. Each retry therefore begins without leaving a contact call unfinished on the return stack. Q reaches line 900, prints Finished. and intentionally stops the program.

Check the complete cycle

Run it and press and release S. Return the ball and check that each paddle contact adds exactly one. Let it miss, then hold R briefly: the result should stay until you release it. You should then see the serve instructions and, after a new serve, a score of zero. Try Q from the instructions and during play.

If R seems ignored, release other keys and try it again. If the score prints as 10 after one return, compare the counter’s printing column with line 30; a digit printed beside an old zero is a display fault, not ten successful hits.

Complete game so far
10 BORDER 0: PAPER 0: INK 7: CLS
15 PRINT AT 5,3;"A up   Z down";AT 7,3;"Q quits. Keep the rally going.";AT 9,3;"S to serve": GO SUB 800: CLS
20 LET x=15: LET y=10: LET dx=1: LET dy=1
25 LET p=9: LET score=0
26 LET missed=0
30 PRINT AT 0,1;"VOLLEY   Returns: ";score
40 FOR c=2 TO 30: PRINT AT 2,c;"-";AT 20,c;"-": NEXT c
50 FOR r=3 TO 19: PRINT AT r,30;"I": NEXT r
90 GO SUB 500
100 PRINT AT y,x;"o"
105 LET k$=INKEY$
106 IF k$="q" THEN GO TO 900
110 PAUSE 2
120 PRINT AT y,x;" "
125 IF k$="a" THEN IF p>3 THEN PRINT AT p+2,2;" ": LET p=p-1
126 IF k$="z" THEN IF p<17 THEN PRINT AT p,2;" ": LET p=p+1
130 GO SUB 500
200 LET nx=x+dx: LET ny=y+dy
210 IF ny=2 THEN LET dy=1: LET ny=4
220 IF ny=20 THEN LET dy=-1: LET ny=18
230 IF nx=30 THEN LET dx=-1: LET nx=28
240 IF nx=2 THEN GO SUB 600
245 IF missed=1 THEN GO TO 700
250 LET x=nx: LET y=ny
300 GO TO 100
500 FOR r=p TO p+2: PRINT AT r,2;"I": NEXT r
510 RETURN
600 IF ny<p THEN LET missed=1: RETURN
610 IF ny>p+2 THEN LET missed=1: RETURN
620 LET dx=1: LET nx=4: LET score=score+1: PRINT AT 0,19;score
630 RETURN
700 PRINT AT 21,1;"Miss. R retry, Q quit."
710 IF INKEY$<>"" THEN GO TO 710
720 LET k$=INKEY$: IF k$="q" THEN GO TO 900
730 IF k$<>"r" THEN GO TO 720
740 IF INKEY$<>"" THEN GO TO 740
750 GO TO 10
800 IF INKEY$<>"" THEN GO TO 800
810 LET k$=INKEY$: IF k$="q" THEN GO TO 900
820 IF k$<>"s" THEN GO TO 810
830 IF INKEY$<>"" THEN GO TO 830
840 RETURN
900 PRINT AT 21,1;"Finished.                    ": STOP

This is a complete rally game. Keep this checkpoint: next we will change its appearance, then examine the drawing loop without changing its contact rules.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 3 and 5 (conditions and subroutines), chapter 15 (printing), and chapter 18 (keyboard polling).