--- title: "Artic Explorer" id: 54543 type: "computer_media" slug: "artic-explorer" url: "http://localhost/computer_media/artic-explorer/" markdown_url: "http://localhost/computer_media/artic-explorer.md" published_at: "2024-06-02T16:43:03+00:00" modified_at: "2026-03-30T21:40:58+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Guide your explorer across treacherous arctic terrain using string-rotation scrolling, UDG sprites, and seven distinct levels of icy obstacle patterns." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 51207 title: "CATS Library Tape 6" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-6/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/Arctic-Explorer-2.png" - url: "http://localhost/wp-content/uploads/2024/06/Arctic-Explorer-1.png" media_type_tags: "Game" --- # Artic Explorer 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 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. ## 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 ```