SE3K Survivors Experience 3000

VOLUME A2 -- BASIC DEMO PROGRAMS

SC-3000 BASIC Level III-B — part of the SE3K documentation library, also readable inside the emulator.

============================================================================
VOLUME A2 -- BASIC DEMO PROGRAMS
============================================================================
A collection of ready-to-type BASIC demo programs for the SC-3000,
grouped by category. Each demo is self-contained: type it in (or LOAD it)
and RUN. Line numbers are local to each demo. The comments explain the
technique so you can adapt it to your own programs.
Companion to Volume A1 (the BASIC Guide): where a chapter illustrates a
command, it points here for a full working example.
----------------------------------------------------------------------------
CONTENTS
----------------------------------------------------------------------------
1.  SOUND & MUSIC
1.1  Ride of the Valkyries -- articulated 4-channel sequencer
2.  GRAPHICS
2.1  Graphics tour -- every graphics primitive
3.  SPRITES
3.1  Sprite playground -- sizes, animation, motion, limits
4.  INPUT & GAMES
4.1  Input test -- STICK / STRIG / INKEY$ live
4.2  Dodger -- a joystick game
5.  TEXT & SCREEN                         [.] to write

1. SOUND & MUSIC

1.  SOUND & MUSIC
============================================================================

1.1 Ride of the Valkyries -- articulated 4-channel sequencer

  1.1  Ride of the Valkyries -- articulated 4-channel sequencer
----------------------------------------------------------------------------
A small DATA-driven sequencer that plays R. Wagner's "Ride of the
Valkyries" on all four PSG channels: a singing lead (ch1), a sustained
drone (ch2), a STACCATO galloping bass (ch3) and timpani/cymbal on the
noise channel (ch4).
How the sequencer works
The song is a stream of events, each "CH, FREQ, DUR, VOL":
CH    1-3 tone channel, 4 = noise   (-1 = end of song)
FREQ  pitch in Hz (tones); for ch4: 0 = low timpani, 2 = cymbal
DUR   hold time in steps; 0 = set this channel and read the NEXT
event AT THE SAME TIME (this is how chords/percussion stack)
VOL   0-15 loudness
Only the event that carries DUR>0 actually waits, so notes already set
with DUR=0 keep ringing under it. A short REST is an event at VOL 0 (keep
a real FREQ -- a 0 frequency could divide by zero in the divisor calc).
The bass uses rests to play a STACCATO gallop (hit-rest-hit) -- the
detached "hoofbeats" -- while the lead sings on ch1 and ch2 holds a
sustained drone. Tempo = TM.
All pitches come from the frequency table in Vol. A1 ch. 6, e.g.
B  123   D  147   F+ 185   A  220   B  247
D  294   F+ 370   A  440   B  494   D  587   (Hz)
Edit the DATA to compose your own tune (RESTORE + GOTO 1170 loops it).
```
1000 REM ===================================================
1010 REM   RIDE OF THE VALKYRIES  --  articulated PSG version
1020 REM   R. Wagner.  ch1 lead, ch2 sustained drone,
1030 REM   ch3 STACCATO galloping bass, ch4 timpani/cymbal.
1040 REM   Event = CH,FREQ,DUR,VOL ; DUR=0 stacks ;
1050 REM   rest = real FREQ at VOL 0 ; CH=-1 ends song.
1060 REM ===================================================
1130 TM = 20 : REM tempo: smaller = faster gallop
1140 PRINT "RIDE OF THE VALKYRIES"
1150 PRINT "SC-3000 -- ARTICULATED DEMO -- BREAK TO STOP"
1160 REM --- sequencer play loop ---
1170 READ C,F,D,V
1180 IF C<0 THEN 1220
1190 SOUND C,F,V
1200 IF D=0 THEN 1170
1210 FOR T=1 TO D*TM : NEXT T : GOTO 1170
1220 SOUND 0 : REM master off -- silences all 4 channels
1230 END
1240 REM === DATA : lead(1)/drone(2)/timp(4)/bass(3) ===
1250 REM  STACCATO gallop = hit(1) / rest(1) / hit(1).  A REST is
1260 REM  3,bass,1,0 : a real pitch at VOL 0 -- never SOUND ch,0
1270 REM  (a 0 frequency could divide by zero in the divisor calc).
1273 REM --- PART 1 : the rising calls --------------------------
1275 REM  phrase 1 : Bm  B-D-F+ , bass B , drone F+
1280 DATA 1,247,0,13, 2,185,0,8, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11
1290 DATA 1,294,0,13, 3,123,1,11
1300 DATA 1,370,0,13, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11, 3,123,1,0
1305 REM  phrase 2 : repeat
1310 DATA 1,247,0,13, 2,185,0,8, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11
1320 DATA 1,294,0,13, 3,123,1,11
1330 DATA 1,370,0,13, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11, 3,123,1,0
1335 REM  phrase 3 : up  D-F+-B , bass D , drone A
1340 DATA 1,294,0,13, 2,220,0,8, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11
1350 DATA 1,370,0,13, 3,147,1,11
1360 DATA 1,494,0,13, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11, 3,147,1,0
1365 REM  phrase 4 : repeat
1370 DATA 1,294,0,13, 2,220,0,8, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11
1380 DATA 1,370,0,13, 3,147,1,11
1390 DATA 1,494,0,13, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11, 3,147,1,0
1395 REM  phrase 5 : higher  F+-A-D , bass F+ , drone A
1400 DATA 1,370,0,13, 2,220,0,8, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11
1410 DATA 1,440,0,13, 3,185,1,11
1420 DATA 1,587,0,14, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11, 3,185,1,0
1425 REM  phrase 6 : turn  A-F+-B , bass D , drone F+
1430 DATA 1,440,0,13, 2,185,0,8, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11
1440 DATA 1,370,0,13, 3,147,1,11
1450 DATA 1,494,0,13, 4,0,0,13, 3,147,1,12, 4,0,0,0, 3,147,1,0, 3,147,1,11, 3,147,1,0
1455 REM --- PART 2 : the second strain ------------------------
1460 REM  phrase 7 : high restatement  F+-A-D , bass F+ , drone A
1465 DATA 1,370,0,13, 2,220,0,8, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11
1470 DATA 1,440,0,13, 3,185,1,11
1475 DATA 1,587,0,14, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11, 3,185,1,0
1480 REM  phrase 8 : descent  D-C+-B , bass B , drone F+
1485 DATA 1,587,0,13, 2,185,0,8, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11
1490 DATA 1,554,0,13, 3,123,1,11
1495 DATA 1,494,0,13, 4,0,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,1,11, 3,123,1,0
1500 REM  phrase 9 : dominant  F+-A-F+ , bass F+ , drone A
1505 DATA 1,370,0,13, 2,220,0,8, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11
1510 DATA 1,440,0,13, 3,185,1,11
1515 DATA 1,370,0,13, 4,0,0,13, 3,185,1,12, 4,0,0,0, 3,185,1,0, 3,185,1,11, 3,185,1,0
1520 REM  phrase 10 : final cadence on Bm + cymbal
1525 DATA 1,494,0,14, 2,185,0,9, 4,2,0,13, 3,123,1,12, 4,0,0,0, 3,123,1,0, 3,123,8,11
1530 DATA -1,0,0,0
```
Notes
* Articulation is the key to the "ride" feel: the bass is STACCATO --
every beat is "hit (DUR 1) - rest (DUR 1) - hit (DUR 1)" so each
hoofbeat is detached, not slurred. The down-beat hit is accented
(VOL 12 vs 11) and the timpani (ch4 rate 0, VOL 13) punches it, then
is cut off at once for a sharp attack.
* ch2 holds a sustained DRONE (set once per phrase, VOL 8) under the
detached bass, so the texture is: singing lead + organ-like pad +
galloping bass + percussion.
* Rests are VOL 0 with the bass pitch kept (3,bass,1,0), never SOUND
ch,0 -- so the divisor maths is never asked to divide by a 0 frequency.
* The tune is in two parts: PART 1 (phrases 1-6) is the rising call;
PART 2 (7-10) restates it higher, descends D-C+-B and cadences on Bm
with a cymbal crash.
* Tune it: lower TM for a faster charge; for crisper hoofbeats make the
bass rests longer (e.g. 3,B,1 / 3,B,2,0 / 3,B,1); ch4 rate 2 = snare.

2. GRAPHICS

2.  GRAPHICS
============================================================================

2.1 Graphics tour -- every graphics primitive

  2.1  Graphics tour -- every graphics primitive
----------------------------------------------------------------------------
A guided tour that demonstrates every SC-3000 graphics primitive in turn,
one scene at a time, pausing between scenes. Type it in and RUN.
Primitives covered:
SCREEN 2,2 / SCREEN 1,1     graphics / text mode
COLOR                       on/off pixel colours
PSET / PRESET               set / clear a pixel          (scene 1)
LINE / LINE..B / LINE..BF   line / box / filled box      (scene 2)
CIRCLE (+ratio/arc/B/BF)    circle/ellipse/arc/pie/fill  (scene 3)
PAINT                       flood fill                   (scene 4)
POSITION                    origin + direction           (scene 5)
PATTERN S# / SPRITE / MAG   define + animate a sprite    (scene 6)
VPOKE / VPEEK               direct VRAM write / read     (scene 7)
BLINE / BCIRCLE             erase box / circle           (scene 8)
```
2000 REM ===================================================
2010 REM   GRAPHICS TOUR  --  every SC-3000 graphics primitive
2020 REM   SCREEN COLOR PSET PRESET LINE(/B/BF) BLINE
2030 REM   CIRCLE(/ratio/arc/BE/BF) BCIRCLE PAINT POSITION
2040 REM   PATTERN SPRITE MAG VPOKE VPEEK
2050 REM ===================================================
2060 SCREEN 1,1 : CLS
2070 PRINT "SC-3000 GRAPHICS TOUR"
2080 PRINT : PRINT "EACH PRIMITIVE IN TURN -- WATCH..."
2090 GOSUB 2960
2100 SCREEN 2,2 : COLOR 15,1 : REM graphics 256x192, white on black
2110 REM --- 1. PSET / PRESET : starfield ---
2120 FOR I=1 TO 70 : PSET (INT(RND(1)*256),INT(RND(1)*192)),15 : NEXT I
2130 GOSUB 2960
2140 FOR I=1 TO 30 : PRESET (INT(RND(1)*256),INT(RND(1)*192)) : NEXT I
2150 GOSUB 2960 : CLS
2160 REM --- 2. LINE : rays, frame (B), filled bars (BF) ---
2170 FOR I=0 TO 255 STEP 20 : LINE (128,96)-(I,0),11 : NEXT I
2180 LINE (8,8)-(247,184),15, B
2190 FOR I=0 TO 4 : LINE (30+I*40,150)-(58+I*40,182),9+I, BF : NEXT I
2200 GOSUB 2960 : CLS
2210 REM --- 3. CIRCLE : circle, ellipses, arc, pie (BE), fill (BF) ---
2220 CIRCLE (128,96),50,14
2230 CIRCLE (128,96),78,9,0.5
2240 CIRCLE (128,96),78,11,2.0
2250 CIRCLE (60,96),28,7,,0.0,0.5
2260 CIRCLE (200,96),28,10,,0.0,0.25, B
2270 CIRCLE (128,40),16,12,,,, BF
2280 GOSUB 2960 : CLS
2290 REM --- 4. PAINT : outline then flood fill ---
2300 CIRCLE (128,96),45,14
2310 PAINT (128,96),7
2320 GOSUB 2960 : CLS
2330 REM --- 5. POSITION : origin + direction (4-way mirror) ---
2340 POSITION (128,96),0,0 : GOSUB 2940
2350 POSITION (128,96),1,0 : GOSUB 2940
2360 POSITION (128,96),0,1 : GOSUB 2940
2370 POSITION (128,96),1,1 : GOSUB 2940
2380 POSITION (0,0),0,0
2390 GOSUB 2960 : CLS
2400 REM --- 6. PATTERN S# + SPRITE + MAG : animate a blob ---
2410 PATTERN S#0,"183C7EFFFF7E3C18"
2420 LINE (0,150)-(255,150),8
2430 MAG 0
2440 FOR X=0 TO 232 STEP 4 : SPRITE 0,(X,135),0,10 : GOSUB 2950 : NEXT X
2450 MAG 2
2460 FOR X=232 TO 0 STEP -6 : SPRITE 0,(X,128),0,14 : GOSUB 2950 : NEXT X
2470 GOSUB 2960 : CLS
2480 REM --- 7. VPOKE / VPEEK : direct VRAM read/write ---
2490 LINE (112,88)-(143,119),12, BF : REM solid block (sets colour+pattern)
2500 B=INT(96/8)*256+INT(112/8)*8 : REM gfx VRAM addr, top row of a cell
2510 VPOKE B,&H00 : REM carve a visible gap in the block
2520 V=VPEEK(B) : IF V=0 THEN CIRCLE (170,103),6,14, BF : REM read-back OK
2530 GOSUB 2960 : CLS
2540 REM --- 8. BLINE / BCIRCLE : erase shapes ---
2550 CIRCLE (128,96),50,14 : LINE (50,50)-(206,140),11, B
2560 GOSUB 2960
2570 BCIRCLE (128,96),50 : BLINE (50,50)-(206,140),0, B
2580 GOSUB 2960
2590 REM --- end ---
2600 SCREEN 1,1 : CLS : PRINT "GRAPHICS TOUR COMPLETE"
2610 END
2940 LINE (0,0)-(70,35),11 : LINE (0,0)-(35,70),13 : RETURN
2950 FOR T=1 TO 60 : NEXT T : RETURN
2960 FOR T=1 TO 1500 : NEXT T : RETURN
```
Notes
* Each scene clears with CLS and pauses via GOSUB 2960; GOSUB 2950 is the
short per-frame delay for the sprite. Lower those counts to speed up.
* Scene 5 sets the drawing origin to the centre and draws the same little
figure with the four direction combos, giving a 4-way mirror:
POSITION (x,y),xdir,ydir -- xdir 0=right/1=left, ydir 0=down/1=up.
* Scene 6 uses MAG 0 (8x8) then MAG 2 (8x8 zoomed x2 = 16x16 look) on the
same 8-byte S# pattern, so no extra pattern data is needed.
* Scene 7 fills a block with LINE..BF (which sets both colour and pattern
for those cells), then VPOKEs one pattern byte to 0 to carve a visible
gap, and VPEEKs it back -- the marker circle is drawn only if the read
returns 0. SCREEN 2 pattern address = INT(y/8)*256+INT(x/8)*8+(y MOD 8).
* PAINT (scene 4) needs a fully closed border or the fill leaks; a very
large/complex fill can raise error [08] (stack overflow).
* To loop the whole tour: replace 2610 END with GOTO 2100 (BREAK stops).
For sound, borrow SOUND calls from demo 1.1.

3. SPRITES

3.  SPRITES
============================================================================

3.1 Sprite playground -- sizes, animation, motion, limits

  3.1  Sprite playground -- sizes, animation, motion, limits
----------------------------------------------------------------------------
Six scenes showing what the TMS9918A sprites can do, beyond the single
sprite of the graphics tour (2.1).
Scenes:
1. MAG sizes      same sprite at MAG 0/1/2/3 in turn (MAG is GLOBAL,
so the four sizes are shown one after another)
2. Animation      one sprite alternating two patterns
3. Bouncing flock 8 sprites with independent velocities, bouncing
4. 4-per-line     5 sprites on one scanline -> the 5th (highest number)
drops; stagger their Y and all reappear
5. Collision      two sprites crossing; flash colour when they overlap
(computed in BASIC -- the VDP coincidence flag is not
reliable from BASIC, the interrupt clears it each frame)
6. Priority       a sprite slides across a fixed one; the LOWER sprite
number is always drawn in front
Sprite notes
* PATTERN defines one 8x8 cell and MUST end with "*". A 16x16 sprite is
four cells (n..n+3, order TL/BL/TR/BR) shown with MAG 1/3 (see Vol. A1
5.7). Hide a sprite with colour 0 (transparent).
* MAG is a global VDP setting -- every sprite shares the current size.
```
3000 REM ===================================================
3010 REM   SPRITE PLAYGROUND  --  SC-3000 sprite features
3020 REM   MAG sizes / animation / bouncing flock /
3030 REM   4-per-scanline limit / collision / priority
3040 REM ===================================================
3050 DIM SX(8),SY(8),VX(8),VY(8)
3060 SCREEN 2,2 : COLOR 15,1
3070 REM -- patterns ('*' terminates each cell) --
3080 PATTERN S#8,"183C7EFFFF7E3C18*" : REM 8x8 ball (cell 8)
3090 PATTERN S#9,"0000183C3C180000*" : REM 8x8 dot  (cell 9, anim frame 2)
3100 REM 16x16 ball = cells 0-3, order TL/BL/TR/BR
3110 PATTERN S#0,"071F3F7F7FFFFFFF*" : REM top-left
3120 PATTERN S#1,"FFFFFF7F7F3F1F07*" : REM bottom-left
3130 PATTERN S#2,"E0F8FCFEFEFFFFFF*" : REM top-right
3140 PATTERN S#3,"FFFFFFFEFEFCF8E0*" : REM bottom-right
3150 REM --- 1. MAG : the four magnifications in turn ---
3160 MAG 0 : SPRITE 0,(124,90),8,10 : GOSUB 3920 : REM 8x8
3170 MAG 2 : SPRITE 0,(124,90),8,11 : GOSUB 3920 : REM 8x8 zoom x2
3180 MAG 1 : SPRITE 0,(120,86),0,13 : GOSUB 3920 : REM 16x16 (cells 0-3)
3190 MAG 3 : SPRITE 0,(116,82),0,14 : GOSUB 3920 : REM 16x16 zoom x2
3200 GOSUB 3900 : MAG 0
3210 REM --- 2. ANIMATION : alternate two patterns ---
3220 MAG 2
3230 FOR J=1 TO 18
3240  SPRITE 0,(124,90),8,10 : GOSUB 3910
3250  SPRITE 0,(124,90),9,10 : GOSUB 3910
3260 NEXT J
3270 GOSUB 3900 : MAG 0
3280 REM --- 3. BOUNCING FLOCK : 8 moving sprites ---
3290 FOR I=1 TO 8
3300  SX(I)=INT(RND(1)*232) : SY(I)=INT(RND(1)*176)
3310  VX(I)=INT(RND(1)*5)-2 : IF VX(I)=0 THEN VX(I)=2
3320  VY(I)=INT(RND(1)*5)-2 : IF VY(I)=0 THEN VY(I)=2
3330 NEXT I
3340 FOR K=1 TO 200
3350  FOR I=1 TO 8
3360   SX(I)=SX(I)+VX(I) : IF SX(I)<0 OR SX(I)>240 THEN VX(I)=-VX(I) : SX(I)=SX(I)+VX(I)
3370   SY(I)=SY(I)+VY(I) : IF SY(I)<0 OR SY(I)>176 THEN VY(I)=-VY(I) : SY(I)=SY(I)+VY(I)
3380   SPRITE I,(SX(I),SY(I)),8,I+1
3390  NEXT I
3400 NEXT K
3410 GOSUB 3900
3420 REM --- 4. 4-PER-SCANLINE LIMIT : 5 sprites, one Y ---
3430 FOR I=1 TO 5 : SPRITE I,(30+I*36,90),8,I+9 : NEXT I
3440 GOSUB 3920 : GOSUB 3920 : REM sprite 5 (highest) drops on this line
3450 FOR I=1 TO 5 : SPRITE I,(30+I*36,50+I*18),8,I+9 : NEXT I
3460 GOSUB 3920 : GOSUB 3920 : REM staggered Y -> all 5 visible
3470 GOSUB 3900
3480 REM --- 5. SOFTWARE COLLISION : flash on overlap ---
3490 SA=20 : SB=220
3500 FOR K=1 TO 70
3510  SA=SA+3 : SB=SB-3
3520  CC=15 : IF ABS(SA-SB)<12 THEN CC=9
3530  SPRITE 1,(SA,90),8,CC : SPRITE 2,(SB,90),8,CC
3540  GOSUB 3910
3550 NEXT K
3560 GOSUB 3900
3570 REM --- 6. PRIORITY : lower number drawn in front ---
3580 SPRITE 1,(120,90),8,14 : REM fixed sprite 1
3590 FOR SA=80 TO 164 STEP 3 : SPRITE 2,(SA,90),8,9 : GOSUB 3910 : NEXT SA
3600 GOSUB 3900
3610 SCREEN 1,1 : CLS : PRINT "SPRITE PLAYGROUND COMPLETE" : END
3900 REM -- hide sprites 0-8 (colour 0 = transparent) --
3902 FOR I=0 TO 8 : SPRITE I,(0,0),0,0 : NEXT I : RETURN
3910 FOR T=1 TO 50 : NEXT T : RETURN
3920 FOR T=1 TO 1400 : NEXT T : RETURN
```
Notes
* Scene 4 is a real TMS9918 limit: at most 4 sprites show per scanline,
and it is the HIGHEST-numbered ones that drop. Aligning Y makes sprite
5 vanish; staggering Y (so no line holds >4) brings it back.
* Scene 5 detects overlap with ABS(SA-SB)<12 (a simple 1-D distance);
for a real game compare both X and Y. Add SOUND 4,0,12 on overlap and
SOUND 0 otherwise for an audible "clack".
* Variables: arrays SX/SY (position) and VX/VY (velocity); scalars
I,J,K,T,SA,SB,CC. Only the first 2 letters of a name are significant.
* TO VERIFY on an emulator: the 16x16 scenes (MAG 1/3) assume sprite
pattern 0 selects cells 0-3 and the TL/BL/TR/BR byte order above. If
the 16x16 ball looks scrambled, that is the part to adjust.

4. INPUT & GAMES

4.  INPUT & GAMES
============================================================================

4.1 Input test -- STICK / STRIG / INKEY$ live

  4.1  Input test -- STICK / STRIG / INKEY$ live
----------------------------------------------------------------------------
Shows the three real-time input primitives updating live. Move joystick 1,
press the fire buttons, press keys; BREAK to quit.
STICK(f)  joystick f (1=P1,2=P2): 0=none,1=up,2=upR,3=R,4=dnR,5=dn,
6=dnL,7=L,8=upL  (clockwise from up)
STRIG(f)  buttons: 0=none, 1=T1, 2=T2, 3=both
INKEY$    current key as a string ("" if none) -- non-blocking
```
4000 REM ===================================================
4010 REM   INPUT TEST  --  STICK / STRIG / INKEY$ live
4020 REM ===================================================
4030 SCREEN 1,1 : CLS
4040 PRINT "INPUT TEST"
4050 PRINT "MOVE JOYSTICK 1, PRESS FIRE, PRESS KEYS"
4060 PRINT "BREAK TO QUIT"
4070 D=STICK(1) : B=STRIG(1) : K$=INKEY$
4080 CURSOR 0,6 : PRINT "STICK(1) =";D;"  ";
4090 CURSOR 0,7 : PRINT "STRIG(1) =";B;"  ";
4100 CURSOR 0,8 : PRINT "INKEY$   = [";K$;"]  ";
4110 GOTO 4070
```

4.2 Dodger -- a joystick game

  4.2  Dodger -- a joystick game
----------------------------------------------------------------------------
Move the ship left/right with the joystick and dodge the falling rocks.
Score = rocks dodged; the rocks speed up as you score. On a hit it shows
the score and waits for a key to play again (BREAK quits). Demonstrates
STICK control, several moving sprites, software collision and scoring.
```
4200 REM ===================================================
4210 REM   DODGER  --  joystick dodging game
4220 REM ===================================================
4250 DIM OX(3),OY(3)
4260 REM -- (re)start --
4270 SCREEN 2,2 : COLOR 15,1
4280 PATTERN S#0,"18183C7E7EFFFF66*" : REM ship  (cell 0)
4290 PATTERN S#1,"3C7EFFFFFFFF7E3C*" : REM rock  (cell 1)
4300 PX=120 : SK=0 : SP=2
4310 FOR I=1 TO 3 : OX(I)=INT(RND(1)*240) : OY(I)=INT(RND(1)*100) : NEXT I
4320 REM -- game loop --
4330 D=STICK(1) : HT=0
4340 IF D=6 OR D=7 OR D=8 THEN PX=PX-5
4350 IF D=2 OR D=3 OR D=4 THEN PX=PX+5
4360 IF PX<0 THEN PX=0
4370 IF PX>240 THEN PX=240
4380 SPRITE 0,(PX,176),0,11
4390 FOR I=1 TO 3
4400  OY(I)=OY(I)+SP
4410  IF OY(I)>184 THEN OY(I)=0 : OX(I)=INT(RND(1)*240) : SK=SK+1 : SP=2+INT(SK/8)
4420  SPRITE I,(OX(I),OY(I)),1,8
4430  IF OY(I)>162 AND ABS(OX(I)-PX)<13 THEN HT=1
4440 NEXT I
4450 IF HT=0 THEN 4330
4460 REM -- game over --
4470 FOR I=0 TO 3 : SPRITE I,(0,0),0,0 : NEXT I
4480 SCREEN 1,1 : CLS
4490 PRINT "GAME OVER -- SCORE =";SK
4500 PRINT : PRINT "PRESS A KEY TO PLAY AGAIN (BREAK QUITS)"
4510 IF INKEY$="" THEN 4510
4520 GOTO 4270
```
Notes
* STICK maps 8 directions clockwise from up; left = 6/7/8, right = 2/3/4
(so diagonals also move you sideways). For up/down (e.g. Pong) test
1/2/8 (up) and 4/5/6 (down).
* Collision is a simple box test: the rock is near the ship's row
(OY>162) and close in X (ABS(OX-PX)<13). Widen/narrow 13 for difficulty.
* The hit is flagged (HT=1) and handled AFTER the FOR loop finishes, so we
never GOTO out of a FOR (which would leak the loop stack over restarts).
* Difficulty: SP (fall speed) rises with the score (every 8 dodges). For
more rocks raise the array size and the 1..3 loops together.
* Add fire/sound: read STRIG(1) for a button, or SOUND 4,0,12 on a hit.

5. TEXT & SCREEN

5.  TEXT & SCREEN
============================================================================
[.] to write -- e.g. scroller, colour text, screen-mode switch.