Question
I need to create a Zork game with python code based on the following premise: The game takes place in a world of connected locations.
I need to create a Zork game with python code based on the following premise:
The game takes place in a world of connected locations. The purpose of the game is to collect edible items and then bring them to the elf in the woods behind campus. The elf needs 500 calories of edible food before it will save GVSU. Each item can have 0 or more calories. If a player gives the elf something inedible (something with 0 calories), the elf will be displeased and will teleport the player to a random location in the world. The player can only carry 30 pounds at a time, so multiple trips to the elf may be needed. Once the elf has enough calories, it will save campus and the game will end.
Location: 8 connected locations based of the locations given below.
Each Location represents a place on campus that may be visited. A location holds a name, a description, a bool that indicates if it has been yet visited, a dictionary of neighbors, a list of NPC s, and a list of items.
The neighbors dictionary will have a key that is a direction, that refers to a Location as its value. For instance, if we have a Location called zumberg and another Location called kirkhoff , zumberg would have a dictionary entry "west" that holds kirkhoff . We then want kirkhoff to hold in its dictionary a key-value pair of "east" that refers to zumberg .
If we want to have two locations attached such that the player can enter but not exit the way they came, we can merely leave the entry off one of the objects. For instance, we could have a portal Location that has a "through" key pointing to zumberg but no corresponding key-value pair in the zumberg neighbor dictionary.
I have the following code for this:
def create_world(self): neighbor_dict = { 'kirkhoff_upstairs': ['kirkhoff_downstairs', 'mary_idema'], 'kirkhoff_downstairs': ['kirkhoff_upstairs', 'library', 'mary_idema'], 'mary_idema': ['kirkhoff_upstairs', 'kirkhoff_downstairs', 'library', 'laker_village'], 'library': ['kirkhoff_downstairs', 'mary_idema', 'laker_village', 'commons'], 'laker_village': ['mary_idema', 'library', 'commons', 'alumni_house'], 'commons': ['library', 'laker_village', 'alumni_house'], 'alumni_house': ['laker_village', 'commons', 'woods'], 'woods': ['alumni_house'] } for location in self._locations: if location.get_name() in neighbor_dict: neighbor_names = neighbor_dict[location.get_name()] for neighbor_name in neighbor_names: neighbor_location = self.get_location_by_name(neighbor_name) location.add_neighbor(neighbor_location) neighbor_location.add_neighbor(location) def get_location_by_name(self, name): for location in self._locations: if location.get_name() == name: return location return None
NPC: Create 5 Non-playable characters.
The NPC class represents information about a character that can be in a Location . An NPC has a name, description, message number, and list of messages. Each time the player speaks to an NPC, the message number should increase by 1, resulting in the next message in the list being printed the next time the player speaks to the character. The message number should go back to 0 after it goes past the length of the message list. The class must have:
a constructor that accepts a name and a description
getters for name and description a getter for a message that returns the current message (as indicated by message number), then changes the message number appropriately
a __str__(self) -> str method that returns only the name of the NPC.
Items: Create 10 items (including food items) that can be equipped and given to the elf. ex( rusty nail, sword, burger, burrito, etc.)
An Item represents objects the player may encounter along the way, and is an object that has a name, a description, the number of calories it can provide (0 if it isn't edible), and a weight. It must provide: A constructor that can take a name, description, calories, and weight. You must ensure the following:
- the name variable cannot be blank.
Raise a ValueError with an appropriate message if a blank string is passed in.
- the calorie variable cannot be less than 0 or more than 1000 and must be an int .
- the description cannot be blank.
- the weight must be an int and must be between 0 and 500. A __str__ method that returns a string representing the Item . The format should be
NAME - X lb - DESCRIPTION , i.e. Rusty Nail - 1 lb - A rusty nail (I hope you've had a tetanus shot)
Game
The game takes place in a world of connected locations. The purpose of the game is to collect edible items and then bring them to the elf in the woods behind campus. The elf needs 500 calories of edible food before it will save GVSU. Each item can have 0 or more calories. If a player gives the elf something inedible (something with 0 calories), the elf will be displeased and will teleport the player to a random location in the world. The player can only carry 30 pounds at a time, so multiple trips to the elf may be needed. Once the elf has enough calories, it will save campus and the game will end.
The Game class holds all the logic for a game instance. This class will hold several pieces of data. Make sure it has a dictionary of commands a list of Item s the player currently has in their inventory an int that holds the current weight the player is carrying
a list of Locations that exist in the world
a variable to hold the player's current location an int to hold the number of calories the elf needs before it will save the campus
a bool to store whether the game is still in progress
Game will adhere to the Command Pattern. Instead of having a loop body with a large number of if statements, for instance
command = input("What is your command? ") if command == 'help': self._help() elif command == 'talk': self._talk() elif command == 'go': self.move() ... On and on ... elif command = 'quit': self.quit() We can instead create a data structure that maps commands to functions. Python makes this simple with dictionaries. We could for instance do something like this:
self._commands = { 'help': self.show_help, 'talk': self.talk, ... and so on ..., 'quit': self.quit } In this example, the values of the dictionary (i.e. self._show_help , self.talk , and self.quit ) are the names of functions. Note that we are not calling the functions by putting the parentheses after the name (we didn't type self.quit() for example); we are merely giving the name of the method. Now, our input loop can look something like command = input("What is your command? ") self._commands[command]() Notice here that we did use the parentheses to call the function. We can do this because Python supports first-class function. This simply means that a function can be used just like any other piece of data. For instance, we can store a function in a list or dictionary (as we did here), or we could pass a function as a parameter to another function. The Command Pattern allows us to abstract away all of the if statements. We merely call the function that corresponds with the typed command (if one exists). Note that we can check if the command is a key of our dictionary with the in keyword:
if input in self._commands: ... do something ...
The Game class will require the most code to be written.
The Game class holds all the logic for a game instance. This class will hold several pieces of data. Make sure it has a dictionary of commands
a list of Item s the player currently has in their inventory
an int that holds the current weight the player is carrying
a list of Locations that exist in the world
a variable to hold the player's current location
an int to hold the number of calories the elf needs before it will save the campus
a bool to store whether the game is still in progress.
Game will adhere to the Command Pattern. Instead of having a loop body with a large number of if statements.
It needs a constructor that takes no parameters (other than self ). The constructor will set the commands dictionary equal to the return call from our setup_commands function. It will call the create_world method. It will then set default values for all other variables. Set the current location to a random location selected from the random_location method.
a create_world(self) -> None method that creates all the Locations , Items , and NPCs in the game. This function can get messy, as it will have a lot of text for names and descriptions of objects. Remember that your code should not be more than 72 characters long (this is marked in PyCharm with a vertical line). If a line goes beyond that, you should separate it into more than one line. You can do this by splitting the string: kirkhoff_upstairs = Location("kirkhoff upstairs", "The student union. There are restaurants, a store, and places to congregate.") becomes kirkhoff_upstairs = Location("kirkhoff upstairs", "The student union. There are restaurants, a store, and " "places to congregate.") This implicitly concatenates the two strings together, so formatting this way poses no issues. In this function you will need to add all Items and NPC s to the rooms in which they belong, as well as add each Location to the neighbors to which it needs to connect.
Also, be sure to add each Location to the self._locations list. Because there will be so much setup code, you may wish to break the function into commented regions, wherein each region focuses on the creation and setup of a single Location . Your game needs at least 8 Location s.
There is no requirement for how many Item s and NPC s must be in each Location , but your game does need at least 10 Item s and 5 NPC s.
- a setup_commands(self) -> Dict[str, Callable] method. This method will create a new dictionary. The keys will be a command such as talk , give , go , etc. The values of the dictionary will be the names of the functions that should be called for each of those commands. Note that we can have more than one command per function; for instance, we could have both "?" and "help" correspond to a self.show_help method. Be sure this function returns the dictionary.
- a random_location(self) -> Location method that selects a random Location from the locations list and returns that Location .
- a play(self) -> None method. This is the core game loop. It should first print a message describing the game, then call the method to list all commands. Then, while the game is still in progress, it will loop. In the loop, we will prompt the user for a command. The user may enter multiple words in a prompt. We will split the user's input into a list of words. We can split on spaces with code tokens = user_response.split() . Once we have the tokens list, create a variable called command and set it equal to the first element in the list. Then, remove the first element with the del(tokens[0]) command. Then, use the code target = ' '.join(tokens) code to put the remaining tokens together. Thus, if the user enters talk ball of light then command will be equal to talk , and target will be ball of light We will then call the function from the commands dictionary by using this key.
Pass target as a parameter to the called function. If the command does not exist in the dictionary print a message to the user telling them so. Once the loop ends (i.e. the in-progress variable is False), check if the elf got enough calories. If it did, print a success message and quit. Otherwise, print a failure message and quit. a show_help(self) method that prints out a help message and all the commands from the command dictionary's keys. This method must also post the current time. You will need to read the datetime documentation to do this - Print the time in a nicely formatted string, but you can decide if you wish to use 12 or 24-hour time.
- a talk(self, target) -> None method. This method will check if the provided NPC is in the current room. If it is, it will call the NPC's get_message method and print the resulting message.
- a meet(self, target) -> None method. It will check if the NPC is in the room, and if it is will ask the NPC for its description and print it. a take(self, target) -> None method. If the target item is in the room it will remove it from the room's inventory, add it to the user's inventory, and add the weight of the item to the user's carried weight.
- a give(self, target) -> None method. Removes the target item (if it exists) from the user's inventory, adds it to the current location's inventory and decreases the user's carried weight. The function will then check if the current location is the woods. If it is, it will check if the item given was edible. If the item is edible, reduce the number of calories the item has from the total the elf needs. If the item was not edible, transport the player to a new location by setting the current location equal to the return from random_location .
- a go(self, target) -> None method. Sets the current location's visited status to True. Checks if the player has over 30 weight; prints a message and returns if so. Otherwise, it checks if provided direction exists in the current location's neighbor dictionary. If so, sets the current location equal to the value from the dictionary.
- a show_items(self, args: str = None) -> None method. This method doesn't need any parameters but has an args parameter so it can be called with the same syntax as the other commands. It should print all items the player is carrying, and the current amount of weight carried.
- a look(self, args: str = None) -> None method. This method doesn't need parameters either but has args for the same reason as given above. This method will print the current location, a list of Item s in the location or a message indicating there are none, a list of NPC s in the room or the message "You are alone.", and a list of directions in which the player can go. If a location has been visited previously, print the direction and the location. Otherwise, simply print the direction.
- a quit(self, args: str = None) -> None method that prints a failure message and exits the game.
- two additional command functions that you design and create. You could add teleportation, magic, etc.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started