Smuggler’s Cove

Products: Smuggler's Cove
Developer(s): John Keneally
Date: 1983
Type: Program
Platform(s): TS 2068

Smuggler’s Cove is a text adventure set in 1753, in the caves and tunnels under the north Cornish coast where Blackbeard is said to have hidden his treasure. You type a verb in capitals and a noun in lower case (TAKE torch, OPEN door), move with N, E, S, W, U and D, and the top of the screen shows a line drawing of each location. INVENTORY, LOOK and SCORE work at any time, and SAVE and LOAD keep a game position on tape. Dark tunnels need a light, and some deaths can be undone if the omens favour your birthdate.

The 1983 Quicksilva tape’s title line reads “By John Keneally”; the copy on Bob Swoger’s disk had changed it to “BY J.R. KENEALLY”. The zip also holds the command sheet Joan Kealy wrote for it, as text.

Program Analysis

The BASIC is a thin shell around about 30 KB of machine code at 32768, which holds the parser, the room and object database, the messages and the pictures. BASIC passes requests through two addresses: it POKEs a function number into PR (35407) and calls USR U0 (35390), so 43 describes the room, 36 followed by 35 or 41 lists the objects carried or present, and 40 fetches a message. USR u1 (32768) parses the command in a$ and USR u2 (33304) handles the turn. Line 2500 picks the location picture from the string P$ and draws it with USR 62892.

Notable Techniques

  • Long messages are built into the blank string Z$ by the machine code and word-wrapped by BASIC at lines 500–535.
  • Game positions are saved as the 12,600-byte block CODE 33400,12600, the part of the code that holds the game state.
  • Line 9999 is the original tape-mastering routine that saves the BASIC, the title screen and the code.

Potential Issues

  • The machine code finds the BASIC variables by their position: the program must keep the 1983 layout exactly, with a$ saved as the first variable. The copy on the Larken disk had extra lines and saved variables, and reset the computer the first time you moved; this download restores the original layout.

This copy came from a Larken disk. The BASIC was put back to the 1983 release’s lines (the disk version’s renamed files, extra help line and disk prefixes would not run), one game-state byte that had been saved mid-game was reset to the release value, and the Quicksilva logo loader from the disk runs first. Tested in ZEsarUX on a stock TS2068: moving, taking objects and scoring work.

Related Products

It’s 1753 and you are on a hunt for Blackbeard’s famous treasure, hidden in a complex of caves on the north Cornish Coast.

Related Articles

Complete listing of authorized word commands for the adventure game Smuggler’s Cove (Quicksilva), compiled by member John Shillinglen.
List of the commands in the program.

Image Gallery

Source Code

    5 CLEAR 32767: BORDER 3: LOAD "p"SCREEN$ : PRINT #0;AT 1,0; INK 9;"       * QUICKSILVA  1983       ": PRINT #0;AT 0,0; INK 9;"        By John Keneally        ": LOAD "p"CODE 
   10 INK 0: PAPER 4: FLASH 0: BRIGHT 0: OVER 0: INVERSE 0: POKE 23658,8: BORDER 3: POKE 23609,40: CLS : PRINT AT 0,0; PAPER 5; INK 0;,,,,,,,,,,,,,,,,;: PAPER 8: INK 8
   15 LET U0=35390: LET PR=35407: POKE PR+1,0: PRINT AT 8,0;: POKE PR,46: LET J=USR U0: LET P$="0123745677879:8;<998===>>?@282A"
   16 POKE PR,44: LET J=USR U0
   20 LET j=0: LET k=0: LET l=0: LET m=0: LET n=0: LET p=0: LET q=0: LET r=0
   30 LET u1=32768: LET u2=33304
   40 LET ai=35528: LET aj=35529: LET at=36815
   50 LET a$="": LET am=35550
   60 GO TO 800
  100 LET r=0: PRINT "_______________________________": GO SUB 2500: INPUT "What now? ";a$: PRINT AT 8,0;: POKE PR,48: LET M=USR U0: IF a$="INVENTORY" OR a$="INV" THEN GO TO 200
  101 IF A$="SAVE" THEN CLS : PRINT AT 12,0; FLASH 1;"GAME SAVE": SAVE "dat"CODE 33400,12600: GO TO 100
  102 IF a$="LOOK" THEN GO SUB 3500: PRINT : LET r=1: GO TO 250
  103 IF A$="LOAD" THEN GO SUB 750: GO TO 800
  104 IF A$="SCORE" THEN POKE PR,48: LET M=USR U0: PRINT AT 8,0;"YOUR SCORE IS: ";PEEK 35562: GO TO 100
  105 IF a$="" THEN GO TO 100
  106 LET a$=a$+" ": LET a$=a$: POKE PR+2,PEEK 23666: LET j=USR u1
  107 IF j=1 THEN LET j=0: LET r=1: POKE ai,0: PRINT a$;" what?"
  108 IF PEEK ai>0 AND PEEK ai<3 THEN LET r=1
  110 IF j<=0 OR J>100 THEN GO TO 150
  120 IF j=38 THEN GO TO 820
  130 IF j=39 THEN PAUSE 100: CLS : PRINT AT 10,11;"WELL DONE"'"Few have lived to tell the tale.You have survived, but will you brave the dangers once again to find a better route?": LET j=INT (PEEK (at)/2): LET j=j-2*INT (j/2): PRINT "Without the treasure, you have  nothing to prove to the world   your prowess and skill" AND (1-j): PRINT : GO TO 3000
  135 IF j=41 THEN GO TO 250
  140 POKE pr,j: LET j=USR u0
  150 IF PEEK ai=0 AND PEEK aj=0 THEN GO TO 195
  170 LET l=0
  175 LET K=PEEK (AJ+L): IF K<>0 THEN LET L=L+1: GO TO 175
  180 FOR L=L-1 TO -1 STEP -1: LET K=PEEK (AJ+L): POKE AJ+L,0: IF K<>0 THEN GO SUB 500: PRINT 
  185 NEXT L
  190 GO TO 110
  195 IF r=0 THEN LET r=1: LET j=USR u2: GO TO 110
  196 GO TO 100
  200 POKE pr,36: LET m=USR u0: LET r=1: PRINT "You are carrying:-"
  210 POKE pr,35: LET m=USR u0: IF m<>0 THEN PRINT "A ";: GO SUB 600: GO TO 210
  220 PRINT "_______________________________": GO TO 150
  250 LET j=0: POKE pr,36: LET M=USR U0: PRINT "Objects here are:-"
  260 POKE pr,41: LET m=USR u0: IF m<>0 THEN PRINT "A ";: GO SUB 600: GO TO 260
  270 PRINT "_______________________________": GO TO 150
  500 LET P=0: POKE am,k: POKE pr,40: LET m=USR u0
  510 LET Z$="                                                                                                                                                                                                                                  ": POKE PR+2,226: POKE PR,45: LET N=USR U0: FOR P=31 TO 256 STEP 31: IF Z$(P TO P+2)="   " THEN LET N=P: LET P=256: NEXT P: GO TO 530
  515 FOR Q=P TO P-30 STEP -1: IF Z$(Q)=" " THEN PRINT Z$(P-30 TO Q-1): LET P=Q: LET Q=0
  520 NEXT Q
  525 NEXT P: RETURN 
  530 FOR Q=N TO N-30 STEP -1: IF Z$(Q)<>" " THEN LET P=Q: LET Q=0
  535 NEXT Q: PRINT Z$(N-30 TO P);: RETURN 
  600 LET P=0: LET k=PEEK ai: IF k=0 THEN GO SUB 510: PRINT : RETURN 
  610 POKE ai,0: LET l=PEEK 36335: LET Z=PEEK 36336:: GO SUB 500: PRINT " ";: POKE 36335,L: POKE 36336,Z: GO SUB 510: PRINT : RETURN 
  750 CLS : PRINT AT 12,0; FLASH 1;"START TAPE": LOAD "dat"CODE : CLS : RETURN 
  800 LET J=PEEK (34223+PEEK 35559): POKE AI,J: LET J=0: LET R=1: GO TO 150
  820 PRINT ''"Just a second, if the omens are propitious, you might be saved": INPUT FLASH 1;"What is your birthdate? ";a$: PAUSE 200: IF RND<.37 THEN CLS : PRINT AT 12,0;"Sorry, your stars are in the    wrong house."'' FLASH 1;"REST IN PEACE": GO TO 3000
  830 CLS : PRINT AT 12,0;"Yep. Your in luck. Stand by....": FOR j=1 TO 40: BORDER RND*7: PAUSE 9: NEXT j: POKE 36383,0: BORDER 3: CLS : PRINT PAPER 5;AT 0,0;,,,,,,,,,,,,,,,,: PRINT AT 8,0;:: GO TO 800
 2500 LET j=PEEK 35559: LET M=CODE P$(j): POKE 62887,M-48
 2510 IF J=27 AND PEEK (at-3)=3 THEN POKE 62887,18
 2520 IF (J=3 OR J=28) AND PEEK (36703)=169 THEN POKE PR,47: LET m=USR U0: LET m=USR 62892: POKE 62887,19: LET m=USR 62892: RETURN 
 2530 IF J=6 AND PEEK 36541=166 THEN POKE 62887,20
 2540 IF J=16 AND PEEK 36797=43 THEN POKE PR,47: LET m=USR U0: LET m=USR 62892: POKE 62887,21: LET j=USR 62892: RETURN 
 2550 POKE PR,47: LET m=USR U0: LET m=USR 62892: RETURN 
 3000 PRINT '"YOUR SCORE IS: ";PEEK 35562: INPUT "WANT TO TRY AGAIN? (Y/N) ";A$: IF A$="Y" THEN POKE 36383,0: POKE PR,47: LET J=USR U0: PRINT AT 8,0;"";: GO TO 10
 3010 NEW : STOP 
 3500 IF PEEK 35559=11 THEN RETURN 
 3510 POKE pr,43: LET n=USR u0: GO SUB 510: RETURN 
 9998 CLEAR 32767: LOAD "p"CODE : LOAD "p"SCREEN$ 
 9999 INPUT "LOAD A BLANK, PRESS ENTER";a$: SAVE "smugl" LINE 1: SAVE "p"SCREEN$ : SAVE "p"CODE 32768,30300: GO TO 9999

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