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