Tag - STOS

STOS Address Book

Welcome to this tutorial on writing a database program in STOS. A simple database which will store information in the way of names, addresses and other details. I will call this program “STOS Address Book”. Note there are no prizes for guessing a better name.

First, what is a database? Well it’s a program that stores information entered by the user, and allows them to view it later. But why write a database to store names and addresses when you can quite simply use an address book to write in? Well there are certain advantages…..for example, a program can find the info quicker than someone searching through a book. Also, should you wish to delete someone’s entry at anytime then you can do it quite easily without having blotted out entries.

Each entry is entered into a field. In other words an element of an array. So lets first set the screen up.

5 rem —ADDRESS BOOK
10 key off : curs off : hide on : flash off : mode 1
15 rem—SET UP ARRAYS FOR FILE INFO
20 dim SURNAME$(1000) : dim NAME$(1000) : dim ADDR$(1000) :
dim T0WN$(1000) : dim POST$(1000) : dim PHONE$(1000) :
dim INFO$(1000)
25 rem—SET UP VARIBLES
30 FILE=0 : FILES=0

Most databases are displayed in medium resolution which makes them look more professional. There are five fields: Surname, Names, Addresse, Towns, Postcode, Phone, and Info. Note the way the TOWN array is spelt. The O is actually a nought. This stops STOS from interpreting the word as to WN$

Each field has space reserved for 1000 entries. The more entries we have, the more memory is used. Now lets set up the rest of the screen.

35 rem—OPEN FIRST WINDOW AND ENTER TITLE”
40 windopen 1,0,0,80,3,3,1
50 cdown : centre “ADDRESS BOOK”
55 rem—OPEN SECOND WINDOW AND ENTER OPTIONS”
60 windopen 2,59,3,21,17,3,1
70 locate 1,2 : print “(C)REATE A FILE”
80 locate 1,4 : print “(D)ELETE A FILE”
90 locate 1,6 : print “(F)IND A FILE”
100 locate 1,8 : print “(L)IST ALL FILES”
110 locate 1,10 : print “(P)RINT A FILE”
120 locate 1,12 : print “(Q)UIT AND SAVE”
125 rem—OPEN THIRD WINDOW FOR PROGRAM INFO
130 windopen 3,0,20,80,3,3,1
140 centre “CHOOSE AN OPTION”

This part of the program opens three windows which displays the title, program options, and the bottom window is used for program information, meaning that we use it prompting the user what to do.

The next thing to do is to use the blank part of the screen so we can print the field names but first we have to leave the windows.

145 rem—LEAVE WINDOW AND GOTO SCREEN
150 qwindow 0

This is an undocumented feature of STOS. The manual tells us that when using the window commands the values range from 1 to 15 while nought is the STOS system window. You can however leave the windows completely without going to another or deleting them by using a “qwindow 0”. Now we can print the field names on screen without affecting the windows.

155 rem—PRINT FIELD NAMES
160 locate 0,4 : print “SURNAME:”
170 locate 0,6 : print “NAME:”
180 locate 0,8 : print “ADDRESS:”
190 locate 0,10 : print “TOWNS:”
200 locate 0,12 : print “POSTCODE:”
210 locate 0,14 : print “PHONE:”
220 locate 0,16 : print “INFO:”
225 locate 0,18 : print “FILES:”;FILES

Everything’s set up. Now we just have to wait for the user to select an option.

230 rem—WAIT FOR AN INPUT
240 K$=input$(1)
250 rem—CHECK WHICH KEY HAS BEEN PRESSED
260 if K$=”C” or K$=”c” then goto 400
270 if K$=”D” or K$=”d” then goto 500
280 if K$=”F” or K$=”f” then goto 600
290 if K$=”L” or K$=”l” then goto 700
300 if K$=”P” or K$=”p” then goto 800
310 if K$=”Q” or K$=”q” then goto 900
320 K$=”” : goto 240

The variable K$ is used to store the users selection. At the moment he only chose C to create a file…the program will then go to line 400 which is the input routine. Line 320 clears the variable and returns to line 240 ready to await another selection.

400 rem—-CREATE A FILE
410 curs on : inc FILES
420 rem—GET SURNAME
430 X=8 : Y=4 : gosub 2000 : SURNAME$(FILES)=K$
440 rem—GET NAME
450 X=5 : Y=6 : gosub 2000 : NAME$(FILES)=K$
460 rem—GET ADDRESS
470 X=8 : Y=8 : gosub 2000 : ADDR$(FILES)=K$
480 rem—GET TOWNS
490 X=6 : Y=10 : gosub 2000 : T0WN$(FILES)=K$
500 rem—GET POSTCODE
510 X=9 : Y=12 : gosub 2000 : POST$(FILES)=K$
520 rem—GET PHONE NUMBER
530 X=6 : Y=14 : gosub 2000 : PHONE$(FILES)=K$
540 rem—GET INFO
550 X=5 : Y=16 : gosub 2000 : INFO$(FILES)=K$
555 rem—FILE CREATED SO GO BACK AND WAIT FOR NEXT INPUT
560 K$=”” : curs off : gosub 2070 : goto 225

This is a kind of set up to enter the information needed. The X and Y variables hold the X and Y co-ordinates of the text cursor. Notice at the start of this part we turns the cursor on and add one to the FILES variable. This is the number of the file we are currently creating.

The X and Y variables are needed to position the text cursor just after each field name…IE SURNAME, NAME, etc… The routine then does a subroutine to the routine that actually enters the information into a variable. Once the file has been created the program turns off the cursor, does a subroutine to clear the wording entered off the screen then goes back to wait for another selection from the user.

2000 rem—INPUT ROUTINE
2010 locate X,Y
2020 input “”;K$
2030 if K$=”” then K$=”UNKNOWN”
2040 return

The actual input routine. Note how we use the locate command to position the cursor at the right place for every field name. Line 2020 allows you to type in the information while line 2030 checks if the users just pressed the enter key without typing anything in.

2070 rem—CLEAR INFO OFF SCREEN
2080 wait 30
2090 locate 8,4 : print space$(50)
2100 locate 5,6 : print space$(53)
2110 locate 8,8 : print space$(50)
2120 locate 6,10 : print space$(52)
2130 locate 9,12 : print space$(49)
2140 locate 6,14 : print space$(52)
2150 locate 5,16 : print space$(53)
2160 return

The final part which clears the wording off the screen once the file is created. The space$ command just prints a line of spaces to clear it.

Now we are adding a Delete File function to our Address Book program. Here is the main routine for it.

600 rem—DELETE A FILE
610 if FILES=0 then goto 310
620 locate 5,6 : curs on : input “”;N$ : curs off : if N$=”” then goto 310
630 rem—LOOK FOR FIRST THREE LETTERS OF N$ IN NAME$ ARRAY
635 FILE=0
640 FOUND=0 : repeat
650 inc FILE : if left$(NAME$(FILE),3)=left$(N$,3) then FOUND=1 : goto 690
660 until FILE=FILES
670 rem—IF THE FILE IS’NT FOUND THEN GO BACK TO INPUT
680 if FOUND=0 then qwindow 3 : clw : curs off : centre “FILE NOT FOUND” : wait 100 : qwindow 0 : locate 5,6 : print space$(53) : qwindow 3 : clw : goto 200
690 rem—FILE FOUND SO PRINT INFO
700 locate 8,4 : print SURNAME$(FILE)
710 locate 5,6 : print NAME$(FILE)
720 locate 8,8 : print ADDR$(FILE)
730 locate 6,10 : print T0WN$(FILE)
740 locate 9,12 : print POST$(FILE)
750 locate 6,14 : print PHONE$(FILE)
760 locate 5,16 : print INFO$(FILE)
770 locate 0,18 : print “FILES:”;FILES
780 rem—ASK USER IF HE WANTS TO DELETE THE FILE
790 qwindow 3 : clw : curs off : centre “DELETE THIS FILE (Y/N)?” : D$=input$(1)
800 if D$=”n” or D$=”N” then qwindow 0 : gosub 3000 : goto 640
810 rem—DELETE FILE AND SORT THEM INTO ORDER
820 for X=FILE to FILES
830 SURNAME$(X)=SURNAME$(X+1)
840 NAME$(X)=NAME$(X+1)
850 ADDR$(X)=ADDR$(X+1)
860 T0WN$(X)=T0WN$(X+1)
870 POST$(X)=POST$(X+1)
880 PHONE$(X)=PHONE$(X+1)
890 INFO$(X)=INFO$(X+1)
900 next X : dec FILES
910 rem—GO BACK TO OPTIONS
920 qwindow 0 : gosub 3000 : qwindow 3 : clw : goto 200

What this routine actually does is it first checks if there is any files in memory, and if so asks the user for the first name of the person they wish to delete. The routine finds the name then asks the user if he wants to delete it.

Note that only the first three letters of the name are searched for, this increases speed when searching. If the user doesn’t wish to delete the first file then the program will continue to list the other files under that name until either it reaches the end or the user deletes a file.

The program also uses window three to display the information for the function. It also does a gosub to a clearing routine to get rid of the excess wording on screen. It then deletes the selected record by doing a loop from FILE which is the file number to be deleted, to FILES which is the number of records held in memory. After this it subtracts the FILE variable by one then goes back to the selection routine. As a file has been removed the program brings all the other records back one to replace the deleted file.

I have added a FIND FILE function to the database program. This allows us to enter the name of the person whos details we wish to find and the program will list every name it finds under that input, allowing us to step through each one till we find the one we want.

1000 rem—FIND A FILE
1010 if FILES=0 then goto 310
1020 locate 5,6 : curs on : input “”;N$ : curs off : if N$=”” then goto 310
1030 rem—LOOK FOR FIRST THREE LETTERS OF N$ IN NAME$ ARRAY
1040 FILE=0
1050 FOUND=0 : repeat
1060 inc FILE : if left$(NAME$(FILE),3)=left$(N$,3) then FOUND=1 : goto 1100
1070 until FILE=FILES
1080 rem—IF THE FILE ISN’T FOUND THEN GO BACK TO INPUT
1090 if FOUND=0 then qwindow 3 : clw : curs off : centre “FILE NOT FOUND” : wait 100 : qwindow 0 : locate 5,6 : print space$(53) : qwindow 3 : clw : goto 200
1100 rem—FILE FOUND SO PRINT INFO
1110 locate 8,4 : print SURNAME$(FILE)
1120 locate 5,6 : print NAME$(FILE)
1130 locate 8,8 : print ADDR$(FILE)
1140 locate 6,10 : print T0WN$(FILE)
1150 locate 9,12 : print POST$(FILE)
1160 locate 6,14 : print PHONE$(FILE)
1170 locate 5,16 : print INFO$(FILE)
1180 locate 0,18 : print “FILES:”;FILES
1190 rem—ASK USER IF HE WANTS TO CONTINUE THE LISTING
1200 qwindow 3 : clw : curs off : centre “FILE NO:”+str$(FILE)+” NEXT FILE (Y/N)” : D$=input$(1)
1210 if FILE=FILES then qwindow 0 : gosub 3000 : goto 3100
1220 if D$=”Y” or D$=”y” and FILE<FILES then qwindow 0 : gosub 3000 : goto 1050

This is almost the same as the Delete file function only it allows you to step through the records stored so you can read them. Notice how the program only checks the first three letters of the name for speed. The final part of the program checks if the user wants to continue and only goes back to list another record if the variable FILE (no of present file) is lower that the varible FILES (total no of files stored). Now let’s look at listing all the files.

1230 rem —LIST ALL FILES
1290 FILE=0 : if FILES=0 then goto 310
1300 for FILE=1 to FILES
1310 locate 8,4 : print SURNAME$(FILE)
1320 locate 5,6 : print NAME$(FILE)
1330 locate 8,8 : print ADDR$(FILE)
1340 locate 6,10 : print T0WN$(FILE)
1350 locate 9,12 : print POST$(FILE)
1360 locate 6,14 : print PHONE$(FILE)
1370 locate 5,16 : print INFO$(FILE)
1380 locate 0,18 : print “FILES:”;FILES
1390 rem—ASK USER IF HE WANTS TO CONTINUE THE LISTING
1400 qwindow 3 : clw : curs off : centre “FILE NO:”+str$(FILE)+”
NEXT FILE (Y/N)” : D$=input$(1)
1410 if FILE=FILES then qwindow 0 : gosub 3000
1420 if D$=”Y” or D$=”y” and FILE<FILES then qwindow 0 : gosub 3000
else qwindow 0 : gosub 3000 : goto 3100
1430 next FILE

This routine uses a loop to step through each file in turn and print it on the screen. The user is then asked if he would like to continue listing or to terminate. If he continues then the loop continues. If the variable FILE equals the same as FILES (number of files stored) then the program terminates itself.

STOS Compiler Errors

The STOS compiler is a very useful program to have because it does the following things.

It speeds STOS programs up to three times their normal speed.

It saves the program as a single PRG file so there’s no need to copy the STOS folder onto the copy disk.

Compiled STOS programs are smaller than normal ones, saving disk space.

There’s no way a PRG file can be changed back into a BAS file so no-one can hack into it.

Even though the compiler seems like a great piece of software, it does have its issues. For example, when you compile a program to disk and then load it, the Function Key window flashes twice before the program starts. The way around this problem is to remove these commands from the program before you compile it.

key off
mode 0
hide on
curs off

From the Compiler’s main screen, go to the option menu and set the MODE option to LOW. Next, turn off the other commands by clicking on the OFF boxes. Compile the program and the screen appears blank when the program is loaded. Works better when the compiler sets the commands.

If you are pressed for space, then reduce the Sprite Buffer to 500 bytes. If the mouse pointer is not used in your game then select the NONE option in the option menu, but if your program just uses low res pointers then turn off the LOAD MED/HI option instead.

The Compiler has a couple of problems on the STE, first, trying to set it to change to Medium Rez results in the compiled program to run in the rez it was loaded in. Change the mode option to medium.

The second problem is with the STOS Tracker. On the STE the compiler always tells you that the last line of your program has an error, no matter what it is. To fix this you need to update the Compiler with the program on the Tracker disk called COMP207.PRG which updates the Compiler to v2.07 so the tracker commands will compile okay.

The compiler will sometimes list a line in your program and report an error, even though the line is okay. The reason it does this is because it is having trouble compiling it. This can happen on long lines of code and the FOR/NEXT loops. Look at this example.

10 pen 6: for x=1 to 10 : print”Hello” : next x

The compiler doesn’t like this line because of the “pen” command, why is a mystery, but remove the “pen” command and everything is fine. When using the FOR command, make sure it’s the first command on the line, like so…

10 for x=1 to 10 : pen 6 : print”Hello” : next x

See how I have put the “pen” command inside the loop? This lead to another problem I found. Look at this example.

10 box 10,10 to 100,20

When this line is found in a compiled program, the box is drawn in the current paper colour. The solution is to add an “ink” command at the start of the line.

10 ink 1 : box 10,10 to 100,20

The compilers main problems lie in the basic listing, it will report any lines it doesn’t understand. Normal errors would be spelling mistakes or the wrong use of a command. But sometimes it just has trouble compiling it in this case just play about with the listing and re-word it a bit, then try again.

In the COMMANDS.BAS file, there is a list of words that cannot be used in a compiled program. Most of them are Direct Commands so they can’t be put on a line anyway. The “run” command can’t be used so if your program requires a BAS file to load and run later in the program then you’ll just have to add it to the end of the program and call it using the ‘goto’ command.

Also, if your program has LOAD”name.var” in it, it will not work when compiled. The compiler will compile it but prints an error in the compiled program when it comes across this command. The solution is to save your variables as SEQ or RANDOM ACCESS file. For example:

10 open #1,”R”,”varible.dat”
20 put #1,N$
30 close #1

You can then load the contents of N$ like this.

10 open #1,”R”,varible.dat”
20 get #1,N$
30 close #1

Despite these issues most programs should compile fine. One other important thing to remember is that extensions have a compiler version with the extension .ECA. Make sure you have that installed.

STOS Code to Amos Code

As STOS and Amos are similar languages it was easier to port the STOS code of some of my games to Amos rather than rewrite it. In this article I will show you how to port your code over to Amos.

Converting STOS source code to Amos is easy. Simply save it as an ASCII file with the command save”game.asc”. Then port it over to your Amiga by formatting a MSDOS disk with Fastcopy 3, making sure you turn the fast format option off.  Then it’s a simple case of reading the disk in your Amiga’s drive using the Crossdos driver which you’ll find in the Devs drawer on your workbench disk. Simply double click on the icon to activate it. Once it’s on disk then you can simply load the ascii file into Amos with the Load Ascii option.

Now a thing to remember is although Amos has most normal STOS commands, there are still some differences. Let’s take this line.

10 key off : mode 0

In Amos there are no such commands. You should change this to…

10 Screen Open 1,320,200,16,Lowres

This does the same job as the command ‘mode 0’.

When you list your source code you will notice that Amos will show commands it doesn’t understand in capital letters.  You just need to find the Amos versions of those commands and change them around.

Sometimes there are problems with loading in certain files with long lines and you will get a “Line too Long” message. All you have to do is load the ASCII file into a word processor and make the lines shorter. For example:

10 for X=1 to 20 : XB(1,X)=FRNE+39*20/200 : next X

This can be set out as…

10 for X=1 to 20
20 XB(1,X)=FRNE+39*20/200
30 next X

If you have a lot of conditions in an If Then statement then you can use an Amos feature which allows you to have as many conditions as you want. This following routine will show you what I mean.

10 If CHOICE=1
20 Screen Copy 5 To 3
30 Music 1
40 FE=FE+100
50 Endif

Once the source is converted then it’s time to port over and convert your program’s data. Random Access files and Seq files can still be read within Amos but the commands are slightly different. Chip music will not play on the Amiga but you can play mods in your game instead. Sample banks I have not found a way to convert but you can simply load single samples into Protracker then save the lot as a mod,  then save them out when you port the mod over.

Pictures can be loaded into STpaint and saved as IFF files for the Amiga. Sprite banks can be converted to pictures using the Put Sprite command to fill a picture screen with sprites.

Final note: Amos uses both line numbers and labels so there is no need to change that unless you want to.

First STOS Game for Newbies

Well you’ve opened the STOS manual. You’ve read it and seen all the clever commands and accessories you can use. You’ve read and heard that all this can enable you to write your very own masterpiece. But how do you start, what do you do, how do you tell STOS to do this? These are the questions the beginner asks. In this article I will show you how to get started and even write a simple game.

How do we start? Well first we need to learn some commands. A program is just a group of commands that tell STOS what to do. We start off with simple commands and we type out the examples in the STOS manual. This helps to give us a good idea of commanding STOS and telling it what to do.

Lets say we wanted STOS to print something on the screen over and over again. We can use the PRINT and GOTO commands like this…

10 print”STOSSER”
20 goto 10

Here we have a simple program. First it prints the word STOSSER onto the screen, and then it goes onto the next line that tells STOS to go back to line 10 and print STOSSER on the screen again.

So as you can see, we have grouped two commands together to make a small program, actually a small program like this is better known as a routine. A program such as a game is just a large group of routines. Let’s try a routine that counts up to ten.

10 for X=1 to 10
20 home:print X:wait 5
30 next X

What we have here is a loop that adds one to the variable X, prints it on the screen, then stops when X reaches 10. The HOME command is used to tell STOS to keep the count printing on the same part of the screen, and the WAIT command stops STOS from printing too fast.

So once we have learned the commands we can easily group them together. Once you’ve been learning them, typing out examples and looking at other routines, you’ll find it all comes clearer.

Lets program a small game. First we have to decide what the program is going to be, and what it does. The game in question is a Guess the Number game where STOS will first choose a random number then ask the player to guess it. If the players guess is wrong then STOS will tell him so. First…let’s set up the screen.

10 key off : hide : mode 0
Rem Now to start printing the information we need on screen.
20 locate 0,1 : centre”NUMBER GUESSER”
Rem Now we need to tell STOS to choose a random number, like this.
30 RN=rnd(10) : if RN=0 then goto 30

This line will choose a different number from 1 to 10 every time STOS comes across it. With programming we are sometimes faced with problems, in this case, the RND command will sometimes choose nought as a random number. The problem is that we only want numbers from 1 to 10. So therefore we add an IF THEN statement to tell STOS that if it chooses nought…then go back and try again.

When STOS has chosen a number between 1 and 10, it needs to ask the player to guess the number.

40 locate 2,4 : print”I am thinking of a number between 1 and 10?
50 locate 2,5 : print”Can you guess what it is?”

Next we need a way of letting the player enter his guess.

60 input A

This command waits for the player to enter a number and press return. Now so far we have the RN variable which holds the random number chosen by the game, and the A variable which holds the number chosen by the player. But what if the player has typed in a number which is out of range? We can check for this with these two lines.

70 if A<1 then print”Your guess is too low, try again” : goto 60 80 if A>10 then print”Your guess is too high, try again” : goto 60

So if the number in the A variable is out of range then the game informs the player to try again then goes back to the input at line 60. Now we need a line to check if the player has guessed the right number.

90 if A<>RN then print”That’s not it, try again” : goto 60

This line checks if the A variable contains the same number as the variable chosen by the game. Here we are telling the game that if the players guess is other than the number the game has chosen then to give them a chance to try again.

Finally we need to check if the player has guessed the right number.

100 if A=RN then print”Well done, you’ve guessed the number” : stop

So there we have it. A small game produced by just a group of routines. We can easily improve it, such as getting the game to loop back to the start after the player wins. We could also add extras such as a score by simply adding points to a variable and printing it on the screen like this.

110 SC=SC+10 : print”Your score is now:”;SC
120 wait 50 : cls : goto 20

I recommend you download The Beginner Guide to STOS Basic by MT Software as this is much more detailed.

Programming an Art Package

Ever fancied writing your own art package? Well in this tutorial I am going to show you how to program a few options that you would normally find in an art package. I have written a full art package called Grafix Art and the routines printed here are taken straight from it.

First off all, this is the routine for the normal freehand draw tool.

4410 rem DRAW
4420 hide on : off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : show on : K=1
4430 set mark 1,1
4440 wait 10 : repeat
4450 X=x mouse : Y=y mouse
4460 if hardkey=97 then hide : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : fastcopy logic,back : show
4470 until mouse key=1 or mouse key=2
4480 hide on : SCR$(SC)=screen$(logic,0,0 to 330,200)
4490 if mouse key=2 then hide on : wait 10 : goto 230
4500 if mouse key=1 then polymark X,Y
4520 repeat
4540 X=x mouse : Y=y mouse
4550 if mouse key=1 then polyline to X,Y
4560 until mouse key=0
4570 fastcopy logic,back
4580 show on : goto 4440

In other STOS art packages people have tried using the PLOT command for this routine. However this causes the line to draw broken. What happens here is we use polymarks to make the lines. The opaque command is from the EXTRA extension and what it does is places an image in a string put there using SCREEN$ onto the screen as a normal screen copy and not merged. In an art package we have workscreens to place our picture in so we can design so many different pictures at a time and flick through them. The routine starts by waiting for the user to click the left mouse button before it will draw a polymark. The right mouse button allows you to abort the operation.

This next routine will draw a continuous line.

4590 rem LINE
4600 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : K=1 : set line val(LTYPE$),L_SIZE,0,0 : show on
4610 clear key : wait 10 : repeat
4620 X=x mouse : Y=y mouse : M=mouse key : K$=inkey$
4630 if asc(K$)=0 and scancode=97 then hide : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back : show
4640 wait vbl : until M
4650 if M=2 then hide on : wait 10 : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : cls : goto 200
4660 Y1=Y : X1=X : hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200)
4670 logic=back : wait 10 : repeat
4680 opaque screen back,0,0,SCR$(SC) : polyline X,Y to X1,Y1
4690 X1=x mouse : Y1=y mouse
4700 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
4710 screen swap : wait vbl
4720 until mouse key=1
4730 logic=physic
4740 show on : goto 4610

You’ll notice in these routines that we have implanted an UNDO feature. This means that if you are not happy with the last thing you have done you can erase it from screen before you carry on. Note that the routine will put the current picture into a screen with SCREEN$. This is your present workscreen.

Drawing a box is easy as well, here is the routine.

4750 rem BOX
4760 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : K=1 : set line val(LTYPE$),L_SIZE,0,0 : show on
4770 wait 10 : repeat
4780 X=x mouse : Y=y mouse : wait vbl
4790 if hardkey=97 then hide : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back : show
4800 M=mouse key : until M
4810 Y1=Y : X1=X : hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200)
4820 if M=2 then hide on : wait 10 : cls : goto 200
4830 logic=back : repeat
4840 opaque screen back,0,0,SCR$(SC) : box X,Y to X1,Y1
4850 X1=x mouse : Y1=y mouse
4860 screen swap : wait vbl
4870 until mouse key
4880 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
4890 logic=physic : fastcopy logic,back
4900 show on : goto 4770

You can also alter the routine to draw a rounded box just by changing the command BOX to RBOX.

Something a little more interesting……a triangle.

4910 rem TRIANGLE SHAPE
4920 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : K=1 : set line val(LTYPE$),L_SIZE,0,0 : show on
4930 repeat
4940 X=x mouse : Y=y mouse
4950 if hardkey=97 then hide : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back : show
4960 wait vbl : M=mouse key : until mouse key : hide on
4970 X1=X : Y1=Y : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : logic=back : wait 10
4980 if M=2 then logic=physic : wait 10 : cls : goto 200
4990 repeat
5000 opaque screen logic,0,0,SCR$(SC) : X1=x mouse : Y1=y mouse
5010 polyline X,Y to X1,Y1 to X,Y to X,Y
5020 screen swap : wait vbl
5030 until mouse key
5040 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
5050 wait 10 : repeat
5060 opaque screen logic,0,0,SCR$(SC) : X2=x mouse : Y2=y mouse
5070 polyline X,Y to X1,Y1 to X2,Y2 to X,Y
5080 screen swap : wait vbl
5090 until mouse key
5100 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
5110 wait 10 : logic=physic : fastcopy logic,back : show on : goto 4930

The first part of the routine draws the first angle of the triangle and the second part draws the rest of it.

And now, an eclipse type circle.

5120 rem CIRCLE
5130 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : show on : K=1
5140 repeat
5150 X=x mouse : Y=y mouse
5160 if hardkey=97 then hide : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back : show
5170 wait vbl : M=mouse key : until M
5180 if M=2 then hide on : wait 10 : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : cls : goto 200
5190 hide on : logic=back : wait 10
5200 SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200)
5210 repeat
5220 opaque screen logic,0,0,SCR$(SC) : X1=x mouse : Y1=y mouse
5230 earc X,Y,abs(X1-X),abs(Y1-Y),0,3600
5240 screen swap : wait vbl
5250 until mouse key
5260 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
5270 logic=physic : fastcopy logic,back : show on : wait 10 : goto 5140

The ABS command stops the circle from drawing inwards.

No picture is complete without a bit of colour. This routine will fill a area of screen with the current ink and pattern number, which can be altered with the SET PAINT and INK commands.

5280 rem FILL SHAPE
5290 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : show on : set paint 2,PSTYLE,1 : K=1
5300 repeat
5310 if mouse key=1 then hide : paint x mouse,y mouse : show
5320 if hardkey=97 then hide : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back : show
5330 wait vbl : until mouse key=2
5340 hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : wait 10 : cls : goto 200

Another interesting tool is the RAYS effect.

5350 rem RAYS
5360 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : K=1 : set line val(LTYPE$),L_SIZE,0,0 : show on : wait 10
5370 repeat
5380 X=x mouse : Y=y mouse : wait vbl
5390 M=mouse key : until M
5400 Y1=Y : X1=X : hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200)
5410 if M=2 then hide on : wait 10 : cls : goto 200
5420 logic=back : repeat
5430 X1=x mouse : Y1=y mouse
5440 opaque screen back,0,0,SCR$(SC) : polyline X,Y to X1,Y1
5450 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
5460 screen swap : wait vbl
5470 until mouse key=1
5480 logic=physic : polyline X,Y to X1,Y1 : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : wait 2 : goto 5420

A K line is like a normal line except that it does not stop drawing itself when you reclick the mouse button. Here is the routine……

5490 rem K-LINE
5500 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : K=1 : set line val(LTYPE$),L_SIZE,0,0 : show on
5510 repeat
5520 X=x mouse : Y=y mouse : wait vbl
5530 M=mouse key : until M : wait 10
5540 Y1=Y : X1=X : hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200)
5550 if M=2 then goto 200
5560 logic=back : repeat
5570 opaque screen back,0,0,SCR$(SC) : polyline X,Y to X1,Y1
5580 X1=x mouse : Y1=y mouse
5590 if mouse key=2 then logic=physic : wait 10 : cls : goto 200
5600 screen swap : wait vbl
5610 until mouse key=1
5620 logic=physic : polyline X,Y to X1,Y1 : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : wait 2 : X=X1 : Y=Y1 : goto 5560

Two more interesting tools are the SPRAY and BRUSH.

6010 rem SPRAY
6020 off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : show on : K=1 : wait 10
6030 repeat
6040 K$=inkey$ : X=x mouse+4 : Y=y mouse+4 : wait vbl
6050 if hardkey=97 then hide : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : show
6060 if mouse key=0 then show on
6070 M=mouse key : until M : hide on : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : wait vbl
6080 if M=1 and X>=SIZE and X<=319-SIZE and Y>=SIZE and Y<=199-SIZE then plot X+rnd(SIZE),Y+rnd(SIZE) : plot X-rnd(SIZE),Y-rnd(SIZE) : plot X+rnd(SIZE),Y-rnd(S IZE) : plot X-rnd(SIZE),Y+rnd(SIZE) 6090 if SPEED>0 and M=1 then wait SPEED
6100 if M=2 then SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : wait 10 : cls : goto 200
6110 if mouse key=0 then show on
6120 goto 6030

6180 rem BRUSH
6190 hide on : off : cls : ink PE-1 : opaque screen back,0,0,SCR$(SC) : fastcopy back,logic : wait vbl : wait 10 : K=1 : show on
6200 repeat
6210 XM=x mouse : YM=y mouse
6220 if hardkey=97 then off : opaque screen logic,0,0,SCR$(SC) : fastcopy logic,back
6230 if M=1 and XM+BRUSH<320 and YM+BRUSH<200 then hide on : bar XM,YM to XM+BRUSH,YM+BRUSH else show on
6240 M=mouse key : until M=2
6250 if M=2 then hide on : wait 10 : SCR$(SC)=”” : SCR$(SC)=screen$(logic,0,0 to 330,200) : cls : goto 200
6260 goto 6200

These are some of the more common tools used in an art package. There are more interesting features like MAGNIFY and RESIZE and all kinds of effects. But with these simple routines and a bit of imagination there is no reason why you can’t write your very own art package in STOS.

You can download Grafix Art and run it under an emulator.

Adventure Game Planning

Adventure games have been a popular source of amusement for years. This type of game puts you into a created fantasy world where you make the decisions. For example you could be a knight in shining armour attempting to rescue a princess from a tall tower guarded by a fire breathing dragon. In adventure games, the player would be told where he is and what’s going on around him, with people and creatures to communicate with, and puzzles to solve. A world where your dreams become reality. The first adventure games were ‘text based’, meaning that you communicated to the game by typing words and it answered back by printing a reply on the screen. For example, typing “get the lamp” will result in the computer replying “You take the lamp” – providing there was a lamp there in the first place. Playing an adventure game is like being a character in a film, what happens depends on your choice.

The only problem with these early adventure games was that they couldn’t understand everything the player typed in. So along came the graphic adventure games which hands control over to the mouse with little or no keyboard input. Commands would be clicked on instead of typed. These type of games include the early Monkey Island and Simon The Sorcerer series. These games really bring your adventure to life as you can actually see the world you are in rather than reading a text description.

PLANNING A GAME

Before we can start writing an adventure game we need to plan it out. First we need an idea then built the game around it. Let’s say our game takes place in a castle. This would be our fantasy game world which is broken down into a number of small locations. We would then make a list of the various locations you would find in a castle like this:

  1. Throne location.
  2. Main Hall.
  3. Drawbridge.
  4. Servants Quarters
  5. Bed Chamber.
  6. Tower.
  7. Dungeon.
  8. Castle Grounds.
  9. Staircase.

The next thing to do is connect each location to the nearest one. For example the nearest location to the Drawbridge would be the Main Hall or the Castle Grounds. This is important because you don’t want the player to enter the castle and find himself stepping into the Dungeon. The list would now look like this.

  1. Castle Grounds.
  2. Drawbridge.
  3. Main Hall.
  4. Throne location.
  5. Dungeon
  6. Servant’s Quarters.
  7. Staircase.
  8. Bed Chamber.
  9. Tower.

OBJECTS

An object is something the player can use in his quest. It could be: a coat, a lamp, some food, a bag or anything that can be picked up and moved. Each object has its own normal location number, it could also be in special locations which are known as Worn, Carried and Not Created. If the main character is a Barbarian we could give him a sword and put it in the carried location, so when the game starts the Barbarian is carrying the sword. We could also define a magic potion for him and put it in a normal location waiting for him to find it.

  1. Sword. (Carried Location)
  2. Potion. (Location Five)
  3. Robe. (Worn Location)

If you’ve ever played an adventure game and actually found something which was hidden, then you’ve found a “Not Created” object. This is a normal object without a normal location number. When the player finds the object the object location variable will become the number of the location the player is in.

PUZZLES

In adventures games, puzzles are there to give the player a challenge and make solving his quest harder. For example: finding a way or opening a chest or getting past a guard dog. Lets note down some puzzles for the castle game.

Puzzle: The player has to get past the guard at the drawbridge.
Answer: The player must find a guards uniform and wear it.

Puzzle: The player can’t unlock the door of the Bed Chamber.
Answer: The player must break the lock with his sword.

Puzzle: The player can’t get past the guard dog in the Tower.
Answer: The player must find a bone and give it to the dog.

TRAPS

As with puzzles, traps are set up for the player to fall into. If he tried attacking the guard then the guard would kill him and the game would be over. Here’s some traps for our castle game.

1> If the player takes the Kings Robe the guards will kill him.
2> If the player drinks the green potion he will die.
3> If the player trys to walk past the dog it will bite him.

EVENTS

Events are the outcome of things that happen in the game. For example if the player had solved the puzzle of the dog then an event would be called to put the bone in the Not Created location and the player would be told that the dog ran off with the bone. The dog and bone would be removed from the game. Here is some more examples of events

1> When the player examines the vase, he finds the key.
(Note: put the key in the players present location).

2> When the player breaks the lock on the door, he can open it.
(Note: set the DOOR variable to one to indicate it’s open).

3> When the player drinks the potion, his strength will be restored.
(Note: Set STREN variable to full and put potion in Not Created location).

EXITS (CONNECTIONS)

The player needs a way of moving between locations so we have to define the exits from each location. Exits take on the form of North, South, East, West, Up, Down, etc.. We can also have false exits. This means that the player can’t move to another location just yet, in other words it’s blocked off. Let’s take our castle game. From the drawbridge we have two exits: one leads to the Main Hall (location 3) and the other leads to the Castle Grounds (location 1). We could make a note like this.

Drawbridge: (North goes to location 3, South goes to location 1)

So the drawbridge is location 2 and from there the player can go north to location 3 or South to location 1. A false exit could be noted down as an event, so when the player opens the door of the dungeon, he can enter it. (Note: Connect Main Hall to Dungeon). You can think of this as a Not Created location being created.

Before we can get these options working, we need to set up the game data. The best way of doing this is to type it all out as data statements and then read them into an array. So let’s put our location descriptions down as data statements first.

data”You are in a cave, an opening is east.”
data”You are outside a cave, the entrance lies west.”

In order to put and hold this in memory we need to define an array using the DIM command like so.

dim location$(2)

This array will hold two location descriptions, next we need a line to put the location descriptions in the array so we use the READ command.

for X=1 to 2 : read location$(X) : next x

You can check if the line has done its job by typing ‘print location$(1)’, the description for location one should appear.

Now let’s define the EXIT data. For this we need to use a two dimension array called MAP.

dim MAP(2,4)

Next we use a nested loop to read the data into the array.

for X=1 to 2 : for Y=1 to 4 : read MAP(X,Y) : next Y : next X

Finally the data lines for each location.

data 0,0,0,2
data 0,0,1,0

Here we have a two dimension array which holds all the exit data for each location. So in the above example the first number is the number of locations in the game and the second is the number of exits.

To use this example we have to give each exit a number for the game to refer to like this.

North………Exit one
South………Exit two
West………..Exit three
East…………Exit four

So if we wanted exit two (south) to lead to location 3 we would use the following line of data.

data 0,3,0,0

Here we have four numbers on a line. As south is exit two then we replace the second number on the line with the number three so we now have an exit leading south to location three. Let’s connect a north exit to location four from this location.

data 4,3,0,0

Each data statement must have four numbers on it. If you didn’t want to use a certain exit then you would set the exit number to nought.

We also need a routine to allow the player to move from location to location via the defined exits. Use this line.

if MAP(location,CH)<>0 then location=MAP(location,CH) else print”You can’t go that way.”

OBJECTS

We can use the same method to store the object examine messages.

dim OBJECT$(2)
for X=1 to 2 : read OBJECT$(X) : next X
data”a small lamp.”,”a sharp sword.”

OBJECT LOCATIONS

Each object has its own location number which could either be a normal or a special one. First we set up the array which hold the object location numbers.

dim OB_LOC(4)

Next we use READ to put it into the array.

for X=1 to 4 : read OB_LOC(X) : next X

And next, the data line containing the object location numbers.

data 1,5,10,15

So object 1 at location 1, object 2 at location 5, object 3 at location 10 and object 4 at location 15

for x=1 to 4
if OB_LOC(X)=location then print”You can see”;OBJECT$(X)
next X

Where the OBJECT$ array holds the description of the objects IE: a small lamp.

SPECIAL OBJECT LOCATIONS

Normal object locations would would be as many as the locations in the adventure game as they appear in the actual game. But there are special object locations such as these.

CARRIED…………….Object is carried by the player
WORN………………..Object is worn by the player
NOT CREATED……Object does not yet exist in the game

To keep them separate from normal objects we need to give them higher numbers than the total number of locations in the game.

CARRIED=1000 : WORN=2000 : NC=3000

Each variable can be used to specify which special location the object is in. So for example if we wanted the game to list our carried objects then it could be checked like this. First, using an array like OB_LOC, we can put our first object in the CARRIED special location like this..

OB_LOC(1)=CARRIED

We can then add some lines to our game to inform the player what objects he is carrying……

for X=1 to 10
if OB_LOC(X)=CARRIED then print”You are carrying…..”;OBJECT$(X)
if OB_LOC(X)=WORN then print”You are wearing….”;OBJECT$(X)
next X

I have only covered a few basics here. For full information why not try my STOS Adventure Creator and STOS Graphic Adventure Creator which you can download from my Atari ST Page. Most of the work is done for you so you can start knocking out many adventure games.

STOS Basic Routines

A collection of STOS Basic routines I programmed. Taken from Stosser, Power and ST+ diskzines

HIGH SCORE TABLE

10 key off : cls
20 dim NAME$(10) : dim SC(10)
30 for X=1 to 10 : read NAME$(X) : next X
40 for X=1 to 10 : read SC(X) : next X
50 for X=1 to 10
60 print NAME$(X);” “;SC(X)
70 next X
80 print : input “Name:”;A$ : input “Score:”;B
85 for X=1 to 10
90 if B>SC(X) then swap NAME$(X),A$ : swap SC(X),B
100 next X : cls : goto 50
150 data “DEANO”,”MICK”,”JEFF”,”MIKE”,”STEVE”,”TOM”,”PHIL”,”PETE”,”JACK”,”ANDY”
160 data 1000,900,800,700,600,500,400,300,200,100

POKING CHARACTERS INTO A BANK

10 reserve as work 5,400 : S5=start(5)
20 input “STRING:”;A$ : LE=len(A$)
30 for X=1 to LE : poke S5+X,asc(mid$(A$,X,1)) : next X
40 for X=1 to LE : print chr$(peek(S5+X)); : wait 5 : next X

RANDOM NUMBERS IN AN ARRAY WITH NONE REPEATING

10 cls
20 dim NUMB(12)
30 for LOOP=1 to 12
40 NUMB(LOOP)=0
50 next LOOP
60 for LOOP=1 to 12
70 repeat
80 EL=rnd(11)+1
90 until NUMB(EL)=0
100 NUMB(EL)=LOOP
110 next LOOP
120 for X=1 to 12 : print NUMB(X); : next X

RANDOM WORDS IN AN ARRAY WITH NONE REPEATING

1 rem WRD$() holds the words to be placed in a random order
2 rem RWRD$() hold the same words but in a random sequence
100 key off
110 dim WRD$(12),RWRD$(12) : for W=1 to 12 : read WRD$(W) : next W
120 rem clear array
130 for W=1 to 12 : RWRD$(W)=”” : next W
140 for W=1 to 12
150 R=rnd(11)+1 : if RWRD$(R)<>”” then 150
160 RWRD$(R)=WRD$(W)
170 next W
180 for W=1 to 12
190 print using “##”;W;” “;RWRD$(W)
200 next W
210 rem The 12 words, put anything here!
220 data “One”,”Two”,”Three”,”Four”,”Five”,”Six”,”Seven”,”Eight”,”Nine”,”Ten”,”Eleven”,”Twelve”

SIN WAVE LINES

10 curs off : hide on : key off : mode 0
20 palette $0,$11,$577,$377,$177,$375,$573,$771,$750,$730,$700,$702,$703,$705,$727,$747
30 def scroll 1,64,16 to 256,200,0,8
40 logic=back : A=0 : C=1
50 X1=160+sin(A/21.6)*95
60 X2=160+sin(A/16.6)*95
70 Y1=58+cos(A/22.6)*40
80 Y2=58+cos(A/12.6)*40
90 ink C : C=(C mod 14)+2
100 draw X1,Y1 to X2,Y2
110 scroll 1 : screen swap
120 wait vbl : inc A
130 goto 50

SIN WAVE BOXES

10 curs off : hide on : key off : mode 0
20 palette $0,$11,$577,$377,$177,$375,$573,$771,$750,$730,$700,$702,$703,$705,$727,$747
30 def scroll 1,64,16 to 256,200,0,8
40 logic=back : A=0 : C=1 : A=musauto(start(5),1,7858)
50 X1=160+sin(A/21.6)*95
60 X2=160+sin(A/16.6)*95
70 Y1=58+cos(A/22.6)*40
80 Y2=58+cos(A/12.6)*40
90 ink C : C=(C mod 14)+2
100 bar X1,Y1 to X2,Y2
110 scroll 1 : screen swap
120 wait vbl : inc A
125 if inkey$=” ” then A=musauto(0,0,0) : stop
130 goto 50

FILL UP THE SCREEN WITH TILES

10 key off : hide on : curs off : flash off : mode 0
20 rem RESERVE BANK AS SCREEN AND ASSIGN LOGIC TO IT
30 reserve as screen 7 : logic=7
40 rem PLACE SPRITE TILE ON SCREEN AND MAKE A COPY OF IT
50 sprite 1,0,0,1 : put sprite 1 : wait vbl : sprite off
60 rem COPY THE TILE BLOCK TO A variable
70 T$=screen$(logic,0,0 to 16,16)
80 rem START OF LOOP
90 for X=0 to 330 step 16 : for Y=0 to 199 step 16
100 rem PLACE COPYS OF TILE AT CO-ORDINATES X AND Y
110 screen$(logic,X,Y)=T$
120 rem END LOOP
130 next Y : next X
140 rem SET SCREEN BACK TO NORMAL AND SHOW THE TILE PICTURE
150 logic=physic : screen copy 7 to physic

This routine fills the screen with copies of a sprite which has been copied on screen so it can be grabbed into a variable with SCREEN$. The sprite has to be a size of 16×16 pixels so the loop can make copies of it fit evenly onto the screen. The size could be changed but it must be in sizes of 16 so you could copy a 32×32 sprite block if you wish. This makes sure the loop can fit it into the screen perfectly. Note the step size is that of the sprite size. I’ve also got it to build it up in a memory bank so you don’t see it build up on screen. This is quite fast but you could change it to grab a tile block from a screen in memory instead of the copied sprite block.

SIMPLE TEXT SCROLLER

10 rem SCROLLING TEXT LINE
20 :
30 rem SET SCREEN
40 key off : mode 0 : curs off : hide on
50 :
60 rem DEFINE SCROLLING AREA
70 Y=ygraphic(10) : Y1=ygraphic(11)
80 def scroll 1,0,Y to 320,Y1,-4,0
90 :
100 rem DEFINE TEXT TO SCROLL
110 T$=”This is a simple scrolling routine which scrolls text in a variable across the screen……………………………. “
120 :
130 rem SCROLL THE TEXT
140 for L=1 to len(T$)
150 locate 39,10
160 print mid$(T$,L,1)
170 wait vbl : scroll 1
180 wait vbl : scroll 1
190 next L
200 rem START AGAIN
210 goto 130

Its more or less straight forward. The use of the ygraphic command converts the text co-ordinates to graphic co-ordinates so the def scroll command knows where to place the scrolling zone. The above example will place the text at co-ordinates at 39,10 so the variable Y sets the top part of the scrolling zone downwards while Y1 sets the bottom part.

Y—————————————————————————-
THE SCROLLING ZONE FOR THE TEXT
Y1—————————————————————————

So Y equals y co-ordinate 10 whilst y1 equals the next line down which is 11. So the thing to remember is Y equals the y co-ordinate where you wish to position the text and Y1 equals the next text line. Try changing the values to see how it works. The loop actually does the scrolling. It works by placing one character at a time at the edge of the screen then scrolling it along by eight pixels then printing the second character at the same co-ordinate and moving that along. It continues this until the contents of the full string (T$) has been printed and scrolled. Its not very easy to explain so the best way to learn it to play around with the routine.

GET COLOUR HEX VALUES FROM A PICTURE IN MEMORY BANK

10 key off : curs off : hide : flash off : mode 0
20 get palette (5)
30 for X=0 to 15 : print hex$(colour(X)) : next X

CHANGING PALETTE VALUES OF PICTURES DRAWN WITH STOS

10 key off : hide : flash off : curs off : mode 0
20 for X=0 to 15 step 10 : paper x : bar X,10 to X+10 : next X
30 rem Coloured boxes on screen, now lets change colours
40 wait key
50 palette $0,$777,$756,$676….etc: Rem put 16 hex numbers on line and
change one or two
60 wait key
70 colour 1,$0 : rem change colour one to black

This method won’t work with a picture saved from an art package. What I think you need to do is poke the new hex value into the screen bank. The first 32 bytes of the bank is the screen palette.

UNPACK AN MBK SCREEN

STOS has two commands for packing and unpacking pictures. These are PACK and UNPACK. The MBK file has been packed with the STOS compact accessory so you need to use the unpack command in your routine to unpack it like so.

10 key off : hide : curs off : flash off : mode 0
20 load”picture.mbk”,5
30 unpack 5,back
40 screen copy back to physic

So in other words, line 20 loads the packed picture into bank five. For MBK files you don’t usually need to reserve a bank first. The unpack command then unpacks the picture to the background screen then the whole screen is copied to the main physic screen. Note you can also unpack a screen into a bank.

NICE FADE EFFECT

10 key off : hide on : flash off : curs off : mode 0
20 rem first set all colours to white
30 wait 10
40 fade 5,$777,$777,$777,$777,$777,$777,$777,$777,$777,$777,$777,$777,$777,
$777,$777,$777,$777
50 rem wait for fade to happen
60 wait 80
70 rem now fade colours back to present palette
80 fade 5,$523,$777,$0,$123,$232,…etc

FIND WHICH KEYS ARE ASCII CODES AND WHICH ARE SCANCODES

10 key off : hide on: curs off
20 print”press a key”
30 c$=inkey
40 if c$=”” then goto 30
50 if not(scancode) then print”This is an ascii character” else the scancode
for this key is “;scancode
60 goto 20

PRINT CONTENTS OF A FOLDER

10 key off : hide on
20 dir$=”DATA”: rem name of folder
30 print all files to screen
40 P$=”.“: N$=dir first$(P$-1): if N$=”” then end
50 print N$
60 repeat
70 N$=dir next$
80 print N$
90 until N$=””
100 dir$=”A:”: rem close folder and default back to root directory
110 rem print contents of folder on printer
120 dir$=”DATA”
130 ldir
140 dir$=”A:”

GET RID OF THE MISSING LINK REGISTRATION REMINDER MESSAGE

In the full version of missing link you get a third extension (EXS) which contains a command “mostly harmless” to gets rid of that message. Type out this routine.

10 A=mostly harmless (1,2,3,4,5)
20 put key “NEW”

Save this in the root directory (not in a folder) of your STOS disk under the name of ‘autoexec.bas’. Now when you load STOS this file will run, a message will appear saying ‘You got it’ and the NEW command pops up. Press return and the message has gone.

PASSWORD ROUTINE THAT STORES IN A VARIABLE

10 key off : hide on : curs off : mode 0
20 locate 0,10 : centre”Please enter the password.”
30 A$=input$(5) : rem password is five characters long
40 if A$=”POWER” or A$=”power” then locate 0,12:centre “Okay, loading.” else locate 0,12: centre”That is not the password, try again.” : goto 30

SCREEN UNPACKING TIP

Normally when you unpack a screen from a bank, the screen palette changes. The method to fix it is to use the missing link “floodpal” command like this:

10 key off : flash off : curs off: mode 0
20 reserve as screen 5 : unpack 4,5 : floodpal 0 : wait vbl
30 get palette (5) : screen copy 5 to back : screen copy back to logic

The wait vbl is important in this routine.

Thanks to Tony Greenwood for this tip.

HAVE SOMETHING HAPPEN AFTER TWO HOURS

10 time$=”10:00:00″
20 repeat
30 until time$=”12:00:00″
40 print “Two hours in real time have passed.”

SIMPLE SPELL CHECKER

How this routine works is to hold a list of words in arrays and check each word of the document against the ones in the arrays. In the spell checking part of a WP, all words are stored in alphabetical order, so first we can store a list of words beginning with A in a data statement. We can then use the SORT command to put them in order then the MATCH command to check each word in the document against the words in the array. Assuming each word of the document is held in an array then this routine does the checking.

10 rem A$ array holds all words in doc, B$ array holds words to check
against
20 dim B$(3)
30 for X=1 to 10 : read B$(X) : next X
40 sort B$
50 rem Check all words in doc against words in B$
60 inc W : W$=A$(W) : POS=match(B$(0),W$)
70 if POS<0 then goto 90
80 if W<10 then goto 60
90 rem WORD NOT FOUND
100 for X=0 to 2 : print B$(X) : next X
110 data”love”,”lovely”,”lover”

What happens here, is that the SORT command puts the words you want to check against the doc in alphabetical order, then the W$ variable gets each word of the document and checks it against the sorted word array (B$). If POS is less than nought then the routine has found a word it doesn’t understand and will print out the list of words it does know. What you can do for speed is just list the words beginning with the first letter of the word that the routine couldn’t find. Like this.

120 rem A$ holds all words beginning with A
130 if left$(W$,1)=”a” then goto 140
140 for X=0 to 2 : print B$(X) : next X

RPG AND ADVENTURE GAME EXITS ROUTINES

The quickest way of reading things like exits and such in a maze of rooms is to store all the info in arrays, then check which room the player is in and set zones in that room.

10 key off : curs off : mode 0
20 dim MAP(5,4) : dim XZ1(5,4),YZ1(5,4),XZ2(5,4),YZ2(5,4) : ROOM=1
25 rem SET UP MAP EXIT VALUES
30 for X=1 to 5 : for Y=1 to 4
40 read MAP(X,Y)
50 next Y : next X
52 rem SET UP ZONE CO-ORDINATES FOR EACH ROOM
55 for X=1 to 5 : for Y=1 to 4
66 read A,B,C,D
70 XZ1(X,Y)=A : YZ1(X,Y)=B : XZ2(X,Y)=C : YZ2(X,Y)=D
75 next Y : next X
76 rem DRAW EXIT BOXES AND INFO OF WHERE EACH ONE GOES
80 home : print “ROOM”;ROOM : locate 0,6
90 for X=1 to 4
100 box XZ1(ROOM,X),YZ1(ROOM,X) to XZ2(ROOM,X),YZ2(ROOM,X)
110 set zone X,XZ1(ROOM,X),YZ1(ROOM,X) to XZ2(ROOM,X),YZ2(ROOM,X)
115 print “EXIT”;X;” GOES TO ROOM”;MAP(ROOM,X)
120 next X
125 rem WAIT FOR PLAYER TO CHOOSE A ZONE
130 repeat
140 EXIT=zone(0)
150 until EXIT<>0 and mouse key=1
155 rem SET ROOM VALUE TO NEW ROOM
160 ROOM=MAP(ROOM,EXIT) : goto 80
1000 rem EXIT VALUES FOR EACH OF THE FIVE ROOMS IN MAZE
1010 data 2,3,4,5
1020 data 1,2,3,4
1030 data 2,1,3,4
1040 data 3,2,1,5
1050 data 1,2,3,4
2000 rem ZONE CO-ORDINATES FOR ROOM ONE
2010 data 10,20,20,40
2020 data 30,20,40,40
2030 data 50,20,60,40
2040 data 70,20,80,40
2060 rem ZONE CO-ORDINATES FOR ROOM TWO
2070 data 10,20,20,40
2080 data 30,20,40,40
2090 data 50,20,60,40
2100 data 70,20,80,40
2120 rem ZONE CO-ORDINATES FOR ROOM THREE
2130 data 10,20,20,40
2140 data 30,20,40,40
2150 data 50,20,60,40
2160 data 70,20,80,40
2170 rem ZONE CO-ORDINATES FOR ROOM FOUR
2180 data 10,20,20,40
2190 data 30,20,40,40
2200 data 50,20,60,40
2210 data 70,20,80,40
2220 rem ZONE CO-ORDINATES FOR ROOM FIVE
2230 data 10,20,20,40
2240 data 30,20,40,40
2250 data 50,20,60,40
2260 data 70,20,80,40

In this routine we have five rooms in the maze, each with four exits which all lead to other parts of the maze. The MAP array works like this: the variable ROOM holds the number of the players position in the maze, in other words the room number. The first set of data statements allow us to specify which exit leads to which room. For example….

10 read MAP(1,1),MAP(1,2),MAP(1,3),MAP(1,4)
20 data 2,3,4,5

This means that exit one leads to room two, exit two leads to room three and so on. When you run this routine you will see four boxes on screen, representing four zones, or exits in this case. Clicking the left mouse key
in a zone will set the variable ROOM to the new destination room. With this method you can easily tell where you are just by reading the ROOM variable. With this you can call up the part of the maze you want.

100 screen$(logic,16,0)=R$(ROOM)

The arrays XZ1, YZ1, XZ2, and YZ2 hold the co-ordinates of the exit boxes on screen. The format goes:

XZ1(ROOM,EXIT)

So we can set up four zones in the present room using the SET ZONE command then check which zone the player chooses. The exit zones could be four arrows pointing in four directions. Using this method you can check what’s on screen in this method. For example, if the player clicked on a baddie in order to fight him, then you could say that the baddie is in room three and is in zone two, and check like this.

10 repeat
20 CH=zone(0) : wait vbl
30 until CH<>0 and mouse key=1
40 if ROOM=3 and CH=2 then gosub 1000

Where line 1000 onwards holds the routine for fighting the baddie.

BANK STACKING

Think of a large box, this allows us to put more than one item into it. It’s the same with banks, we can actually set the size of it then load the files into it one after another. This method with stack PAC pictures.

First make a note of the length of each PAC file then add them all together, then add about twenty bytes and make it an even number. You then choose a bank and reserve it to this size.

10 reserve as data 5,80000

Note reserving a work bank makes it a temporary bank while reserving a data bank means it can be saved along with your program.

Load the first file in like this.

20 load”pic1.pac”,start(5)

Now the next thing to do is load the next picture into the position where the last picture ends. So, get the length of the first file and make it into an even number. For example, if the file is 1787 bytes long then call it 1790 bytes long. We can now load the second file in, in front of the first file just like this.

30 load”pic2.pac”,start(5)+1790

After this we just take the length of the pictures already loaded and load the next picture in. For example, let’s say our pictures are like this.

PIC1.PAC LENGTH 1787 ROUNDED TO EVEN 1790
PIC2.PAC LENGTH 2136 ROUNDED TO EVEN 2140

We take these two values and add them together, which makes 3930. If the value is an odd number then you must make it even. We can then load this file in.

30 load “pic3.pac”,start(5)+3930

Do the same with the other files already loaded, add them together and round them up to even numbers to find where to load the next picture in. To get at them, all you have to do is this.

40 unpack 5 : rem unpack the first picture
50 unpack start(5)+3930 : rem unpack picture three

There is an easier method if you have the missing link extension. This has two commands called BANK LOAD and BANK COPY. Use the MAKEBANK program on the source disk to load all files and save them as an FBANK with the extension BNK. You can then load and use them like this. PICNO is Picture Number.

10 mode 0 : key off : flash off : curs off
20 PICNO=1
30 reserve as work 5,80000
40 bload”pics.bnk”,5
50 reserve as work 6,9000
60 bank copy start(5),start(6),PICNO
70 unpack 6

This copies the specified picture from the stacked bank into bank six and unpacks it to the screen. You can use this method with the smaller files but it tends to corrupt some larger ones. The first method however should work with all files.

In case you were wondering, the BANK LOAD command allows you to load a file from a stacked bank on disk.