Swarm

This file is part of SINCUS Exchange Tape 101 - Entertainment, and Timex Sinclair Public Domain Library Tape 2004. Download the collection to get this file.
Type: Program
Platform(s): TS 2068
Tags: Arcade, Game

This program is a single-screen shoot-the-swarm game in which the player uses a joystick to aim a crosshair and fire rockets at a grid of giant mutant bees attacking a city. Up to 16 custom User-Defined Graphics (UDGs) are defined via DATA statements and POKE USR at startup to render the bees, rocket exhaust frames, and city silhouette. The SOUND keyword is used at line 75 to initialize a multi-channel audio chip with register values for background atmosphere. Game logic is driven by a state machine encoded in the variable `c`, with GO TO targets computed as `1080+c*100` to dispatch rocket flight animation, bee destruction, and city-damage phases. Scoring penalizes the player five points per surviving bee and two points per civilian killed, with a persistent high score tracked across playthroughs.


Program Analysis

Program Structure

The program is organized into several distinct regions by line number range:

  1. Lines 2–370: Initialization — UDG definition, SOUND setup, title screen graphics, and variable initialization.
  2. Lines 1000–1050: Instructions screen with randomized BEEP noise while waiting for ENTER.
  3. Lines 1060–1130: Game loop entry — score/status display and bee swarm animation (horizontal oscillation).
  4. Lines 1200–1900: State-machine dispatcher for rocket flight phases (approach, impact, explosion, retreat).
  5. Lines 2000–2090: Joystick polling, crosshair movement, and fire detection.
  6. Lines 3000–3830: Rocket animation in flight, hit detection against bees and city, scoring.
  7. Lines 4000–4510: End-of-game scoring summary, high score check, and restart.
  8. Lines 5000–5040: City-destroyed failure ending.
  9. Lines 8010–8900: Diagnostic routine (prints UDG bytes) and STOP — not part of normal gameplay.
  10. Lines 9000–9120: DATA blocks for all UDG bitmaps.
  11. Lines 9998–9999: CLEAR and SAVE with auto-run, followed by VERIFY.

UDG Definition Strategy

Lines 40–60 define 16 UDGs using a clever indirect method. The string a$="akblcidjegfhmonp" contains pairs of UDG letters. The outer loop steps through odd indices of a$, and for each pair, eight DATA bytes are read and POKEd into both USR a$(i) (top half of a 2×2 glyph) and USR a$(i+1)+7-j (the second character, stored in reverse row order). This mirror technique means each paired UDG automatically forms the bottom half of a sprite reflected vertically from the top half, halving the number of unique DATA rows required.

Lines 280–280 define five additional UDGs (q through u) from a second DATA block. These are used for rocket exhaust animation frames and the city skyline strip (UDG u), which is displayed along row 21 as a destructible city bar (p$).

State Machine via Computed GO TO

The variable c acts as a phase counter. After the main game loop at line 1080, c=0 causes a fall-through to line 1100 (swarm oscillation). Non-zero values of c (1 through 8, advancing each frame via line 1900) dispatch to lines 1200, 1300, 1400, 1500, 1600, 1700, 1800 representing rocket approach, impact flash, explosion stages, city hit, and retreat. The dispatch expression at line 1080 is GO TO 1100+c*100, producing clean 100-line-apart jump targets.

Swarm Representation with DIM b$

b$ is declared as a two-dimensional string array DIM b$(8,21) at line 290, effectively an 8-row × 21-column character grid holding the bee swarm. Each bee occupies a 2×2 character cell within this grid. Rows 300–320 initialize b$ with embedded INK color control characters and UDG pairs, tiling six bees per row across four vertical pairs. When a bee is shot, its corresponding b$ cells are cleared to spaces (lines 3580–3590 or 3670–3680), causing it to vanish from subsequent PRINT redraws.

Joystick Input via STICK

Lines 2010–2040 use STICK(1,1) four times to read directional input, testing return values 2, 1, 8, and 4 for down, up, right, and left respectively. Line 2090 tests STICK(2,1)=1 for the fire button. The crosshair coordinates d (row) and a (column) are bounded to the play area with wrap-prevention arithmetic on lines 2030–2040 using the idiom d=d+(d=0)-(d=21).

City Destruction Tracking

The city is represented as the string p$ (line 1075), initialized with 30 UDG u characters representing citizens. Variable p starts at 30. When a rocket lands at a city column (line 1710), the program checks whether p$(a2) and p$(a2+1) contain "u" and decrements p accordingly. Those positions are then blanked in both p$ and the display. If p reaches zero (line 1713 check via NOT p), the game branches to line 5000 (city destroyed ending). The penalty scoring at end-game deducts (30-p)*2 for casualties.

Rocket Animation

In-flight rocket frames cycle through characters from the string "\q\q\r\r\s\s\t\t" (indexed by f, lines 3020) for eight frames, then switch to "*" for the trailing fade-out phase (lines 3500–3510). The rocket travels from the crosshair position toward the target bee, with dd and aa capturing the launch coordinates at line 2100.

Scoring

EventPoints
Bee hit (rows 3–4 of swarm)+20
Bee hit (row 2 of swarm)+30
Bee hit (row 1 of swarm)+40
Active bee hit (same logic, higher base)+40/+60/+80
Surviving bee at end−5 each
Civilian killed−2 each

The high score h is stored in a variable initialized at line 5 and persists across playthroughs within a session via the restart loop at line 4510 which GO TOs line 10, preserving h.

SOUND Initialization

Line 75 uses a chained SOUND statement with 13 register/value pairs to configure multiple channels and noise settings on the audio chip at startup. Line 4502 uses SOUND to silence all channels before the replay prompt.

Notable Idioms and Techniques

  • POKE 23692,255 at line 70 disables the scroll prompt (“scroll?” message) by setting the scroll counter to its maximum.
  • The string slicing "000"( TO 4-LEN STR$ s) (line 3760) pads scores with leading zeros up to four digits.
  • LET x$=CHR$ 16+CHR$ (...) at line 300 embeds an INK color control character directly into the b$ string rows, so color is applied automatically when the rows are PRINTed.
  • The diagnostic section at lines 8010–8900 is unreachable during normal play but could be manually RUN from the command line for debugging UDG content.
  • The AND operator is used as a conditional multiplier in several expressions, e.g., (10 AND d3=2) at line 3600, a standard Sinclair BASIC boolean arithmetic idiom.

Potential Bugs and Anomalies

  • Line 1210 checks b$(d1*2,a1*3+1)="\c" — this tests only the first byte of the two-character UDG pair. Since the cell is blanked to two spaces on kill, this correctly detects a live bee, but depends on the UDG character code never matching a space or the embedded INK control character.
  • Line 3565 guards against re-hitting the currently active bee mid-flight, but does not guard against re-hitting a bee that was already destroyed and whose b$ cells are now spaces, which is handled implicitly by the b$(d3,a3)=" " check at line 3570.
  • The hit-detection for the active bee on line 3520 only triggers when m=0 (a bee is actively descending), meaning a bee approaching the city can only be shot in that specific state, not while it is retreating.

Content

Appears On

One of a series of library tapes compiled from multiple user groups.

Related Products

Related Articles

Related Content

Image Gallery

Swarm

Source Code

    2 CLS : BEEP .2,20
    5 LET h=0
   10 RESTORE 
   15 FLASH 0: BRIGHT 0: OVER 0
   20 INVERSE 0: BORDER 0
   30 PAPER 0: INK 6: CLS 
   40 LET a$="akblcidjegfhmonp"
   50 FOR i=1 TO 15 STEP 2
   60 FOR j=0 TO 7: READ n: POKE USR a$(i)+j,n: POKE USR a$(i+1)+7-j,n: NEXT j: NEXT i
   70 POKE 23692,255: PRINT AT 21,0;
   75 SOUND 7,56;0,68;1,3;8,16;2,151;3,2;9,16;4,46;5,2;10,16;12,100;13,14
   80 PRINT "      \i\j\a\b\i\j \a\b  \a\b \m\n\e\f\e\f"
   90 PRINT "      \k\l\c\d\k\l \c\d  \c\d \o\p\g\h\g\h"
  100 PRINT "        \a\b   \a\b  \a\b \a\b"
  110 PRINT "        \c\d   \c\d\i\j\c\d \c\d\e\f\e\f"
  120 PRINT "        \a\b   \a\b\k\l\a\b \i\j\g\h\g\h"
  130 PRINT "        \c\d   \c\d  \c\d \k\l"
  140 PRINT "        \a\b   \a\b  \a\b \i\j\e\f\e\f"
  150 PRINT "        \c\d   \c\d  \c\d \k\l\g\h\g\h"
  160 PRINT 
  170 PRINT "  \m\n \i\j  \i\j  \m\n\e\f  \m\n\e\f  \a\b  \a\b"
  180 PRINT "\m\n\o\p \k\l  \k\l  \o\p\g\h  \o\p\g\h  \c\d\i\j\c\d"
  190 PRINT "\o\p   \i\j  \i\j \i\j  \i\j \e\f \e\f \a\b\k\l\a\b"
  200 PRINT "\m\n\e\f \k\l  \k\l \k\l  \k\l \g\h \g\h \c\d  \c\d"
  210 PRINT "\o\p\g\h \i\j  \i\j \i\j\a\b\i\j \m\n\e\f  \a\b  \a\b"
  220 PRINT "  \e\f \k\l\a\b\k\l \k\l\c\d\k\l \o\p\g\h  \c\d  \c\d"
  230 PRINT "\e\f\g\h \i\j\c\d\i\j \i\j  \i\j \e\f \i\j \a\b  \a\b"
  240 PRINT "\g\h   \k\l  \k\l \k\l  \k\l \g\h \k\l \c\d  \c\d"
  250 PRINT '''''
  260 FOR i=1 TO 7: INK i
  270 BEEP .1,RND*24: FOR j=0 TO 19: PRINT AT j,0; OVER 1;TAB 31: NEXT j: NEXT i
  280 FOR i=USR "q" TO USR "u"+7: READ n: POKE i,n: NEXT i
  290 DIM b$(8,21): FOR i=1 TO 4
  300 LET x$=CHR$ 16+CHR$ (3+(2 AND i=2)+(3 AND i>2))
  310 LET b$(i*2-1)=x$+" \a\b \a\b \a\b \a\b \a\b \a\b "
  320 LET b$(i*2)=x$+" \c\d \c\d \c\d \c\d \c\d \c\d "
  330 NEXT i
  340 LET r=24: LET s=0: LET m=12
  350 LET b=24: LET f=0: LET p=30
  360 LET d=20: LET a=0: LET z=1
  370 LET t=0: LET x=1
 1000 BRIGHT 0: PRINT AT 21,0;
 1010 PRINT ''"  A swarm of giant mutant bees"''"is attacking a city by night."''"You have a rocket launcher"
 1020 PRINT '"positioned one kilometer away,"''"but only enough ammunition to"''"allow you one shot at each"''"bee."
 1030 PRINT '"  Use joystick to move and fire"
 1040 PRINT '''"Type ENTER to start"
 1050 IF INKEY$<>CHR$ 13 THEN BEEP .05,RND*48-24: GO TO 1050
 1060 CLS 
 1070 PRINT "SCORE:0000 HIGH:";"000"( TO 4-LEN STR$ h);h;"  ROCKETS:24"
 1075 LET p$=" \u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u"
 1076 PRINT AT 21,1;p$
 1080 IF m=0 THEN GO TO 1100+c*100
 1090 IF z=0 THEN BEEP .12,-35: GO TO 2000
 1100 LET t=t+x
 1110 IF t=0 OR t=13 THEN LET x=-x
 1120 PRINT AT 1,t;b$(1);AT 2,t;b$(2);AT 4,t;b$(3);AT 5,t;b$(4);AT 7,t;b$(5);AT 8,t;b$(6);AT 10,t;b$(7);AT 11,t;b$(8)
 1130 GO TO 2000
 1200 LET d1=4: LET a1=1
 1210 IF b$(d1*2,a1*3+1)="\c" THEN GO TO 1240
 1220 LET a1=a1+1: IF a1=7 THEN LET a1=1: LET d1=d1-1: IF d1=0 THEN LET d1=4
 1230 GO TO 1210
 1240 LET d2=d1*3-2
 1250 LET a2=a1*3-2+t
 1260 PRINT AT d2,a2;"\a\b";AT d2+1,a2;"\c\d"
 1265 BEEP .01,22-d2
 1270 GO TO 1900
 1300 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\e\f";AT d2+1,a2;"\g\h"
 1305 BEEP .07,21-d2
 1310 GO TO 1900
 1400 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\i\j";AT d2+1,a2;"\k\l"
 1405 BEEP .07,20-d2
 1410 GO TO 1900
 1500 PRINT AT d2,a2;"  "
 1510 LET d2=d2+1
 1520 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\i\j";AT d2+1,a2;"\k\l"
 1530 IF d2=19 THEN LET c=c+1
 1535 BEEP .07,20-d2
 1540 GO TO 2000
 1600 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\m\n";AT d2+1,a2;"\o\p"
 1605 BEEP .07,-1
 1610 GO TO 1900
 1700 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\a\b";AT d2+1,a2;"\c\d"
 1710 LET p=p-(p$(a2)="u")-(p$(a2+1)="u")
 1712 IF p$(a2)="u" OR p$(a2+1)="u" THEN BEEP .01,20: BEEP .01,24: BEEP .01,27
 1713 IF NOT p THEN GO TO 5000
 1720 LET p$(a2 TO a2+1)="  ": PRINT AT 21,a2;"  "
 1730 GO TO 1900
 1800 PRINT AT d2+1,a2;"  "
 1810 LET d2=d2-1
 1820 PRINT AT d2,a2; BRIGHT 1;b$(d1*2-1,1 TO 2);"\a\b";AT d2+1,a2;"\c\d"
 1830 IF d2=d1*3-2 THEN LET m=INT (b/2+.5): LET z=1
 1835 BEEP .05,20-d2
 1840 GO TO 2000
 1900 LET c=c+1
 2000 IF m THEN LET m=m-z: LET z=1-z: IF NOT m THEN LET z=0: LET c=1
 2010 LET d=d+(|(1,1)=2)-(|(1,1)=1)
 2020 LET a=a+(|(1,1)=8)-(|(1,1)=4)
 2030 LET d=d+(d=0)-(d=21)
 2040 LET a=a+(a=-1)-(a=32)
 2050 PRINT AT d,a; OVER 1; INK 8; PAPER 8; BRIGHT 8;"+"
 2060 BEEP .001,50
 2070 PRINT AT d,a; OVER 1; INK 8; BRIGHT 8;"+"
 2080 IF f THEN GO TO 3000
 2090 IF |(2,1)=1 THEN GO TO 1080
 2100 LET dd=d: LET aa=a
 3000 LET f=f+1
 3010 IF f>8 THEN GO TO 3500
 3020 PRINT AT dd,aa;"\q\q\r\r\s\s\t\t"(f)
 3030 GO TO 1080
 3500 IF f=20 THEN GO TO 3800
 3510 PRINT AT dd,aa;"*"
 3520 IF m=0 THEN IF (dd=d2 OR dd=d2+1) AND (aa=a2 OR aa=a2+1) THEN GO TO 3650
 3530 IF dd>11 OR dd/3=INT (dd/3) THEN GO TO 1080
 3540 IF aa<=t OR aa>t+17 OR (a-t)/3=INT ((a-t)/3) THEN GO TO 1080
 3550 LET d3=INT (dd/3)*2+1
 3560 LET a3=INT ((aa-t)/3)*3+4
 3565 IF (d3-1)/2+1=d1 AND (a3-4)/3+1=a1 THEN GO TO 1080
 3570 IF b$(d3,a3)=" " THEN GO TO 1080
 3580 LET b$(d3,a3 TO a3+1)="  "
 3590 LET b$(d3+1,a3 TO a3+1)="  "
 3600 LET s=s+20+(10 AND d3=2)+(20 AND d3=1)
 3610 GO TO 3750
 3650 PRINT AT d2,a2;"  ";AT d2+1,a2;"  ": LET m=INT (b/2+.5): LET z=1
 3660 LET s=s+40+(20 AND d1=2)+(40 AND d1=1)
 3670 LET b$(d1*2-1,a1*3+1 TO a1*3+2)="  "
 3680 LET b$(d1*2,a1*3+1 TO a1*3+2)="  "
 3750 BEEP .01,40: BEEP .01,44: BEEP .01,47
 3755 LET b=b-1
 3760 PRINT AT 0,6;"000"( TO 4-LEN STR$ s);s
 3770 GO TO 1080
 3800 IF SCREEN$ (dd,aa)="*" THEN PRINT AT dd,aa;" "
 3810 LET r=r-1
 3820 PRINT AT 0,30;("0" AND r<10);r
 3825 LET f=0
 3830 IF r THEN GO TO 1080
 4000 FOR i=1 TO 100: NEXT i
 4010 CLS 
 4015 IF b THEN GO TO 4200
 4020 PRINT "  You have killed all the bees."''"The bees killed ";30-p;" people."''"  SCORE:";s''
 4030 GO TO 4220
 4200 PRINT "  You have used up all your"''"rockets, with ";b;" bees left."''"The bees killed ";30-p;" people."''"  SCORE:";s''
 4210 PRINT "       -";b*5,"(5 per bee)"''
 4220 PRINT "       -";(30-p)*2,"(2 per corpse.)"
 4230 LET s=s-b*5-(30-p)*2
 4240 PRINT "        ===="''"        ";s,"(Final Score.)"
 4250 IF s<=h THEN GO TO 4500
 4260 PRINT '''"  Well done!"''"  You have the high score!"
 4270 LET h=s
 4500 PRINT '"  Type ENTER to play again."
 4502 SOUND 8,0;9,0;10,0;7,63
 4505 IF INKEY$<>CHR$ 13 THEN GO TO 4505
 4510 CLS : GO TO 10
 5000 FOR i=1 TO 100: NEXT i
 5010 CLS 
 5020 PRINT "  The bees have killed all the"''"people. you have failed."''"  SCORE:0."
 5030 FOR i=1 TO 500: NEXT i
 5040 CLS : GO TO 10
 8010 FOR w=0 TO 7: PRINT PEEK (USR "q"+w): NEXT w
 8900 STOP 
 9000 DATA 6,1,11,7,3,23,11,17
 9010 DATA 96,128,208,224,192,232,208,136
 9020 DATA 35,71,135,159,103,11,11,9
 9030 DATA 196,226,225,249,230,208,208,144
 9040 DATA 12,18,17,8,232,30,127,255
 9050 DATA 0,0,0,160,68,41,125,254
 9060 DATA 0,0,0,5,34,148,190,127
 9070 DATA 48,72,136,16,23,120,254,255
 9080 DATA 0,56,84,146,254,146,84,56
 9090 DATA 0,0,56,84,124,84,56,0
 9100 DATA 0,0,0,16,56,16,0,0
 9110 DATA 0,0,0,0,16,0,0,0
 9120 DATA 16,56,16,254,16,16,40,68
 9998 CLEAR : SAVE "SWARM" LINE 1
 9999 VERIFY ""

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top