Tuesday, 9 January 2018

Underground Adventure (Duckworth)

Track
|
Nearer Turn Bear
| | |
100ft Drop Bricked Around Gate Mix Large
| | | | | |
Vast Chasm Heart Deep Wall Entrance E/W Tree Twisty Old
| | | (Rope)
Rock Jumble Chasm Rock Cave Chasm
|
Sharp Twist Main
| |
West Mine Offshoot Choice Long Drop Twist E/W Dead End
| (Axe) \ | (Parchment) (Dynamite)
Panther Bottom Twisty

I have ported the text adventure "Underground Adventure" by Peter Gerrard found in the book series "Exploring Adventures" by Duckworth publishing house. I worked from a Dragon 32 version. The game is evocative of Colossal Cave Adventure (the original text adventure), in that it involves a descent into an apparently ordinary cave, which quickly turns from a mundane to a magical realm. There is a magical bridge in both and mysterious mists and twisty passages. And a sinister "living gargoyle" (instead of a dwarf) occasionally shows up to throw knives at you.

There are two other Exploring Adventures games. The main purpose of all three programs was to illustrate how to program your own adventure games in BASIC on a variety of 8-bit home computers systems (C64, Atari, Spectrum).

The map above is incomplete. It only illustrates the preliminary rooms. The adventure is quite extensive and took quite a bit of squeezing to get it to fit into the 20K of the MC-10. Most of the classic 8-bit systems had a least 32K to work with. Using my standard techniques described elsewhere in my blog posts, I got it below 20K. I condensed and simplified descriptions and you have to load the direction data from a separate file to avoid reading them into an array variable from DATA statements which then are redundantly left in memory.

In the course of doing the port I changed what I felt were some unclear or inconsistent descriptions and items. The most significant "alteration" was the use of the terms "track" and "cave." For example, there is an instance in which a track must be "oiled" so that it can "slide away" to reveal a blocked entrance. The use of these terms seemed to indicate to me that the "caves" were actually an old abandoned mine and the obstruction was actually an old mining cart, so I "fixed" the use of these terms in various descriptions to fit that theme better.

There were also several errors in the code I got from the Dragon. The axe could be thrown even if it had been dropped somewhere else.  It then would appear in the room you threw it in and could be picked up.  Also there was a place where you could go east but not back west for no apparent reason.

I maintained a save-game feature, but it involves saving and loading two separate array variables. The first file is called "UNDRGAME" the second "UNDROBJS." Couldn't unify them into one array as I have done for other games. Just not enough memory. Little clunky, but workable.

Here's a vid:

3 comments:

  1. Great work squeezing all that into 20k! That's amazing.

    If you want to save more space (e.g. maybe to get that one-file save routine) it looks like there could be places where you might be able to do it.

    For example:

    427 PRINT,,"you can see:":F=0:FORI=1TOLO:IFO(I)=CTHENM$=O$(I):GOSUB1:F=1
    429 NEXTI:IFF=0THENPRINT"NOTHING SPECIAL"
    430 IFC=3ANDP(0,2)=0THENPRINT:PRINT"THE GATE IS NOW SHUT."
    431 F=0:PRINT,,"you can go:":FORI=0TO3:IFP(C,I)<>0THENPRINTD$(I)" ";:F=1
    433 NEXT:IFF=0THENPRINT"NOWHERE!"
    434 PRINT:IFO(54)=1THEN453

    In most BASICs, the IF THEN takes any non-zero value as true, so you can rewrite this as:

    427 PRINT,,"you can see:":F=1:FORI=1TOLO:IFO(I)=CTHENM$=O$(I):GOSUB1:F=0
    429 NEXTI:IFFTHENPRINT"NOTHING SPECIAL"
    430 IFC=3ANDP(0,2)=0THENPRINT:PRINT"THE GATE IS NOW SHUT."
    431 F=1:PRINT,,"you can go:":FORI=0TO3:IFP(C,I)THENPRINTD$(I)" ";:F=0
    433 NEXT:IFFTHENPRINT"NOWHERE!"
    434 PRINT:IFO(54)THEN453

    I swapped the values of F so that the IF statements are looking for the non-zero value. I also removed unnecessary test for non-zero value in the IFs in lines 431 & 434 above.

    It only saves a couple of bytes each time, but there are other places where you can do this, and it all adds up.

    And lines like:

    500 IFC=10ANDP(C,3)=0THENM$="FACING A VAST CHASM"
    501 IFC=10ANDP(C,3)=14THENM$="WALKING THE PLANK"

    could become something like:

    500 IFC=10THENM$="FACING A VAST CHASM":IFP(C,3)THENM$="WALKING THE PLANK"

    which must save even more bytes.

    ReplyDelete
    Replies
    1. Forgot to add, you know me as "Pippa" in CASA.

      Delete
    2. Pippa, thanks so much for those suggestions. I'm aware of the non-zero default for if-then, but translating the logic and flow to use non-zero values (to save those few bytes) is a challenge for me and a risk of introducing new errors, so I sometimes avoid going to that extent in condensing. But thanks for doing that work! Don't know if it'll save enough space to fix up the dual file save problem. That would require replacing a lot of single dimension array vars v(#) with dual dimension and offset vars v(1+offset,#). Since the second array is commonly used, this could amount to a lot of bytes needed. oh well. All my progs are ongoing works in progress, so we'll see...

      Delete