Artic Explorer

This file is part of and CATS Library Tape 6. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

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:

LinePurpose
9900Background tune (32 notes, used for bonus/death fanfares)
9910Game-over melody (25 notes)
9950Jump 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 9050 at line 10, but line 9051 is the actual first executable line of that subroutine. GO SUB targeting 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 before 7,0 appears to be a syntax anomaly; it likely should be PRINT AT 7,0;n$, possibly a typo in the original listing.
  • Line 9510 is defined but the label GO SUB 9500 at line 25 would fall through to 9510. It clears lines 12–21 with PAPER 0 and calls RESTORE to reset the DATA pointer.
  • Line 20 is referenced by GO TO 20 at 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

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

Artic Explorer

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.

People

No people associated with this content.

Scroll to Top