TIPS FOR ADVENTURE WRITING This episode - by Dave Whitmore I would like to start a column that may help those of us who like to dabble with programming. As you have probably guessed by now, I'm hopeless with machine code, but this doesn't stop me wanting to learn more. Until I bought SAM, I used to struggle with BASIC on the Spectrum, but now we have the much improved SAM BASIC and the advanced MasterBASIC it is much easier to write small games, even if they are only for our own amusement. I'd be grateful if other members would send in routines that may help in writing adventures. The TEXT FORMATTER from the last issue was a very good start, as David Haire even provided the assembly listing. I'd like to continue publishing routines of this sort and to kick off the column, I've wrote the following article that some of you may find a bit too simple - Well, I tried to make it sound simple! If you want to send in something for the column, MORE >>>> please bear in mind that some people may not be as experienced with programming as you are, and try to give a few pointers that will explain what's happening in your program. On the other hand no one may be interested in a column like this, so if nothing is offered by members, then we will drop the subject. I wrote the following routine a few months ago after I ditched the ADVSYS thingy. The general idea was to store messages or location texts high in memory, without using String DATA arrays, and an easy way to get them back later. So let's kick off... If you are writing an adventure in BASIC, you may consider putting your location text, messages, object text, and other strings into memory in the form of DATA. You will find that this works alright, but then it does use more memory than is necessary. MORE >>>> For instance, if you want to have 50 locations in the Adventure then you must decide how long you want the largest location description to be. If you decide that the absolute maximum will be a string of 512 characters, and you want 50 messages or locations etc, then you will DIMension the string to 50*512 chars. So you use the line- 10 DIM LOCO$ (50,512) Then LET each substring equal your varied text entries, and when the player changes location, you simply program the game to PRINT LOCO$ (number). This is all very well, until you consider that each and every location description will probably take different numbers of characters. You may find that some of your descriptions only need to be MORE >>>> short, as they may have little significance or some other reason, but the total sum of characters is still 512 characters long because the end will be padded out with spaces So the text for your least significant location, say location 15 may look something like this; "You are on a stretch of road that leads NORTH to SOUTH." When in fact the location looks like this, if we say the character * = spaces " " You*are*on*a*stretch*of*road*that*leads*NORTH*to*SOUTH.********* **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** **************************************************************** MORE >>>> So you will be left with many spaces after the location or message text, perhaps causing important text that is already on the screen to scroll off the screen leaving an unexplained number of blank lines below the text. (Another thing to remember is that the TRUNC$ function will only TRUNCate a string up to 255 characters long, so if your text length is over 255 that option is ruled out.) This is a massive waste of memory, and besides that, you may later find that you want to tag extra text to a location or message that will make the string longer than 512 characters. A method of saving memory, that does not make use of strings in the conventional sense can be found by using the following routines that use the functions INSTR and MEM$. Using this method you can have up to 254 strings of any reasonable length, that can be summoned by a BASIC PROCedure and all the necessary BASIC to get the string back can fit on one program line. MORE >>>> For example, if we poke a string into high memory and want to get it back, we have to know exactly where it is and how long the string is. A way of doing this would be to give the string an identifier so that the start of the string you want to retrieve can easily be found using INSTR. So we have to give each string a number. We don't want the routine to look for just any number, as what will confuse the routine is the fact that all characters are really numbers ASCII numbers (a = 69). So, why suffer the limitations of only 31 usable locations or messages (" " = 32)?! So what we will do, is put the number 255 and THEN the number before each string to be poked. Next, and most importantly, we want to know the length of the string so that our PROCedure will know how many characters to print. MORE >>>> The method we will use pokes the length of the string into two bytes in the form of a Double POKE (DPOKE). So for message 1 we will do the following; LET mesno=1 LET start = 140000 (where we want the first message) LET A$ = "Have a nice day" (16 characters) LET L = LEN A$ (now L = 16) POKE START,255 (the first identifier) POKE start+1,mesno (the message number identifier) DPOKE start+2,L (the length of message - upto 65520! POKE start+3,A$ (the string) MORE >>>> Please either use separate line numbers or split one line into statements for the above. Now when we look at PEEK 140000 onwards the situation is this; 255,1,1,0,H,a,v,e, ,a, ,n,i,c,e, ,d,a,y,0,0,0,0,0 etc (^ = CHR$ PEEK ^) Next we will use the procedure to find it. 10000 DEF PROC mess n LET first=140000,last=190000 LET position=INSTR(MEM$(first TO last),CHR$ 255+CHR$ n) LET position=position-1 IF position=-1 THEN PRINT #0; "ERROR: No such message" PAUSE STOP ELSE LET start=(position+first) LET strlen=DPEEK (start+2) LET mess$=MEM$((start+4) TO (start+3+strlen)) PRINT mess$ END PROC MORE >>>> (Don't forget to put colons : between statements if only on the one line) Type MESS 1 and "Have a nice day", should be on your screen (without the quotations!) Now to put in more strings. The following method is manual and would not normaly be used but you can try it. 10 LET pos= 140000 (start pokeing at 140000) 20 FOR t=1 TO 3 (or the number of messages you want) 30 PRINT "message ";t (tells you the number for input) 40 INPUT mess$ ( Your text strings ) 50 LET lenmess=LEN mess$ (the length of message) 60 LET mno=t (the message number) 70 POKE pos,2 55,mno (etc) 80 DPOKE pos+2,lenmess (etc) 90 POKE pos+4,mess$ (etc) 100 LET pos=pos+lenmess+4 (^gives memory location to place next string) MORE >>>> 110 NEXT t (loops back to value of t if not reached ) 120 PRINT "file length = ";pos 130 SAVE "filename" code 140000,pos (for later use) 10000 DEF PROC MESS N etc....... Save the program then RUN it, and then delete 10 to 130 You will find that your messages can be recalled using MESS n, where n is the message number. The only limitation using this method is the fact that your string cannot easily be edited and poked back in future, so the best way round this is to make sure that the string you want to enter is FINAL. A better way is to prepare your strings as DATA lines and then use the above method with the following changes; Delete lines 30 and 40 and insert the new line 30 MORE >>>> 30 READ mess$ Then write your text string$ as DATA line's after the program at line 1000. eg; 1000 DATA "You are under the magician's spell. Hypnotised, you walk to the cliff edge and jump." 1010 DATA "To your amazement you flap your arms and you find you are flying. The magician laughs and scatters a packet of Trill on the ground. You are very hungry." 1020 DATA etc, etc, etc Make sure that (t) equals the number of DATA lines, and as an afterthought add the line; 5 RESTORE 1000 It may be that you want to have more than 254 strings in memory. MORE >>>> Well, there is nothing to stop you. Remember that the MESS n PROCedure only looks at memory 140000 to 190000. The length of your full 254 strings (may, or) may not reach 190000. You can adjust the 190000 figure to be the number at the end of the last string. If POS = 181950 then linit the MESS n proceedure to only look between MEM$ (140000 TO 181950), or if it is more than 190000 then you will have to change it anyway to avoid errors. You can make a copy of MESS n to line 10010 and change it to MESS2 n (or LOCO n or whatever) and then instruct the PROCedure to look for MESS2 n after the end of the strings covered by MESS n - eg; MEM$ (181951 TO 220000), but make sure that your compiler program knows that initialy POS must equal 181951 so it wont overwrite the strings covered by the original MESS n, and don't forget that the start and length for saving the code in line 130 must also be changed. MORE >>>> If you have any short routines (or even long ones) that you would like to tell us about, then please send them in. Dave *** --- ***