array about_script -->
	"About baZic"
	"cls"
	"print:print:print"
	"print ~baZic is a downright scary implementation of ~;"
	"print ~Basic for the Z-machine. It features proper dynamic ~;"
	"print ~memory allocation, mark-sweep garbage collection, ~;"
	"print ~fully tokenised program storage, a built-in program ~;"
	"print ~editor (cough, cough) and is almost entirely useless. ~;"
	"print ~It is complete enough to play Hunt the Wumpus on, and ~;"
	"print ~a copy is provided.~"
	"print"
	"print ~The language is not complete. I gave up after a certain ~;"
	"print ~point when I realised that Basic is so crappy a language ~;"
	"print ~that it's not fun to implement, just annoying. I am now ~;"
	"print ~even more impressed with the authors of things like 8kB ~;"
	"print ~Microsoft Basic and BBC Basic; impressive work.~"
	"print"
	"print ~The main lacks to baZic are string operations, proper arrays, and ~;"
	"print ~subroutines. The bulk of the string code is in there --- the ~;"
	"print ~scary garbage collector --- but I haven't done the string ~;"
	"print ~operators themselves. Arrays are sort of implemented, but they're ~;"
	"print ~done by munging the variable name with the index. (See the Wumpus ~;"
	"print ~program for an example.) Subroutines just haven't been done.~"
	"print"
	"print ~If you're interested in the innards of the program, you can do ~;"
	"print ~'list -1' to list the stored Basic program with byte-code, or ~;"
	"print ~'list -2' to view the variables in memory. If you do this while ~;"
	"print ~an array is in use, odd things will happen.~"
	"print"
	"print ~baZic is licensed under the MIT public license. For more information, contact ~;"
	"print ~dg@@64cowlark.com.~"
	"print:print"
	0;
	
array higherlower_script -->
	"Higher / Lower"
	"new"
	"10print ~Higher, Lower~"
	"15print"
	"20target = rnd(100)"
	"30tries = 1"
	"40input ~What is your guess? ~; guess"
	"50guess = val(guess)"
	"60if guess < target then print ~Too low!~"
	"70if guess > target then print ~Too high!~"
	"80if guess = target then goto 110"
	"90tries = tries + 1"
	"100goto 40"
	"110print ~You got it!~"
	"120print ~In only~, tries, ~tries, too.~"
	0;

array wumpus_script -->
	"Hunt the Wumpus"
	"new"
	"10cls"
	"20print ~Hunt the Wumpus --- loading data~"
	"30cave1(0)=1:cave2(0)=4:cave3(0)=7"
	"40cave1(1)=0:cave2(1)=2:cave3(1)=9"
	"50cave1(2)=1:cave2(2)=3:cave3(2)=11"
	"60cave1(3)=2:cave2(3)=4:cave3(3)=13"
	"70cave1(4)=0:cave2(4)=3:cave3(4)=5"
	"80cave1(5)=4:cave2(5)=6:cave3(5)=14"
	"90cave1(6)=5:cave2(6)=7:cave3(6)=16"
	"100cave1(7)=0:cave2(7)=6:cave3(7)=8"
	"110cave1(8)=7:cave2(8)=9:cave3(8)=17"
	"120cave1(9)=1:cave2(9)=8:cave3(9)=10"
	"130cave1(10)=9:cave2(10)=11:cave3(10)=18"
	"140cave1(11)=2:cave2(11)=10:cave3(11)=12"
	"150cave1(12)=11:cave2(12)=13:cave3(12)=19"
	"160cave1(13)=3:cave2(13)=12:cave3(13)=14"
	"170cave1(14)=5:cave2(14)=13:cave3(14)=15"
	"180cave1(15)=14:cave2(15)=16:cave3(15)=19"
	"190cave1(16)=6:cave2(16)=15:cave3(16)=17"
	"200cave1(17)=8:cave2(17)=16:cave3(17)=18"
	"210cave1(18)=10:cave2(18)=17:cave3(18)=19"
	"220cave1(19)=12:cave2(19)=15:cave3(19)=18"
	"225print:input ~Do you want instructions? (y/n) ~; i$"
	"226if i$ <> ~y~ then goto 1000"
	"230cls"
	"240print ~Welcome to HUNT THE WUMPUS!~"
	"250print:print ~The wumpus lives in a cave of twenty rooms. ~;"
	"260print ~Each room has three tunnels leading to other rooms. ~;"
	"270print ~Two rooms have bottomless pits --- don't fall on. ~;"
	"280print ~Two more contain Alien Space Bats. Disturb them, ~;"
	"290print ~and they will whisk you away to some other room. ~;"
	"300print:print:print ~Naturally, the wumpus is immune to all hazards. ~;"
	"310print ~Usually, he's asleep: he'll wake up if he hears you ~;"
	"320print ~shooting an arrow, or if you walk in on him. ~;"
	"330print ~Once awake, he'll move around most turns (1 in 4 ~;"
	"340print ~probability). If *he* walks in on *you*, he'll eat yer. ~;"
	"350print:print:print ~Your only defence is your arrows. These arrows, ~;"
	"360print ~which contain a Z-machine microcontroller, can be ~;"
	"370print ~programmed to follow a certain course for up to five ~;"
	"380print ~rooms. If they can't go where you told them, they'll ~;"
	"390print ~move randomly. Did I mention they'll kill you, too, ~;"
	"400print ~if you program them incorrectly? ~;"
	"410print:print:print ~The wumpus has smelly feet; you can smell him in the ~;"
	"420print ~next room. The bats rustle, you can hear them; the pits are ~;"
	"430print ~drafty, and you can feel that.~"
	"1000print:print ~Placing objects in maze...~"
	"1010wumpus=rnd(20):player=rnd(20):pit1=rnd(20):pit2=rnd(20)"
	"1020bat1=rnd(20):bat2=rnd(20)"
	"1030if wumpus = player then goto 1000"
	"1040if wumpus = pit1 then goto 1000"
	"1050if wumpus = pit2 then goto 1000"
	"1060if wumpus = bat1 then goto 1000"
	"1070if wumpus = bat2 then goto 1000"
	"1080if player = pit1 then goto 1000"
	"1090if player = pit2 then goto 1000"
	"1100if player = bat1 then goto 1000"
	"1110if player = bat2 then goto 1000"
	"1120if pit1 = pit2 then goto 1000"
	"1130if pit1 = bat1 then goto 1000"
	"1140if pit1 = bat2 then goto 1000"
	"1150if pit2 = bat1 then goto 1000"
	"1160if pit2 = bat2 then goto 1000"
	"1170if bat1 = bat2 then goto 1000"
	"1180awake=0"
	"2000print"
	"2010print ~You are in room number ~; player; ~. Exits lead off to rooms ~;"
	"2020print cave1(player); ~, ~; cave2(player); ~ and ~; cave3(player); ~. ~"
	"2030if cave1(player) = wumpus then goto 2070"
	"2040if cave2(player) = wumpus then goto 2070"
	"2050if cave3(player) = wumpus then goto 2070"
	"2060goto 2080"
	"2070print ~You can smell the wumpus!~"
	"2080if (cave1(player) = pit1) or (cave1(player) = pit2) then goto 2120"
	"2090if (cave2(player) = pit1) or (cave2(player) = pit2) then goto 2120"
	"2100if (cave3(player) = pit1) or (cave3(player) = pit2) then goto 2120"
	"2110goto 2121"
	"2120print ~You feel a draught!~"
	"2121if (cave1(player) = bat1) or (cave1(player) = bat2) then goto 2125"
	"2122if (cave2(player) = bat1) or (cave2(player) = bat2) then goto 2125"
	"2123if (cave3(player) = bat1) or (cave3(player) = bat2) then goto 2125"
	"2124goto 2130"
	"2125print ~You hear rustling!~"
	"2130input ~Which room do you want to go to (or -1 to fire an arrow)? ~; i$"
	"2135dest = val(i$)"
	"2140if dest = -1 then goto 3000"
	"2150if (cave1(player) = dest) or (cave2(player) = dest) or (cave3(player) = dest) then goto 2200"
	"2160print:print ~You can't go that way.~"
	"2170goto 2130"
	"2200print"
	"2210if dest=wumpus then goto 2600"
	"2220if (dest=pit1) or (dest=pit2) then print ~*** AAAAAAaaaaaah ***~:print:print ~You have fallen down a pit.~:goto 5000"
	"2230if (dest=bat1) or (dest=bat2) then print ~You have been abducted by alien space bats.~:dest=rnd(20)"
	"2240player=dest"
	"2500if awake=0 then goto 2000"
	"2510i = rnd(4)"
	"2520if i<>0 then goto 2000"
	"2530print ~You hear the patter of tiny feet as the wumpus moves.~"
	"2540i = rnd(3)"
	"2550if i=0 then wumpus = cave1(wumpus)"
	"2560if i=1 then wumpus = cave2(wumpus)"
	"2570if i=2 then wumpus = cave3(wumpus)"
	"2580goto 2000"
	"2600player=dest"
	"2210if awake=1 then print ~*** CRUNCH ***~:print:print ~You have been eaten by the wumpus.~:goto 5000"
	"2620awake=1"
	"2630print ~The wumpus is here! Asleep, though it won't stay like that for long.~"
	"2640goto 2000"
	"3000print"
	"3005arrow=player"
	"3010for i=1 to 5"
	"3020input ~Please enter the next room for the arrow to go to: ~; i$"
	"3025j = val(i$)"
	"3030if (j = cave1(arrow)) or (j = cave2(arrow)) or (j = cave3(arrow)) then arrow=j:goto 3071"
	"3040j = rnd(3)"
	"3050if j = 0 then arrow = cave1(arrow)"
	"3060if j = 1 then arrow = cave2(arrow)"
	"3070if j = 2 then arrow = cave3(arrow)"
	"3071if j = wumpus then print:print ~You hear a distant scream... the wumpus is dead! Now you just have to deal with the RSPCA lawyers.~:goto 5010"
	"3080if j = player then print:print ~You have just been impaled on one of your own arrows.~:goto 5000"
	"3090next"
	"3095awake=1"
	"3100goto 2500"
	"5000print:input ~You have died. Play again? (y/n) ~; i$:goto 5020"
	"5010print:input ~You have won. Play again? (y/n) ~; i$"
	"5020if i$=~y~ then goto 1000"
	"5030print:print ~Bye bye!~"
	0;

array scripts -->
	about_script
	higherlower_script
	wumpus_script
	0;
constant NUM_SCRIPTS 3;

global script_id = 0;
global script_lineno = 0;

! List the available scripts.

[ script_list  i;
	print "Available scripts:^";
	i = 0;
	while (scripts-->i)
	{
		print "  ", i, ": ", (string) scripts-->i-->0, "^";
		i++;
	}
	return ESTATE_NORMAL;
];

! Invoke a script.

[ script_invoke i;
	if ((i < 0) || (i >= NUM_SCRIPTS))
	{
		error("Script ID out of range");
		return ESTATE_ERROR;
	}

	print "Invoking script ~", (string) scripts-->i-->0, "~...^";
	script_id = i;
	script_lineno = 1;

	do {
		store_init(heap, heap+HEAP_SIZE);
		do {
			i = command_loop(script_reader);
		} until ((i == ESTATE_QUIT) || (i == ESTATE_NEW));
	} until (i == ESTATE_QUIT);

	print "Script finished.^";
	return ESTATE_NORMAL;
];

! Read in a command from a script into the parse buffer.

[ script_reader  buf in l;
	buf = mem_alloc(255);
	if (buf == 0)
		return -2;

	! Get the compressed data.

	l = scripts-->script_id-->script_lineno;
	if (l == 0)
		l = "quit";
	else
		script_lineno++;

	! Decompress it into the temporary buffer. 

	buf-->0 = 255;
	@output_stream 3 buf;
	print (string) l;
	@output_stream -3;

	! Ensure the string is zero-terminated.

	in = buf+2;
	in->(buf-->0) = 0;

	! Tokenise the stream.

	in = tokenise_stream(in, parsebuffer);

	mem_free(buf);
	return in;
];

