Stage 6 - Use Items

Introduction

Our game is progressing nicely. They player can move between multiple rooms, interact with different types of characters. We also have different items in these room.

The next step is to allow the player to collect the items and use them.

To achieve this we will:

  • create a backpack variable that can store items

  • add a take command that collects the items

  • add a backpack command to list the items in the backpack

  • restrict the fight weapon to items in the backpack

Class Diagram

If we look at the class diagram, we notice that there are no changes. All of the changes in this section will be made in the main.py file, and will not involve adjusting any classes.

lesson 6 class diagram

Creating a backpack

The first thing we need to create is a backpack variable, so we can store the items we collect. To achieve this, we need a variable type that can hold multiple values. In Python these are called collections. We will be using lists, a type of collection that you will be familiar with.

Collections in Python

In Python, a collection is a way to group things together. There are different types of collections like lists, sets, and dictionaries. You can use them to store a bunch of values or items, like a shopping list or a list of names. Each type of collection has different rules and ways to use it. By choosing the right type of collection for what you need, it can help you write better code that works faster and is easier to read.

Python has following collections built it:

  • Lists: ordered collections of values, which can be of any data type. They are created using square brackets [] and values are separated by commas.

  • Tuples: similar to lists, but they are immutable, which means that their values cannot be changed after they are created. They are created using parentheses () and values are separated by commas.

  • Sets: unordered collections of unique values. They are created using curly braces {} or the set() constructor.

  • Dictionaries: unordered collections of key-value pairs. They are created using curly braces {} and key-value pairs are separated by commas, with a colon : between the key and value.

It also has modules to support other collections:

  • Arrays: used to store a sequence of values of the same data type. They are created using the array module.

  • Queues: data structures that use a first-in, first-out (FIFO) method to store and retrieve data. They are implemented using the queue module.

  • Stacks: Stacks are data structures that use a last-in, first-out (LIFO) method to store and retrieve data. They are implemented using the stack module.

Lists are the perfect collection for our purposed. It can start as empty and we can then use the append() method to add items as they are picked up by the user. We can also check if out backpack contains an item using the in operator. We can access the time using list indexation, as well as using pop to remove the item from the backpack. So let’s create it.

Open main.py and add the highlighted code below:

 1# main.py
 2
 3from room import Room
 4from character import Enemy, Friend
 5from item import Item
 6
 7# create rooms
 8cavern = Room("Cavern")
 9cavern.description = ("A room so big that the light of your torch doesn’t reach the walls.")
10
11armoury = Room("Armoury")
12armoury.description = ("The walls are lined with racks that once held weapons and armour.")
13
14lab = Room("Laboratory")
15lab.description = ("A strange odour hangs in a room filled with unknownable contraptions.")
16
17# link rooms
18cavern.link_rooms(armoury,"south")
19armoury.link_rooms(cavern,"north")
20armoury.link_rooms(lab,"east")
21lab.link_rooms(armoury,"west")
22
23# create characters
24ugine = Enemy("Ugine")
25ugine.description = "a huge troll with rotting teeth."
26ugine.weakness = "cheese"
27
28nigel = Friend("Nigel")
29nigel.description = "a burly dwarf with golden bead in woven through his beard."
30nigel.conversation = "Well youngan, what are you doing here?"
31
32# add characters to rooms
33armoury.character = ugine
34lab.character = nigel
35
36# create items
37cheese = Item("Cheese")
38cheese.description = "super smelly"
39
40chair = Item("Chair")
41chair.description = "designed to be sat on"
42
43elmo = Item("Elmo")
44elmo.description = "wanting to be tickled"
45
46# add items to rooms
47cavern.item = chair
48armoury.item = elmo
49lab.item = cheese
50
51'''
52# describe the rooms
53cavern.describe()
54armoury.describe()
55lab.describe()
56'''
57
58# initialise variables
59running = True
60current_room = cavern
61backpack = []
62
63# ----- MAIN LOOP -----
64while running:
65    current_room.describe()
66    
67    command = input("> ").lower()
68    
69    if command in ["north", "south", "east", "west"]:
70        current_room = current_room.move(command)
71    elif command == "talk":
72        if current_room.character is not None:
73            current_room.character.talk()
74        else:
75            print("There is no one here to talk to")
76    elif command == "hug":
77        if current_room.character is not None:
78            current_room.character.hug()
79        else:
80            print("There is no one here to hug")
81    elif command == "fight":
82        if current_room.character is not None:
83            weapon = input("What will you fight with? > ").lower()
84            if current_room.character.fight(weapon):
85                current_room.character = None
86            else:
87                running = False
88        else:
89            print("There is no one here to fight")
90    elif command == "quit":
91        running = False
92    else:
93        print("I don't understand.")

We don’t need to investigate this line of code, as we all know what it does.

Add take command

Now that we have a backpack we need to create a command that allows the user to pick up items in the room and place them in the backpack. We will use take as that command.

Still working in main.py add the take command using the highlighted code below:

  1# main.py
  2
  3from room import Room
  4from character import Enemy, Friend
  5from item import Item
  6
  7# create rooms
  8cavern = Room("Cavern")
  9cavern.description = ("A room so big that the light of your torch doesn’t reach the walls.")
 10
 11armoury = Room("Armoury")
 12armoury.description = ("The walls are lined with racks that once held weapons and armour.")
 13
 14lab = Room("Laboratory")
 15lab.description = ("A strange odour hangs in a room filled with unknownable contraptions.")
 16
 17# link rooms
 18cavern.link_rooms(armoury,"south")
 19armoury.link_rooms(cavern,"north")
 20armoury.link_rooms(lab,"east")
 21lab.link_rooms(armoury,"west")
 22
 23# create characters
 24ugine = Enemy("Ugine")
 25ugine.description = "a huge troll with rotting teeth."
 26ugine.weakness = "cheese"
 27
 28nigel = Friend("Nigel")
 29nigel.description = "a burly dwarf with golden bead in woven through his beard."
 30nigel.conversation = "Well youngan, what are you doing here?"
 31
 32# add characters to rooms
 33armoury.character = ugine
 34lab.character = nigel
 35
 36# create items
 37cheese = Item("Cheese")
 38cheese.description = "super smelly"
 39
 40chair = Item("Chair")
 41chair.description = "designed to be sat on"
 42
 43elmo = Item("Elmo")
 44elmo.description = "wanting to be tickled"
 45
 46# add items to rooms
 47cavern.item = chair
 48armoury.item = elmo
 49lab.item = cheese
 50
 51'''
 52# describe the rooms
 53cavern.describe()
 54armoury.describe()
 55lab.describe()
 56'''
 57
 58# initialise variables
 59running = True
 60current_room = cavern
 61backpack = []
 62
 63# ----- MAIN LOOP -----
 64while running:
 65    current_room.describe()
 66    
 67    command = input("> ").lower()
 68    
 69    if command in ["north", "south", "east", "west"]:
 70        current_room = current_room.move(command)
 71    elif command == "talk":
 72        if current_room.character is not None:
 73            current_room.character.talk()
 74        else:
 75            print("There is no one here to talk to")
 76    elif command == "hug":
 77        if current_room.character is not None:
 78            current_room.character.hug()
 79        else:
 80            print("There is no one here to hug")
 81    elif command == "fight":
 82        if current_room.character is not None:
 83            weapon = input("What will you fight with? > ").lower()
 84            if current_room.character.fight(weapon):
 85                current_room.character = None
 86            else:
 87                running = False
 88        else:
 89            print("There is no one here to fight")
 90    elif command == "take":
 91        if current_room.item is not None:
 92            backpack.append(current_room.item)
 93            print(f"You put {current_room.item.name} into your backpack")
 94            current_room.item = None
 95        else:
 96            print("There is nothing here to take")
 97    elif command == "quit":
 98        running = False
 99    else:
100        print("I don't understand.")

Save main.py predict what you think will happen and then run the code. What happens to the room description after you take an item?

In investigating this code, most of it should be familiar from our previous command event handlers. The different code is:

  • backpack.append(current_room.item) → take the Item object in the room and adds it to the end of the backpack list.

  • print(f"You put {current_room.item.name} into your backpack") → informs the user that they have collected the item

  • current_room.item = None → removes the Item object from the room by setting the Room object’s item attribute to None

Add backpack command

Now that we are putting items in the backpack, we need to create a way for the user to see what they have. We will make a new backpack command that lists the Item objects stored in their backpack.

Still working in main.py, add the code below:

  1# main.py
  2
  3from room import Room
  4from character import Enemy, Friend
  5from item import Item
  6
  7# create rooms
  8cavern = Room("Cavern")
  9cavern.description = ("A room so big that the light of your torch doesn’t reach the walls.")
 10
 11armoury = Room("Armoury")
 12armoury.description = ("The walls are lined with racks that once held weapons and armour.")
 13
 14lab = Room("Laboratory")
 15lab.description = ("A strange odour hangs in a room filled with unknownable contraptions.")
 16
 17# link rooms
 18cavern.link_rooms(armoury,"south")
 19armoury.link_rooms(cavern,"north")
 20armoury.link_rooms(lab,"east")
 21lab.link_rooms(armoury,"west")
 22
 23# create characters
 24ugine = Enemy("Ugine")
 25ugine.description = "a huge troll with rotting teeth."
 26ugine.weakness = "cheese"
 27
 28nigel = Friend("Nigel")
 29nigel.description = "a burly dwarf with golden bead in woven through his beard."
 30nigel.conversation = "Well youngan, what are you doing here?"
 31
 32# add characters to rooms
 33armoury.character = ugine
 34lab.character = nigel
 35
 36# create items
 37cheese = Item("Cheese")
 38cheese.description = "super smelly"
 39
 40chair = Item("Chair")
 41chair.description = "designed to be sat on"
 42
 43elmo = Item("Elmo")
 44elmo.description = "wanting to be tickled"
 45
 46# add items to rooms
 47cavern.item = chair
 48armoury.item = elmo
 49lab.item = cheese
 50
 51'''
 52# describe the rooms
 53cavern.describe()
 54armoury.describe()
 55lab.describe()
 56'''
 57
 58# initialise variables
 59running = True
 60current_room = cavern
 61backpack = []
 62
 63# ----- MAIN LOOP -----
 64while running:
 65    current_room.describe()
 66    
 67    command = input("> ").lower()
 68    
 69    if command in ["north", "south", "east", "west"]:
 70        current_room = current_room.move(command)
 71    elif command == "talk":
 72        if current_room.character is not None:
 73            current_room.character.talk()
 74        else:
 75            print("There is no one here to talk to")
 76    elif command == "hug":
 77        if current_room.character is not None:
 78            current_room.character.hug()
 79        else:
 80            print("There is no one here to hug")
 81    elif command == "fight":
 82        if current_room.character is not None:
 83            weapon = input("What will you fight with? > ").lower()
 84            if current_room.character.fight(weapon):
 85                current_room.character = None
 86            else:
 87                running = False
 88        else:
 89            print("There is no one here to fight")
 90    elif command == "take":
 91        if current_room.item is not None:
 92            backpack.append(current_room.item)
 93            print(f"You put {current_room.item.name} into your backpack")
 94            current_room.item = None
 95        else:
 96            print("There is nothing here to take")
 97    elif command == "backpack":
 98        if backpack == []:
 99            print("It is empty")
100        else:
101            print("You have:")
102            for item in backpack:
103                print(f"- {item.name.capitalize()}")
104    elif command == "quit":
105        running = False
106    else:
107        print("I don't understand.")

Save the main.py file, predict and then run your code. This time we should do some serious testing.

We need to make sure that:

  • we can pick up all the items in all the rooms

  • the items are added to the backpack when they are picked up

  • the items are removed from the room when they are picked up

If your testing all works out, then it’s time to investigate the code.

  • elif command == "backpack": → the event handler for the backpack command

  • if backpack == []: → checks if the backpack is empty

  • print("It is empty") → informs the user that the backpack is empty

  • else: → if the backpack is not empty

  • print("You have:") → displays a message before listing backpack items

  • for item in backpack: → iterates over each item in the backpack

  • print(f"- {item.name.capitalize()}") → capitalizes and prints the name of the current item that the for loop is dealing with.

Adjusting the fight command

Finally we will adjust the fight event handler so the user can only use items they currently have in their backpack.

Still working in main.py, add the code below.

  1# main.py
  2
  3from room import Room
  4from character import Enemy, Friend
  5from item import Item
  6
  7# create rooms
  8cavern = Room("Cavern")
  9cavern.description = ("A room so big that the light of your torch doesn’t reach the walls.")
 10
 11armoury = Room("Armoury")
 12armoury.description = ("The walls are lined with racks that once held weapons and armour.")
 13
 14lab = Room("Laboratory")
 15lab.description = ("A strange odour hangs in a room filled with unknownable contraptions.")
 16
 17# link rooms
 18cavern.link_rooms(armoury,"south")
 19armoury.link_rooms(cavern,"north")
 20armoury.link_rooms(lab,"east")
 21lab.link_rooms(armoury,"west")
 22
 23# create characters
 24ugine = Enemy("Ugine")
 25ugine.description = "a huge troll with rotting teeth."
 26ugine.weakness = "cheese"
 27
 28nigel = Friend("Nigel")
 29nigel.description = "a burly dwarf with golden bead in woven through his beard."
 30nigel.conversation = "Well youngan, what are you doing here?"
 31
 32# add characters to rooms
 33armoury.character = ugine
 34lab.character = nigel
 35
 36# create items
 37cheese = Item("Cheese")
 38cheese.description = "super smelly"
 39
 40chair = Item("Chair")
 41chair.description = "designed to be sat on"
 42
 43elmo = Item("Elmo")
 44elmo.description = "wanting to be tickled"
 45
 46# add items to rooms
 47cavern.item = chair
 48armoury.item = elmo
 49lab.item = cheese
 50
 51'''
 52# describe the rooms
 53cavern.describe()
 54armoury.describe()
 55lab.describe()
 56'''
 57
 58# initialise variables
 59running = True
 60current_room = cavern
 61backpack = []
 62
 63# ----- MAIN LOOP -----
 64while running:
 65    current_room.describe()
 66    
 67    command = input("> ").lower()
 68    
 69    if command in ["north", "south", "east", "west"]:
 70        current_room = current_room.move(command)
 71    elif command == "talk":
 72        if current_room.character is not None:
 73            current_room.character.talk()
 74        else:
 75            print("There is no one here to talk to")
 76    elif command == "hug":
 77        if current_room.character is not None:
 78            current_room.character.hug()
 79        else:
 80            print("There is no one here to hug")
 81    elif command== "fight":
 82        if current_room.character is not None:
 83            weapon = input("What will you fight with? > ").lower()
 84            available_weapons = []
 85            for item in backpack:
 86                available_weapons.append(item.name)
 87            if weapon in available_weapons:
 88                if current_room.character.fight(weapon):
 89                    current_room.character = None
 90                else:
 91                    running = False
 92            else:
 93                print(f"You don't have {weapon}")
 94                print(f"{current_room.character.name} strikes you down.")
 95                running = False
 96        else:
 97            print("There is no one here to fight")
 98    elif command == "take":
 99        if current_room.item is not None:
100            backpack.append(current_room.item)
101            print(f"You put {current_room.item.name} into your backpack")
102            current_room.item = None
103        else:
104            print("There is nothing here to take")
105    elif command == "backpack":
106        if backpack == []:
107            print("It is empty")
108        else:
109            print("You have:")
110            for item in backpack:
111                print(f"- {item.name.capitalize()}")
112    elif command == "quit":
113        running = False
114    else:
115        print("I don't understand.")

Save main.py. Predict what you think will happen, and then run the code.

Let’s investigate that code, but be aware that there are a number of different sections to that code.

First we need to check that the user actually has the entered weapon in their backpack.

  • available_weapons = [] → creates a new list that contains the name attribute for all items in the backpack.

    • the backpack stored Item objects

    • the user entered the item name as a string

    • therefore, we need to create a list of the name of all the items in the backpack

  • for item in backpack: → iterates over each item in the backpack

  • available_weapons.append(item.name) → add the name attribute of the current item to the available_weapons list.

  • if weapon in available_weapons: → checks that the weapon entered by the user is in the list of available weapons.

If the user entered an available weapon, then we need to fight with this weapon. Lines 88 to 91 are the same as before, but the have been indented one level. To to this easily increase a block of code’s indentation:

  • highlight lines 88 to 91, ether using the mouse or shift + arrow keys.

  • then press the Tab key once

If the user didn’t enter an available weapon, then we need to inform them, then make them loose the fight and end the game. This happens in lines 92 to 95

  • else: → the weapon entered is not in the available_weapons list

  • print(f"You don't have {weapon}") → inform the user that they do not have that item in the backpack

  • print(f"{current_room.character.name} strikes you down.") → resolves the fight as a defeat for the user

  • running = False ends the game by exiting the main loop.

Testing

We now need to test our code. This code now has nested branches of if statements so we have to be aware of testing all the possible options. We will test with Ugine as we know his weakness is cheese.

Collected Cheese

Fought Ugine

Weapon Used

Expected Result

Actual Result

Yes

Yes

Cheese

You strike Ugine down with cheese.

Yes

Yes

Elmo

Ugine crushes you. Puny adventurer

No

Yes

Cheese

You don’t have cheese…

If your code passes all the tests, it’s time to make some code in the stage 6 task.

Stage 6 task

You need to apply the changes we made to your other characters. Especially if you have another enemy. Make sure that the user can collect their weakness and use it against them.