Press 1. The count advances once. Leave the machine alone and the world waits for you. That is enough to give an adventure its rhythm: look around, make a choice, then let the world respond.
Here the world is just a counter. Replace that update with a room change, a board move or an opponent’s response. Input, persistent state and presentation still have different jobs.

Put it in your project
Enter this source on a stock 3 KiB Jupiter Ace with its normal FORTH ROM, one definition at a time, ending with TURNS. It uses the real interpreter’s input and display routines.
A complete untimed caller
: NEWKEY
BEGIN INKEY 0= UNTIL
BEGIN INKEY ?DUP UNTIL ;
: TURNS 0 BEGIN
CLS ." TURN " DUP U.
NEWKEY 49 = IF 1+ THEN
0 UNTIL ;
TURNSTake NEWKEY as a reusable word. Its stack effect is ( — key ): it waits for release, then leaves one nonzero INKEY value. Keeping the release wait prevents a held key from spending turns repeatedly. TURNS leaves one unsigned 16-bit counter on the data stack; DUP U. displays without consuming it. NEWKEY 49 = recognises 1, 1+ advances, and the false 0 UNTIL repeats without growing the stack. The counter wraps after 65535.
Replace the accepted-key body with your state update while preserving its stack effect. Every new branch must leave the same number of cells; a forgotten DROP or DUP can eventually exhaust the stack. FORTH owns the dictionary, display and both stacks. There are no arbitrary fixed RAM reservations in this version. Other keys leave the counter unchanged; Return is not required for each action. The word runs until the machine’s normal BREAK handling interrupts it.
Customise the update
This alternative adds three units for each accepted action: 0 → 3 → 6. It is still one action, rather than running the entire game three times.
Three progress units per action
: NEWKEY
BEGIN INKEY 0= UNTIL
BEGIN INKEY ?DUP UNTIL ;
: TURNS 0 BEGIN
CLS ." TURN " DUP U.
NEWKEY 49 = IF 3 + THEN
0 UNTIL ;
TURNS
Common mistake: erasing the previous turn
This listing is deliberately broken. DROP 0 discards the old count at the start of every iteration. Each redraw shows zero again, even after an accepted action.
Broken: initialisation inside the iteration
: NEWKEY
BEGIN INKEY 0= UNTIL
BEGIN INKEY ?DUP UNTIL ;
: TURNS 0 BEGIN
DROP 0 CLS ." TURN " DUP U.
NEWKEY 49 = IF 1+ THEN
0 UNTIL ;
TURNS
Restore the original loop target to repair it. The repaired source is executed separately, as is a nonzero initial count; an absent initialiser must not pass simply because zero happens to be there already.
Add presentation deliberately
The companion probe keeps the input policy and adds an original text-cell box and a blocking BEEP word:
Input, text-cell drawing and sound
: BOX CR ." XXX" CR ." X X" CR ." XXX" ;
: NEWKEY
BEGIN INKEY 0= UNTIL
BEGIN INKEY ?DUP UNTIL ;
: TURNS 0 BEGIN
CLS ." TURN " DUP U. BOX
NEWKEY 49 = IF 1+ 478 120 BEEP THEN
0 UNTIL ;
TURNSThese are separate jobs. The retained run omits sound to check that its audio guard rejects silence. The FORTH BOX word preserves the counter beneath its display work. Text cells are not a bitmap drawing primitive. A blocking tone delays the next input sample; a background sound service would need a different loop.
Decide when time matters
This loop spends CPU waiting, but does not spend a game turn. A timed decision needs a separate clock, an input policy that checks it and a rule for a command arriving with the deadline. Continuing display or firmware interrupts do not imply that the world should advance on every tick.
Compare the loop choices and the assembly version. These are different resource and input agreements, not a compulsory ladder from one language to another.
Source and verification
Native-emulator executed: Emu198x 0.44.1, the named machine and firmware configuration above. Actual keyboard input drives the program; host writes do not supply the count. The images are native framebuffer captures.
The maintained source includes the working variation and deliberate fault. The retained record identifies sources and observations. Five cold starts check normal use, step three, the reset mistake and repair, and a nonzero start. The refreshed baseline also checks idle and ignored input. An independent checker decodes screen RAM and rejects altered counts, missing stages, changed sources and changed captures.
This qualifies the small workload and named configuration. It is not an original-hardware, pitch, cassette-transfer or whole-emulator claim.
Primary references
Jupiter Ace User’s Manual, issue 2 (Jupiter Cantab, 1982), chapters 12 and 16 (input and conditional loops), chapter 24 (memory), chapter 25, pp. 144–146 (machine-code CALL and return), chapter 26, p. 152 (keyboard and speaker I/O); Ace schematic (keyboard half-row bit positions).