--- title: "Number Master" id: 57609 type: "computer_media" slug: "number-master" url: "http://localhost/computer_media/number-master/" markdown_url: "http://localhost/computer_media/number-master.md" published_at: "2024-10-06T00:25:08+00:00" modified_at: "2026-04-04T08:38:58+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/number-master-1.png" excerpt: "A digit-based Mastermind clone where you decode a secret four-digit sequence, with block-graphic scoring markers and a nine-guess limit." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56724 title: "Synchro-Sette June 1983" type: "computer_media" url: "http://localhost/computer_media/synchro-sette-june-1983/" media_type: "Program" mediadate: "June 1983" images: - url: "http://localhost/wp-content/uploads/2024/10/number-master-1.png" media_type_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 range | Content | | --- | --- | | Col 9–12 | Player’s four-character guess (`B$`) | | Col 0, 2, 4, 6 | Scoring markers (exact = `\;;` ▐, misplaced = `\..` ▄) | | Col 6, row 1 | Title “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. ## 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 ```