Sub-Niner

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

Sub-Niner is a single-player number puzzle game where the player must reduce all nine digits of a number string to zero by repeatedly subtracting a randomly generated value. Each turn, a random number R (1–9, weighted toward smaller values via RND*RND) is displayed, and the player selects which digit position (1–9) to subtract it from; selecting position 0 skips the turn. If a digit would go below zero, a penalty subroutine adds 10 to the digit and increases the move count by R, simulating a borrow/wrap mechanic. The score is calculated as 101 minus the total number of moves taken, and a high-score table tracking the best player name and score persists across rounds within the same session.


Program Analysis

Program Structure

The program is divided into clearly separated functional blocks:

  1. Lines 10–60: Initialisation and high-score display; player name input.
  2. Lines 100–600: Screen setup — title, playing grid, column headers, player announcement.
  3. Lines 1000–1140: Main game loop — random number generation, digit selection, subtraction, and penalty handling.
  4. Lines 1150–1190: End-of-game display, high-score update trigger, and loop-back to the name/high-score screen.
  5. Lines 2000–2020: Penalty subroutine — applies a borrow (+10) and adds R to the move counter.
  6. Lines 3000–3020: High-score update subroutine — records winning player name and score.
  7. Lines 9998–9999: Save and auto-run block.

Gameplay Mechanics

The game string A$ is initialised to "999999999" (nine nines). Each turn, a random digit R is generated and displayed. The player presses a key (1–9) to subtract R from that digit position. Pressing 0 skips the turn without consuming a move counter increment — though M is still incremented at line 1080 before the skip check at line 1110, meaning skipping is not truly free. The game ends when all characters in A$ equal "0" (i.e., CHR$ 28 in internal representation — see below).

Character Code Arithmetic

This is the program’s most technically interesting idiom. Digits are stored as their Sinclair character codes (e.g., "9" = CHR$ 57 on Spectrum, but on ZX81/TS1000, digit ‘0’ = CHR$ 28, ‘1’ = CHR$ 29, …, ‘9’ = CHR$ 37). The variable A is computed as CODE A$(P) - R. The zero-check at line 1070 tests A$="000000000", meaning each character must be CHR$ 28. The INKEY$ handling at line 1090 uses CODE INKEY$ - 28 to extract the numeric value of the pressed digit key directly from its character code, confirming ZX81/TS1000 character encoding is in use.

Penalty / Borrow Subroutine

Lines 2000–2020 handle the case where subtracting R from a digit would take it below CHR$ 28 (i.e., below zero). The fix adds 10 to the character code (CODE A$(P) + 10 - R), wrapping the digit around, and penalises the player by adding R to the move count M. This subroutine is called both before the player’s choice is applied (line 1075, checking if A — still holding the last result — is under 28) and after computing the new value (line 1125).

Weighted Random Number Generation

Line 1050 uses INT (1 + RND*RND*9) rather than the simpler INT (1 + RND*9). Multiplying two independent uniform random values produces a triangular distribution skewed toward lower numbers, meaning small values of R appear more frequently. This subtly adjusts game difficulty.

Key BASIC Idioms

  • RAND (line 1000) without an argument re-seeds the random number generator from the system clock, ensuring different sequences each game.
  • PAUSE 0 is not used here; instead, INKEY$ is polled in a tight loop (lines 1090–1100) to wait for a valid keypress.
  • The high-score check at line 1180 uses IF HS < 101-M THEN GOSUB 3000 — a clean conditional subroutine call pattern.
  • Screen layout uses multiple AT clauses within a single PRINT statement (line 300) to efficiently draw the board.

Bugs and Anomalies

LocationIssue
Line 1075IF A<28 THEN GOSUB 2000 is executed before the player has chosen a position for the current turn. On the very first iteration A=28 (set at line 1030), so this is safe initially, but on subsequent loops A holds the result from the previous turn, potentially triggering an erroneous penalty call.
Line 1080The move counter M is incremented before checking if the player pressed 0 to skip (line 1110). Pressing 0 costs a move.
Line 1030A is initialised to 28 to prevent a false penalty trigger on the first pass of line 1075, but this value is a bare character code magic number with no comment.

Display and Inverse Video

The title “SUB-NINER” at line 100 is rendered entirely in inverse video using the %X escape for each character, producing a solid highlighted title bar. The board background uses a string of inverse spaces (B$ at line 200) to draw filled rectangular cells across five rows, creating a visual grid for the nine digit positions.

Content

Appears On

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

Related Products

Related Articles

Related Content

Image Gallery

Sub-Niner

Source Code

  10 LET C$=""
  20 LET HS=0
  30 IF LEN C$>0 THEN PRINT AT 5,0;"HIGH SCORE - ";C$;" - ";HS
  50 PRINT AT 20,0;"WHAT IS YOUR NAME?"
  60 INPUT N$
 100 PRINT AT 2,7;"% %S%U%B%-%N%I%N%E%R% "
 200 LET B$="% % % % % % % % % % % "
 300 PRINT AT 9,7;B$;AT 10,7;B$;AT 11,7;B$;AT 12,7;B$;AT 13,7;B$
 400 PRINT AT 8,8;"123456789"
 600 PRINT AT 20,0;N$;" IS NOW PLAYING."
\n1000 RAND 
\n1020 LET A$="999999999"
\n1030 LET A=28
\n1040 LET M=0
\n1050 LET R=INT (1+RND*RND*9)
\n1060 PRINT AT 10,8;A$;AT 12,12;R
\n1070 IF A$="000000000" THEN GOTO 1150
\n1075 IF A<28 THEN GOSUB 2000
\n1080 LET M=M+1
\n1085 PRINT AT 2,20;"SCORE = ";101-M;"   "
\n1090 LET P=CODE INKEY$-28
\n1100 IF P<0 OR P>9 THEN GOTO 1090
\n1110 IF P=0 THEN GOTO 1060
\n1120 LET A=CODE A$(P)-R
\n1125 IF A<28 THEN GOSUB 2000
\n1130 LET A$(P)=CHR$ A
\n1140 GOTO 1050
\n1150 PRINT AT 18,0;"FINAL SCORE = ";101-M;AT 20,0;"PRESS ENTER TO PLAY AGAIN"
\n1160 INPUT Z$
\n1170 CLS 
\n1180 IF HS<101-M THEN GOSUB 3000
\n1190 GOTO 30
\n2000 LET A=CODE A$(P)+10-R
\n2010 LET M=M+R
\n2020 RETURN 
\n3000 LET C$=N$
\n3010 LET HS=101-M
\n3020 RETURN 
\n9998 SAVE "SUB-NINE%R"
\n9999 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