Skip to content
Game 5 Unit 14 of 128 1 hr learning time

Sound Effects

Every action has audio feedback. Menu select, claim, error, victory, draw.

11% of Ink War

We already have two sounds: a rising tone when claiming cells, and a harsh buzz for invalid moves. But the game is missing audio feedback for other events — selecting menu options, game outcomes. This unit completes the audio experience.

The ZX Spectrum’s beeper is simple: one bit controls the speaker. But by toggling it at different rates, we can create distinct sounds for every game event.

Run It

pasmonext --sna inkwar.asm inkwar.sna

Unit 14 Screenshot

Select a menu option and hear the confirmation beep. Claim cells and hear the rising tone. Win and hear the victory fanfare.

Sound Design Philosophy

Each sound should be:

  • Distinctive — Immediately identifiable
  • Appropriate — Matches the emotional context
  • Brief — Doesn’t interrupt gameplay
EventSound CharacterPurpose
Menu selectQuick high beepConfirms input
Cell claimRising tonePositive feedback
Invalid moveLow buzzNegative feedback
VictoryAscending fanfareCelebration
DrawNeutral two-toneNeither win nor loss

A quick, high-pitched beep confirms menu choices:

Short duration (15 cycles) and high pitch (delay of 20) creates a crisp “click” feeling. We add call sound_select at the start of each menu handler.

Victory Fanfare

When someone wins, we play three ascending notes — a triumphant scale:

The pitch decreases with each note (delay decreases = higher frequency). A brief pause between notes creates distinct tones rather than a continuous sweep.

Draw Sound

A draw gets a neutral sound — two identical tones:

Same pitch for both tones signals neither triumph nor defeat — just equilibrium.

Result Sound Dispatch

We need to play the right sound based on the game outcome:

play_result_sound:
            ; Compare scores
            ld      a, (p1_count)
            ld      b, a
            ld      a, (p2_count)
            cp      b
            jr      z, .prs_draw        ; Equal = draw
            ; Someone won - play victory
            call    sound_victory
            ret
.prs_draw:
            call    sound_draw
            ret

We check if scores are equal (draw) or different (someone won). The victory sound plays regardless of which player won — both humans and AI get the same celebration.

Beeper Fundamentals

The Spectrum beeper works by toggling bit 4 of port $FE:

ld      a, $10              ; Bit 4 = speaker
out     (KEY_PORT), a       ; Speaker on
; ... delay ...
xor     a
out     (KEY_PORT), a       ; Speaker off
; ... delay ...

The delay duration determines the pitch:

  • Short delay (20) = High pitch
  • Long delay (80) = Low pitch

The number of cycles determines the duration:

  • Few cycles (15) = Brief sound
  • Many cycles (30) = Longer sound

Sound Placement

We added sound calls at key points:

  • state_title: call sound_select before starting game
  • try_claim/.tc_valid: Already had call sound_claim
  • try_claim/.tc_invalid: Already had call sound_error
  • Game over: call play_result_sound before showing results

The Complete Code

Try This: Turn Change Sound

Add a brief sound when the turn switches:

sound_turn:
            ld      b, 8
.st_loop:
            ; Quick descending chirp
            ; ... tone generation ...
            djnz    .st_loop
            ret

Call it after switching players in try_claim.

Try This: AI Thinking Sound

Add a subtle sound while the AI “thinks”:

; Before AI makes move
ld      b, 3
.think:
            ; Short quiet tick
            push    bc
            ; ... minimal beep ...
            pop     bc
            djnz    .think

This creates anticipation before the AI moves.

What You’ve Learnt

  • Beeper programming — Toggling speaker bit for sound
  • Pitch control — Delay duration determines frequency
  • Sound design — Matching sounds to events
  • Audio feedback — Every action acknowledged

What’s Next

In Unit 15, we’ll create a proper results screen with winner display and final scores.

What Changed

Unit 13 → Unit 14