Directions = {
	"N": [0, "NORTH"],
	"S": [1, "SOUTH"], 
	"E": [2, "EAST"],
	"W": [3, "WEST"],
	"U": [4, "UP"],
	"D": [5, "DOWN"]
}

class Player:
	def __init__(self):
		self.inventory = []
		self.room = 1
		self.counter = 0	
		self.wantDescription = True
		self.coinFound = False
		self.ratsAsleep = False
		self.computerActive = False
		self.manualFound = False
		self.computerDead = False
		self.loggedIn = False
		self.bats = True
		self.mountedTape = False
		self.copyRunning = False

class Thing:
	def __init__(self, description, takable):
		self.description = description
		self.takable = takable

class Room:
	def __init__(self, description, contents, exits):
		self.description = description
		self.contents = contents
		self.exits = exits

	def describe(self):
		print(self.description)

		if len(self.contents) > 0:
			print("You see:")
			for thing in self.contents:
				print(thing.description)

		print("Exits are:")
		for direction in Directions:
			if self.exits[Directions[direction][0]] != 0:
				print(direction, end=" ")

		print()

Things = {
	"RATS":		Thing("Hungry rats", False),
	"TAPE":		Thing("Computer tape", True), 
	"MACHI":	Thing("Vending machine", False), 
	"TERMI":	Thing("Broken-down terminal", True), 
	"COIN":		Thing("Coin", True), 
	"CANDY":	Thing("Candy Bar", True), 
	"COMPU":	Thing("Computer", False), 
	"BATS":		Thing("Bats", False), 
	"DESK":		Thing("Desk", False), 
	"MANUA":	Thing("Computer Manual", True), 
	"CLOCK":	Thing("Elaborate Clockwork", False), 

	# pseudo-objects 
	"ROAD": 1,
	"DIR": 2,
	"ADVEN": 3,
	"COPY": 4,
	"LOGOU": 5,
	"NORTH": 6,
	"SOUTH": 7,
	"EAST": 8,
	"WEST": 9,
	"UP": 10,
	"DOWN": 11,
}

Rooms = []
Rooms.append(Room("You are nowhere.", [], [0, 0, 0, 0, 0, 0]))
Rooms.append(Room("You are in front of an old factory with a clock tower.", [], [2, 0, 0, 0, 0, 0]))
Rooms.append(Room("You are at the bottom of the stairwell.", [], [3, 1, 0, 0, 7, 0]))
Rooms.append(Room("You are at the top of some basement steps.", [], [0, 2, 0, 0, 0, 4]))
Rooms.append(Room("You are in a damp cellar.", [Things["RATS"]], [0, 0, 5, 0, 3, 0]))
Rooms.append(Room("You are in a storeroom.", [Things["TAPE"]], [0, 0, 0, 4, 0, 0]))
Rooms.append(Room("You are in the cafeteria.", [Things["MACHI"]], [0, 0, 7, 0, 0, 0]))
Rooms.append(Room("You're at a landing on the stairs.", [], [0, 0, 8, 6, 9, 2]))
Rooms.append(Room("Around you is a manufacturing area.", [Things["TERMI"]], [0, 0, 0, 7, 0, 0]))
Rooms.append(Room("You're at a landing on the third floor.", [], [0, 0, 10, 0, 12, 7]))
Rooms.append(Room("You are in the computer room.", [Things["COMPU"]], [0, 0, 0, 9, 0, 0]))
Rooms.append(Room("You are inside the clock tower.", [Things["CLOCK"]], [0, 12, 0, 0, 0, 0]))
Rooms.append(Room("You're at the top of the stairs.", [], [11, 0, 13, 0, 0, 9]))
Rooms.append(Room("You are in a long corridor going east.", [Things["BATS"]], [0, 0, 14, 12, 0, 0]))
Rooms.append(Room("You're at the east end of the corridor.", [Things["DESK"]], [0, 0, 0, 13, 0, 0]))

def parse(command):
	words = command.upper().split()[:2]	# Convert to uppercase and split words into list

	if len(words) <= 0:
		return

	if len(words) > 0:					# Split command into two words and shorten to five characters
		verb = words[0][:5]

	if len(words) > 1:
		noun = words[1][:5]
	else:
		noun = None

	if verb in Directions:					# Special treatment for directions
		doGo(verb)
	elif verb == "GO":
		doGo(noun[0])
	elif not verb in Verbs:
		print("I don't know the verb", verb)
	else:
		act = Verbs[verb]
		if noun == None:
			act(None)
		else:
			if not noun in Things:
				print("I don't know the object", noun)
			else:
				thing = Things[noun]
				if verb != "TYPE" and not thing in Rooms[player.room].contents and not thing in player.inventory:
					print("It isn't here.")
				else:
					return act(thing)
		
def doGo(object):
	if Rooms[player.room].exits[Directions[object][0]] == 0:
		print("You can't go that way.")
	elif player.room == 4 and not player.ratsAsleep:
		print("The rats look too fierce.")
	else:
		player.room = Rooms[player.room].exits[Directions[object][0]]
		player.wantDescription = True

	return True

def doEat(object):
	if not object == Things["CANDY"]:
		print("That's silly!")
	else:
		print("GAG! COUGH! CHOKE! PUKE!")
		if Things["CANDY"] in Rooms[player.room].contents:
			Rooms[player.room].contents.remove(Things["CANDY"])
		if Things["CANDY"] in player.inventory:
			player.inventory.remove(Things["CANDY"])

def doKick(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object != Things["COMPU"] or player.computerDead:
		print("Nothing happens.")
	elif player.computerActive:
		player.counter = 9
	else:
		print("The computer starts up!")
		print("The console displays: 'PLEASE LOG IN.'")
		player.computerActive = -1

	return True

def doInsert(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object != Things["COIN"]:
		print("That's silly!")
		return False
	elif player.room != 6:
		print("You can't do that now.")
	else:
		player.inventory.remove(Things["COIN"])
		Rooms[player.room].contents.append(Things["CANDY"])
		print("A candy bar comes out.")

	return True

def doType(object):
	if object == None:
		print("Please give an object.")
		return False
	elif player.room != 10:
		print("You can't do that now.")		
	elif not player.computerActive:
		print("The computer isn't running.")
	elif not player.loggedIn:
		if object != Things["ROAD"]:
			print("'Invalid login ID.'")
		else:
			print("'ROAD' logged in.'")
			player.loggedIn = True
	elif not player.copyRunning:
			if object == Things["DIR"]:
					print("'COPY LOGOU ADVEN'")
			elif object == Things["ADVEN"]:
					print("'Welcome to Adventure! W#uld Y#$*'")
					player.counter = 9
			elif object == Things["COPY"]:
					print("Mount tape then type filename.")
					player.copyRunning = True 
			else:
				print("'Invalid command.'")
	else:
		player.copyRunning = False
		if player.mountedTape:
			if object in [Things["COPY"], Things["DIR"], Things["ADVEN"]]:
				print("The tape spins...")
				print("'File copied.'")

				if object == Things["ADVEN"]:
						print("Congratulations, you've done it!")
						exit()
			else:
				print("'No such file'")
		else:
				print("'Error: Tape not mounted'")

	return True

def doTake(object):
	if object == None:
		print("Please give an object.")
		return False
	elif not object.takable:
		print("That's beyond your ability.")
		return True
	elif object in player.inventory:
		print("You already have it!")
		return False
	elif object == Things["TERMI"] and not player.coinFound:
		print("There was a coin underr it.")
		Rooms[player.room].contents.append(Things["COIN"])
		player.coinFound = True
	elif object == Things["TAPE"]:
		mountedTape = False

	Rooms[player.room].contents.remove(object)
	player.inventory.append(object)
	print("O.K.")

	return True

def doDrop(object):
	if object == None:
		print("Please give an object.")
		return False
	elif not object in player.inventory:
		print("You don't have it.")
	else:
		player.inventory.remove(object)
		Rooms[player.room].contents.append(object)
		if player.room == 4 and object == Things["CANDY"]:
			print("The rats devour the candy and get sleepy.")
			Rooms[player.room].contents.remove(Things["CANDY"])
			Things["RATS"].description = "Sleepy rats"
			player.ratsAsleep = True

	return True

def doInventory(object):
	print("You are carrying:")
	if player.inventory == []:
		print("Nothing.")
	else:
		for thing in player.inventory:
			print(thing.description)

	return True

def doMount(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object != Things["TAPE"]:
		print("That's silly!")
		return False
	elif player.room != 10 or player.mountedTape:
		print("You can't do that now.")
	else:
		player.inventory.remove(Things["TAPE"])
		Rooms[player.room].contents.append(Things["TAPE"])
		player.mountedTape = True
		print("O.K.")

	return True

def doRead(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object == Things["MACHI"]:
		print("'INSERT COIN.'")
	elif object == Things["MANUA"]:
		print("'...USER ID IS ROAD...'")
		print("'TYPE DIR FOR LIST OF COMMANDS...'")
		print("The rest is illegible.")
	else:
		print("Nothing is written on it.")

	return True

def doFight(object):
	print("That won't work.")
	return True

def doStart(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object == Things["COMPU"]:
		print("Nothing happens.")
	else: 
		print("That's silly!")
		return False

	return True

def doOpen(object):
	if object == None:
		print("Please give an object.")
		return False
	elif object == Things["DESK"]:
			if player.manualFound:
				print("It already is.")
			else:
				Rooms[player.room].contents.append(Things["MANUA"])
				player.manualFound = True
				print("Inside it is a manual.")
	else:
		print("That's silly!")
		return False

	return True

def doQuit(object):
	exit()

def doLook(object):
	player.wantDescription = True
	return False

def doWind(object):
	if object == Things["CLOCK"]:
		if player.bats:
			print("The clock chimes deafeningly and something flies past.")
			player.bats = False
			Rooms[13].contents.remove(Things["BATS"])
		else:
			print("It's fully wound.")
	else:
		print("That's silly!")
	
	return True

def doExamine(object):
	if object == Things["MACHI"] or object == Things["MANUA"]:
		print("Something is written there.")
	elif object == Things["DESK"] and not player.manualFound:
		print("It is closed.")
	elif object == Things["TERMI"]:
		print("It looks beyond repair.")
	elif object == Things["COMPU"]:
		print("This is an ancient mainframe with a console.")
	elif object == Things["CLOCK"]:
		print("There is a large handle for winding the clock.")
	elif object == Things["TAPE"] and player.mountedTape:
		print("It is mounted on the computer.")
	else:
		print("You see nothing special.")

	return True

Verbs = {
	"N": doGo,
	"S": doGo,
	"E": doGo,
	"W": doGo,
	"U": doGo,
	"D": doGo,
	"GO": doGo,
	"EAT": doEat,
	"KICK": doKick,
	"INSER": doInsert,
	"DEPOS": doInsert,
	"TYPE": doType,
	"TAKE": doTake,
	"GET": doTake,
	"DROP": doDrop,
	"THROW": doDrop,
	"INVEN": doInventory,
	"I": doInventory,
	"MOUNT": doMount,
	"READ": doRead,
	"FIGHT": doFight,
	"KILL": doFight,
	"START": doStart,
	"POWER": doStart,
	"OPEN": doOpen,
	"QUIT": doQuit,
	"LOOK": doLook,
	"WIND": doWind,
	"EXAMI": doExamine
}

player = Player()

while True:
	if player.wantDescription:
		Rooms[player.room].describe()

	player.wantDescription = False

	complete = parse(input("> "))

	if complete:
		if player.computerActive:
			player.counter = player.counter + 1
			if player.counter >= 10 and player.room == 10:
				print("The computer dies with a loud pop.")
				player.computerDead = True
				player.computerActive = False
				Things["COMPU"].description = "Dead computer"

	if Things["BATS"] in Rooms[player.room].contents:
		print("A horde of bats carries you out.")
		player.room = 1
		player.wantDescription = False
