Skip to content

Make a storm with an end

  • Sinclair ZX Spectrum
  • Assembly

A longer storm can be data rather than a longer sequence of special-case instructions. We will replace the three meteors that new_game starts with a prepared course of one hundred meteors, released one at a time.

The event table lives after the sprite data in assets.inc, at meteor_events. At this stage each event has three bytes: X, speed, delay until the next event. WAVES equ 100 names the number of events. The event index is the new byte wave; it counts individual spawns, not a whole row of meteors.

Source · view and edit
ZX Spectrum
Companion file: assets.inc

The include line reads this editable data when you assemble. Keep it beside your source for a local build.

Edit the source, then assemble.

Edits are saved in this browser. Keep a downloaded copy of work you want to keep.

Focus the Spectrum screen to use the keyboard, or hold these buttons. Assemble again for a fresh machine.

Run the program to inspect it. Editing source does not change the running machine.

wave
—
active_count
—
phase
—
pool_overflow
—
Read the active object records

These rows read the twenty-slot pool. Empty slots are omitted. The display samples RAM while the program runs, so values can change between observations.

SlotXYKind / activeSpeed

The X positions and speeds vary, but the table is fixed. Retry gives the same course. A host-side generator prepared the scattered values; the Spectrum is not choosing new random numbers during each run. Repeatability lets a player learn a route and lets us reproduce a failure.

Count down, then read a record

A second new byte, wave_timer, counts course steps until the next event. In new_game, ld a,20 and ld (wave_timer),a take the place of the three spawns. The main loop calls the new waves routine once per update, after the hull check. It returns at once when wave has reached WAVES. Otherwise it decrements the timer, and when that reaches zero it calculates the event address as meteor_events + wave*3, reads the three fields, and loads the next delay into the timer. Then it increments wave and jumps to spawn, whose RET returns straight to the main loop.

meteor-storm.asm, excerpt
waves:
 ld a,(wave)
 cp WAVES
 ret z
 ld a,(wave_timer)
 dec a
 ld (wave_timer),a
 ret nz
 ld a,(wave)
 ld e,a
 ld d,0
 ld hl,meteor_events
 add hl,de
 add hl,de
 add hl,de
 ld a,(hl)
 ld (spawn_x),a
 inc hl
 ld a,(hl)
 ld (spawn_speed),a
 inc hl
 ld a,(hl)
 ld (wave_timer),a
 ld a,(wave)
 inc a
 ld (wave),a
 jp spawn

The multiplication here is three additions of the index to HL. It is short because the event record is only three bytes. When we later add drift and kind, the event stride must change with the data layout.

A delay belongs to the event just read: it says how long to wait after this spawn before reading the next. The initial twenty-step wait comes from new_game, before any event has been read.

Do not finish while the last meteor is falling

Reaching WAVES means there are no more events to read. It does not mean the screen is clear. The completion check in the main loop now asks both questions: has wave reached WAVES, and is active_count zero? Either answer “no” branches to the new label race_continue and the next update.

meteor-storm.asm, excerpt
 call waves
 call count_objects
 ld a,(wave)
 cp WAVES
 jr nz,race_continue
 ld a,(active_count)
 or a
 jr nz,race_continue
 jp won
race_continue:
 jp main_loop

Watch the final spawn on a successful route: wave reaches 100 while active_count remains positive. The game keeps updating those objects until they leave. Contact is checked before the completion decision, so a fatal hit does not become a win just because the table is exhausted.

The final event's speed is 2 and it spawns at y=24. Can the game finish on that spawn's step?

Show the explanation

No. The new meteor is active and still near the top. At that speed it needs seventy-five movement updates to reach retirement at y=174. Event exhaustion and object exhaustion describe different things.

For a shorter experiment, set WAVES equ 3 without deleting the longer table. The program reads only the first three entries. The third, X=42 at speed 4, is read on update 36, but CLEAR SPACE waits until update 74, when that meteor passes y=174. Steer through them and check that it waits for the last object. Restore 100 to play the full meteor-only course. Do not increase WAVES beyond the number of complete records: the routine trusts that bound.

Sources

The maintained Meteor Storm source linked through this page supplies the game rules and data layout. Its experiments run original Z80 instructions on an emulated 48K PAL Spectrum; the game rules are design choices, not hardware properties.

Run it here

This unit's program, built for you.

Program
meteor-storm.tap
Machine
ZX Spectrum 48K (PAL)

Download meteor-storm.tap