
 PILOT-IN-BASIC for Altair 680 BASIC 1.1
		based on
PILOT INTERPRETER FOR CBM 8-BIT COMPUTERS
	   BY MICHAEL TINGLOF

As presented in COMPUTE! magazine, Dec. 1982, iss. 31.

Converted to and augmented for Altair 680 BASIC as implemented on the Hassler's Monster 6800 (HM-68) homemade computer by Dave Hassler, Feb. 2024.  This documentation also by Dave Hassler, borrowing from Tinglof's article.
(HM-68 plans and software are at www.vanportmedia.com/hm68)

INTRODUCTION

	The "VIC and PET PILOT Interpreter" contains all of the "core" statements of PILOT as described by its author, Dr. John Starkweather, in 1973.  In addition, there is facility for making mathematical comparisons and enhanced matching capability.
	The system requires 32KB of RAM from $0000 to $7FFF on the HM-68 (or similar homebrewed machine) and Altair 680 BASIC 1.1.  This allows for PILOT programs/scripts up to 8K in size.  Further, the interpreter can accept up to 200 lines of PILOT instructions, allowing for an average of 41 characters per line.
	 PILOT is an acronym for Programmed Instruction, Learning, or Teaching.  Originally designed for computer-aided instruction (CAI) in the late '60s, it allowed non-tech-savvy instructors (of that time) to simply develop CAI lessons, and for young students to learn the basics of programming by using the conversational manner of the language.
	The PILOT-IN-BASIC program is organized into two sections: the editor and the interpreter: the former provides an environment to write, edit, save, and load PILOT programs/scripts; the latter is the runtime environment for those programs.  A third part of the overall package is the tokenizer.  The tokenizer takes a plain text file of a PILOT program/script and transforms it into a machine-readable set of data that can be loaded and run from PILOT-IN-BASIC.
	The format for preparing user programs 'off-line' is the same as working in the in-program editor, with two additional requirements:
	1) the program must end with   199 R:
	2) the text file must use only CR for line endings.
	This is the internal PILOT-IN-BASIC format, which is also the way the Apple Macintosh saves text files; Windows/DOS is CRLF, while straight UNIX is LF only.  Most modern text editors will allow the user to select the type of line ending for a given file.


INITIAL SET UP

	After loading Altair 680 BASIC, when the MEMORY SIZE? question comes up, set the limit at 22822.  Also, you must answer 'Y' to the trig question.  This sets aside about 9K above BASIC and the PILOT interpreter, which allows for the SAVE and LOAD commands, and it's required for PILOT-IN-BASIC to work correctly.  While the trig functions are not used by PILOT-IN-BASIC, this sets the bottom of user RAM correctly for the PILOT-IN-BASIC S record file.

To load via the supplied PILOT-IN-BASIC S record file:
	1) break out of BASIC
	2) load the S record via the SWTBUG monitor L command
	3) enter $18F3 into locations $7A/7B, then $2A1D into $7C/7D, $7E/7F, and $80/81
	4) warm start BASIC from the vector at $0007 by entering 'J 0007'
	5) type RUN at the BASIC 'OK' prompt

A memory use table:
	$0000-1AFF: Altair 680 BASIC ($F0 used as a 1-byte input buffer)
	$1BFC-2A1D: PILOT interpreter in BASIC
	$2A1E-5926: PILOT scripts/programs and BASIC variables
	$5E00-7DFF: Transfer area for SAVE and LOAD
	$7F00-7F7F: SWTBUG scratch RAM
	$7F80-7F96: Altair BASIC I/O patch
	$7FA0-7FA5: PILOT input routine (equivalent to GET$)


THE EDITOR

	Unlike standard PILOTs, this version makes use of line numbers, a holdover from the Commodore version to keep the structure of the interpreter coherent.  Line numbers may be from 1-198, and line length must be less than 72 characters.  This should not be a serious limitation, as the longest PILOT program I have seen so far sits at 122 lines.
	While the internal Editor is functional, it is not particularly efficient.  Much easier is to write programs and scripts off-line in a modern text editor, then later load that file into PAL PILOT.  See the Tokenizer section, below, for details.
	In any case, back to the Editor....
	A line of script/program text is entered into a BASIC string array called L$(x).  As expected with BASIC, the backspace key is recognized and *appears* to work as a line is entered, but it is NOT destructive. ASCII 08 is simply added to the string when you press backspace or delete.  If a mistake is made during line entry, or you want to make a change in a line, simply press <RETURN> and type it over (unless you want to embed non-printing ASCII...).  You can insert new lines between existing lines, but there is no facility for renumbering, other than typing a line over on a fresh line.  Skipping line numbers by 2 or 3 during initial program entry should be sufficient.

	From the Editor, a user may issue the following commands:
	LIST  - Lists the script/program lines, churning through all 199 elements of array L$(x) each time.  If the listing runs off the screen, use your terminal's scrollback buffer to see earlier lines.  Program text may also be saved in this manner (but not for later loading) by capturing the text of a listing.
	RUN   - Executes the program in memory.
	SAVE  - Interprets the tokenized program lines and places them in memory sequentially starting at $5E00 in a format allowing the making of an S record file or audio save.
	LOAD  - Brings in a previously saved script and fills L$(x).
	NEW   - Clears user memory and cold starts the interpreter. If not issued before loading a new program, the new program script will be merged with the one already in memory.
	BASIC - Exits the interpreter to BASIC.

	Loading programs works like this (PILOT already loaded and running): 
	A) Drop out of PILOT with the BASIC command.
	A) Break out of BASIC via the reset switch on the HM-68.
	B) Load the PILOT script/program S record file at $5E00.
	C) Warm start BASIC at $0007.  
	D) Type RUN. 
	E) Issue the PILOT interpreter's LOAD command.  LIST or RUN.

	Alternatively, you can load the script you want run right after you load in PILOT-IN-BASIC (but after you start Altair BASIC with limited memory, of course).

	Saving programs is similar.  The SAVE command will save L$(x) in a tokenized format and report the end-of-program address, in decimal.  Issue the BASIC command, then use the reset button on the HM-68 to break out of that, then go save memory from $5E00 to end-of-program-plus-1 in the usual manner.  When you want to go back to the PILOT interpreter, warm start BASIC via $0007 and enter PILOT via GOTO 40 instead of RUN; this is the PILOT warm start point. 
	A final thought on loading: I tried all kinds of different character and line delays to do a simple ASCII upload of a PILOT program, but never got it to work satisfactorily or consistently.  My guess is that having a high-level language interpreter inside *another* high-level language interpreter is just too much for a regular text upload at any speed or delay.  That's why I wrote a simple "tokenizer" program that will accomplish this outside of PILOT-IN-BASIC (see below).


THE INTERPRETER

Variables

	Variables are either string ($) or integer (#), with the type symbol preceding a single letter A-Z.  Variable #R is a special case: when encountered in an expression, a pseudo-random number between 0 and 1 will be returned in #R.  E.g., C:#A=#R*6+1 places a value 1-6 in #A.  String variables should be less than 40 characters in length.

Statements

	A: - Accept	Inputs a response from the user.  If no variable
		is given, the response is stored in a buffer that can be
		used by the M: statement.

		8 A:		put response in buffer to test
		12 A:#H		put response in integer var. H
		14 A:$T		put response in string var. T

	C: - Compute	Performs arithmetic (+ - * /) in a linear,
		left-to-right order without parentheses.

		5 C:#N=2+#G*8+12/4-5	given #G=3, #N=8

	E: - End	Marks the end of a subroutine.
		Same as BASIC "RETURN".

	I: - If		A non-standard statement that allows for 
		mathematical comparison. = < > are acceptable operators.

		26 I:#N<12      if true, sets Y flag, else sets N flag.
		26 I:#A=#B	if true, sets Y flag, else sets N flag.

	J: - Jump	Transfer execution to a specified place in the
		script, marked with a label or a line number, the 
		latter of which is non-traditional.

		133 J:*ROLLDICE		sends control to *ROLLDICE area.
		14 J:22			sends control to line 22.

	M: - Match	Compares a string variable or the Accept buffer
		for any keywords specified.  The element to match does
		not need to be first in the string; it can be anywhere.
		Both of the following responses will set the Y flag:

		15 A:		user: I AM GOOD, THANKS
		17 M:GOOD	user: GOT ANY GOODIES, PAL?

		Placing a space after GOOD will not match with GOODIES.

		22 T:HOW DO YOU FEEL TODAY:
		25 A:
		28 M:BAD, CRAP,SAD ,ANGRY

		The Y flag will get set on user input of:
		BAD and I FEEL CRAPPY and I'M NOT SAD OR UPSET
		but not these: I AM SAD or CRAPPY

	R: - Remark	Insert a remark here.  Will be ignored by the
		interpreter.  Just like BASIC's "REM".
		
	T: - Type	Outputs text and variable values to the screen,
		and both lower case and upper case letters are OK to use.
		If the statement ends with a semicolon, no carriage
		return or linefeed will occur (as in BASIC).  T: alone
		will print a CRLF.

		10 T:A LINE OF TEXT. TELL ME YOUR NAME: ;
		15 A:$N
		20 C:#J=42
		25 T:
		30 T:DEAR $N, THE VALUE OF J IS #J.

	U: - Use	As in, "Use the following subroutine module."
		Calls a subroutine via a label or line number.  The
		next line in the program is stored for E:.
		
		66 U:*TEST7	 to subroutine with label *TEST7
		14 UY:22	 to routine at line 22 if Y flag true.
	
Other Elements
		
	END - 		The last statement of the program should be 
		the single word END.

		190 END

	Y and N - Conditionals   May be placed after any statement
		letter.  Based on the results of the M: or I:
		statements, a flag will go up in the Y or N conditional
		registers.  If a conditional is specified/follows a
		statement letter, that statement will execute only if 
		the flag is present.

		42 A:		--> user enters SNAKE
		44 M:DOG,CAT 
		46 TY:THOSE ARE POPULAR PETS.
		48 TN:WOW - THAT'S A RARE PET!

		Also quite useful for conditional jumps and arithmetic.

	*LABELS - 	A label should appear alone on its own line 
		number, at the start of a part of the script that J: 
		and U: statements will branch to.

		15 *BRANCH1
		    . . .
		90 JY:*BRANCH1

	Error Messages - Two kinds: Run Time and Editor.  The editor
		will relay only if a statement is unknown or improper,
		and if a line number is out of range.
		In run time, seven errors will be reported, with the
		line number on which it occurred:

			1 - Variable name (not a single char.)
			2 - Unknown label
			3 - Stack overflow (too many subroutines)
			4 - Stack empty (no return address)
			5 - Bad format (syntax)
			6 - Div. by zero
			7 - Num. out of Rng (<-32767 or >32767)


THE TOKENIZER

	To use, load the tokenizer S record file at $0100.  Set your serial terminal emulator's ASCII text upload delays to no less than 15 ms for characters and 150 ms for the line; you may need more time than that (I get flawless uploads at 20/300).  Then, run the tokenizer.
	Select and upload your prepared PILOT-IN-BASIC script.  The text file *must* use only a carriage return for the end-of-line character; UNIX's LF-only, or Win/DOS's CRLF will not work with this program.  Most modern text editors allow you to change a document's line-ending style.  Also, the format of the text file must follow the following convention:

	linenumber<space>token[conditional]<colon>bodytext

	E.g.,  15 T:Hello, World!     or      114 JY:*LABEL

	Sometimes, the program (which could use improvement) will quit showing the ending address of the data, or show it in the terminal emulator's transfer window.  Sometimes, it won't, but the data is still there - just look in locations $E1 and $E2 for the end address of the conversion, plus 1.  Data always starts at $5E00.  From there, you can punch out an S record.  Here's how to use your 'tokenized' file with PILOT-IN-BASIC (this also goes for programs your wrote in the PILOT editor and SAVEd from PILOT):

	1. Load BASIC, run it, and limit it's user RAM
	2. Break out of BASIC with the RESET button on the HM-68
	3. Load a tokenized PILOT script/program (an S record)
	4. Load PILOT-IN-BASIC via S record, as in the INITIAL SETUP section
	5. Set the memory pointers and enter BASIC via warm start (J 0007)
	6. type RUN, then once in PILOT, type LOAD

	Here's a chart of how PILOT-IN-BASIC stores its data:

	RECORD FORMAT:

	POS 1: The PILOT line number (in hexidecimal).
	POS 2: The statement/token code.
	POS 3 to C/R-1: The object of the statement.
	LAST POS: C/R = end-of-record marker.
	FINAL: $FF = end-of-file marker.

	E.g.,	3 T:AN ANIMAL?
		5 A:
		7 M:TIGER
		9 END
	
	 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 
	 --------------------------------------
	 03 01 41 4E 20 41 4E 49 4D 41 4C 3F 0D
	  3  T  A  N     A  N  I  M  A  L  ? CR

	 0D 0E 0F
	 --------
	 05 07 0D 
	  5  A CR

	 10 11 12 13 14 15 16 17
	 -----------------------
	 07 05 54 49 47 45 52 0D
	  7  5  T  I  G  E  R CR

	 18 19 1A 1B 1C 1D
	 ------------------
	 09 45 4E 44 0D FF
	  9  E  N  D CR EOF

	Finally, here's a statement token chart:

	STMT:	T:  J:  E:  U:  M:  C:  A:  I:  R:
	NMBR:	1   2   3   4   5   6   7   8   9
	TOKEN:	01  02  03  04	05  06  07  08  09   +00
	T YES:	0B  0C  0D  0E	0F  10  11  12  13   +0A (#10)
	T NO:	15  16  17  18  19  1A  1B  1C  1D   +14 (#20)

	LABEL MARKER:  $2A = '*'


CONCLUSIONS

	I hope you enjoy using -- and maybe improving -- PILOT-IN-BASIC.  I had a lot of fun modifying this from the original 1982 VIC-20 program, and coming up with a way to save and load programs, and how to use plain text files for easier program development.  It should also be possible to modify PILOT-IN-BASIC to run inside TSC BASIC 2 or Extended BASIC, as long as one has about 20 KB of RAM left after loading BASIC.
	To show what PILOT can do, I've included in the package a sample script written in the '70s by a couple of Stanford grad students, plus a take on the NIM game, and a guessing game from Mark Tinglof's original article.  There are also Tiny PILOT games that can easily be converted to PILOT-IN-BASIC's format ... and likely expanded upon.
	Due to the interpreter sitting inside *another* interpreter, it's pretty slow.  However, I don't think that a 6-year-old child would mind (my inner 6-year-old doesn't, really!).  It's a fun language with which to learn some basic programming concepts, and due to its conversational/dialog-driven nature, actually quite useful.  There are modern versions that run on modern OSs: psPILOT for Windows Power Shell and RPILOT (UNIX) are two.
	Another point about the slowness: if you're a fast typist, it's quite easy to break the interpreter while it's running a program.  Take your time, be deliberate (15-20 wpm), and it'll work fine.
	As for the Tokenizer, it works, but on on my serial terminal emulator (minicom), when the program is done, the ending address of the tokenized file shows up in the transfer window, not on the main screen.  Odd.
	If you have a disk drive, cassette interface, or some other storage medium, lines 500-699 do the loading and saving, and could be added there.
	In researching this language, I do not know how much of Mike Tinglof's work is indebted to Dave Gomberg, who wrote PETPILOT early in 1979.  If anyone can find a copy of this program I'd love to see it.

	Have fun PILOTing the friendly skies!
