Skip to content

Wait for a player action on Aquarius in BASIC

Reuse an untimed update with a small native caller, clear state ownership, a custom step and a reset mistake you can recognise.

Enter GO, then Return. The count advances once. Wait as long as you like: the world waits with you. That is a useful starting point for an adventure, a board game or a menu-driven decision.

The counter stands in for your game rules. Input collects a command, the update decides whether it counts, and presentation shows the result. You can replace any one of those without moving initialisation into the loop.

Aquarius BASIC showing turn two after two accepted commands.
Two commands, two updates. Waiting does not spend a turn.

Put it in your project

Use normal unexpanded Aquarius S2 BASIC. Enter the complete reusable.bas from the source folder, then RUN. These two maintained pieces concatenate to that complete program; keep their line numbers distinct from the rest of your project.

Initialise once, then collect and handle commands

caller.bas
10 N=0:S=1
20 PRINT CHR$(11):PRINT "TURN";N
30 INPUT A$
35 IF A$="Q" THEN END
40 GOSUB 1000
50 GOTO 20

A reusable conditional update

routines.bas
1000 C=0
1010 IF A$<>"GO" THEN RETURN
1020 N=N+S
1030 IF N>255 THEN N=N-256
1040 C=1
1050 RETURN

NO leaves the count alone; Q ends the caller. Commands are uppercase exact matches. This is a command gate, rather than a text-adventure parser.

Value Contract
N Persistent count, initialised once; whole number 0–255.
S Step, a whole number 0–255; unchanged by the routine.
A$ Submitted command; unchanged by the routine.
C Result: 1 when accepted, 0 when ignored.

GOSUB 1000 uses these global variables. Reserve the names and line range, or rename them consistently. The routine touches no hardware addresses. BASIC owns variable storage, keyboard input, screen output and interrupts. These are ordinary BASIC numbers: the 0–255 limit is this routine’s agreement, rather than the interpreter’s storage format.

With both inputs in range, N+S is at most 510, so one subtraction is enough to wrap it into a byte. Passing a fractional, negative or larger value breaks that agreement. Use a different range rule if your game needs an unbounded score.

PRINT CHR$(11) clears the screen in this caller. Move the count into your own status panel if other text must survive. The update does not need a screen clear. INPUT blocks until Return; an on-screen countdown would need input and deadline checks that can keep running while the player thinks.

Change the amount, keep the policy

This complete variation uses a step of three. Two accepted commands give 0 → 3 → 6. It still accepts only two actions.

Three units for each accepted command

customise.bas
10 N=0:S=3
20 PRINT CHR$(11):PRINT "TURN";N
30 INPUT A$
35 IF A$="Q" THEN END
40 GOSUB 1000
50 GOTO 20
1000 C=0
1010 IF A$<>"GO" THEN RETURN
1020 N=N+S
1030 IF N>255 THEN N=N-256
1040 C=1
1050 RETURN
Aquarius BASIC showing six.
Change the rule update without changing how commands are collected.

Common mistake: starting over every time

This listing is deliberately broken. Its jump returns through the initialiser. The action briefly changes N, then the next pass erases it. The visible count stays at zero.

Broken: return through the initialiser

reset-each-command.bas
10 N=0:S=1
20 PRINT CHR$(11):PRINT "TURN";N
30 INPUT A$
35 IF A$="Q" THEN END
40 GOSUB 1000
50 GOTO 10
1000 C=0
1010 IF A$<>"GO" THEN RETURN
1020 N=N+S
1030 IF N>255 THEN N=N-256
1040 C=1
1050 RETURN
Aquarius BASIC still showing zero after two accepted commands.
Keep persistent state outside the repeated path.

Restore the jump to line 20 to repair it. Initialisation belongs at the start of a game or a deliberate restart. A new turn should inherit the previous turn’s state.

Where time belongs

An untimed world advances on an accepted action. A timed turn also needs a deadline and a rule for an action arriving at that deadline. Display refresh, firmware interrupts and CPU activity do not decide that policy for you.

Compare the loop choices and the assembly implementation. The languages have different storage and ownership agreements; choose the one that suits your project.

Source and verification

Native-emulator executed: Emu198x 0.44.1, with Aquarius S2 firmware; assembly is built with Asm198x 0.0.71. Actual keyboard input drives the program. Host writes do not supply game state. The images above are native framebuffer captures.

The maintained source includes the complete caller, reusable pieces and deliberate fault. The retained observations cover normal use, idle waits and ignored commands, a custom step, reset and repair, 254 → 255 → 0, and a nonzero start. An independent checker rejects altered counts, sources and captures, missing observations and falsely repaired faults.

This qualifies these small workloads on the named configuration. It does not establish original-hardware, cassette-transfer, other-model or whole-emulator compatibility. The older input/drawing/sound probe remains a separate record; this loop entry makes no fresh audio claim.

Primary references

Aquarius S2 ROM, disassembly with Kenny Millar’s annotations: USR vector, BASIC RAM boundary, keyboard row and screen layout. The executable firmware is not distributed with these samples.