Wednesday 6 April 2016

The Joys of 10 Line BASIC Programming

A real MC-10 with the basic kit
It's been a while since I posted. I have been busy mostly with creating 10-liner games for the NOMAM competition. The competition results came in and I was able to crack the top 10 in a number of categories. I think this is something to be reasonably proud of since the MC-10 is such a modest 8-bit computer and the competition included MSX systems, the Commodore 64 and the latest of the Atari 8-bit line, along with all their bells and whistles, including updated versions of BASIC. That being said, I too used a few tricks involving an updated version of Basic for the MC-10 called MCX Basic. This extension to the language by Darren Atkinson adds all kinds of commands. However, it is not compatible with a regular MC-10 without using add-on hardware or lots of fancy loading of special software. I generally want to stick to writing programs for an ordinary MC-10 so I only used MCX (under the emulator) to allow me to create programs with lines longer than the normal 128 character limit. It's nice to have the space to cram just a few more things onto a single line if I need. Of course I can already do this (somewhat) by replacing PRINT commands with questions marks ("?"). When these get expanded to full PRINT commands the line can go over 128 characters. Using MCX I can get lines almost up to 255 characters long and regardless of how they are entered, programs with long lines load just fine in a regular MC-10.

The 10-line programs I ended up submitting to the competition were the following:
  1. MINIPAC (version of Pacman arcade game)
  2. AREA51 (text adventure)
  3. CAVMARS (descent in a randomly generated cave, while collecting fuel from the sides)
  4. KONG (version of Donkey Kong arcade game)
  5. MINDUNG (3D first person dungeon crawl)
  6. DASH (Puzzle game based loosely on the arcade game Boulder Dash)
There were difficult challenges to fit these programs into only 10 lines each. I had to really refine some techniques to reduce the number of lines used. These techniques included new ways to process key input that don't require use of multiple IF statements and techniques using ON-GOTO commands, arrays and pointer variables and variable assignments combined with logical tests to accomplish multiple tasks, so that multiple IF statements could be done away with.

In regard to key input, I generally used a technique I've discussed before of using variable assignment commands with logical operators embedded in them. So a command like this:

I$=INKEY$:X=X+(I$="A"):X=X-(I$="S"):Y=Y+(I$="W"):Y=Y-(I$="Z")

will allow X and Y to be modified continuously depending on which of the standard cursor keys are pressed on the MC-10. If you need boundary checking this can also be added:

X=X+(I$="A"ANDX>0)

will only change the value of X if it does not drop below 0. This method takes advantage of the fact that logical operations return either 0 if false, or -1 if true on the MC-10 (I think some non-Microsoft Basics used 1 for true). This is why I have to subtract from Y in the example using (I$="Z"). When Z is pressed we want to move forward/downward one space, so we must negate the -1 returned by the operation to get a positive value added to X. If you need to modify your input by values other than 0 (i.e. no modification) or + or -1 just times the result by some value. Sometimes, for example, it might be speedier to have a single POKE or PRINT@ location for a moving object, and then changes its motion to +-1 for horizontal motion, or +-32 for vertical motion. In such a case you can just use:

POS=POS-(I$="Z")*32

to get the right kinds of changes to your object's position. Remember, if it turns out to be false the 32 will be times by zero resulting in nothing being added to POS. If you need bigger jumps just use bigger numbers (i.e. *2 in the horizontal, or *64 in the vertical).

This kind of method can save a lot of use of IF statements for boundary checking and determining which keys have been pressed.

The other method of doing multiple IF/THENs on one line that may not even be related to a single function is to change variables to some desired value, do a check using an ON-GOTO function, and then change those values back to what they were before the test before proceeding onto other variable changes and checks in the line. So, for example, you can have a line like this:

9 TEMP=A:A=NEWA:ON-(B>10)GOTO1:A=TEMP:TEMP=C:C=NEWC:ON-(D=1)GOTO2:C=TEMP

In this example line 9 can assign a new value to A and then branch to line 1. It can also assign a new value to C and proceed to line 2. As long as you have a good awareness about when the conditions you are searching for are triggered, it will be possible for you to construct lines that do a multiplicity of checks, variable changes and branchings and even other possible actions (sound events for example), even if these have nothing to do with each other.  With the use of the MCX 255 character line technique, you can pack a lot of decision making activity into a single line.  I had to use this technique a lot in my 10 line adventure game AREA51. Text adventures need to engage in lots of decision making and event triggering.

By using lots of array variables, loaded with different stuff in their various numbered slots, you can mimic lots of event decision simply by changing certain pointer variables to those slots in the array variable. For example, you can change whether a win or lose message is printed at the end of a game by changing the variable WINSTATUS used in an array WINMSG. If WINMSG$(0)="YOU LOSE" and WINMSG$(1)="YOU WIN" all you need to do is PRINTWINMSG$(WINSTATUS) at the end and make sure that WINSTATUS is set appropriately somewhere in the program, such as in one of the densely packed decision lines.  In general, I had to use lots of arrays and lots o pointer variable in these programs, but hey the limit was just about the number of lines used, not the amount of memory wasted!  I was also able to use variation on the techniques above used for processing key input to change the pointers values to array locations.  So you could do something like this in regard to the WINMSG$ array. WINSTATUS=-(DEAD=1).  Such a construction allows for something to be checked and an event like printing the right message at the end of a program to be done without having to use a line wasting IF command.  The MC-10 doesn't have an ELSE command so any IF command will utilize one whole line just for itself.

By using the variable assignment structure of A=B with B replaced by a bracketed logical operations with the appropriate sign in front of it and multiplied by whatever values besides 1 that are required, along with arrays and point variables, you can fit a lot of actions into a single line. My sense is that these techniques really move Basic to being a lot like assembly language or higher level languages like C.  If that's so, I guess I should really get off my duff and learn some of these other languages, instead of just persisting in my use of Basic.  My fellow MC-10er Greg (phyber0pt1k) from the MC-10 group on Yahoo, for example, has generously created a whole set of machine language lessons (very professionally done I might add) to entice people like me into the joys of assembly language coding. It is a very generous contribution to the group on his part.  I certainly recommend it to anyone with an interest (they're in the "Greg Folder" in the files section of the group). For me though, programming is more like knitting.  Porting the existing Basic code from some other machine or writing my own small programs (the 10 line thing has been very nice) is something I can almost do without thinking while sitting with my wife in our den as she watches curling or the news in the evening.  I don't think this would be possible while learning assembly, so I unfortunately have to pass on Greg's generosity, at least for the time being.

I'd like to thank the organizers of the 10-liner competition and especially Gunnar, for all the work they put into running, judging, and publishing the results of the competition. They had over 80 entries, which must have been a lot of work to get running (on various emulators) and then to judge. The large turnout is an indication of the vibrancy of the retrocomputing hobby. Here are some links to videos of my entries which I haven't already discussed or shared somewhere else in this blog:

CavMars
Kong
Area51

In my next postings I'll discuss some of my most recent ports from other computers (i.e. code scavenged from the net) and some games inspired by the suggestions/visual mock-ups of a Brazilian Coco clone user from back in the day, Erico Monteiro.

No comments:

Post a Comment