!\---------------------------------------------------------------------------
	
	THE VAULT OF HUGO
	Hugo v2.2 Tutorial Game

	by Kent Tessman (c) 1995-1996

---------------------------------------------------------------------------\!

#version 2.2

#set DEBUG                              ! include HugoFix library and grammar
#set VERBSTUBS                          ! include verb stub routines

#set USE_VEHICLES                       ! from OBJLIB.H
#set USE_PLURAL_OBJECTS                 !
#set USE_ATTACHABLES                    !

#set NO_AUX_MATH                        ! don't need advanced math routines

#ID = "vh"                              ! i.e. "The Vault of Hugo"

#switches -ls                           ! print statistics to SAMPLE.LST


! The following limit setting reserves 512 extra bytes of dictionary space
! so that the play can name the unnamed object.  512 bytes are required
! because the game needs to write the name, adjective, and misc properties
! of the object.

$MAXDICTEXTEND = 512


!----------------------------------------------------------------------------
! NEW GRAMMAR:

verb "kick", "punt", "boot"
	*                                               DoVague
	* object                                        DoPunt

verb "board"
	* (minecar)                                     DoEnter

verb "roll", "drive", "steer", "ride"
	*                                               DoVague
	* object                                        DoMoveinVehicle
	* "to" object                                   DoMoveinVehicle

! In the grammar definitions below, STRING refers to any section of the
! player's input enclosed in quotation marks.

verb "write", "scribble", "scrawl", "print"
	*                                               DoVague
	* "on" object                                   DoWriteOn
	* "on" object "with" held                       DoWriteOn
	* string                                        DoWrite
	* string "on" object                            DoWrite
	* string "on" object "with" held                DoWrite
	* string "with" held                            DoWrite

verb "name", "call", "christen"
	*                                               DoVague
	* (unnamedobject)                               DoNameWhat
	* (unnamedobject) string                        DoName

verb "stick"
	*                                               DoVague
	* (dart)                                        DoAttachObject
	* (dart) "in"/"on" (dartboard)                  DoAttachObject


#include "grammar.g"                    ! normal game grammar

!----------------------------------------------------------------------------

#ifset PRECOMPILED_LIBRARY
#link "hugolib.hlb"
#endif
#ifclear PRECOMPILED_LIBRARY
#include "hugolib.h"                    ! standard library routines
#endif

! Normally, the library's PrintScore routine uses a MAX_SCORE/score
! formula to determine a ranking (if rankings are provided); the following
! global is used in the replaced PrintScore routine to ensure that rank is
! set by the game, not approximated by the library.

global rank

routine init
{
	MAX_SCORE = 50
	ranking[0] = "Amateur Adventurer"
	ranking[1] = "Competent Door-Unlocker"
	ranking[2] = "Bomb-Meddling Adventurer"
	ranking[3] = "Master Magic Wand Finder"
	ranking[4] = "The Genuine Article Sample Game Solver"
	MAX_RANK = 4

	counter = -1                    ! 1 turn before turn 0

	STATUSTYPE = 1                  ! score/turns
	TEXTCOLOR = DEF_FOREGROUND
	BGCOLOR = DEF_BACKGROUND
	SL_TEXTCOLOR = BRIGHT_WHITE
	SL_BGCOLOR = BLUE

	prompt = ">"
	color TEXTCOLOR, BGCOLOR

	cls
	"You brace yourself, check your flashlight, and, with \
	source code in hand, prepare to enter...\n"
	
	Font(BOLD_ON)
	"THE VAULT OF HUGO"
	Font(BOLD_OFF)
	"An Interactive Example"
	print BANNER

	player = you
	location = outsidevault
	old_location = location

	move player to location         ! initialize player location
	FindLight(location)             ! whether the player can see
	DescribePlace(location)         ! the appropriate description
	location is visited
	CalculateHolding(player)        ! total size of player contents

	Acquire(player, flashlight)     ! give the player the flashlight
	flashlight is known
	
	Activate(key_daemon)            ! set up initial daemons

	plural_count = 4                ! initialize plural/identical objects
	plurals[0] = goldcoins
	plurals[1] = boxes
	plurals[2] = notes
	plurals[3] = balls
}

#ifset PRECOMPILED_LIBRARY
replace main
{
#endif
#ifclear PRECOMPILED_LIBRARY
routine main
{
#endif
	counter = counter + 1
	PrintStatusLine
	run location.each_turn
	runevents
	RunScripts
	if speaking not in location     ! in case the character being spoken
		speaking = 0            ! to leaves
}

character you "you"
{
	nouns "me", "myself"
	capacity 100
	is plural                       ! for matching first-person verbs
	long_desc {"Looking good."}
}


! flashlight
!
! The flashlight is an example of a light source.  The rules for
! the FindLight routine in HUGOLIB.H check to see if any light sources
! are available (starting with the room itself, then working through
! the visible contents) before deciding if the player is able to see 
! in any given location.

object flashlight "flashlight"
{
	in you
	nouns "flashlight", "light", "torch", "lamp"
	adjective "flash"
	article "your"
	short_desc
	{
		CArt(self)
		" is here, ";
		if self is switchedon
			"glowing brightly."
		else
			"turned off."
	}
	long_desc
	{
		"It's one of those disposable kinds.  Built-in battery.  \
		$3.99 at the corner store.  That sort of thing.  At the 
		moment, it is ";
		if self is switchedon
			"on."
		else
			"off."
	}
	before
	{
		! The before property routine attempts to match the verb                
		! routine based on a given specifier.  In the case below,
		! if the verbroutine global is set to DoBurn (technically
		! &DoBurn, the address of the DoBurn routine) and the 
		! object global is set to the flashlight object, the
		! following routine is run before (in place of) the DoBurn
		! routine.

		object DoBurn
			{Perform(&DoSwitchOn, self)}
	}
	after
	{
		! The two routines below are similar to the before routine
		! above, except that they are run after the verb routine.

		object DoSwitchOn
		{
			"A beam of serviceable light appears from your 
			flashlight."
			self is light
			FindLight(location)
			if location is not visited
				{DescribePlace(location)
				location is visited}
		}
		object DoSwitchOff
		{
			"Your flashlight goes dark.  ";
			self is not light
			if FindLight(location)
				print newline
			else
				"And so does everything else."
		}
	}
	is switchable
}

!----------------------------------------------------------------------------
! OUTSIDE THE VAULT
!----------------------------------------------------------------------------
room outsidevault "outside a vault"
{
	long_desc
		{"Kind of that 1930s, Bela Lugosi, graveyardy motif at 
		work here.  It's a pretty creepy place.  Directly in 
		front of you is the giant door to an even more giant 
		vault.  Above the door hangs a rusty sign."}
	e_to {return vaultdoor.door_to}
	in_to {return vaultdoor.door_to}
	cant_go
		{"Vines, thorns, and bent, twisted trees bar travel in any 
		direction away from the vault."}
	before
	{
		location DoDig
		{
			if object ~= bump
				"You can't dig in that."
			else
				Perform(&DoSearch, bump)
		}
	}
}


! key_daemon
!
! This basic daemon is simply a trigger that checks every turn to see
! if 10 turns have passed.  If so, it prints a brief section of prose
! before deactivating itself.  (It is also deactivated if the player
! pre-emptively searches the bump in the ground.)

daemon key_daemon
{}

event key_daemon
{
	if counter = 10
	{
		"\nAll this shuffling around outside the door has uncovered 
		a little bump in the ground."
		
		event_flag = true
		Deactivate(key_daemon)
	}
}

scenery bump "little bump"
{
	in outsidevault
	nouns "bump", "ground"
	adjective "little"
	article "a"
	long_desc
	{
		if key is not moved
			{"It looks like there might be something there."
			bump is moved}
		else
			{"You've already got the key.  What more do 
			you want?"}
	}
	before
	{
		! More than one verb routine may be given as a potential
		! match to a specifier in a before or after routine, as in:
		
		object DoSearch, DoDig
		{
			if key is moved
				"You already did.  There's nothing else 
				to find."
			else
			{
				bump is moved
				"You find a rusty iron key!\n(Taken.)"
				Acquire(player, key)
				score = score + 10
				Deactivate(key_daemon)
			}
		}
	}
}

object key "rusty iron key"
{
	noun "key"
	adjectives "rusty", "iron"
	article "a"
	size 20
	long_desc
		{"A skeleton key.  Rusty.  Iron.  And heavy, too.  A perfect 
		match for the vault door, no?"}
	before
	{
		xobject DoUnlock
		{
			if object = oakdoor
				"The rusty key doesn't work on this door."
			else
				return false    ! library continues as usual
		}
	}
}

scenery sign "rusty sign"
{
	in outsidevault
	noun "sign"
	article "a"
	adjective "rusty"
	long_desc {"\"Here lies Hugo.\""}
	is readable
}


! vaultdoor
!
! Notice that the found_in property specifies the rooms on either side
! of the door; OBJLIB.H does the rest.  The vault door's special attribute
! is set once the player scores points for opening it.

door vaultdoor "vault door"
{
	nouns "door", "doorway"
	adjective "vault"
	article "the"
	between outsidevault, insidevault
	key_object key
	after
	{
		object DoUnlock
		{
			if self is not special
			{
				self is special
				score = score + 10
				rank = 1
			}
			return false    ! library continues as usual
		}
	}
	is not open, lockable, locked
}

scenery vault "vault"
{
	in outsidevault
	noun "vault"
	article "the"
	long_desc {"Big, imposing, and complete with rusty sign."}
	door_to                         ! so a player can "go vault"
		{return vaultdoor.door_to}
	before
	{
		object DoEnter
		{
			object = vaultdoor      ! change object before letting
			return false            ! library continue normally
		}
	}
}

!----------------------------------------------------------------------------
! INSIDE THE VAULT
!----------------------------------------------------------------------------
room insidevault "inside the vault"
{
	long_desc
	{
		"Standing in the middle of this dimly lit chamber, you 
		realize that just maybe you should've splurged on a 
		more expensive flashlight.  You also realize that there 
		are four ways you can go:  a marble archway to the north, 
		a muddy cave opening to the east, ";
		if oakdoor is not blown_open
			"an oak door set in a brick frame";
		else
			"an empty brick frame where the oak door used to be";
		" to the southeast, and west back outside where you came 
		from."
	}
	w_to {return vaultdoor.door_to}
	out_to {return vaultdoor.door_to}
	se_to {return oakdoor.door_to}
	n_to objectroom
	e_to characterroom
	in_to {"You'll have to be a little more specific about which way 
		you want to go."}
	is not light
	after
	{
		location DoGo
			
			! changes the way the vault is refered to from 
			! "a vault" to "the vault"--a stylistic thing

		{
			outsidevault.name = "outside the vault"  
			return false
		}
	}
	vehicle_path minecar    ! i.e. the mine car can travel here
}


! minecar
!
! This is an excellent example of a basic vehicle from OBJLIB.H.  The 
! vehicle_verbs property must mirror the valid words provided in the 
! verb grammar at the start of this file.  The vehicle_move property is 
! checked before the vehicle is allowed to move.  (This is where, for 
! example, a car object would be checked to make sure that the ignition 
! is turned on, or the tires aren't flat, etc.)  Any room in which travel 
! in the mine car is permitted must have minecar in its vehicle_path 
! property.

vehicle minecar "mine car"
{
	in insidevault
	nouns "car", "cart"
	adjectives "mine", "my", "old"  ! because:  synonym "mine" for "my"
					! in HUGOLIB.H
	article "a"
	vehicle_verbs "roll", "drive", "steer", "ride"
	vehicle_move
	{
		! Here, the mine car will not roll until the big rock is
		! removed from under it.  Note that the rock is not actually
		! under the car, but looking under the car moves it from
		! the nothing object to the room object.
		
		if bigrock in nothing
			{"Something seems to be stopping the mine car 
			from rolling."
			return false}
	}
	initial_desc
		{"An old mine car sits abandoned to one side."}
	long_desc
		{"It was probably used to haul rocks during the 
		excavation of the original Hugo.  You could probably 
		get in it."}
	contains_desc
		{"The old mine car is loaded with";}
	before
	{
		object DoClimb
			{Perform(&DoEnter, self)}
		object DoLookUnder
		{
			if bigrock not in nothing
				"You don't find anything else."
			else
			{
				"You find a big rock lodged between the 
				wheels, which you manage to wrestle out of 
				the way."
				move bigrock to insidevault
			}
		}
	}
	after
	{
		object DoEnter
		{
			pencil is known
			return false
		}
	}
	capacity 100
	holding 0
	reach minecar                   ! can't reach things outside the car
	is container, open, static

	! Because the mine car has the quiet attribute set, its contents
	! (i.e. the pencil) are not immediately obvious--they are not 
	! listed by WhatsIn until the player specifically looks inside.

	is quiet

	! Also, it is mobile and therefore may be pulled by the rope.

	is mobile
	attach_immobile                 ! returns false if the car is mobile
	{
		if bigrock in nothing
			"Something seems to be stopping the mine car 
			from rolling."
		else:  return false
	}
}

object bigrock "big rock"
{
	nouns "rock", "stone"
	adjectives "big", "large", "huge"
	article "a"
	after
	{
		object DoGet
			{"Oof.  It's a struggle, but you manage to 
			pick it up."}
	}
	size 50
}

!----------------------------------------------------------------------------
! THE OBJECT ROOM
!----------------------------------------------------------------------------
room objectroom "Object Room"
{
	article "the"
	prep "in"
	s_to insidevault
	out_to insidevault
	long_desc
	{
		"This room contains a collection of objects with different 
		properties, attributes, and associated routines in order 
		to give some idea of basic object design.  In addition to 
		the various furnishings, you notice a dartboard hanging on 
		one wall."
	}
	vehicle_path minecar
	is not light
}

! chair
!
! Try sitting in it.

object chair "wooden chair"
{
	in objectroom
	noun "chair"
	adjective "wooden"
	article "a"
	reach cardtable         ! i.e. only the chair and the card table
				! may be reached from the chair
	is enterable, static
}


! cardtable
!
! Try sitting on it.  (You can't--it's not enterable.)  But it can hold
! things on its surface.

object cardtable "card table"
{
	in objectroom
	nouns "table", "cardtable"
	adjective "card"
	article "a"
	capacity 50
	holding 0
	is platform, static
}


! deckofcards and playingcard
!
! A rather unimpressive example of how to extract a single object from
! a group of similar objects.  Pick a card, any card.

object deckofcards "playing cards"
{
	in cardtable
	noun "cards"
	adjective "deck", "playing"
	article "some"
	initial_desc
		{"A deck of playing cards has been placed appropriately 
		on the table."}
	size 10
	is plural
}

object card "playing card"
{
	found_in deckofcards
	noun "card" , "diamonds"
	adjective "playing", "nine"
	article "a"
	size 5
	long_desc {"It's the nine of diamonds."}
	after
	{
		object DoGet
		{
			if object.found_in ~= false
			{
				object.found_in = false
				"You deal the nine of diamonds."
				object.name = "nine of diamonds"
				object.article = "the"
			}
			else
				return false
		}
	}
}


! goldcoins
!
! A simple demonstration of identical_class from OBJLIB.H.  The coins can 
! be referred to individually, by number (i.e. "two coins"), or as a 
! group ("the coins").

identical_class goldcoins "shiny gold coins"
{
	article "some"
	nouns "coins"
	adjectives "shiny", "gold"
	single_noun "coin"
	long_desc
		"Shiny and gold:  both admirable qualities in a coin."
	plural_of coin1, coin2, coin3
}

object coin1 "shiny gold coin"
{
	in cardtable
	article "a"
	noun "coin"
	adjectives "shiny", "gold"
	identical_to goldcoins
}

coin1 coin2 "shiny gold coin"           ! copy coin1 to coin2
{
	in cardtable
}

coin1 coin3 "shiny gold coin"
{
	in cardtable
}


! mittens
!
! Try wearing them.  Try writing when you're wearing them.

object mittens "pair of mittens"
{
	in transparentbox
	nouns "mitten", "mittens"
	adjective "pair"
	article "a"
	size 10
	initial_desc
		{"A pair of mittens is inside the transparent box."} 
	is clothing
}


! box
!
! The basic box class is used by transparentbox and opaquebox.  The boxes
! plural_class (from OBJLIB.H) exists only to allow the boxes to be referred 
! to as a group.

plural_class boxes "boxes"
{
	article "some"
	noun "boxes"
	single_noun "box"
	plural_of transparentbox, opaquebox
}

class box "box"
{
	noun "box"
	article "a"
	size 20
	capacity 20
	holding 0
	long_desc
	{
		if self is open
			"It's open."
		else
			"It's closed."
	}
	after
	{
		! This after routine replaces the normal library "Taken."
		! response whenever a box object is the parent of the
		! taken object.
		
		parent(object) DoGet
		{
			print "You take "; The(object); " out of "; \
			The(self); "."
		}
	}
	is openable, not open, container
}


! transparentbox
!
! Try getting something out of it when it's closed, even if you can see
! the contents.  Then try putting the flashlight in here and closing it.

box transparentbox "transparent box"
{
	in objectroom
	adjective "transparent", "clear"
	plural_is boxes
	is transparent
}


! opaquebox
!
! Now try putting the flashlight in here and closing it.  The library does
! all the work of checking to see if the DoClose verb routine hides the
! light source in the room.

box opaquebox "opaque box"
{
	in objectroom
	adjective "opaque"
	article "an"
	plural_is boxes
}

box largedrum "large drum"
! the special attribute is set once it has been opened
{
	in objectroom
	nouns "drum", "can", "barrel"
	adjectives "large", "big", "larger"
	short_desc
	{
		"A large drum--not the musical kind--is here.  ";
		if warningnote is hidden
		{
			"Attached to it is a warning note."
			warningnote is known
			warningnote is already_listed
		}
		print newline
	}
	long_desc
		{"It's one of those big barrels used for storing and shipping 
		oil, chemicals, and other hazardous materials.  Hint."}
	before
	{
		object DoGet
			{"It's much too heavy to take."}
	}
	after
	{
		object DoOpen
		{
			! if drum hasn't been opened the first time
			if self is not special
			{
				"Ignoring all warnings to the contrary, you 
				open the drum.  Inside is another, smaller 
				drum, as well as a second warning note."
				self is special
				smalldrum is known
				warningnote.name = "first warning note"
			}
			else
				return false
		}
	}
}

plural_class notes "notes"
{
	nouns "notes", "paper"
	adjectives "warning", "pieces"
	single_noun "note"
}

object warningnote "warning note"
{
	in objectroom
	nouns "note", "paper"
	adjectives "warning", "first", "piece"
	article "a"
	long_desc
		{"\"Do not open this drum.  Whatever you do, don't open 
		this drum.  Do not.  Open.  This drum.\""}
	before
	{
		object DoGet
			{self is not hidden}
	}
	plural_is notes
	is readable, hidden
}

box smalldrum "smaller drum"
! the special attribute is set once the bomb has been found
{
	in largedrum
	nouns "drum", "can", "barrel"
	adjectives "small", "smaller", "little"
	long_desc
	{
		"It's a smaller version of the first drum";
		if secondnote is hidden
		{
			" (with a second warning note attached, of course)";
			secondnote is known
			secondnote is already_listed
		}
		print "."
	}
	before
	{
		object DoGet
			{"Small is a relative term here.  It's still too 
			big to pick up."}
	}
	after
	{
		object DoOpen
		{
			if self is not special   ! if bomb hasn't been found
			{
				"You find a bomb.  What luck."
				self is special
				bomb is known
				Activate(bomb_fuse, 10)
				score = score + 10
				rank = 2
			}
			else
				return false
		}
	}
}

object secondnote "second warning note"
{
	in largedrum
	nouns "note", "paper"
	adjectives "warning", "second", "piece"
	article "a"
	long_desc
		{"\"You listen well.  But this time we mean it.  Don't open 
		this drum.\""}
	before
	{
		object DoGet
			{self is not hidden}
	}
	plural_is notes
	is readable, hidden
}

object bomb "bomb"
{
	in smalldrum
	nouns "bomb"
	article "a"
	long_desc
		{"Just your typical, garden-variety bomb."}
}


! bomb_fuse
!
! This fuse begins running as soon as the player opens the small drum.
! It prints a message only when it is within earshot or view of the player,
! but keeps ticking regardless.

fuse bomb_fuse
{}

event bomb_fuse
{
	if bomb in player                       ! player is holding it
		{"\nThe bomb you're holding is ticking."
		event_flag = true}
	elseif FindObject(bomb, location)       ! bomb is visible in the room
		{"\nThe bomb is ticking."
		event_flag = true}
	elseif Contains(location, bomb)         ! bomb is otherwise in room
		{"\nYou hear a ticking noise."
		event_flag = true}

	if not self.tick                        ! when self.timer = 0
	{
		if Contains(location, bomb)     ! if in player's location
		{
			"\nKABOOM!\n\n\
			(Right next to the bomb was not, as they say, such 
			a great place to be as it went off.  You're dead now.)"
			endflag = 2
			return
		}
		else
		{
			"\nYou hear a muffled kaboom."
			event_flag = true
			if bomb in insidevault
			{
				oakdoor is blown_open
				oakdoor is not openable
				oakdoor is not hidden
				score = score + 10
				
				! The following activates the dwarf's 
				! script with eleven steps; the DwarfDropBall
				! ensures that she drops whatever she was 
				! holding before going anywhere.
				
				setscript[script(dwarf,11)] = \
					&CharMove, s_obj, 
					&CharMove, w_obj, 
					&CharWait, nothing, 
					&CharShakeHead, oakdoor, 
					&CharWait, nothing, 
					&CharMove, n_obj, 
					&CharWait, nothing, 
					&CharShakeHead, largedrum, 
					&CharMove, s_obj, 
					&CharMove, e_obj, 
					&CharMove, n_obj
				DwarfDropBall
			}
			remove bomb
			Deactivate(bomb_fuse)
		}
	}
}


attribute written alias special         ! for the pad only
array writing[65]                       ! up to 64 characters of writing

! pad
!
! Try:  write "something" on paper.

object pad "pad of paper"
{
	in cardtable
	article "a"
	nouns "paper"
	adjective "pad", "regular", "writing"
	long_desc
	{
		"It's a regular pad of writing paper.  ";
		if self is written
		{
			"Written on it is:  \"";
			print StringPrint(writing); "\"."
		}
		else:  "It's blank."
		print newline
	}
	is readable
}

object pencil "pencil"
{
	in minecar
	article "a"
	noun "pencil"
	adjective "wooden"
	long_desc
		"Not just a wooden pencil, but a magical wooden pencil, 
		which one might use, perhaps, to name a hitherto unnamed 
		object."
	size 5
}


! unnamedobject
!
! The unnamed object can be given a name by the player--i.e. have a word
! written on it by which the object may be referred to--in order to
! demonstrate the DICT command.

object unnamedobject "unnamed object"
! the special attribute is set once the player has given it a name
{
	in objectroom
	article "an"
	noun "object"
	adjective "unnamed", "non-descript", "nondescript"
	misc 0                          ! will eventually contain the non-
					! case-altered version of the name
	initial_desc
		"Lying in the corner of the room is a non-descript, 
		unnamed object."
	short_desc
		print "The "; self.name; " is here."
	long_desc
	{
		"Nothing special about it.  You can't even tell what it 
		might be for.";
		if self is special
			{"  Written on the side of it is:  \"";
			print object.misc; "\".";}
		print newline
	}
	is openable, clothing, switchable
}

scenery dartboard "old dartboard"
{
	in objectroom
	article "a"
	noun "dartboard", "board"
	adjective "old", "dart"
	short_desc
		"Hanging on one wall is an old dartboard."
	is static
}


! dart
!
! The dart can be attached to the dartboard either by sticking it in or
! throwing it.  Since the attach_take property is true, the dart is released
! when attached and taken when detached.

attachable dart "green dart"
{
	in objectroom
	article "a"
	noun "dart"
	adjective "green"
	size 5
	attach_verb "stick", "throw"
	detach_verb "get"
	attach_prep "in"
	attached_desc "sticking out of"
	attach_take true
	attach_drop true
	attached_to dartboard           ! space for one attachment
	attachable_to dartboard
	before
	{
		object DoThrowAt
		{
			if xobject is living
				"Trying to start something, are we?"
			else
				Perform(&DoAttachObject, object, xobject)
		}
	}
}       


! rope
!
! The rope is another attachable--but unlike the dart, because attach_take
! is not set to true, it may still be carried after being attached to another
! object.  Since the minecar has the mobile attribute set, it may be pulled
! around; the chair and cardtable, however, may not.

attachable rope "heavy rope"
{
	in objectroom
	article "a"
	nouns "rope", "twine"
	adjective "heavy", "thick"
	attach_verbs "tie", "attach"
	detach_verbs "untie", "detach"
	attached_to chair, 0            ! space for two attachments
	attachable_to chair, cardtable, minecar
}


!----------------------------------------------------------------------------
! THE CHARACTER ROOM AND THE BALL ROOM
!----------------------------------------------------------------------------
room characterroom "Character Room"
{
	noun "room"
	adjective "character"
	article "the"
	prep "in"
	w_to insidevault
	out_to insidevault
	n_to ballroom
	in_to ballroom
	long_desc
		{"The Character Room provides a couple of good examples of 
		character scripts and events.  Exits are north and west."}
	vehicle_path minecar
}


! guard
!
! Ask him about things in the game.  Try:
!
!       ask guard about the minecar
!       guard, tell me about the minecar
!       guard, what about the minecar?
!
! Or, once you've begun talking to him, simply:
!
!       tell me about...
!       what about...

character guard "burly guard"
{
	in characterroom
	noun "guard"
	adjective "burly"
	article "a"
	long_desc
		{"He's wearing a button that reads:  \"Just ask me.\""}
	before
	{
		! The guard is the object, since the question is asked as:
		! "ask <object> about <xobject>".
		
		object DoAsk
		{
			select xobject
			case minecar
				"\"You bring that in here, and you're asking 
				for trouble.\""
			case ballroom
				"\"Don't let me catch you taking none of them 
				there balls out of the Ball Room.\""
			case bomb
				"\"I don't know what kind of loopy nut 
				would want to be carting a bomb in here.\""
			case dwarf
				{"\"She's a short little one.  Kinda strange, 
				I have to say.  Spends all her time in there 
				just a-kickin' away.  I think she's mad 
				'cause she lost her magic wand.\""
				wand is known}
			case wand
				"\"Wish I had one.\""
			case oakdoor
				"\"I have no idea how to get that thing 
				open.  The only way would be to blast it, 
				if you had something to blast it with...\""
			case you
				"The guard doesn't think too much of you."
			case guard
				"I wouldn't pry if I were you."
			case else
				return false
		}
	}
}


! This object-linked event is checked only when the guard is in the player's
! location.

event guard
{
	if minecar in location
	{
		"\nThe guard lifts his big boot up to the mine car and gives 
		you a firm shove back out the door.  \"Not in that thing, 
		you don't, pal!\""
		if player in minecar
		{
			move minecar to insidevault
			location = insidevault
			PrintStatusLine
		}
		else
		{MovePlayer(insidevault)
		MoveAllAttachables(player, characterroom, insidevault, true)
		}
	}
	if Contains(player, bomb)
	{
		"\nThe guard grabs you and throws you back out the door.  \
		\"Get out of here with that bomb, pal!\"  An unsubtle 
		approach, yes, but one that works."
		MovePlayer(insidevault)
	}
	if Contains(player, soccerball) or Contains(player, basketball)
	{
		"\nThe guard grabs you and throws you back out the door.  \
		\"Read the sign, pal!  They call it the Ball Room for a 
		reason.  Keep 'em in there!\""
		MovePlayer(ballroom)
	}
}

room ballroom "Ball Room"
{
	noun "room", "ballroom"
	adjective "ball"
	article "the"
	prep "in"
	s_to characterroom
	out_to characterroom
}


! This event runs whenever the player is in the ballroom.

event ballroom                          ! the dwarf plays with the balls
{
	local a, b
	
	if dwarf in ballroom
	{
		a = random(5) + 1      ! 1 to 6
		select a
			case 1
				DwarfGetBall(soccerball)
			case 2
				DwarfGetBall(basketball)
			case 3, 4
				DwarfDropBall
			case else
			{
				if child(dwarf)
				{
					"\nThe dwarf winds up and gives the ";
					print child(dwarf).name;
					" a kick.  It ricochets off the wall 
					and bounces back to her."
					event_flag = true
				}
			}
	}               
}

routine DwarfDropBall
{
	if child(dwarf)
	{
		"\nThe dwarf drops the ";
		print child(dwarf).name; "."
		move child(dwarf) to ballroom
		event_flag = true
	}
}

routine DwarfGetBall(obj)
{
	if obj in ballroom
	{
		DwarfDropBall
		move obj to dwarf
		"\nThe dwarf picks up the ";
		print obj.name; "."
		event_flag = true
	}
	else                            ! player must have ball obj
	{
		if obj = basketball     ! so try to choose the other ball
			obj = soccerball
		else
			obj = basketball

		if obj not in ballroom  ! player must have both balls
			"\nThe dwarf looks at you impatiently and more than 
			a little accusingly, waiting for you to give her 
			back her balls."
	}
}

plural_class balls "balls"
{
	article "some"
	noun "balls"
	single_noun "ball"
	plural_of soccerball, basketball
}

object soccerball "checkered soccer ball"
{
	type balls                      ! for identification as a ball
	in ballroom
	nouns "ball", "soccerball"
	adjective "soccer", "checkered"
	article "a"
	before
	{
		object DoGet
		{
			if self in dwarf        ! if she's holding it
				{"The dwarf shakes a fist at you and 
				mutters, \"Get your own, kid.\""}
			else
				return false
		}
	}
}

soccerball basketball "orange basketball"       ! copy the other ball object
{
	in ballroom
	nouns "ball", "basketball"
	adjective "basket", "orange"
	article "an"
}

female_character dwarf "little dwarf"
{
	in ballroom
	noun "dwarf"
	adjective "little"
	article "a"
	order_response          ! i.e. "dwarf, (do something)", such as
	{                       ! "dwarf, kick ball"
		
		if verbroutine = &DoPunt
		{
			if object.type ~= balls
				{"The dwarf looks at you like you're nuts."
				return true}
			if object in player
				{"(first giving the ball to her)"
				if child(dwarf)
					move child(dwarf) to location
				move object to dwarf}
			
			if object not in dwarf
				{"The dwarf shrugs.  \"I would, but I don't 
				have "; 
				print The(object); "."}
			else
				{"The dwarf winds up and gives the ";
				print object.name;
				" a kick.  It ricochets off the wall and 
				bounces back to her."}
		}
		else
			return false
	}
	after
	{
		object DoAsk
		{
			if xobject = wand
				"\"I'd like to have it back.\""
			else
				return false
		}
		object DoTell
		{
			if xobject = wand
				"\"I'd like to have it back.\""
			else
				return false
		}
		
		! In this case, the dwarf is the xobject, since the command
		! is given as:  "show <object> to <xobject>". 
		
		xobject DoShow
		{
			if object = wand
				"\"Give that to me!\""
			else
				return false
		}
		xobject DoGive
		{
			if object = wand
			{
				"\"Thank you!  I've been looking for 
				that.\"  The dwarf takes the wand and bonks 
				you a little roughly on the head with it, 
				transporting you back to your nice, warm bed."
				rank = 4
				score = score + 10
				endflag = 1
			}
			else
				return false
		}
	}
}

routine CharShakeHead
{
	local char, obj
	if char in location
		print CThe(char); " shakes her head at "; The(obj); "."
}

!----------------------------------------------------------------------------
! BRICK ROOM
!----------------------------------------------------------------------------

! Special attribute for the oak door:
attribute blown_open alias special

object oakdoor "oak door"       ! a little more complicated door object
{
	in insidevault
	noun "door", "doorway"
	adjective "oak"
	article "an"
	short_desc
		{"Lying on the floor is the oak door."}
	door_to
	{
		if self is not blown_open
			"The oak door is locked up tight as a drum."
		else
			return brickroom
	}
	vehicle_path minecar
			   
	! Setting key_object to a non-zero value means the door is not 
	! openable without a key.  In this case, the ! key is 
	! technically object 1, which doesn't exist in the game.  So 
	! for all intents and purposes, the player can never unlock 
	! this door.  (It has to be blown open.)
	
	key_object 1

	is static, openable, not open, lockable, locked

	! Since the door is hidden at the outset, its short_desc is
	! not printed (until the door is blown open).

	is hidden
}

room brickroom "Brick Room"
{
	noun "room"
	adjective "brick"
	article "the"
	prep "in"
	long_desc
		{"This room is finished entirely in brick masonry.  Good, 
		solid workmanship.  You can head back out to the northwest."}
	nw_to insidevault
	out_to insidevault
}

object trophy "shining golden trophy"
{
	in brickroom
	nouns "award", "trophy", "inscription"
	adjectives "shining", "golden"
	article "a"
	initial_desc
		{"A shining golden trophy--an award for your efforts--is 
		here.  It bears an inscription."}
	long_desc
		{"Congratulations for solving this sample game's one and 
		only major puzzle.  (Although it really wasn't that hard, 
		was it?  And you probably don't deserve such a nice shining
		golden trophy.)"}
	after
	{
		object DoGet
		{
			if parent(letter) = nothing
				{"As you pick up the trophy, a magic wand 
				falls to the ground, and a small piece of 
				paper flutters down after it."
				move wand to brickroom
				move letter to brickroom
				rank = 3}

			else
				return false
		}
	}
	is readable
}

object letter "handwritten letter"
{
	nouns "paper", "letter"
	adjective "handwritten", "piece"
	article "a"
	long_desc
		{"It's a letter from the author of this sample game.  Goes 
		something like this:\n\n\"Give this to the dwarf to solve 
		the game.\"  Nothing fancy, but I'm sure it was late 
		when he was writing this."}
	is readable
}

object wand "magic wand"
{
	noun "wand"
	adjective "magic", "twinkling"
	article "a"
	short_desc {"A magic wand is twinkling on the floor here."}
	long_desc 
		{"\"The official magic wand of social democrats 
		everywhere.\""}
	before
	{
		object DoWave
		{
			"You wave the magic wand, a cloud of orange mist 
			appears, and...\n\n...Aw, forget it.  I'm just 
			kidding.  What makes you think you know what to 
			do with a magic wand, anyway?"
		}
	}
}

!----------------------------------------------------------------------------
! NEW VERB ROUTINES
!----------------------------------------------------------------------------

routine DoPunt
{
	if object is living
		"Oh, good.  Real good.  Pick a fight, now.  That's really 
		going to get you places."
	elseif object.type ~= balls
		"You won't get very far trying to kick that around."
	else
	{
		"You wind up and give ";
		The(object)
		" a good boot.  ";
		if dwarf in ballroom
			"The dwarf nods approvingly."
		else
			print newline
		move object to ballroom
		player.holding = player.holding - object.size
	}
	return true
}

routine DoWriteOn       ! response to an improperly phrased command
{
	if xobject and xobject ~= pencil
		{"You can't write with ";
		print The(xobject); "!"}
	elseif object ~= pad and object ~= unnamedobject
		{"There's not much point in defacing ";
		print The(object); "."}
	else
		"You'll have to be a little more specific about exactly 
		what you'd like to write.  Try:  'write \"something\".'"
}

routine DoWrite
{
	local len

	if not xobject
	{
		if pencil not in player
			{"You're not holding anything to write with."
			return false}
		else
			xobject = pencil
	}
	if not object
	{
		if FindObject(pad, location) ~= 1
			{"Nothing to write on."
			return false}
		else
			object = pad
	}

	if xobject ~= pencil or (object ~= pad and object ~= unnamedobject)
		{DoWriteOn
		return}
	elseif mittens is worn
		"Good luck writing with those mittens on."
	elseif object = unnamedobject
		return Perform(&DoName, unnamedobject)
	else
	{
		if pad is written
			{"You scratch out \"";
			print StringPrint(writing); "\" and ";}
		else:  "You ";
		
		! Read the engine parse$ into the writing[] array, to a
		! maximum of 64 characters
		len = string(writing, parse$, 64)

		print word[1]; " \""; StringPrint(writing); "\"";
		" on the pad."
		pad is written
	}
	return true
}


! Notice that the DoName routine only allows the player to create one new
! entry in order to avoid overrunning MAXDICTEXTEND.

array name_array[50]

routine DoName
{
	if object is special
		{"You already named it ";
		The(object)
		"--don't go changing your mind now."}
	elseif pencil not in player
		"Would help if you were holding something to write that 
		on the object, so you'll remember it."
	else
	{
		local i, len
		
		len = string(name_array, parse$, 49)    ! maximum 49 char.
print "Trying to name it:  "; StringPrint(name_array)!***
		for (i=0; i<len; i=i+1)
		{
			! Because the parser cannot recognize multiple
			! words...
			if name_array[i] = ' '          ! a space
				{"Better keep it to one word."
				return}

print "name_array["; number i; "] is '";
printchar name_array[i]
print "' (ASCII "; number name_array[i]; "]"
			
			! ...or non-alphanumeric characters
			if name_array[i] < '0' or name_array[i] > 'z' or
			  (name_array[i] > '9' and name_array[i] < 'A') or
			  (name_array[i] > 'Z' and name_array[i] < 'a'):
				{"Better to keep the fancy punctuation 
				out of it."
				return}
		}

		"You write \"";
		StringPrint(name_array)
		"\" on the object."
		
		! The misc property contains the non-case-corrected version
		! of the name.
		
		object.misc = dict(name_array, 49)
		
		! The name is converted to '"<string>" object':
		
		! initial quote first...
		name_array[0] = '\"'
		
		! then read parse$ into name_array (after the first quote)...
		len = string(name_array+1, parse$, 49)
		
		! and append the last part to name_array...
		string(name_array+len+1, "\" object")
		
		! ...before turning name_array into a dictionary entry
		object.name = dict(name_array, 49)
		
		! Since the adjective will be referred to by the parser,
		! it must be lowercase--name_array must also be reloaded
		! with parse$ since it has been modified above.
		
		len = string(name_array, parse$, 49)
		for (i=0; i<len; i=i+1) ! the actual case-conversion loop
		{
			if name_array[i] >= 'A' and name_array[i] <= 'Z'
				name_array[i] = name_array[i] + ('a'-'A')
		}
		! then write the word as a dictionary entry
		object.adjective #1 = dict(name_array, 49)

		object.article = "the"  ! i.e. 'the "<string>" object'
		object is special
		object is moved
	}
}

routine DoNameWhat
{
	"Try:  name object \"(something)\"."
}

!----------------------------------------------------------------------------
! REPLACE LIBRARY ROUTINES:
!----------------------------------------------------------------------------

global already_warned

replace DarkWarning
{
	if not already_warned           ! player is only warned once...
	{
		"It's pitch black in here.  Stumbling around in the dark 
		isn't such a hot idea:  you're liable to be eaten by a grue."
		already_warned = true
	}
	else                            ! ...and gets three safe moves before
	{                               ! becoming a snack for a grue
		already_warned = already_warned + 1
		if already_warned > 4
			{"You stumble around in the dark...and are eaten 
			by a grue!  Bad move.  Should've used a light."
			endflag = 2}
		else
			"You stumble around in the dark."
	}
}

! Below is the new PrintScore routine.  Note that it differs from the
! library routine in that it uses the new global rank to print the ranking.

replace PrintScore(end_of_game)
{
	"You ";
	if not end_of_game
		"have ";
	"scored a total of ";
	print number score; " out of "; number max_score; 
	print ", giving you the rank of "; ranking[rank]; "."
}

