Your Spectrum
Issue 18, September 1985 - The Ghostwriter
Home Contents KwikPik
T H E   G H O S T W R I T E R
Have you made good your Escape From Castle Rathbone yet? Or are you still haunted by the fiendishly difficult adventure that appeared in last month's YS? Either way you probably never noticed the ghostly presence of the code that created the adventures. Dougie Bern, a shadow of his former self, reveals all ... or nearly all!
 
Well, intrepid adventurers, how does it feel to have spent a whole month cooped up at Castle Rathbone? Now you know how we all feel, eh? Are your fellow prisoners still to be found languishing within these walls or have they made their break for freedom? Either way, your brain should be in a suitably pulped state by now to attempt the next assault on the dreaded Castle! OK, who screamed in terror at the mere thought of crossing the threshold again? You have nothing to fear ... hahahahaha!
Now Castle Rathbone is ready to offer up its final secret. For buried deep in its depths, there are not just one but two terrific programs. Fiendish, eh? One you're already familiar (and frustrated) with but you've probably not even noticed the other.
Yes folks, not only is Castle Rathbone one of the most difficult adventures you've ever played, it's also an adventure generator in disguise. Gasps of amazement - cries of, well I never - slapped thighs and blow me downs! It's true and now I'll show you how you can write your own amazing adventures using this clever and clandestine program. All you'll need to bring with you are your imagination and a devilish sense of humour.
First though, we have to unravel the secrets of Castle Rathbone. I hope you're now as puzzled about how it works as you were about solving it. Let's take a look at the program
THE DECODER
The routine decodes all the encrypted PRINT statements between lines 3000 and 5000.
When you've written your own adventure, if you want to encode your data in the same way as we did for Castle Rathbone, change the S$ in line 5 to:

S$="GNUAKRCXHESZFLBTIWYMDVQJOP"

Run this routine once and then delete lines 5 to 300 and enter lines 400 to 430 from Castle Rathbone.
This routine as printed in the magazine had several errors in it; lines marked in RED have been corrected.
5 LET S$="DOGUJMAIQXENTBYZWFKPCVRHSL"
10 LET loc=PEEK 23635+256*PEEK 23636
20 LET lno=PEEK (loc+1)+256*PEEK loc
30 LET loc=loc+2
40 LET lln=PEEK loc+256*PEEK (loc+1)
45 LET loc=loc+2
46 PRINT #0;AT 0,0;"LINE ";lno
50 IF lno<3000 THEN LET loc=loc+lln: GO TO 20
60 IF lno>5000 THEN STOP
70 IF PEEK loc=245 THEN GO SUB 90

80 LET loc=loc+lln: GO TO 20
90 LET f=loc+2: IF PEEK f=245 THEN LET f=f+2
100 LET ch=PEEK f: LET f=f+1
110 IF ch<65 OR ch>90 THEN GO TO 200
120 POKE f-1,CODE S$(ch-64)
200 IF ch=34 THEN RETURN
210 GO TO 100
300 STOP
LEVEL BEST
Ask seasoned adventurers who writes the best adventures and nine times out of ten the answer that comes back will be Level 9. Their games will contort your cranium and burst your brain cells - they're complex, full of surprises and, best of all, they're well written. To underline their commitment to good adventure writing, Level 9 has generously offered five of their top games to the writers of the best five adventures created with The Ghostwriter. So, you could be the lucky winner of Emerald Isle, Colossal Adventure, Adventure Quest, Dungeon Adventure and the brand new, Red Moon. And if the best of the five knocks us all out, it'll be published in the pages of YS. You may never achieve the standards Level 9 has set but you can strive ...
ACTION STATIONS
Here is a step-by-step guide to setting out on your own adventure. At a glance you can see the stages you should follow but it you need more detail, always refer to the full instructions.

programming flowchart

listing between lines 3000 and 5000. Czech? Serbo-Croat? Total gibberish? No, it just looks that way 'cos we've sneakily encoded the data so's you can't cheat when you're playing the game. In fact, these lines contain all the location descriptions and messages printed by the program. Before we go any further, we'll have to decode these lines.
Take a look at lines 400 to 430 - this is the machine code routine that unscrambles the encrypted lines. It works by intercepting the Speccy's PRINT routine, decodes the statement enclosed in quotes and then prints the correct message or location description on the screen.
Your first job is to delete the lines from 400 to 430 from Castle Rathbone (making sure, of course, that you have a back- up copy of the program). Then type in the decoder program below and run it. You'll now have a copy of Castle Rathbone in which all the location descriptions and text messages are in English. This will be your working copy of the program, so you
should now delete the short program you've just typed in and save a copy of the new readable version.

THE INNER WORKINGS

It'll help to think of the adventure as being split into three parts. The lines up to line 3000 contain the adventure controller and it does just that - completely controls what happens in the rest of the program. The lines from 3000 to 5000 contain the location descriptions and the text messages. Finally, the lines starting from 9000 contain all the data used in the program.
When you come to creating your own adventure, you'll have to delete parts of Castle Rathbone but don't do anything yet - all will be revealed. In the meantime, though, you'll need Castle Rathbone to show you how to construct your own data. As soon as you understand how everything works, follow the course laid down by Action Stations and you'll soon have your very own adventure.
GHOSTWRITING A STEP-BY-STEP GUIDE

THE IDEA

The hardest part of writing any adventure comes right at the beginning. But it can also be the bit where you can have most fun. Think of it - creating your very own worlds, planets, time-zones. This is the bit where your imagination will have to go into overdrive. You'll need to rack your brains to come up with a story line and scenario. Let's face it, if you haven't got a good idea, you're not going to end up a good adventure. But once you've come up with the world's most fantastic, never before imagined, mega mind-blowing adventure you can get on with the job of coding it.

THE MAP

Your first step is to draw a map of your brave new world. This'll help you when you come to creating the data and it'll give you a visual reminder of what you should be doing. When you've drawn the map, number each of the locations and stick to those numbers. Once you've decided on the number of locations, you must change the value assigned to the variable LOCATE at line 9010.
And remember, your map doesn't have to be flat and dull. Set parts of the adventure on different levels, put in secret passages so that rooms connect that normally wouldn't. Create a true labyrinth!

PRIMARY LOCATION DESCRIPTIONS

Now you have your map, you can start describing the locations. This is where your way with words will set the tone for the whole adventure. Will it be dark and mysterious or everyday and funny? If you're short of ideas, think about your favourite periods of history and try to write a scenario set in that time. Or how about basing your adventure on your favourite book? If it's good enough for The Hobbit ...
Also, try to make your descriptions as visual as possible. Remember you are the player's eyes - he sees only what you tell him to see. But be careful that you don't include in these primary descriptions anything that is likely to change on subsequent visits. If you want to put an object into the room that'll have to be picked up, don't describe it here.
When you're ready to enter your descriptions, first delete lines 3500 to 4090 from Castle Rathbone. Now you must enter your primary location descriptions at lines 3500, 3520, 3540 and so on for locations 1,2,3 ... If you've written very long location descriptions it's an idea to split the PRINT statements over several lines.

SECONDARY LOCATION DESCRIPTIONS

The next job is to write another location description. For example, if your first location reads, "You're on the bridge of an intergalactic starship. Facing you are banks upon banks of instruments and controls. The main ship's computer hums
efficiently in the background etc ...", you won't want to read all of that every time you enter the bridge. Once is enough! So, your secondary description should read "You are on the bridge of the starship".
The location descriptions are printed by the lines 2450 and 2455 and you can enter the secondary location descriptions at lines 3510, 3530, 3550 and soon for locations 1,2,3 ...

LOCATION CONNECTIONS

Once you've entered all your location descriptions, the next step is to join them all together. You do this by constructing the Data statements that'll tell the program what commands take you to which location. If you have a look at Castle Rathbone, you'll find the location connections at lines 9300 to 9372. As you can see from line 9040, the size of the array that holds the data for the connections is determined by the variable LOCATE into which you've put the number of locations.
Each connection to another location is made up of a four character code. The first pair of characters is a code number of the location you'll end up in by going in the chosen direction.
So, if an entry reads "01050302042100", then:
0105 means 'NORTH' leads to location number 5
0302 means 'EAST' leads to location number 2
0421 means 'WEST' leads to location number 21
00 signifies the end of the data for that location.
To connect up the locations in your adventure, follow your
RATHBONE REVISITED
To find out how to connect locations, type in the following short listing into your copy of Castle Rathbone, then type GOTO 5000 and press enter. You'll then see how the connections for each location are made there.
5000 RESTORE 9000: GO SUB 9000
5005 FOR n=1 TO locate
5010 PRINT "AT LOCATION NO:";n: PRINT
5020 PRINT "THE CONNECTION ENTRY IS:-": PRINT
5025 FOR i=1 TO LEN(L$(n)) STEP 4: PRINT L$(n,i TO i+3);" ";: NEXT i: PRINT L$(n,i TO ): PRINT
5030 PRINT "This means that:-": PRINT: LET p=1
5040 LET J$=L$(n,p TO p+1): IF J$="00" AND p=1 THEN PRINT "The connections for this location are found in the ACTIONtable.": GO TO 5100
5045 IF J$="00" THEN GO TO 5100
5050 LET K$=L$(n,p+2 TO p+3)
5060 GO TO 5060+2*VAL (J$)
5062 PRINT "NORTH";: GO TO 5080
5064 PRINT "SOUTH";: GO TO 5080
5066 PRINT " EAST";: GO TO 5080
5068 PRINT " WEST";: GO TO 5080
5070 PRINT " UP";: GO TO 5080
5072 PRINT " DOWN";
5080 PRINT " leads to location No: ";VAL (K$): PRINT
5090 LET p=p+4: GO TO 5040
5100 PRINT AT 21,3;"PRESS 'ENTER' TO CONTINUE"
5105 IF INKEY$="" THEN GO TO 5105
5110 CLS: NEXT n
5120 STOP
Lines 5000-5120 These lines take the entries from the location connection table and they decode them on the screen.

map and produce a data statement for each location similar to the ones in Castle Rathbone.

OBJECTS AND TREASURES

We now come to the important list of objects and artefacts that are to appear in your adventure. First, decide what you want - gold doubloons, swords, half-eaten sarnies, an alien's toe-nail, you name it, you can include it. Now choose where it's going to be placed and you're ready to put them into your program.
The Data statement for each object comprises of a description of the object followed by a number. This number corresponds to the location where the object first appeared. If you don't want the object to appear straight away, simply make the number equal 0. When you want the object to make its appearance, then use action codes J or K in an action table entry. If an object is being carried the number will be -1. The program changes that automatically when you pick up or drop an object.
It's very important that when you come to write the dictionary of words that the program will recognise, you include a word or words for each object. If you don't the player's going to have a tricky time telling the program to pick it up! Also don't forget to count up your objects and change the variable TNOBS at line 9020.
RATHBONE REVISITED
To help clarify how to use objects type the following program into Castle Rathbone, then type GOTO 5200 and press enter.
5200 RESTORE 9000: GO SUB 9000
5210 FOR n=1 TO tnobs
5220 PRINT: PRINT "OBJECT No.";n;" is:-": PRINT
5230 PRINT O$(n): PRINT
5240 IF O(n)>0 THEN PRINT "and it's initial position is location No.";O(n): GO TO 5290
5250 IF O(n)=0 THEN PRINT "and it's not been created yet.": GO TO 5290
5260 PRINT "and it is being carried."
5290 PRINT : NEXT n: STOP
Lines 5200-5290 These lines print a list of objects in Castle Rathbone and the start location of each one.

MESSAGES AND RESPONSES

An adventure, if it's good, has got to give you the impression that it knows what you're up to all the time. That means it'll often have to respond to the actions and inputs of the player with something a trifle more intelligent than the normal "You can't do that!" or "I don't understand". These responses will also take the form of hints and warnings to the player about what they are doing (or not doing).
Now, you'd have to be a pretty good planner to know all your messages from the beginning. But fortunately, it doesn't matter as you can add new responses as fresh ideas occur to you.
But what Sort of messages do I put in? I hear you ask. To show you how flexible it is, here's an example. Say the player has 'A LAMP' and 'A BOX OF MATCHES'. Rather than respond to 'LIGHT LAMP' with just an OK, the message could read "The room is now brightly illuminated" or "Don't be a Wally. You can't light an electric lamp with matches". As always, you're in control and you decide what you want to happen.
When you're ready to add your messages, delete lines 3000- 3305. Now write your messages and then enter them in the program at lines 3000, 3005, 3010 and so on. These lines correspond to message numbers 1,2,3 ... and must go here as they're called by the program at line 2605. Take a look at Castle Rathbone lines 3000 to 3305 if you're not sure what sort of messages you'll need.

FLAGS AND COUNTERS

The primary function of flags is to let the program keep track of what's going on. They are held in the array F(). They record all the important happenings. Perhaps you can think of them as on/off, true and false switches. For example, if you're in the attic in Castle Rathbone, the program has to know whether the skylight is open. So, there is an entry in the Status table that checks if F(12) is set. If it is, then the program prints the message at line 3135. In the same way, there is another entry in the Status table that'll print the message "There is a rope fixed to the battlements" when F(18) is set ON, that is to 1.
If you want to see how the Flags were used in Castle Rathbone, use the program that decodes the Action table from Rathbone Revisited. You'll then see where the tests on the Flags occur.
Here's a full list of the Flags that were used in Castle Rathbone. It should help you to see how many Flags you'll need in your adventure. When you've decided how many you want, change the DIM F(21) statement at line 9065.
F(1)=1 Means the current location is dark
F(2)=1 Unused
F(3)=1 The player has read the HELPLINE message
F(4)=1 Unused
F(5)=1 Unused
F(6)=1 Unused
F(7)=1 The player has read the Blue Peter book
F(8)=1 The player's standing on the chair at location 17
F(9)=1 The player has searched the kitchen and found the cornflakes
F(10)=1 The tyres on the motorbike have been pumped up (that means the motorbike with flat tyres has been swapped for the other one)
F(11)=1 The secret attic door is open
F(12)=1 The attic skylight is open
F(13)=1 Roger has escaped
F(14)=1 Tony has escaped
F(15)=1 Pete has escaped
F(16)=1 The hole at location 15 has been dug
F(17)=1 The ramp made of earth has been built
F(18)=1 The rope of sheets is fixed to the battlements
F(19)=1 Peter is giving his grand performance
F(20)=1 The dragon is dead
F(21)=1 The first help message for location has been printed

THE DICTIONARY

This is where your program becomes word perfect. The dictionary must contain all the words that it recognises. You'll see from the one in Castle Rathbone (Lines 9400-9474) that its dictionary is quite large but yours needn't be this big. In fact, the smaller the vocabulary, the faster the program. (Is this why Troubleshootin' Pete talks so fast? Ed). Just remember to keep the direction commands identical to those in Castle Rathbone (North, South, East, West, Up, Down). As for the rest, well, you have a whole language to choose from!
You'll notice that each of the words in the dictionary data statements is preceded by a two digit number. This is the code used by the rest of the program. If two words have the same meaning, you should assign them the same code number and treat them as one word. When the player enters something, the routine at line 2000 searches through the dictionary until it finds a match for the words entered. When a match is found, the program then tries to match the prefixed code to an entry in the Action table.
But before we look at that, don't forget to count up the total number of words and then change the value assigned to the variable WORDS at line 9015.

ACTION TABLE

Prepare for action. Take a look at Castle Rathbone lines 9086- 9199 and you'll see a series of strange looking Data statements. These are the action table entries. When the player types in a command like 'TAKE ROPE', the program finds the code for each word from the dictionary. It then searches for an entry in the action table where the first four characters are the same as the two codes for the words input. When it finds the right entry, it carries out the tests in the entry, such as 'is the rope here?' You couldn't take it, after all, if it wasn't in that location. If all the tests prove positive, the appropriate action is performed - 'get the rope' and then 'print the message OK, YOU'VE GOT THE ROPE'.
Now you can construct a series of actions for your own adventure using the Test and Action tables. The sequence for each entry is as follows: two codes for the input - the numbers at the front of each word in the dictionary. This is followed by a series of tests from the Test table. Then an asterisk to signify the end of the tests. Then a series of actions (from the Action table). Finally, don't forget to put an asterisk at the end of the entry as well.

So an entry for 'TAKE ROPE' in Castle Rathbone could he as follows:
WORD CODES 13 This is the word code for 'TAKE'
87 This is the word code for 'ROPE'
ACTION CODES 2 This is the test for whether an object is present
18 This is the number of the object that is being tested for
* End of tests
ACTION CODES H This is the action code for pick object
18 This is the object to be picked up
B This prints the OK SKIPPER message
* This is the end of the entry
RATHBONE REVISITED
If you're lost in Action, all should become clear if you type the following program into Castle Rathbone and then type GOTO 6000. This will then decode all the action code entries in Castle Rathbone.
6000 RESTORE 9000: GO SUB 9000
6010 FOR n=1 TO action
6020 LET C$=E$(n): LET J$="": LET K$=""
6030 CLS: PRINT "ENTRY No.";n;" in the ACTION table.": PRINT
6040 PRINT "Reads as follows:-": PRINT: PRINT C$
6050 PRINT "It is decoded as follows:-": PRINT
6060 PRINT "THE 'WORD' INPUTS REQUIRED ARE:"
6070 PRINT
6080 FOR i=1 TO words: IF C$(1 TO 2)=D$(i,1 TO 2) THEN LET J$=D$(i,3 TO 6): GO TO 6090
6085 NEXT i
6090 IF C$(3 TO 4)="00" THEN GO TO 6110
6095 FOR i=1 TO words: IF C$(3 TO 4)=D$(i,1 TO 2) THEN LET K$=D$(i,3 TO 6): GO TO 6110
6100 NEXT i
6110 PRINT C$(1 TO 2);" ";J$;" ";C$(3 TO 4);" ";K$
6140 PRINT: PRINT "THE TESTS MADE ARE:-": PRINT
6150 LET p=5
6160 IF C$(p)="*" THEN GO TO 6310
6170 PRINT C$(p TO p+2);" means ": LET c2=VAL (C$(p+1 TO p+2))
6180 GO TO 6180+10*(VAL (C$(p)))
6190 PRINT "Is the player at location ";c2;"?": GO TO 6300
6200 PRINT "Is OBJECT No.";c2: PRINT O$(c2): PRINT "at the current location or being carried?": GO TO 6300
6210 PRINT "Is OBJECT No.";c2: PRINT O$(c2): PRINT "NOT at the current location?": GO TO 6300
6220 PRINT "Is OBJECT No.";c2: PRINT O$(n): PRINT "being carried?": GO TO 6300
6230 PRINT "Is FLAG(";VAL (C$(p+1 TO p+2));") ON (ie. equals 1)": GO TO 6300
6240 PRINT "Is FLAG(";VAL (C$(p+1 TO p+2));") OFF (ie. equals 0)": GO TO 6300
6250 PRINT "Does COUNT(";VAL (C$(p+1 TO p+2));") equal 1"
6300 LET p=p+3: PRINT: GO TO 6160
6310 PRINT: PRINT "ACTIONS TO BE CARRIED OUT ARE:": PRINT
6320 LET p=p+1
6330 IF C$(p)="*" THEN GO TO 6500
6332 LET p1=2: LET A$=C$(p)
6334 IF A$="B" OR A$="C" OR A$="D" OR A$="E" OR A$="F" OR A$="P" OR A$="Q" THEN LET p1=0: PRINT C$(p);" means": GO TO 6350
6336 IF A$="O" THEN LET p1=4: LET c3=VAL (C$(p+3 TO p+4))
6340 PRINT C$(p TO p+p1);" means ": LET c2=VAL (C$(p+1 TO p+2))
6350 GO TO 6350+5*(CODE (C$(p))-64)
6355 PRINT "Print message No.";c2
6356 GO SUB 2995+5*c2: GO TO 6450
6360 PRINT "Prints the message: ~OK SKIPPER~scans the STATUS table and gets new input.": GO TO 6450
6365 PRINT "Tells the computer to scan the STATUS table and get the next command from the keyboard.": GO TO 6450
6370 PRINT "Tells the program to get the next input.": GO TO 6450
6375 PRINT "Print the location description, scans the STATUS table and get the next input.": GO TO 6450
6380 PRINT "Print a list of objects carried.": GO TO 6450
6385 PRINT "Move the player to location:";c2: GO TO 6450
6390 PRINT "Pick up OBJECT No.";c2: PRINT O$(c2): GO TO 6450
6395 PRINT "Drop OBJECT No.";c2: PRINT O$(c2): GO TO 6450
6400 PRINT "Put OBJECT No.";c2;" at current location": PRINT O$(c2): GO TO 6450
6405 PRINT "Destroy/Remove OBJECT No.";c2: PRINT "from the game.": PRINT O$(c2): GO TO 6450
6410 PRINT "Swap objects ";c2;" & ";c2+1: PRINT O$(c2): PRINT O$(c2+1): GO TO 6450
6415 PRINT "Turn FLAG(";c2;") ON ie.=1": GO TO 6450
6420 PRINT "Turn FLAG(";c2;") OFF ie.=0": GO TO 6450
6425 PRINT "Set COUNT(";c2;")=";c3: GO TO 6450
6430 PRINT "Verify QUIT command.": GO TO 6450
6435 PRINT "Quit the game."
6450 LET p=p+p1+1: PRINT: GO TO 6330
6500 IF INKEY$="" THEN GO TO 6500
6510 CLS : NEXT n: STOP
Lines 6000-6510 This routine decodes the action table. After running this you should have a much better idea of how the Action table works. If you want you can modify this routine to decode the Status table as well.
THE ACTION CODES
Action performed Action codes
Print text message/response Axx
Print message 'OK SKIPPER' B
Scan STATUS table and get the next command C
Get the next command from the keyboard D
Print the room description, scan STATUS and get the next command E
Print lists of objects carried F
Move player to location xx Gxx
Pick up object xx Hxx
Drop object xx Ixx
Put object xx at current location (LCL) Jxx
Destroy/remove object xx from the game Kxx
Swap objects xx and xx+1 Lxx
Turn FLAG (xx) on Mxx
Turn FLAG (xx) off Nxx
Set COUNT (xx) to yy Oxxyy
Verify the 'Quit' command P
Quit the game Q
Here's a list of the action codes you may use. The letter corresponds to the action code and the 'xx' is replaced by the number of the location, object or flag.

STATUS TABLE

The entries in the Status table in lines 9240 to 9270 look virtually the same as those in the Action table but they serve a different purpose.
There are really two main differences. One, the Status table entries don't have the codes for WORD inputs at the front of the entry and two, the Status table is only scanned each time the player enters a new location or when one of the entries in the Action table ends in a B, C or E.
THE TEST CODES
Test made by the program Test codes
Is the player at location xx? 1xx
Is object xx at the present location (or carried)? 2xx
Is object xx not at the present location? 3xx
Is object xx being carried? 4xx
Is FLAG (xx) on (or equal to one)? 5xx
Is FLAG (xx) off (or equal to zero)? 6xx
Does COUNT (xx) equal one? 7xx
Here's a list of the tests you can see in the Action and Status tables. The first number corresponds to the test and the 'xx' is replaced by the number of the location or object being tested.

DEBUGGING

And finally, never send your adventure out into the unsuspecting world without thoroughly testing it first. It can be frustrating enough when you can't finish an adventure 'cos it's too tricky - think how frustrating it is if there are bugs preventing you from completing it. The world will never be unsuspecting twice!
Home Contents KwikPik