Mole

This file is part of Timex Sinclair Public Domain Library Tape 1003 . Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Arcade, Game

This program implements a whack-a-mole style arcade game for one player. A mole (represented by a space in an inverse-video row) appears at a random horizontal position and the player moves a crosshair cursor left and right using the N and M keys. The game reads the keyboard via INKEY$ and detects a hit by PEEKing the ZX81’s display file pointer at system variables 16398–16399, checking whether the character under the cursor is 128 (inverse space), indicating the mole’s position. Score is accumulated in variable S and displayed when a hit is detected, after which the program halts.


Program Analysis

Program Structure

The program is organised into a short main loop with two subroutines:

  1. Initialisation (lines 1–6): Clears the screen by printing ten inverse-space rows, then sets the paddle column P=3 and score S=0.
  2. Main game loop (lines 7–19): Picks a random mole column, calls the display subroutines, checks for a hit or a random dwell timeout, then briefly animates the mole sinking back before repeating.
  3. Mole display subroutine (lines 20–23): SCROLLs the play area and prints a row of inverse-space characters with a plain space gap at the mole’s position.
  4. Input/detection subroutine (lines 24–29): Reads the display file at the cursor position to detect a hit, prints a crosshair +, increments the stroke counter, and moves the cursor via N/M keys.
  5. End of game (lines 30–40): Prints the score at the cursor position and STOPs.

Inverse-Video Graphics Technique

The playing field is rendered entirely using inverse-space characters (character code 128 on the ZX81). The mole appears as a gap — a plain space — in an otherwise solid inverse row, making it visually distinct without any custom graphics. Line 3 prints the initial border rows using "% % " where % represents inverse characters.

Display-File PEEK Hit Detection

The most technically interesting aspect is the hit-detection method in lines 24–25. Rather than tracking the mole’s column numerically and comparing it to the cursor column P, the program directly reads the ZX81 display file:

  • System variables at addresses 16398 and 16399 hold the low and high bytes of the display file start address (D_FILE).
  • PEEK 16398 + 256*PEEK 16399 calculates the base address of the display file.
  • PEEK of that address retrieves the character currently under the crosshair position.
  • A result of 128 (inverse space) means the cursor is over part of the mole row, i.e., a hit; line 10 and 17 branch to the end sequence if this is true.

This is a compact and elegant approach that avoids storing or comparing the mole’s column explicitly.

Key BASIC Idioms

  • Movement via boolean arithmetic: Line 28 uses P = P + (INKEY$="M") - (INKEY$="N"). On the ZX81, a true condition evaluates to 1 and false to 0, so this single expression moves the cursor right on M and left on N without any IF statements.
  • Random dwell time: Line 11 uses IF RND<.7 THEN GOTO 8 to keep the mole visible for a geometrically distributed random duration before it dips back down, giving the game unpredictable timing.
  • Partial disappearance animation: Lines 12–18 loop four times, SCROLLing and occasionally printing an inverse-space pair at the cursor row (line 15) to simulate the mole partially hiding.

Variable Summary

VariableRole
AMole column position (lines 7, 22); also loop counter (line 12)
PPlayer crosshair column
SStroke (swing) counter, displayed as score
RCharacter read from display file at cursor position

Bugs and Anomalies

  • Dual use of A: Variable A is used both as the mole’s column (set at line 7, used at line 22) and as the loop counter in the animation loop (lines 12–18). Because the FOR loop overwrites A, the mole’s original column is lost during the sink animation. This is intentional — the mole position is no longer needed at that stage — but could cause confusion.
  • Score semantics: S counts every pass through the input subroutine (line 27), not just successful hits. It therefore measures the total number of swings rather than hits, making it more of a “how many attempts” counter. A hit ends the game immediately, so the final value of S is always the number of misses plus one.
  • No boundary check on P: The cursor column P is not clamped, so the player can move it off the left or right edge of the screen, potentially causing a display error.
  • PRINT AT row discrepancy: The mole is printed at row 9 (lines 14–15, 21), but the crosshair is printed at row 3 (line 24). The crosshair and mole are on different rows, so the PEEK detection does not compare the crosshair character against the mole row directly — it reads from the display file base address, which on a real ZX81 would be the very first character of the display file (the top-left newline marker), not the character at row 3, column P. This may represent a bug in the intended hit-detection logic.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10122 – 10175.

Related Products

Related Articles

Related Content

Image Gallery

Mole

Source Code

   1 REM "MOLE"
   2 FOR A=1 TO 10
   3 PRINT "%        % "
   4 NEXT A
   5 LET P=3
   6 LET S=0
   7 LET A=INT (RND*5+1)
   8 GOSUB 20
   9 GOSUB 24
  10 IF R=128 THEN GOTO 30
  11 IF RND<.7 THEN GOTO 8
  12 FOR A=1 TO 4
  13 SCROLL 
  14 PRINT AT 9,0;"%        % "
  15 IF RND<.3 AND A>1 AND A<4 THEN PRINT AT 9,P;"% "
  16 GOSUB 24
  17 IF R=128 THEN GOTO 30
  18 NEXT A
  19 GOTO 7
  20 SCROLL 
  21 PRINT AT 9,0;"% % % % % % % "
  22 PRINT AT 9,A;" "
  23 RETURN 
  24 PRINT AT 3,P;
  25 LET R=PEEK (PEEK 16398+256*PEEK 16399)
  26 PRINT "+"
  27 LET S=S+1
  28 LET P=P+(INKEY$="M")-(INKEY$="N")
  29 RETURN 
  30 PRINT AT 4,P;S
  40 STOP 
  50 SAVE "1016%4"
  60 LIST 

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

People

No people associated with this content.

Scroll to Top