Arctic Explorer is a scrolling arcade game in which the player guides a character across an icy landscape, avoiding obstacles and collecting bonuses while managing a countdown timer.
The game uses UDG (User-Defined Graphics) characters defined via POKE into USR addresses to render the player sprite and terrain elements. Screen scrolling is simulated by rotating string arrays — for example, line 1100 rebuilds a 224-character string by reordering 32-character segments to shift the background left.
Seven distinct level subroutines (1100–1900, dispatched via GO SUB 1000+(s*100)) each vary the obstacle pattern and movement style, providing increasing difficulty.
Sound effects use BEEP with DATA-driven note sequences read via RESTORE/READ, and a high-score table persists in memory across playthroughs within the same session.
Controls:
- O=Left
- P=Right
- O+CS (capshift) = Jump Left
- P+CS = Jump Right
Program Analysis
Program Structure
The program is organized into a set of functional blocks spread across the line-number space:
- Lines 1–7: Initialization, title screen, and key-wait loop.
- Lines 10–100: Main game loop — calls level setup and game-state subroutines, processes input, detects collisions, handles screen advance.
- Lines 1100–1900: Level-specific scrolling subroutines (dispatched by
GO SUB 1000+(s*100)). - Lines 2000–2550: Boundary detection, bonus scoring, and level-end animation.
- Lines 3000–3840: Death handling, lives management, game-over screen, and high-score logic.
- Lines 4000–5000: Jump mechanics subroutines.
- Lines 8010–8100: Level initialization subroutines — set up
a$string layout and border graphics. - Lines 9000–9999: UDG loader, variable initialization, screen setup, and DATA blocks.
Level Dispatch Idiom
Level selection uses a computed GO SUB: GO SUB 1000+(s*100) at line 40. As the stage variable s increments from 1 to 9, this dispatches to subroutines at 1100, 1200, …, 1900. Similarly, GO SUB 8000+(s*10) at line 25 calls the corresponding level-setup routine (8010, 8020, …, 8090). This avoids a chain of IF statements and compactly encodes the level table.
String-Rotation Scrolling
The background is stored in the string a$ rather than directly on the display. Each frame, segments of the string are permuted to simulate leftward or rightward scrolling, then printed with PRINT AT 0,0 or PRINT AT 5,0. For example, line 1100 does:
LET a$=a$(193 TO 224)+a$(1 TO 32)+a$(33 TO 64)+...+a$(161 TO 192)
This rotates the last 32 characters to the front of a 224-character (7 × 32) string, scrolling seven rows of 32 columns simultaneously. Line 1200 instead uses a two-row, 64-character string scrolled one character at a time.
UDG Sprite Definitions
Line 9000 loads UDG data from line 9920–9940 into memory using POKE f,a iterating from USR "a" to USR "p"+7, defining 16 UDG characters (a–p). The player sprite is \a (UDG ‘a’), referenced as part of the two-character string b$="\a\b". Terrain and obstacle elements use further UDGs including \g–\o.
Collision Detection
Collision is checked using ATTR (a+1,b) — reading the attribute byte of the cell below the player. A value of 56 corresponds to PAPER 7, INK 0 (white background, black ink), which marks solid ground or obstacle tiles. A non-space character at the player’s column in the scroll string also triggers a collision. Both conditions route via GO TO n, where n=3000 is the death handler — using a variable rather than a literal line number.
Jump Mechanic
Jumping is handled by subroutine 4000. It reads a sequence of six (x, y, m) tuples from DATA at line 9950:
DATA 16,-1,0,18,-1,0,20,0,q,22,0,q,22,1,q,20,1,0
Each iteration plays a short BEEP, erases the player, adjusts row by y and column by m (where q is the jump direction set before the call), and redraws the sprite. This produces a small arc. The direction variable q is set to +1 (right jump, key “P”) or -1 (left jump, key “O”) before calling GO SUB 4000.
Sound Design
Music and sound effects are driven by RESTORE/READ loops over three DATA lines:
| Line | Purpose |
|---|---|
| 9900 | Background tune (32 notes, used for bonus/death fanfares) |
| 9910 | Game-over melody (25 notes) |
| 9950 | Jump arc coordinates (6 triples) |
The game-over tune at line 3820 uses fractional durations (a/4) for a smoother tempo. Death sound at 3010 uses a/2 and at 3800 uses a/1.5, creating distinct audio feedback for different events using the same data.
Timer and Scoring
A countdown timer t starts at 100 for each stage. Line 40 decrements it each main loop iteration via LET t=t-(t>0) — the boolean expression (t>0) evaluates to 1 or 0, preventing t from going negative without an IF statement. On stage completion, sc is increased by t+100 plus any bonuses. A separate 500-point bonus is awarded at line 2500 if the player reaches column 25 or beyond.
Notable Anomalies
- Line 9050 is referenced via
GO SUB 9050at line 10, but line 9051 is the actual first executable line of that subroutine.GO SUBtargeting a non-existent line falls through to the next higher line — a known and intentional BASIC technique. - Line 8081 contains
PRINT ;7,0;n$— the semicolon before7,0appears to be a syntax anomaly; it likely should bePRINT AT 7,0;n$, possibly a typo in the original listing. - Line 9510 is defined but the label
GO SUB 9500at line 25 would fall through to 9510. It clears lines 12–21 withPAPER 0and callsRESTOREto reset the DATA pointer. - Line 20 is referenced by
GO TO 20at line 2550 but does not exist; execution falls to line 25, which is the level-restart logic — intentional use of non-existent target line. - The DATA at line 9960 appears to be unused by any READ loop in the visible code, suggesting either dead data or a removed display-setup routine.
- Line 9970 contains what appear to be sine-table values (±45, ±53, etc.) and a final value of 200, also unreferenced — possibly a remnant of a removed circular animation feature.
Content
Source Code
1 LET hi=0: LET n=3000
2 REM by Neil Bates of Coventry
3 PRINT " Artic Explorer": PRINT : PRINT : PRINT : PRINT : PRINT "Control keys:": PRINT " o-Left p-Right"
4 PRINT "o&caps shift jump Left p&caps shift jump Right"
5 PRINT " Press any key to begin"
6 IF INKEY$="" THEN GO TO 6
7 CLS
10 GO SUB 9000: GO SUB 9050
25 CLS : GO SUB 8000+(s*10): GO SUB 9500
40 LET b$=b$(2)+b$(1): LET t=t-(t>0): PRINT AT 15,12; PAPER 0; INK 5; BRIGHT 1;t;" ": BEEP .01,-10: GO SUB 1000+(s*100): LET b=b+(INKEY$="p")-(INKEY$="o" AND b): IF INKEY$="P" THEN LET q=1: IF b<29 THEN GO SUB 4000
75 IF INKEY$="O" THEN LET q=-1: IF b>2 THEN GO SUB 4000
80 PRINT AT a,b;b$(1)
90 IF b>=31 THEN LET s=s+1: FOR f=1 TO 50: OUT 254,59: OUT 254,200: NEXT f: LET b=0: LET sc=sc+t+100: LET t=100: GO TO 25
100 GO TO 40
1100 LET a$=a$(193 TO 224)+a$(1 TO 32)+a$(33 TO 64)+a$(65 TO 96)+a$(97 TO 128)+a$(129 TO 160)+a$(161 TO 192)
1110 PRINT AT 0,0; INK 0;a$: IF a$(193+b)<>" " THEN GO TO n
1130 RETURN
1200 LET a$=a$(2 TO 32)+a$(1)+a$(34 TO 64)+a$(33): PRINT AT 5,0;a$: IF a$(33+b)<>" " THEN GO SUB 8023: GO TO n: IF ATTR (a+1,b)=56 THEN GO SUB 8023: GO TO n
1240 RETURN
1300 IF RND>.45 THEN LET a$=a$(2 TO 32)+a$(1)+a$(34 TO 64)+a$(33): GO TO 1320
1310 LET a$=a$(32)+a$(1 TO 31)+a$(64)+a$(33 TO 63)
1320 PRINT AT 5,0;a$: IF a$(33+b)<>" " THEN GO TO n
1340 RETURN
1400 IF RND>.5 THEN IF z=0 THEN LET v=7: LET j=INT (RND*27)+3: IF ATTR (7,j)=61 THEN LET z=1
1410 IF z=1 THEN PRINT AT v,j;" ";AT v+1,j; INK 5; PAPER 7;"\k": LET v=v+1: IF v=9 THEN PRINT AT 9,j;" ": LET z=0
1420 PRINT AT a,b;" ": IF ATTR (a+1,b)=56 THEN GO TO n
1430 RETURN
1500 GO SUB 1300: RETURN
1600 PRINT AT a,b;" ": IF ATTR (a+1,b)=56 THEN GO TO n
1620 RETURN
1700 GO SUB 1600: GO SUB 1200: RETURN
1800 GO SUB 1700: RETURN
1900 GO SUB 1300: GO SUB 1600: RETURN
2000 PRINT AT a,b;" ": IF ATTR (a+1,b)=56 THEN GO TO n
2020 IF b>=25 THEN GO TO 2500
2030 RETURN
2500 PRINT AT a,b;"\a\p": RESTORE 9900: FOR f=1 TO 32: READ a,b: BEEP a/3,b: NEXT f: LET sc=sc+500: PRINT AT 10,12; INK 0; FLASH 1;"BONUS =500";AT 8,12; INK 2;"WELLDONE"
2540 FOR f=1 TO 20: BEEP .01,f+30: BEEP .01,f*2: NEXT f
2550 LET a=6: LET b=0: LET s=1: LET l=l+1: GO TO 20
3000 PRINT AT a,b; INK 2;"\a": LET l=l-1: IF l=0 THEN GO TO 3800
3010 RESTORE 9900: FOR f=1 TO 6: READ a,b: BEEP a/2,b: NEXT f
3020 LET a=6: LET b=0: GO TO 25
3800 RESTORE 9900: FOR f=1 TO 6: READ a,b: BEEP a/1.5,b: NEXT f: PRINT AT 12,11; INK 7; FLASH 1; BRIGHT 1; PAPER 0;"GAME OVER"
3810 IF sc>hi THEN LET hi=sc: PRINT AT 9,0; INK 5; PAPER 0; BRIGHT 1;n$;AT 9,8;"A NEW HIGH SCORE": FOR f=20 TO 40: BEEP .01,f: BEEP .01,f-20: NEXT f
3820 RESTORE 9910: FOR f=1 TO 25: READ a,b: BEEP a/4,b: NEXT f
3830 FOR f=4 TO 7: PRINT AT 21,0; INK f; PAPER 0; BRIGHT 1;" PRESS ANY KEY FOR ANOTHER GO ": PAUSE 10: IF INKEY$="" THEN NEXT f: GO TO 3830
3840 GO TO 10
4000 RESTORE 9950: FOR f=1 TO 6: READ x,y,m: PRINT AT a,b;" ": LET a=a+y: LET b=b+m: PRINT AT a,b;"\a": BEEP .001,x: NEXT f
4020 RETURN
5000 GO SUB 4000: PRINT AT a,b;" ": LET b=INT b-1: IF b>21 THEN IF a<=6 THEN GO TO 50
5005 LET a=6: GO TO 3000
8010 DIM a$(224): FOR f=1 TO 15: LET c=INT (RND*190)+1: LET a$(c)=CHR$ (INT (RND*2)+148): NEXT f
8011 PRINT AT 7,0; PAPER 7; INK 5;"\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k\k",,: RETURN
8020 GO SUB 8023: GO SUB 8011
8022 RETURN
8023 DIM a$(64): LET a$=" \l\m \l\m \l\m \n\o \n\o \n\o": RETURN
8030 LET a$=" \g\h \i\j ": GO SUB 8011: RETURN
8040 LET j=10: LET v=0: LET z=0: GO SUB 8011: RETURN
8050 GO SUB 8030: LET a$(20 TO 21)="\g\h": LET a$(52 TO 53)="\i\j": RETURN
8061 PRINT AT 7,0; INK 5;"\k\k\k\k";AT 7,5;"\k\k\k";AT 7,9;"\k";AT 7,12;"\k";AT 7,15;"\k\k\k\k\k\k";AT 7,22;"\k\k\k\k";AT 7,27;"\k\k\k\k\k": RETURN
8070 GO SUB 8061
8072 DIM a$(64): LET a$(10 TO 11)="\l\m": LET a$(42 TO 43)="\n\o"
8073 RETURN
8081 GO SUB 8020: PRINT ;7,0;n$: GO SUB 8061: RETURN
8090 GO SUB 8030: PRINT AT 7,0;n$: GO SUB 8061: RETURN
8100 PRINT AT 7,0; INK 5;"\k\k\k\k\k";AT 7,7;"\k\k\k";AT 7,12;"\k";AT 7,14;"\k\k";AT 7,17;"\k\k\k";AT 7,22;"\k\k\k\k\k\k\k\k\k\k": RETURN
9000 RESTORE 9920: FOR f=USR "a" TO USR "p"+7: READ a: POKE f,a: NEXT f: RETURN
9051 LET b$="\a\b": LET l=5: LET a=6: LET b=0: LET sc=0: LET s=1: LET t=100: LET n$=" ": RETURN
9510 FOR f=12 TO 21: PRINT AT f,0; PAPER 0;n$: NEXT f: RESTORE
9900 DATA 1,5,1,5,1,2,.5,4,.5,2,2,0,1,7,.5,7,.5,2,.5,2,.5,4,.5,2,2,7,2,0,1,7,.5,7,.5,5,.5,2,.5,4,1,2,2,5,2,7,2,0,2,2,1,2,.5,4,.5,2,1,0,1,7,1,5,1,2,2,0
9910 DATA 2,7,1,9,.5,11,.5,12,.25,14,.25,16,.25,14,.25,12,1.5,11,.5,12,.125,14,.125,16,.125,14,.125,12,.125,11,.125,12,.125,11,.125,9,2,7,1,9,1,11,2,12,1,11,1,12,3,14
9920 DATA 28,28,8,127,28,28,20,20,28,28,8,28,62,93,20,34,114,116,40,112,112,112,114,62,78,46,20,14,14,14,78,124,48,124,190,255,251,118,126,60,32,12,12,0,0,102,39,3
9930 DATA 3,7,13,15,6,3,1,15,192,224,176,240,96,192,128,240,31,55,99,51,19,6,12,24,248,236,198,204,200,96,48,24
9940 DATA 0,255,255,187,179,19,1,1,7,25,55,111,127,255,255,254,224,248,252,254,254,63,223,221,254,191,191,127,127,63,31,7,125,251,251,246,206,60,248,224,40,44,46,40,32,32,32,32
9950 DATA 16,-1,0,18,-1,0,20,0,q,22,0,q,22,1,q,20,1,0
9960 DATA 13,3,"LIVES",15,20,"LEVEL",15,3,"BONUS",17,3,"SCORE",19,3,"HI-SCORE",13,12,1,15,12,t,17,12,sc,19,12,hi,16,22,s
9970 DATA -45,-53,-34,-61,-21,-67,-7,-70,7,-70,21,-67,34,-61,45,-53,34,-61,21,-67,7,-70,-7,-70,-21,-67,-34,-61,200
9980 RETURN
9998 STOP
9999 SAVE "ArcticExp" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

