/*
	OASYS source code
	'Base' Skeleton of OASYS code
	by Erin Anderson  Dec 14, 1992
*/

// Classes for abnormal objects

class room {}
class player {}
class door {{door}}

// Classes for normal objects

class lamp {{lamp}}

// Miscellaneous global variables

int describe_mode             // When to give full location descriptions
string null_string            // Always left equal to *NULL STRING*

// Global variables for objects

object lamp

// Global variables for locations -- all will be of class room

object intro_room

// Object properties

property object in            // Where is the object
property int is_open          // Is the object open
property int is_worn          // Is the object worn
property object n             // What locations are reached by going in the
property object s             // 8 directions of the compass + up and down
property object e
property object w
property object ne
property object nw
property object se
property object sw
property object up
property object down
property int moved            // Has the object been moved yet
property string short_desc    // Normal text for object when seen
property string word_desc     // One-word name for the object
property string long_desc     // Beginning descrip of object before moved
property string examine_desc  // Text you get when you EXAMINE the object
property object door          // For locations of doors if any
property int direction        // For doors -- Which direction are they in
property int weight           // How much does the object weigh
property int is_on            // Is the object turned on
property int is_dark          // For locations -- Is it dark

method int is_carried
"You haven't got that.\n"
{
	return this in == player and not this is_worn
}

method int is_visible
"I don't see that here.\n"
{
	if this in == player or this in == player in
		return 1
	if not this in exists
		return 0
			// Object is visible if its container is visible and its container
			// is open
	return (this in is_open) and (this in is_visible)
}

// Selector method for METHOD GET -- like is_visible except that something
// being carried is not gettable

method int is_gettable
"It isn't there to take.\n"
{
	if this in == player in or (this in == player and this is_worn)
		return 1
	if not this in exists
		return 0
	return (this in is_open) and (this in is_visible)
}

// Method for doing background stuff like checking for death in given
// situations.  Gets called by other methods after they've finished doing
// their bit.

method go
{
}

method list_contents
{
	object o
	int how_many

	if not this is_open
		return
	o = object 1
	do
	{
		if o in == this and o moved
			how_many = how_many + 1
		o = o next
	}
	while o exists
	if how_many == 0
		return
	print "The "
	print this word_desc
	print " contains "
	o = object 1
	do
	{
		if o in == this and o moved
		{
			print o short_desc
			how_many = how_many - 1
			if how_many
			{
				if how_many == 1
					print " and "
				else
					print ", "
			}
			else
				print ".\n"
		}
		o = o next
	}
	while o exists
	o = object 1
	do
	{
		if o in == this
			o list_contents
		o = o next
	}
	while o exists
}

method int list_objects string initial_message
{
	object o
	int how_many

	o = object 1
	do
	{
		if o in == this and o moved
			how_many = how_many + 1
		o = o next
	}
	while o exists
	if how_many == 0
		return 0
	print initial_message
	o = object 1
	do
	{
		if o in == this and o moved
		{
			print o short_desc
			if o is_worn
			{
				print " (wearing)"
			}
			if o is_on
			{   
				print " (on)"
			}
			how_many = how_many - 1
			if how_many
			{
				if how_many == 1
					print " and "
				else
					print ", "
			}
			else
				print ".\n"
		}
		o = o next
	}
	while o exists
	o = object 1
	do
	{
		if o in == this and o moved
			o list_contents
		o = o next
	}
	while o exists
	return 1
}

// Method to describe current location to player -- the verbose_description
// flag is used to indicate whether the full description should always be
// given

method describe_location int verbose_description
{
	object l
	object o
	int i

	l = this in
	print l short_desc
	print "\n"
	if verbose_description or
		(describe_mode != -1 and (describe_mode == 1 or not l moved))
	{
		l moved = 1
		print l long_desc
		print "\n"
	}
	o = object 1
	do
	{
		if o in == l and not o moved and not o is player
		{
			print o long_desc
			print "\n"
			o list_contents
		}
		o = o next
	}
	while o exists
	i = l list_objects "You can also see "
}

method look verbs {{l} {look}}
{
	this describe_location 1
}

method go_north verbs {{n} {north} {go north}}
{
	if not this in n exists
	{
		print "You can't go that way.\n"
		return
	}
	if this in door exists
		if this in door direction == 1 and not this in door is_open
		{
			print "You can't go through a closed door.\n"
			return
		}
	this in = this in n
	this describe_location 0
	this go
}

method go_south verbs {{s} {south} {go south}}
{
	if not this in s exists
	{
		print "You can't go that way.\n"
		return
	}
	if this in door exists
		if this in door direction == 2 and not this in door is_open
		{
			print "You can't go through a closed door.\n"
			return
		}
	this in = this in s
	this describe_location 0
	this go
}

method go_east verbs {{e} {east} {go east}}
{
	if not this in e exists
	{
		print "You can't go that way.\n"
		return
	}
	if this in door exists
		if this in door direction == 3 and not this in door is_open
		{
			print "You can't go through a closed door.\n"
			return
		}
	this in = this in e
	this describe_location 0
	this go
}

method go_west verbs {{w} {west} {go west}}
{
	if not this in w exists
	{
		print "You can't go that way.\n"
		return
	}
	if this in door exists
		if this in door direction == 4 and not this in door is_open
		{
			print "You can't go through a closed door.\n"
			return
		}
	this in = this in w
	this describe_location 0
	this go
}

method go_northeast verbs {{ne} {northeast} {go northeast}}
{
	if not this in ne exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in ne
	this describe_location 0
	this go
}

method go_northwest verbs {{nw} {northwest} {go northwest}}
{
	if not this in nw exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in nw
	this describe_location 0
	this go
}

method go_southeast verbs {{se} {southeast} {go southeast}}
{
	if not this in se exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in se
	this describe_location 0
	this go
}

method go_southwest verbs {{sw} {southwest} {go southwest}}
{
	if not this in sw exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in sw
	this describe_location 0
	this go
}

method go_up verbs {{u} {up} {go up}}
{
	if not this in up exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in up
	this describe_location 0
	this go
}

method go_down verbs {{d} {down} {go down}}
{
	if not this in down exists
	{
		print "You can't go that way.\n"
		return
	}
	this in = this in down
	this describe_location 0
	this go
}

// Method to calculate total weight of object, which is object's own weight
// plus weight of all objects inside it and inside those etc.

method int total_weight
{
	object o
	int result

	result = this weight
	o = object 1
	do
	{
		if o in == this
			result = result + o total_weight
		o = o next
	}
	while o exists
	return result
}

method get object x is_gettable
	verbs {{get x} {take x} {remove x} {take off x} {take x off}}
{
	if x is_worn
	{
		print "Removed.\n"
		x is_worn = 0
		return
	}
	if x weight == 9999
	{
		print "You can't take that.\n"
		return
	}
	if this total_weight + x total_weight > 9998
	{
		print "You're carrying too much already.\n"
		return
	}
	x in = this
	x moved = 1
	print "Taken.\n"
	this go
}

method drop object x is_carried verbs {{drop x}}
{
	x in = this in
	x is_worn = 0
	print "Dropped.\n"
	this go
}

method put_in object x is_carried object y is_visible
	verbs {{put x in y} {put x into y}}
{
	if x == y
	{
		print "You can't put something into itself!\n"
		return
	}
	if not y is_open
	{
		print "It isn't open.\n"
		return
	}
	print "OK.\n"
	x in = y
	x is_worn = 0
	this go
}

method quit verbs {{quit}}
{
	quit
}

method inventory verbs {{i} {inv} {inventory}}
{
	if not this list_objects "You are carrying "
		print "You are emptyhanded.\n"
}

method save verbs {{save}}
{
	save
}

method load verbs {{load} {restore}}
{
	if load
	{
		this describe_location 0
		this inventory
	}
}

method examine object x is_visible
	verbs {{examine x} {look at x} {read x}}
{
	if x examine_desc != null_string
	{
		print x examine_desc
		print "\n"
	}
	if x is door
	{
		print "The door is "
		if x is_open
			print "open.\n"
		else
			print "closed.\n"
	}
	if x is lamp
	{
		print "The lamp is "
		if x is_on
			print "lit.\n"
		else
			print "unlit.\n"
	}
	x list_contents
}

// To allow something to be worn, remove the /* and */ surrounding the
// following method code

/*
method wear object x is_carried verbs {{wear x}}
{
	if not x is *****          // Replace ***** with items which can be worn   
	{
		print "You can't wear that!\n"
		return
	}
	if x is_worn
	{
		print "You're already wearing it.\n"
		return
	}
	print "OK.\n"
	x is_worn = 1
	this go
}
*/

method use object x is_visible verbs {{use x}}
{
	if x == lamp
	{
		print "Try LIGHT LAMP or EXTINGUISH LAMP.\n"
		return
	}
	print "Sorry, but you'll have to use some other verb.\n"
}

method open object x is_visible verbs {{open x}}
{
	object o

	if not x is door
	{
		print "You can't open that.\n"
		return
	}
	if x is_open
	{
		print "It's already open.\n"
		return
	}
}

method do_open_door
{
	this door is_open = 1
	this door long_desc = "The door is open."
}

method open_door
{
	int dir

	this do_open_door
	dir = this door direction
	if dir == 1
		this n do_open_door
	if dir == 2
		this s do_open_door
	if dir == 3
		this e do_open_door
	if dir == 4
		this w do_open_door
}

method do_close_door
{
	this door is_open = 0
	this door long_desc = "The door is closed.\n"
}

method close_door
{
	int dir

	this do_close_door
	dir = this door direction
	if dir == 1
		this n do_close_door
	if dir == 2
		this s do_close_door
	if dir == 3
		this e do_close_door
	if dir == 4
		this w do_close_door
}

method close object x is_visible verbs {{close x} {shut x}}
{
	if not x is door
	{
		print "You can't close that.\n"
		return
	}
	if not x is_open
	{
		print "It isn't open.\n"
		return
	}
	print "You close the door.\n"
	this in close_door
	this go
}

// To allow something to be eaten, remove the /* and */ surrounding the
// following method code

/*
method eat object x is_carried verbs {{eat x}}
{
	if not x is *****          // Replace ***** with edible item
	{
		print "It doesn't look very edible to me.\n"
		return
	}
	print "OK.\n"
	this go
}
*/

// To allow liquid consumption, remove the /* and */ surrounding the
// following method code

/*
method drink object x is_visible verbs {{drink x}}
{
	if not x is *****          // Replace ***** with drinkable item
	{
		print "You can't drink that.\n"
		return
	}
	destroy x
	print "Glug ... glug ... glug ... hic!\n"
	this go
}
*/

method brief verbs {{brief}}
{
	print "Brief descriptions only.\n"
	describe_mode = -1
}

method verbose verbs {{verbose}}
{
	print "Verbose descriptions.\n"
	describe_mode = 1
}

method normal verbs {{normal}}
{
	print "Normal descriptions.\n"
	describe_mode = 0
}

method turn_on object x is_visible
	verbs {{light x}}
{
	if x is_on
	{
		print "It's already on.\n"
		return
	}
	if x is lamp
	{
		x is_on = 1
		print "You light the lamp.  Light floods the area.\n"
		this go
		return
	}
	else
		print "You can't turn that on!\n"
}

method turn_off object x is_visible
	verbs {{extinguish x}}
{
	if not x is_on
	{
		print "It isn't turned on.\n"
		return
	}
	if x is lamp
	{
		x is_on = 0
		print "You extinguish the lamp.\n"
		this go
		return
	}
}

method kill                   // Method to destroy an object + all contents
{
	object o
	object o2

	o = object 1
	do
	{
		o2 = o next
		if o in == this
			o kill
		o = o2
	}
	while o exists
	destroy this
}

// Method to destroy door in this location plus the corresponding door in the
// next location

method destroy_door
{
	int dir

	dir = this door direction
	destroy this door
	if dir == 1
		destroy this n door
	if dir == 2
		destroy this s door
	if dir == 3
		destroy this e door
	if dir == 4
		destroy this w door
}

method create_other_door int direction
{
	this door = create door
	this door direction = direction
	this door long_desc = "The door is locked."
	this door word_desc = "door"
	this door weight = 9999
	this door in = this
}

// Method to create a door in a location together with the corresponding door
// in the next location

method create_door int direction
{
	this create_other_door direction
	if direction == 1
		this n create_other_door 2
	if direction == 2
		this s create_other_door 1
	if direction == 3
		this e create_other_door 4
	if direction == 4
		this w create_other_door 3
}

method init
{
	print
		"Base Skeleton of OASYS code  by Erin Anderson Dec 14, 1992\n\n"

	player = create player

			// Create all the normal objects

	lamp = create lamp

			// Create all the locations

	intro_room = create room

			// Assign exits from locations

			// Location short descriptions

	intro_room short_desc = "Intro Room"

			// Location long descriptions

	intro_room long_desc =
	"You see nothing interesting."

			// Position all objects initially

	player in = intro_room
	lamp in = intro_room

			// Object short descriptions

	lamp short_desc = "a brass lamp"

			// Object one-word names

	lamp word_desc = "lamp"

			// Object long descriptions. Note that some objects will never need
			// long descriptions as they will be moved when the player sees
			// them for the first time.

	lamp long_desc = "A brass lamp is sitting on the floor."

			// Messages for examining objects

	lamp examine_desc = "A simple brass lamp."

			// Object weights

	lamp weight = 150

			// Create doors between locations (all initially closed)

			// Which locations are dark

			// Start off by describing initial location

	player describe_location 0
}

