10 REM SNEEKIE
20 REM MS(X)DOS Computer Magazine
30 REM GW-Basic versie
40 REM door HerbySoft
70 REM
1
Boot & find the screen
lines 80–100
Three jobs in two lines. DEFINT A-Y makes every variable A…Y an integer — which deliberately leaves the Z* names floating-point, the reason the timer and score are called Z, ZCORE, ZORE. SCREEN 0:WIDTH 80 selects 80×25 text. Then PEEK(&H449) asks the BIOS whether this PC has a mono card (memory at &HB000) or colour (&HB800); from here on every PEEK/POKE aims straight at that screen memory.
80 DEFINT A-Y: SCREEN 0: WIDTH 80: CLS: ZORE=0: RANDOMIZE TIMER: DEF SEG=&H0
↳ DEFINT A-Y = integers; Z* left floating-point (TIMER needs fractions, the score can pass 32767). SCREEN 0:WIDTH 80 = 80x25 text. RANDOMIZE TIMER seeds the dice.
90 IF PEEK(&H449)=7 THEN VIDEO=&HB000 ELSE VIDEO=&HB800
↳ PEEK(&H449) is the BIOS video-mode byte. Mode 7 = mono card at &HB000; anything else = colour at &HB800.
100 DEF SEG=VIDEO: CLS: DIM T(15000),S(168),B(10),D(80,3)
↳ DEF SEG=VIDEO aims PEEK/POKE at screen memory. DIM the four arrays: T()=snake, S()=pop-up backup, B()=gate rows, D()=arrows.
2
Paint the frame & score panel
lines 110–220
Plain LOCATE…PRINT draws the fixed furniture: the outer box, the title bar, and the legend along the bottom. The final line POKEs the four little legend icons (☺ ◙ ♣ ♥) straight into screen memory at fixed offsets.
110 LOCATE 1, 1: PRINT CHR$(218);STRING$(78,CHR$(196));CHR$(191);
↳ Top edge of the frame: corner + 78 bars + corner.
120 LOCATE 2, 1: PRINT CHR$(179);SPC(78);CHR$(179);
130 LOCATE 2,17: PRINT "**** Sneekie **** (c) juli '88 by HerbySoft";
↳ The title in the top bar.
140 LOCATE 22, 1: PRINT CHR$(179);SPC(78);CHR$(179);
150 LOCATE 22, 6: PRINT "10 punten -50 punten Highscore";
160 LOCATE 23, 1: PRINT CHR$(179);SPC(78);CHR$(179);
170 LOCATE 22,55: PRINT "Level Score";
180 LOCATE 23, 6: PRINT "25 punten Steen <ESC> vastgelopen";
190 LOCATE 23,55: PRINT "Lives Bonus";
200 LOCATE 24, 1: PRINT CHR$(192);STRING$(78,CHR$(196));CHR$(217);
↳ Bottom edge of the frame.
210 POKE 3396,1: POKE 3556,10: POKE 3526,5: POKE 3366,3
↳ Drop the four legend icons straight into screen memory by offset: smiley(1), stone(10), club(5), heart(3).
220 '
3
Start a new game
line 230
Zero the score and set three lives, then play levels 1→32.
230 ZCORE=0: LIVE=3
↳ Fresh game: score 0, three lives.
4
The level loop
lines 240–310
For each level: blank the 17 inner rows, drop a two-cell snake in the middle pointing up, and ON LEVEL GOSUB into this level's recipe (lines 2320–2480) which sets the speed and builds the maze.
240 FOR LEVEL=1 TO 32
250 FOR I=1 TO 17: LOCATE 3+I,1: PRINT CHR$(179);SPC(78);CHR$(179): NEXT
↳ Wipe the 17 inner rows back to blank, leaving the side walls.
260 LOCATE 3,1: PRINT CHR$(195);STRING$(78,CHR$(196));CHR$(180)
270 LOCATE 21,1: PRINT CHR$(195);STRING$(78,CHR$(196));CHR$(180)
280 T(1)=2000: T(2)=1840: BTEL=2: ETEL=1
↳ Seed the snake: tail at offset 2000 (row 13), head at 1840 (row 12, right above it) -> it starts pointing up. BTEL=2 is the head slot in T(), ETEL=1 the tail.
290 POKE T(BTEL),219: POKE T(ETEL),186: POKE T(BTEL)+1,15
↳ Paint it: head = block (219), tail = double-bar (186), head attribute bright (15).
300 E=72: F=72: HART=0: KLAVER=0: BONUS=10000: OP=0: GOSUB 1190
↳ Per-level reset: heading up (E=F=72), nothing collected yet, bonus 10000.
310 ON LEVEL GOSUB 2320,2330,2340,2350,2360,2370,2380,2390,2410,2420,2430,2440,2450,2460,2470,2480,2320,2330,2340,2350,2360,2370,2380,2390,2410,2420,2430,2440,2450,2460,2470,2480
↳ ON LEVEL GOSUB -> this level's recipe (2320..2480): speed, item count, bonus step, and the maze. Levels 17-32 reuse the same 16.
5
Status line & scattering the items
lines 320–360
Show the bonus, lives and level, then sprinkle AANTAL hearts and AANTAL smileys onto random empty squares. HART ends up holding how many hearts you must collect to clear the level.
320 LOCATE 23,73: PRINT USING "######";BONUS
330 LOCATE 23,61: PRINT USING "##";LIVE: LOCATE 22,61: PRINT USING "##";LEVEL
340 FOR I=1 TO AANTAL
↳ Scatter the items: AANTAL times, drop one smiley (hazard) and one heart.
350 L=1: GOSUB 1150: L=3: GOSUB 1150: IF K1=1 THEN HART=HART+1
↳ GOSUB 1150 drops a char on a random empty cell. K1=1 means the heart landed -> count it into HART.
360 NEXT
6
The “Level n” pop-up
lines 370–410
Copy the patch of screen the box will cover into S(), draw the box and level number, wait for a key, then paste the screen back — so the pop-up leaves no hole behind it.
370 FOR I=1 TO 42: FOR I3=0 TO 3: S(I+I3*42)=PEEK(1497+I+I3*160): NEXT: NEXT
↳ Back up the 4x42 region the pop-up will cover into S() so it can be restored (1497 = box top-left, +160 per row).
380 GOSUB 2280: LOCATE 11,37: PRINT "Level ";LEVEL
390 LOCATE 12,32: PRINT "Druk op een toets"
400 DEF SEG=0: POKE 1050,PEEK(1052): DEF SEG=VIDEO: A$=INPUT$(1)
↳ Flush the BIOS keyboard buffer (head:=tail) so a stray key does not skip the box, then wait for one key.
410 FOR I=1 TO 42: FOR I3=0 TO 3: POKE 1497+I+I3*160,S(I+I3*42): NEXT: NEXT
↳ Paste the saved region back, erasing the box.
7
The move loop — reading a key
lines 420–460
The heart of the game. It runs until every heart and club is gone, waiting up to Z seconds for a key each tick. On the early levels Z=999 (wait forever — turn-based); later levels give you a fraction of a second, so the snake keeps moving on its own if you don't steer.
420 WHILE+ KLAVER+HART>0
↳ Play this level until every heart AND club is collected (HART+KLAVER reaches 0).
430 A$=INKEY$: Z2=0: Z1=TIMER
↳ Grab whatever key is waiting; start a timer.
440 WHILE+ A$="" AND Z2<Z
450 Z2=TIMER-Z1: A$=INKEY$
↳ Keep polling INKEY$ until a key arrives or Z seconds pass. Z=999 early (wait forever, turn-based); a fraction later (the snake moves itself).
460 WEND
8
Spend bonus, then sort the keypress
lines 470–650
Every tick nibbles BMIN off the bonus. Then the keypress is classified: a 2-character string is an arrow key (or a time-out) and jumps to the movement code at 640; a single character that is ESC starts the give-up routine; any other single key is treated as a wasted move.
470 IF BONUS>0 THEN BONUS=BONUS-BMIN
↳ Each move costs BMIN off the bonus.
480 LOCATE 23,73: PRINT USING "######";BONUS
490 IF LEN(A$)<>1 THEN GOTO 640
↳ A real arrow key is a 2-character string, so length<>1 means a move (or a time-out) -> handle at 640.
500 IF ASC(A$)<>27 THEN GOTO 910
↳ It was a single character. If not ESC (27), it is junk -> 910 (small penalty, no move).
510 FOR I=1 TO 3
↳ ESC (or jumped here from a deadly hit): the you-died / give-up routine.
520 SOUND 2000,3: SOUND 3000,3: SOUND 4000,3: SOUND 3000,3
530 NEXT
540 IF PLAY(0)<>0 THEN GOTO 540
↳ Wait for the sound queue to drain (PLAY(0) = notes still pending).
550 WHILE+ ETEL<=BTEL
↳ Unwind the whole snake, tail-first...
560 Z=TIMER
570 Z1=TIMER-Z: IF Z1<0.075 THEN GOTO 570
580 POKE T(ETEL),32: POKE T(ETEL)+1,7: SOUND 1500,0.1
↳ ...blank each cell (space + normal attribute) with a blip...
590 ETEL=ETEL+1: OP=BMIN*-1: GOSUB 1190
↳ ...advancing the tail and docking the bonus as it goes.
600 WEND
610 LIVE=LIVE-1: HART=0: KLAVER=0
↳ Lose a life; clear the heart/club counters.
620 IF LIVE=0 THEN LEVEL=32 ELSE LEVEL=LEVEL-1
↳ Last life? set LEVEL=32 so the FOR loop ends (game over). Otherwise LEVEL-1 so NEXT replays this level.
630 GOTO 1080
640 IF LEN(A$)=2 THEN E=ASC(MID$(A$,2,1))
↳ A 2-char key: take the scancode from its second byte into E (new heading). A time-out leaves E as-is, so the snake keeps going.
650 A=T(BTEL)
↳ A = where the head is now.
9
Cheats, then turn the head
lines 660–700
Two hidden keys first: F10 (scancode 68) skips the level, F9 (67) grants a life and skips. Otherwise the heading is turned into a step across screen memory — ±160 for a row, ±2 for a column — giving A, the cell the head wants to enter, which is then PEEKed.
660 IF E=68 THEN GOTO 1080
↳ Scancode 68 = F10: skip to the next level.
670 IF E=67 THEN LIVE=LIVE+1: GOTO 1080
↳ Scancode 67 = F9: free life and skip.
680 IF E=80 THEN A=A+160 ELSE IF E=72 THEN A=A-160
↳ Turn the heading into a screen step: +/-160 = up/down a row, +/-2 = left/right a column. A is now the target cell.
690 IF E=77 THEN A=A+2 ELSE IF E=75 THEN A=A-2
700 D=PEEK(A)
↳ Look at what is already in that cell.
10
What is in the next cell?
lines 710–900
The big decision: switch on the character found ahead.
32 empty → slide forward (erase tail, advance).
5 ♣ club → +25 and grow (the tail is not erased).
3 ♥ heart → +10 and grow; on levels past 16 it also breeds a new club.
10 ◙ stone → push it if the square beyond is empty, else you're blocked.
1 ☺ smiley → −50 and grow onto it.
24/26/27 arrow → instant death.
A neat twist: eating a heart or club
spawns fresh smileys, so the board gets busier as you clear it.
710 IF D<>32 THEN GOTO 740
↳ 32 = empty -> just move.
720 POKE T(ETEL),32: POKE T(ETEL)+1,7: SOUND 1500,0.1: ETEL=ETEL+1
↳ Erase the tail cell and advance the tail pointer, so the snake slides forward at the same length.
730 GOTO 920
740 IF D<>5 THEN GOTO 770
↳ 5 = club (worth 25).
750 L=1: GOSUB 1150: GOSUB 2260
↳ Drop a fresh smiley somewhere (L=1) and play the jingle -- collecting tightens the screen.
760 OP=25: GOSUB 1190: KLAVER=KLAVER-1: GOTO 920
↳ +25, one fewer club, finish. No tail erase here, so eating GROWS the snake.
770 IF D<>3 THEN GOTO 800
↳ 3 = heart (worth 10).
780 IF LEVEL>16 THEN L=5: GOSUB 1150: IF K1=1 THEN KLAVER=KLAVER+1
↳ On the hard half (levels past 16) a heart also breeds a new club; if it landed, add it to the clubs you must collect.
790 L=1: GOSUB 1150: GOSUB 2260: OP=10: GOSUB 1190: HART=HART-1: GOTO 920
↳ Spawn a smiley, jingle, +10, one fewer heart, finish (grow).
800 IF D<>10 THEN GOTO 870
↳ 10 = stone -> try to push it.
810 TA=A: IF E=80 THEN TA=TA+160 ELSE IF E=72 THEN TA=TA-160
↳ TA = the cell on the far side of the stone, in the same direction.
820 IF E=77 THEN TA=TA+2 ELSE IF E=75 THEN TA=TA-2
830 D=PEEK(TA)
840 IF D<>32 THEN GOTO 910
↳ If that far cell is not empty the stone cannot move -> 910 (blocked).
850 POKE TA,10: POKE T(ETEL),32: POKE T(ETEL)+1,7
↳ Otherwise shove the stone into TA, erase the tail, and move.
860 SOUND 1500,0.1: ETEL=ETEL+1: GOTO 920
870 IF D<>1 THEN GOTO 900
↳ 1 = smiley -- the bad one.
880 FOR I=50 TO 1 STEP -1: SOUND 600+75*I,0.35: NEXT
↳ A descending 50-note wail.
890 OP=-50: GOSUB 1190: L=1: GOSUB 1150: GOTO 920
↳ -50, drop another smiley, and move onto it (grow).
900 IF D=24 OR D=26 OR D=27 THEN GOTO 510
↳ 24/26/27 = a moving arrow -> instant death (jump to 510).
11
Blocked — walls and your own tail
line 910
If the cell ahead is a wall or part of the snake, you simply can't enter: keep the old heading (E=F), lose a little bonus, buzz, and skip the move. Unlike most snake games, walls and bumping yourself don't kill you here — only arrows, ESC, or completely filling T() do.
910 E=F: OP=BMIN*-1: GOSUB 1190: SOUND 1000,5: GOTO 1020
↳ A wall or your own body: you cannot enter. Keep the old heading (E=F), lose a little bonus, buzz, skip the move. Walls do not kill you here.
12
Lay the body, grow the head, animate
lines 920–1020
The cell the head is leaving is turned into the correct box-drawing piece — straight ═/║ or a corner ╗╝╔╚ chosen from the new heading E and the old one F — then a new █ head is appended at T(BTEL). A "shimmer" lights alternate body cells, and finally this level's animation routine (arrows or gates) takes one step.
920 IF (E=77 AND F=77) OR (E=75 AND F=75) THEN POKE T(BTEL),205: GOTO 980
↳ Straight horizontal run -> the cell you leave becomes = (205).
930 IF (E=80 AND F=80) OR (E=72 AND F=72) THEN POKE T(BTEL),186: GOTO 980
↳ Straight vertical run -> the cell you leave becomes || (186).
940 IF (E=80 AND F=77) OR (E=75 AND F=72) THEN POKE T(BTEL),187: GOTO 980
↳ These four lines choose the corner glyph (corner-pieces) for a bend, from the new heading E and the old heading F.
950 IF (E=72 AND F=77) OR (E=75 AND F=80) THEN POKE T(BTEL),188: GOTO 980
960 IF (E=80 AND F=75) OR (E=77 AND F=72) THEN POKE T(BTEL),201: GOTO 980
970 IF (E=72 AND F=75) OR (E=77 AND F=80) THEN POKE T(BTEL),200: GOTO 980
980 BTEL=BTEL+1: T(BTEL)=A: F=E: POKE T(BTEL),219
↳ Append the new head: BTEL+1, store its offset in T(BTEL), remember F=E, paint the block (219).
990 IF BTEL=15000 THEN GOTO 510
↳ If the trail array is full (15000) the snake has nowhere to grow -> death.
1000 FOR I=BTEL TO ETEL STEP -2: POKE T(I)+1,15: POKE T(I-1)+1,7: NEXT
↳ The shimmer: step through the body by twos, making alternate cells bright (15) and their neighbours normal (7). BTEL flips parity each move, so the bright dashes appear to crawl.
1010 ON LEVEL GOSUB 1170,1170,1170,1170,2130,1830,1970,2130,1170,1170,1170,1170,2130,1830,1970,2130,1170,1170,1170,1170,2130,1830,1970,2130,1170,1170,1170,1170,2130,1830,1970,2130
↳ ON LEVEL GOSUB -> this level animation: 1170 (nothing) on calm levels, or the arrow/gate movers (2130/1830/1970).
1020 WEND
13
Level cleared — bank the bonus
lines 1030–1080
Pour the leftover bonus into the score, 5 points and a beep at a time, then award an extra life.
1030 WHILE+ BONUS>0
↳ Level cleared. Pour the leftover bonus into the score, 5 at a time...
1040 OP=5: GOSUB 1190: BONUS=BONUS-5: LOCATE 23,74
1050 PRINT USING "#####";BONUS: SOUND 3000,0.1
1060 WEND
1070 LIVE=LIVE+1
↳ ...then reward finishing with +1 life.
1080 NEXT LEVEL
14
The End / play again
lines 1090–1140
After all 32 levels (or when the lives run out) show Einde ("The End"), ask Nog een keer (j/n) ("again? y/n"), and either restart at 230 or quit.
1090 GOSUB 2280: LOCATE 11,33: PRINT "Einde"
↳ All 32 done (or out of lives): show Einde (The End).
1100 LOCATE 12,32: PRINT "Nog een keer (j/n)"
1110 DEF SEG=0: POKE 1050,PEEK(1052): DEF SEG=VIDEO
1120 A$=INPUT$(1): IF INSTR("JjNn",A$)=0 THEN GOTO 1120
1130 IF A$="J" OR A$="j" THEN GOTO 230 ELSE CLS: PRINT "Bedankt voor het spelen": END
↳ j = ja = yes -> restart at 230; otherwise clear, thank the player, END.
1140 '
15
Drop an item on a random cell
lines 1150–1180
Pick a random even offset inside the playfield (even so it lands on a character byte, not its colour byte). If that square is empty, write the item there and set K1=1 to report that it landed.
1150 K1=0: K=INT(RND*2720+480): IF K MOD 2=1 THEN K=K+1
↳ Random even offset in the playfield (480..3200); even = a character byte, not a colour byte.
1160 IF PEEK(K)=32 THEN POKE K,L: K1=1
↳ Only if the cell is empty (32): write L there and flag K1=1 (it landed).
1170 RETURN
1180 '
16
Score & high score
lines 1190–1220
Add OP to the score and redraw it; if it beats ZORE, update and show the high score.
1190 ZCORE=ZCORE+OP: LOCATE 22,73: PRINT USING "######";ZCORE
↳ Add OP to the score and redraw it.
1200 IF ZCORE>ZORE THEN ZORE=ZCORE: LOCATE 22,46: PRINT USING "######";ZORE
↳ Beat the high score? update ZORE and show it.
1210 RETURN
1220 '
17
Layout: the labyrinth
lines 1230–1390
Nested loops draw a web of single-line walls joined with ┼ junctions — the densest of the mazes (used by levels 2, 10, 18, 26).
1230 FOR I=1 TO 39: LOCATE 8,1+I: PRINT CHR$(196): LOCATE 16,80-I: PRINT CHR$(196): NEXT
1240 FOR I=0 TO 8
1250 LOCATE 21-I,11: PRINT CHR$(179): LOCATE 3+I,70: PRINT CHR$(179): LOCATE 21-I,26: PRINT CHR$(179)
1260 LOCATE 3+I,55: PRINT CHR$(179): LOCATE 15,22+I: PRINT CHR$(196): LOCATE 6,51+I: PRINT CHR$(196)
1270 LOCATE 15,7+I: PRINT CHR$(196): LOCATE 6,66+I: PRINT CHR$(196): LOCATE 18,7+I: PRINT CHR$(196)
1280 LOCATE 9,66+I: PRINT CHR$(196): LOCATE 18,22+I: PRINT CHR$(196): LOCATE 9,51+I: PRINT CHR$(196)
1290 FOR I1=6 TO 10
1300 LOCATE I1,5+I*4: PRINT CHR$(179): LOCATE 8+I1,44+I*4: PRINT CHR$(179)
1310 NEXT
1320 LOCATE 8,5+I*4: PRINT CHR$(197): LOCATE 16,44+I*4: PRINT CHR$(197)
1330 NEXT
1340 LOCATE 3,70: PRINT CHR$(194): LOCATE 21,11: PRINT CHR$(193): LOCATE 3,55: PRINT CHR$(194)
1350 LOCATE 15,26: PRINT CHR$(197): LOCATE 6,55: PRINT CHR$(197): LOCATE 18,26: PRINT CHR$(197)
1360 LOCATE 9,55: PRINT CHR$(197): LOCATE 15,11: PRINT CHR$(197): LOCATE 6,70: PRINT CHR$(197)
1370 LOCATE 18,11: PRINT CHR$(197): LOCATE 9,70: PRINT CHR$(197): LOCATE 21,26: PRINT CHR$(193)
1380 RETURN
1390 '
18
Layout: scattered stones
lines 1400–1490
Lays ◙ stones in a zig-zag. The four-line helper at 1480 — POKE (Y-1)*160+(X-1)*2,… — is the shared "put one character at column X, row Y" routine that several layouts call.
1400 FOR Y=4 TO 20 STEP 2: FOR I=0 TO 1: Q=1: FOR A=1 TO 6
1410 IF Q=1 THEN Q=0: Y=Y+1 ELSE Q=1: Y=Y-1
1420 IF Y<21 THEN X=17+A+40*I: GOSUB 1480
1430 NEXT: NEXT: NEXT
1440 I1=7
1450 FOR X=2 TO 78 STEP 2: FOR I=0 TO 1
1460 Y=7+8*I: GOSUB 1480: Y=8+8*I: X=X+1: GOSUB 1480: Y=9+8*I: X=X-1: GOSUB 1480
1470 NEXT: NEXT: RETURN
1480 POKE (Y-1)*160+(X-1)*2,10: RETURN
↳ The workhorse: POKE one character at column X, row Y (here a stone, 10). Shared by several layouts.
1490 '
19
Layout: rooms with doorways
lines 1500–1660
Build a grid of little rooms (rails every 6 rows, walls every 10 columns, joined with ┼┬┴├┤), then READ 13 coordinate pairs from the DATA at 1630–1650 and knock doorways through the walls at those spots.
1500 FOR I=2 TO 79: FOR I1=1 TO 2: LOCATE 3+6*I1,I: PRINT CHR$(196): NEXT: NEXT
1510 FOR I=4 TO 20: FOR I1=1 TO 7
1520 LOCATE 3,10*I1: PRINT CHR$(194): LOCATE 21,10*I1: PRINT CHR$(193)
1530 LOCATE I,10*I1: PRINT CHR$(179)
1540 FOR I2=1 TO 2
1550 LOCATE 3+6*I2,10*I1: PRINT CHR$(197): LOCATE 3+6*I2,80: PRINT CHR$(180)
1560 LOCATE 3+6*I2, 1: PRINT CHR$(195)
1570 NEXT: NEXT: NEXT: RESTORE 1500
1580 FOR I=1 TO 13: READ C1,C2,C3,C4
↳ READ 13 coordinate pairs from the DATA and punch doorways through the room walls.
1590 LOCATE C1,C2: PRINT " ": LOCATE C1,C2-1: PRINT CHR$(180)
1600 LOCATE C1,C2+2: PRINT CHR$(195): LOCATE C1,C2+1: PRINT " "
1610 LOCATE C3+2,C4: PRINT CHR$(194): LOCATE C3+1,C4: PRINT " "
1620 LOCATE C3,C4: PRINT " ": LOCATE C3-1,C4: PRINT CHR$(193)
1630 NEXT: RETURN: DATA 15,5
↳ DATA: the doorway coordinates (row,col pairs).
1640 DATA 6,10,9,35,6,20,9,75,6,40,9,55,6,70,9,65,18,10,15,55,18,20,15,65,18,30
1650 DATA 15,75,18,40,9,45,12,20,9,15,12,30,9,15,18,50,9,15,6,50,9,15,18,60
1660 '
20
Layout: vertical gates
lines 1670–1740
Columns each with a 3-cell gap; B(I) remembers the row of each gap. On the moving-gate levels those gaps later slide (see § the moving gates).
1670 FOR I=1 TO 9: B(I)=6+I
↳ B(I) = the opening row of gate I. Draw a full column, then blank the 3-cell gap and cap it.
1680 LOCATE 3,8*I: PRINT CHR$(194)
1690 FOR I1=4 TO 20: LOCATE I1,8*I: PRINT CHR$(179): NEXT
1700 LOCATE 21,8*I: PRINT CHR$(193): LOCATE B(I)-1,I*8: PRINT "┴
1710 FOR I1=0 TO 2: LOCATE B(I)+I1,I*8: PRINT " ": NEXT
1720 LOCATE B(I)+3,I*8: PRINT CHR$(194)
1730 NEXT: RETURN
1740 '
21
Layout: gates + stones
lines 1750–1800
The gate layout (GOSUB 1670) plus a scatter of stones.
1750 GOSUB 1670
1760 FOR I1=4 TO 20 STEP 2: FOR I2=0 TO 9
1770 Y=I1: X=I2*8+3: GOSUB 1480: Y=I1: X=I2*8+5: GOSUB 1480
1780 IF Y<20 THEN Y=I1+1: X=I2*8+4: GOSUB 1480
1790 NEXT: NEXT: RETURN
1800 '
22
Hazard: upward arrows
lines 1810–1910
Set-up gives each even column a random arrow row in D(I,1) and marks the cell behind it empty in D(I,2); sub1830 then nudges every ↑ arrow one row upward each tick, wrapping from row 4 back to row 21. An arrow stepping onto the head (219) is fatal — RETURN 510 jumps into the death routine.
1810 FOR I=2 TO 79 STEP 2: D(I,1)=5+INT(RND*14): D(I,2)=32: NEXT: GOSUB 1830: RETURN
1820 '
1830 FOR I=2 TO 78 STEP 2
1840 I2=(D(I,1)-1)*160+(I-1)*2
1850 IF D(I,1)=4 THEN POKE I2,D(I,2): POKE I2+1,7: D(I,1)=21: I2=I2+2720
↳ When an arrow runs off the top (row 4) it wraps back to the far side (+2720 = 17 rows).
1860 IF PEEK(I2-160)=219 THEN RETURN 510
↳ An arrow about to step onto the head (219)? RETURN 510 = death.
1870 IF PEEK(I2-160)>100 THEN GOTO 1900
1880 IF D(I,1)<>21 THEN POKE I2,D(I,2): POKE I2+1,7
1890 D(I,1)=D(I,1)-1: D(I,2)=PEEK(I2-160): POKE I2-160,24: POKE I2-159,15
↳ Otherwise restore the vacated cell, move the arrow one row, draw it, remembering what was underneath in D(I,2).
1900 NEXT: RETURN
1910 '
23
Hazard: horizontal arrows
lines 1920–2120
Two arrows per row — one travelling right (→), one left (←) — advanced each tick by sub1970 and wrapped at the far column. Touching the head kills.
1920 FOR I=4 TO 20: FOR A=0 TO 1
1930 D(I+A*20,1)=RND*38*2+2+A: D(I+A*20,2)=32
1940 NEXT: NEXT
1950 D(12,1)=14: D(13,1)=6: D(32,1)=65: D(33,1)=55: GOSUB 1970: RETURN
1960 '
1970 FOR I=4 TO 20
↳ Move the vertical arrows: one going right (26), one left (27) per row, each frame.
1980 I2=(I-1)*160+(D(I,1)-1)*2
1990 IF D(I,1)=79 THEN POKE I2,D(I,2): POKE I2+1,7: D(I,1)=1: I2=I2-156
2000 D=PEEK(I2+2): IF D=219 THEN RETURN 510
↳ Hit the head (219)? death.
2010 IF D=27 THEN POKE I2+2,D(I+20,2): D(I+20,2)=26
2020 IF D>100 THEN GOTO 2050
2030 IF D(I,1)<>1 THEN POKE I2,D(I,2): POKE I2+1,7
2040 D(I,1)=D(I,1)+1: D(I,2)=PEEK(I2+2): POKE I2+2,26: POKE I2+3,15
2050 L=I+20: I2=(I-1)*160+(D(L,1)-1)*2
2060 IF D(L,1)=2 THEN POKE I2,D(L,2): POKE I2+1,7: D(L,1)=80: I2=I2+156
2070 D=PEEK(I2-2): IF D=219 THEN RETURN 510
↳ Hit the head (219)? death.
2080 IF D>100 OR D=26 THEN GOTO 2110
2090 IF D(L,1)<>80 THEN POKE I2,D(L,2): POKE I2+1,7
2100 D(L,1)=D(L,1)-1: D(L,2)=PEEK(I2-2): POKE I2-2,27: POKE I2-1,15
2110 NEXT: RETURN
2120 '
24
Hazard: the moving gates
lines 2130–2250
Each tick the nine gate openings slide. The =96 tests (three blank cells sum to 96) check the path is clear before a gap shifts down, and a gap that passes the bottom wraps back to the top.
2130 FOR D1=1 TO 9
↳ For each of the 9 gates, slide its opening; the =96 sums test that three cells are blank before shifting.
2140 D2=(B(D1)-1)*160+(D1*8-1)*2: IF B(D1)<>4 THEN GOTO 2190
2150 A=PEEK(D2+2080)+PEEK(D2+2240)+PEEK(D2+2400)
2160 IF A<>96 THEN GOTO 2240
2170 POKE D2+2560,179: POKE D2+2080,179: POKE D2+2240,179: POKE D2+2400,179
2180 POKE D2,32: POKE D2+160,32: POKE D2+320,32: POKE D2+1920,179
2190 A=PEEK(D2)+PEEK(D2+160)+PEEK(D2+320)
2200 IF A<>96 THEN GOTO 2240
2210 IF B(D1)<>4 THEN POKE D2-160,179
2220 POKE D2,193: POKE D2+160,32: POKE D2+320,32: POKE D2+480,32
2230 POKE D2+640,194: B(D1)=B(D1)+1: IF B(D1)=17 THEN B(D1)=4
↳ Move the opening down a row; past row 16 it wraps back to row 4.
2240 NEXT: RETURN
2250 '
25
The pick-up jingle
lines 2260–2270
PLAY "mb" means "music in the background" (don't pause the game) followed by three rising blips.
2260 PLAY "mb": SOUND 2500,0.1: SOUND 3500,0.1: SOUND 5000,0.1: RETURN
↳ PLAY "mb" = music in background (do not block), then three rising blips.
2270 '
26
The pop-up box
lines 2280–2310
Draws the double-line box used behind the "Level n" and "The End" messages.
2280 LOCATE 10,30: PRINT CHR$(201);STRING$(19,CHR$(205));CHR$(187)
2290 LOCATE 11,30: PRINT CHR$(186);SPC(19);CHR$(186): LOCATE 12,30: PRINT CHR$(186);SPC(19);CHR$(186)
2300 LOCATE 13,30: PRINT CHR$(200);STRING$(19,CHR$(205));CHR$(188): RETURN
2310 '
27
The 32 level recipes
line 2320
Each line sets the three dials — Z (seconds per move), AANTAL (items to scatter), BMIN (bonus drain) — and calls a layout. 2320–2390 are the calm, turn-based first eight; 2410–2480 are the same mazes but real-time and getting faster. The ON LEVEL tables at 310 and 1010 pick one per level and loop the set of 16 for levels 17–32.
2320 Z=999: AANTAL= 75: BMIN=10: RETURN
↳ Level 1: Z=999 (turn-based), scatter 75 of each, bonus drops 10/move, no maze.
2330 Z=999: AANTAL= 75: BMIN=10: GOSUB 1230: RETURN
2340 Z=999: AANTAL= 75: BMIN=10: GOSUB 1500: RETURN
2350 Z=999: AANTAL= 50: BMIN=10: GOSUB 1400: RETURN
2360 Z=999: AANTAL= 50: BMIN=10: GOSUB 1670: RETURN
2370 Z=999: AANTAL= 50: BMIN=10: GOSUB 1810: RETURN
2380 Z=999: AANTAL= 50: BMIN=10: GOSUB 1920: RETURN
2390 Z=999: AANTAL= 50: BMIN=10: GOSUB 1750: RETURN
2400 '
2410 Z= 0.4: AANTAL=125: BMIN= 5: RETURN
↳ From level 9 (Z<1) the snake moves on its own and speeds up; 2410-2480 mirror 2320-2390 but real-time.
2420 Z= 0.6: AANTAL=125: BMIN= 5: GOSUB 1230: RETURN
2430 Z= 0.6: AANTAL=125: BMIN= 5: GOSUB 1500: RETURN
2440 Z= 0.9: AANTAL=100: BMIN= 5: GOSUB 1400: RETURN
2450 Z= 0.9: AANTAL=100: BMIN= 5: GOSUB 1670: RETURN
2460 Z=1 : AANTAL=100: BMIN= 5: GOSUB 1810: RETURN
2470 Z=1 : AANTAL=100: BMIN= 5: GOSUB 1920: RETURN
2480 Z=1.2: AANTAL=100: BMIN= 5: GOSUB 1750: RETURN