Number Master

This file is part of and Synchro-Sette June 1983. Download the collection to get this file.
Date: June 1983
Type: Program
Platform(s): TS 1000
Tags: Game

This is a Mastermind-style code-breaking game using digits 1–6 instead of colours. The program generates a four-digit secret code stored in A$, then gives the player up to nine attempts (lines 80–300 loop from column 21 down to 5 in steps of −2). Exact-position matches are shown with a filled block character and misplaced-digit matches with a dotted block character, displayed to the right of the guess. Line 50 uses the idiomatic VAL “RND*5+1” trick to embed a numeric expression as a string, saving memory and deferring evaluation. The scoring logic modifies working copies B$ and C$ in-place to avoid double-counting matched digits across both the exact and misplaced passes.


Program Analysis

Program Structure

The program is organised into four logical phases:

  1. Initialisation (lines 10–60): Prints the title banner in inverse video, dimensions two four-character string arrays, and fills A$ with a random secret code.
  2. Game loop (lines 80–300): Iterates over FOR A=21 TO 5 STEP -2, giving nine rows on screen, each handling one guess.
  3. End-of-game (lines 310–4020): Prints either “GAME OVER” or nothing (using the AND boolean idiom), reveals the secret, shows the number of tries, pauses, clears, and restarts.
  4. Alternate path (lines 5000–5010): Dead code reachable only by direct GOTO — never actually reached in normal play because line 310 handles all endings. STOP prevents further execution.

Secret Code Generation

Line 50 builds each character of the secret code using:LET A$(N)="123456"(VAL "RND*5+1")

The VAL "RND*5+1" idiom evaluates the expression at run-time while storing it as a string literal in the token stream, saving a few bytes of RAM. Slicing a string literal with a computed index is a clean ZX81/TS1000 pattern to pick a random element from a fixed set — here digits 1 through 6, corresponding to Mastermind’s six colours.

Scoring Algorithm

The scoring is a two-pass algorithm that correctly handles duplicate digits:

  1. Pass 1 (lines 130–190): Scans for exact matches (right digit, right position). Matching positions in both B$ (the guess copy) and C$ (the code copy) are overwritten with a filled block graphic \;; to prevent them being counted again in pass 2.
  2. Pass 2 (lines 210–290): Scans remaining positions for misplaced matches (right digit, wrong position). Each match overwrites the relevant position in B$ with a dotted block \.. to prevent double-counting, and prints the misplaced indicator.

The variable B (reset to 0 each round at line 90) acts as a print-column accumulator for the scoring markers, advancing by 2 per marker. When B>=8 all four positions are matched and the game ends in victory via GOTO 310.

Screen Layout

Column rangeContent
Col 9–12Player’s four-character guess (B$)
Col 0, 2, 4, 6Scoring markers (exact = \;; ▐, misplaced = \.. ▄)
Col 6, row 1Title “NUMBER MASTER” in inverse video

Key BASIC Idioms

  • PRINT "..." AND condition — prints the string only when the condition is true (non-zero), a standard ZX BASIC space-saving trick used in line 310.
  • VAL "11-A/2" in line 320 computes the number of tries from the loop counter A without a separate variable. Since A steps from 21 down by 2, the formula recovers the 1-based attempt count.
  • PAUSE 40000 at line 4000 provides a long but finite pause (approximately 11 minutes at 50 Hz) before auto-restarting — effectively “press any key to continue” without an INKEY$ loop.

Bugs and Anomalies

  • Variable B used for two purposes: B serves as both the scoring-marker column counter and (implicitly) a “score” register. This works because it is reset to 0 at line 90, but the dual role makes the code harder to follow.
  • Line 105 validation: The guard against spaces in the input only checks for a literal space character; it does not validate that each character is in the range 1–6, so invalid input (e.g. letters) is silently accepted.
  • Lines 5000–5010 are unreachable: Line 310 always prints the game-over state and falls through to line 320; no code path issues a GOTO 5000. This block appears to be a leftover from an earlier version.
  • DIM B$(4) at line 30 allocates only four characters, matching the four-digit guess. However, INPUT B$ at line 100 does not constrain input length, so entering more than four characters will cause a subscript error when lines reference B$(5) etc. implicitly through the four-character DIM. In practice the DIM limits the usable string to exactly four characters.
  • NEXT F placement: NEXT F at line 280 is inside the body of the inner loop but positioned after a GOTO 290, meaning it is only reached when no match is found. This is an intentional early-exit loop pattern, not a bug.

Content

Appears On

Cassette to accompany the June 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Number Master

Source Code

  10 PRINT AT 1,6;"% %N%U%M%B%E%R% %M%A%S%T%E%R% "
  20 DIM A$(4)
  30 DIM B$(4)
  40 FOR N=1 TO 4
  50 LET A$(N)="123456"(VAL "RND*5+1")
  60 NEXT N
  80 FOR A=21 TO 5 STEP -2
  90 LET B=0
 100 INPUT B$
 105 IF B$(1)=" " OR B$(2)=" " OR B$(3)=" " OR B$(4)=" " THEN GOTO 100
 110 PRINT AT A,9;B$
 120 LET C$=A$
 130 FOR E=1 TO 4
 140 IF B$(E)<>C$(E) THEN GOTO 190
 150 PRINT AT A,B;";;"
 160 LET B=B+2
 170 LET B$(E)=".."
 175 IF B>=8 THEN GOTO 310
 180 LET C$(E)=";;"
 190 NEXT E
 200 IF B>=8 THEN GOTO 310
 210 FOR E=1 TO 4
 220 FOR F=1 TO 4
 230 IF C$(E)<>B$(F) THEN GOTO 280
 240 PRINT AT A,B;".."
 250 LET B=B+2
 260 LET B$(F)=".."
 270 GOTO 290
 280 NEXT F
 290 NEXT E
 300 NEXT A
 310 PRINT AT 3,0;"GAME OVER" AND A=1;TAB 8;" ";A$,
 320 IF A<>1 THEN PRINT INT VAL "11-A/2";" TRIES"
 4000 PAUSE 40000
 4010 CLS 
 4020 RUN 
 5000 PRINT AT 2,0;"NICE TRY" AND A=1;TAB 8;" ";A$,
 5010 STOP 
 9998 SAVE "NUMBER MASTE%R"
 9999 RUN 

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

People

No people associated with this content.

Scroll to Top