
Global GuideActive = true;
	
Object GuideContext
  with
	count 0,
	brief_look_count 0,
	blank_line_count 0,
	unknown_verb_count 0,
	unknown_verb_ever false,
	just_undid false;

Constant GUIDE_QUEUE_SIZE 10;

Array GuideArray --> GUIDE_QUEUE_SIZE;

[ GuideEnqueue obj   ix;
	for (ix=0 : ix<GuideContext.count : ix++) {
		if (obj == GuideArray-->ix)
			return; ! This message is already queued.
	}

	if (GuideContext.count >= GUIDE_QUEUE_SIZE) {
		"[BUG] too many guide references";
	}
	
	GuideArray-->(GuideContext.count) = obj;
	GuideContext.count++;
];

[ GuideAnyQueued;
	return GuideContext.count;
];

[ GuideBeforePrompt  ix obj;
	if (GuideContext.count == 0)
		return;

	for (ix=0 : ix<GuideContext.count : ix++) {
		obj = GuideArray-->ix;
		GuidePrint(obj);
	}

	GuideContext.count = 0;
];

[ GuidePrint obj force;
	if (obj == nothing)
		return;

	if ((~~GuideActive) && (~~force))
		return;
		
	style underline;
	global_italic = true;
	
	print "^[";
	switch (metaclass(obj)) {
		String: print (string) obj;
		Routine: obj();
		Object: PrintOrRun(obj, description);
		default: print "[BUG] unknown guide reference";
	}
	print "]";

	style roman;
	global_italic = false;

	new_line;
];

[ GuideInvokeOnce;
	! uses "self"; use as a property value
	if (self has general)
		return;
	give self general;
	GuideEnqueue(self);
];

[ GuideSeedMessage;
	! used on the first turn, for unknown verbs, and for blank lines
	if (BasementHall hasnt general) {
		print "Don't know how to get started?";
	}
	else {
		print "Don't know what to do?";
	}

	print " Type ", (helpcmd) "help";

	if (Hall3 hasnt visited)
		print " and then hit enter.";
	else
		print ". If you're trying to find the right word to make
			something happen, try ", (helptopic) "commands", ".";
];

[ GuideLeaveCellMessage;
	print "This cell isn't very exciting. You can stay if you want...
		but life is probably more interesting outside.^^
		Have you looked around for an exit? Type ", (helpcmd) "look",
		".";
];

[ GuideLeaveCell1Message;
	print "Notice the gap in the wall. You can take a closer look by
		typing ", (helpcmd) "examine gap", ".";
];

[ GuideLeaveCell2Message;
	print "Notice the gap in the wall. You can take a closer look by
		typing ", (helpcmd) "examine gap", ".";
];

[ GuideLeaveCell3Message;
	print "To crawl into the narrow gap, type ", (helpcmd) "enter gap",
		" or ", (helpcmd) "go through gap",
		". Typing ", (helpcmd) "east", " will also work. (So will
		just ", (helpcmd) "e", ".
		Compass-direction commands can be abbreviated that way.)^^
		For more information about basic IF commands, type ",
		(helptopic) "basics", ".";
];

[ GuideWelcomeMessage;
	print "Looks like you've taken the first step. Well done.^^
		Let me introduce myself. I am the Voice of this tutorial. Most
		games don't have me; but in ", (emph) "this",
		" game, I will watch over your
		shoulder and give you some help. With a little practice, you'll soon
		be moving around the text adventure world in style.^^
		Back to the story.
		Remember what's going on? Actually, you don't. As the
		introduction said, you can't remember who you are or what
		you're doing here!^^
		Amnesia. Yes, it's a clich@'e, but it'll do for a
		tutorial.^^
		I'll let you go on exploring. The west corridor leads back to
		the cell
		where you started, so you'll want to try up the stairs instead.
		Type ", (helpcmd) "up", " or ", (helpcmd) "climb stairs", ".";
];

Object GuideVerboseMessage
  with
	description [;
	give self general;
	print "The first time you enter a room, you'll see
		a detailed description. But if you ", (emph) "return",
		" to a room, you see just the room name, followed by a list of
		the more portable objects lying around.^^";
	print "You can type ", (helpcmd) "look", " or ", (helpcmd) "l",
		" at any time to see the full description. But if you get tired
		of that, try the ", (helpcmd) "verbose", " command.
		In ", (helpcmd) "verbose", " mode, the game will give a detailed
		description of each room as you enter it -- every time you
		move.";
	],
  has ~general;

Object GuideBriefLookMessage
  with
	evoke [;
		self.number = 1;
	],
	invoke [;
		if (self has general)
			return;
		if (self.number) {
			self.count++;
			self.number = 0;
		}
		if (self.count < 4)
			return;
		if (GuideAnyQueued())
			return;
		give self general;
		GuideEnqueue(self);
	],
	number 0,
	count 0,
	description [;
		print "If you get tired of typing ", (helpcmd) "look", " or ",
			(helpcmd) "l", " every time you return to a room, you can
			try the ", (helpcmd) "verbose", " command.
			In ", (helpcmd) "verbose", " mode, the game will give a detailed
			description of each room as you enter it -- every time you
			move.";
	],
  has ~general;

[ GuideInviteInvMessage;
	print "Time to test some of these commands. You're not sure where
		you are, but it can't hurt to take stock of yourself. Try
		typing ", (helpcmd) "i", " -- that will show what you're
		carrying.";
];
  
[ GuideFirstInvMessage  ix;
	ix = children(player);
	if (ix == 1)
		print "You're carrying something unusual -- well, it's hard to say
			if it's unusual or not, just yet";
	else
		print "You're carrying ", (EnglishNumber) ix, " things. You just
			picked up ", (EnglishNumber) ix-1, " of them, but you must have
			been holding ", (the) quill, " when you awoke. It may
			be important";
			
	print ". Type ",
		(helpcmd) "examine the pen", " to take a close look at it.^^
		Or just ", (helpcmd) "x pen", " will work. ~Examine~
		can be abbreviated to one letter, and you can always leave out
		nonessential words like ~a~, ~an~, and ~the~.";
];
  
[ GuideRoomSceneryObject;
	print "In most games, there isn't any need to refer to the room as
		a whole. If you just want to look around, type ",
		(helpcmd) "look", ". Otherwise, refer to particular objects
		that you see.";
];

[ GuideVagueGoMessage;
	print "If you want help in moving around, type ",
		(helptopic) "moving", ".";
];

Object GuideTakingMessage
  with
	invoke [ obj;
		if (Hall3 has visited)
			return;
		if (obj == self.number)
			return;
		if (obj hasnt moved) {
			self.number = obj;
			GuideEnqueue(self);
		}
	],
	number 0,
	description [;
		print "To pick up what you have discovered, type ";
		if (self.number == whitemask)
			print (helpcmd) "take mask";
		else
			print (helpcmd) "take key";
		print ".^^Remember, you can list what you're carrying by typing ",
			(helpcmd) "i", ". For more about picking up and dropping
			things, type ", (helptopic) "take", ".";
	];
	
[ GuidePutKeyInObject;
	print "It does make sense to say ", (helpcmd) "put key in keyhole",
		", but it's more common to type ", (helpcmd) "unlock door with key",
		". More games will accept the latter.";
];

Array GuideSearchStudyList table
	desk book studydoor studytrunk cabinet cabinetstuff
	studyanimals studyplants studyinstruments studybooks studycandles
	clutter;

Object GuideSearchStudyObject
  with
	description [ num ix;
		num = GuideSearchStudyList-->0;
		ix = self.count();
		self.helpmode = ix;
		print "You've been here before, but it's a particularly crowded
			room. And examining your surroundings -- in detail -- is
			a valuable skill in IF. Not everything you see will be
			needed to solve the game... but anything may give you a clue,
			or a detail, or an insight. Or simply a better sense of
			where you are!^^
			There are at least ", (EnglishNumber) num, " things (or
			groups of things) around here which are worth a look. You";
		if (ix == 0)
			print " haven't examined any";
		else
			print "'ve examined ", (EnglishNumber) ix;
		print " of them. Try ", (helpcmd) "look", " (or ", (helpcmd) "l",
			") to survey the room; then ", (helpcmdobj) "examine",
			" (or ", (helpcmdobj) "x", ") on anything that catches
			your attention.";
	],
	helpmode -1,
	count [ num total ix;
		num = GuideSearchStudyList-->0;
		total = 0;
		for (ix=1 : ix<=num : ix++) {
			if ((GuideSearchStudyList-->ix) has helpflag)
				total++;
		}
		return total;
	];

[ GuideSearchStudySomeMessage  ix num jx obj;
	ix = GuideSearchStudyObject.count();
	num = GuideSearchStudyList-->0;
	GuideSearchStudyObject.helpmode = ix;
	print "That's at least ", (EnglishNumber) ix, " things in this
		room you've examined.";
	if (num-ix <= 3) {
		print " (Namely";
		for (jx=1 : jx<=num : jx++) {
			obj = (GuideSearchStudyList-->jx);
			if (obj has helpflag)
				print ", ", (the) obj;
		}
		print ".)";
	}
	jx = (num-ix);
	print " There";
	if (jx == 1)
		print " is one";
	else
		print " are ", (EnglishNumber) (num-ix);
	print " more worth a glance.";
];

[ GuideSearchStudyDoneMessage;
	GuideSearchStudyObject.helpmode = -1;
	print "Good, good. That's just about everything in this room
		which is worth examining.^^
		Now, don't feel you have to obsessively ",
		(helpcmd) "examine", " every word you see in every room.
		A lot of stuff is just scenery. (For example, the plants,
		animals, instruments, and candles here aren't very important.)
		In a well-written game, you'll have a good idea what's important
		and what's merely decorative.^^
		On the other hand, you ", (emph) "have", " discovered several
		items of interest. (That brass trunk, for example";
	if (studytrunk hasnt general)
		print ". Why didn't you open it? It isn't locked.)";
	else
		print " -- the key inside will certainly be useful.)";
	print " Keep in mind what you've found.
		If you need to refresh your memory about anything, you
		can always ",
		(helpcmd) "examine", " again.";
];

Object GuideOpeningTrunkMessage
  with
	invoke [;
		if (hallkey has moved || studytrunk has open)
			return;
		if (GuideAnyQueued())
			return;
		self.number++;
		if (self.number >= 2) {
			self.number = 0;
			GuideEnqueue(self);
		}
	],
	number 0,
	description [;
		if (studytrunk has general)
			print "You've opened and closed the trunk, but you never
				picked up the key that you found inside. Keys are
				always useful somewhere, so you probably want to
				open the trunk again and grab this one.";
		else
			print "If you're curious what's inside the trunk -- and an
				adventurer is always curious -- you can open it. Try typing ",
				(helpcmd) "open trunk", ".";
	];

Object GuideLockedDoorsMessage
  with
	invoke [ obj;
		if (Hall3 has visited)
			return;
		if (obj hasnt locked)
			return;
		if (self.helpmode ~= obj) {
			self.helpmode = obj;
			self.count = 0;
		}
		self.count++;
		if (self.count == 3) {
			self.count = 1;
			GuideEnqueue(self);
		}
	],
	count 0,
	helpmode nothing,
  	description [;
		if (~~(SittingRoom has visited && Study has visited
			&& MirrorRoom has visited)) {
			print "This door seems to be locked. Maybe you should look
				around a bit more, and come back to tackle the door
				later. It's always good to become familiar with what's
				easy to reach, before you begin struggling with the
				difficulties.";
		}
		else if (studytrunk hasnt general) {
			print "This door seems to be locked. There's probably a key
				lying around somewhere... perhaps not in plain sight.
				Take another look around, and don't fear to be thorough.";
		}
		else if (hallkey hasnt moved) {
			print "This door seems to be locked. Didn't you see a key
				inside that brass trunk you opened?";
		}
		else if (hallkey notin player) {
			print "This door seems to be locked. Didn't you leave a key
				lying around here somewhere?";
		}
		else {
			print "This door seems to be locked, but you have found a
				key. Type ", (helpcmd) "unlock door with key", " to
				try it out.";
		}
	];

Object GuideLockedWrongKeyMessage
  with
	invoke [ obj;
		if (Hall3 has visited)
			return;
		if (sittingdoor hasnt locked)
			return;
		if (self.helpmode ~= obj) {
			self.helpmode = obj;
			self.count = 0;
		}
		self.count++;
		if (self.count == 1) {
			GuideEnqueue(self);
		}
	],
	count 0,
	helpmode nothing,
	description [;
		if (~~(SittingRoom has visited && Study has visited
			&& MirrorRoom has visited)) {
			print "The key doesn't match this door. But have you explored
				everywhere yet? There may be another door elsewhere
				which this key unlocks.";
		}
		else {
			print "The key doesn't match this door. But there are two other
				locked doors nearby.";
		}
	];

[ GuideUpStandUpMessage;
	print "The ", (helpcmd) "up", " command generally means to travel
		upward -- to climb a ladder or a flight of stairs. To get
		up from a chair, type ", (helpcmd) "stand", " or ",
		(helpcmd) "get up", ".";
];

Object GuideWalkedIntoDarkMessage
  with
	invoke GuideInvokeOnce,
	description [;
		print "Oh, dear. You've walked into a very dark place.^^";
		if (torch in player) {
			print "(Yes, you were carrying a torch. Unfortunately you
				forgot to light it, so it isn't going to help much";
			if (warmberries in player)
				print " -- unless you can light it right now, in
					the dark";
			print ".)^^";
		}
		print "Going ", (helpcmd) "south", " probably won't get you back;
		you can't tell directions in the dark. So what now?
		One option is to type ", (helpcmd) "undo",
		". This will let you ~back up~ one move -- back to just before you
		walked in here. Everything will be the same, except that
		you'll be in the Natural Passage, and you'll be able to see.^^
		In this game, you can only ", (helpcmd) "undo", " one move in
		a row. So if you do something else now (even ", (helpcmd) "look",
		" or ", (helpcmd) "south", "), you won't be able to
		jump back to the lit Passage. The ", (helpcmd) "undo",
		" command is intended only to fix immediate mistakes.^^
		If you want to go back more than one turn, you'll have to use
		the ", (helpcmd) "restart", " or ", (helpcmd) "restore", " commands.
		Type ", (helptopic) "saving", " for more information.^^
		Or you could stumble around in the dark, and try to find your
		way out. Since this is an introductory game, there ", (emph) "is",
		" a way out. And maybe more to discover, as well.";
	],
  has ~general;
	
[ GuideOpenedCageMessage;
	print "You may have made a mistake. You're not likely to get that
		apple back. (One never knows, of course, but that decay looked
		very final.) What can you do about it?^^
		One option is to type ", (helpcmd) "undo",
		". This will let you ~back up~ one move -- back to just before you
		opened the cage. Everything will be the same, except that the
		cage will still be closed and the apple will still be fresh.^^
		In this game, you can only ", (helpcmd) "undo", " one move in
		a row. So if you do something else now (even ", (helpcmd) "look",
		" or ", (helpcmd) "examine apple", "), you won't be able to
		jump back to before the cage opened. The ", (helpcmd) "undo",
		" command is intended only to fix immediate mistakes.^^
		If you want to go back more than one turn, you'll have to use
		the ", (helpcmd) "restart", " or ", (helpcmd) "restore", " commands.
		Type ", (helptopic) "saving", " for more information.^^
		(Actually, many games protect you from severe mistakes. Since
		this is an introductory game, you don't really have to worry about
		accidentally running into a dead end. If you truly need a
		fresh apple, you'll probably find another way to get one.)";
];

[ GuideOpenedCageUndoMessage;
	print "Go ahead, play with your food...";
];

[ GuideFellInPitMessage;
	print "Oh, dear. You've gotten yourself killed.^^
		I admit that was a very sudden death... perhaps even an unfair
		death. All you did was";
	if (location ~= CavePit3)
		print " try to climb down a pit.
			A tricky, vertical pit. A vertical pit with
			slippery walls";
	else
		print " climb down a pit.
			A tricky, vertical pit. A vertical pit with
			slippery walls, getting more slippery by the second.
			Where you hung out, waiting to get tired";
	print "... Okay, let's just admit that neither of us
		is entirely blameless. But this ", (emph) "is", " a tutorial
		adventure; and everyone has to discover death,
		sooner or later.^^
		Fortunately, you don't have to start the entire game over.
		You can take back your last move by typing ", (helpcmd) "undo",
		". That will let you ~back up~ one move -- back to just before your
		fatal slip. You'll still be clinging to the pit wall, and you
		can try something safer for your next move. Like climbing ",
		(emph) "up", ".^^
		If you ", (emph) "want", " to start the entire game over, you can --
		type ", (helpcmd) "restart", ". You could also ", (helpcmd) "restore",
		" a save file you saved earlier. Or, if you find death discouraging,
		you could ", (helpcmd) "quit", " -- but I don't think that's
		necessary. You have much yet to discover.";
];

Object GuideDisambiguationMessage
  with
	invoke [ i marker;
		if (self hasnt general) {
			give self general;
			marker = 0;
			i = 1;
			while (((match_classes-->marker) ~= i)
				&& ((match_classes-->marker) ~= -i)) marker++;
			self.number = match_list-->marker;
			GuideEnqueue(self);
		}
	],
	number 0,
	description [;
		print "You typed a command which could refer to more than one
			object. The game is asking you to specify which you mean.
			You can type the name of one of these objects
			-- ", (helpcmd) self.number, ", for example -- and the game
			will execute your command correctly.^^
			(You can type just part of the name.
			A single word will usually suffice, if it picks out
			exactly one option.)^^
			You could also change your mind and type an entirely new
			command.";
	],
  has ~general;

Object GuideUnlimitedInventoryMessage
  with
	invoke [;
		if (self hasnt general) {
			give self general;
			GuideEnqueue(self);
		}
	],
	description [;
		print "You're carrying quite a lot of stuff";
		if (coolberries in player && warmberries in player)
			print " -- including two handfuls of berries";
		print ". You might be wondering how you can juggle it all.
			Some games limit the number of things you can carry,
			or provide you with some kind of sack to carry
			your loot around in.^^
			However, many games -- including
			this one -- simply ignore the problem. Packing your
			luggage, or stowing it in some central location, isn't
			all that much fun. Therefore, the game lets you
			carry around as much as you want.";
	],
  has ~general;
  			
[ GuideIWantAmMessage;
	print "It's not helpful to enter declarations about yourself,
		like ~I want...~ or ~I am...~. The game doesn't know how to
		react to such announcements.
		Instead, enter simple commands, like ", (helpcmd) "take key",
		" or ", (helpcmd) "open door", ".^^
		To learn about the kinds of commands you can use, type ",
		(helpcmd) "help", ". If you're just not sure what to try,
		type ", (helptopic) "strategy", ".";
];

[ GuideQuestionsMessage;
	print "It's not helpful to enter questions like ~What is...~ or
		~Who am I?~ You are alone; there is no-one nearby to answer
		such questions.
		Instead, enter simple commands, like ", (helpcmd) "look",
		" or ", (helpcmd) "climb stairs", ".^^
		To learn about the kinds of commands you can use, type ",
		(helpcmd) "help", ". If you're just not sure what to try,
		type ", (helptopic) "strategy", ".";
];

[ GuideIGiveUpMessage;
	print "What, you give up? Oh, don't. If you want 
		help on how to play IF, type ",
		(helpcmd) "help", ". If you're just not sure what to try,
		type ", (helptopic) "strategy", ".^^
		If you really do want to stop playing (and shut down the game),
		type ", (helpcmd) "quit", ". But you might want to ",
		(helpcmd) "save", " your progress first!";
];

[ GuideUseMessage;
	print "There is no ~use~ command in most text adventures. (If
		there was, what would be the point in providing any other
		commands?) Instead, try a command which is appropriate to
		whatever you're doing. If you have a key, try ",
		(helpcmd) "unlock", " something.
		If you have a book, try to ", (helpcmd) "read", " it.
		If you find a lever, try to ",
		(helpcmd) "pull", " or ", (helpcmd) "push", " it.";
];
