Stage 7 - Victory Conditions¶
Introduction¶
We’re almost done with our text-based adventure game. You now have a dungeon where the player can move around, pick up items, and talk or fight with different characters. What happens in these interactions depends on the type of character they meet.
In this stage, you’re going to set up how the player wins the game.
You will do this by:
Pseudocode
counting how many enemies exist
lowering that count each time an enemy is defeated
checking when the count reaches zero so the player wins the game
Class Diagram¶
Have a look at the class diagram for this stage and you’ll see something new.
The Enemy class now has:
a
num_of_enemyattributea
get_num_of_enemymethod

The num_of_enemy attribute is underlined in the diagram. That underline shows it’s a class variable. A class variable is shared by every object made from that class. All Enemy objects can read it and change it, and whenever one object changes it, the others see the new value too.
In this game, num_of_enemy keeps track of how many Enemy objects exist, and every enemy you create will share that same number.
Count Number of Enemies¶
To keep track of how many Enemy objects are in the game, we need to add a class variable to the Enemy class.
Open character.py and add the highlighted code shown below.
1# character.py
2
3class Character():
4
5 def __init__(self, name):
6 # initialises the character object
7 self.name = name
8 self.description = None
9 self.conversation = None
10
11 def describe(self):
12 # sends a description of the character to the terminal
13 print(f"{self.name} is here, {self.description}")
14
15 def talk(self):
16 # send converstation to the terminal
17 if self.conversation is not None:
18 print(f"{self.name}: {self.conversation}")
19 else:
20 print(f"{self.name} doesn't want to talk to you")
21
22 def hug(self):
23 # the character responds to a hug
24 print(f"{self.name} doesn't want to hug you")
25
26 def fight(self,item):
27 # the character response to a threat
28 print(f"{self.name} doesn't want to fight you")
29 return True
30
31class Friend(Character):
32
33 def __init__(self, name):
34 # initialise the Friend object by calling the character initialise
35 super().__init__(name)
36
37 def hug(self):
38 # the friend responds to a hug
39 print(f"{self.name} hugs you back.")
40
41class Enemy(Character):
42
43 num_of_enemy = 0
44
45 def __init__(self,name):
46 # initialise the Enemy object by calling the character initialise
47 super().__init__(name)
48 self.weakness = None
49 Enemy.num_of_enemy += 1
50
51 def fight(self, item):
52 # fights enemy with provided item and returns if player survives
53 if item == self.weakness:
54 print(f"You strike {self.name} down with {item}.")
55 return True
56 else:
57 print(f"{self.name} crushes you. Puny adventurer")
58 return False
Save the code, and run it to ensure there are no errors.
Investigating the code:
Code Explaination
num_of_enemy = 0→ this creates the class variable.Class variables must be written before the
__init__method.They are indented once, at the same level as the methods.
It does not use
selfbecause it belongs to the whole class, not to one object.
Enemy.num_of_enemy += 1→ this adds 1 tonum_of_enemyevery time a newEnemyis created.Because
__init__runs whenever you make a new enemy, the total number of enemies goes up each time.
Now that we are keeping track of the number of enemies, but we can’t see what that number is. So let’s create a method to find out how many enemies are in the dungeon
Still working in character.py, add the highlighted code below:
1# character.py
2
3class Character():
4
5 def __init__(self, name):
6 # initialises the character object
7 self.name = name
8 self.description = None
9 self.conversation = None
10
11 def describe(self):
12 # sends a description of the character to the terminal
13 print(f"{self.name} is here, {self.description}")
14
15 def talk(self):
16 # send converstation to the terminal
17 if self.conversation is not None:
18 print(f"{self.name}: {self.conversation}")
19 else:
20 print(f"{self.name} doesn't want to talk to you")
21
22 def hug(self):
23 # the character responds to a hug
24 print(f"{self.name} doesn't want to hug you")
25
26 def fight(self,item):
27 # the character response to a threat
28 print(f"{self.name} doesn't want to fight you")
29 return True
30
31class Friend(Character):
32
33 def __init__(self, name):
34 # initialise the Friend object by calling the character initialise
35 super().__init__(name)
36
37 def hug(self):
38 # the friend responds to a hug
39 print(f"{self.name} hugs you back.")
40
41class Enemy(Character):
42
43 num_of_enemy = 0
44
45 def __init__(self,name):
46 # initialise the Enemy object by calling the character initialise
47 super().__init__(name)
48 self.weakness = None
49 Enemy.num_of_enemy += 1
50
51 def fight(self, item):
52 # fights enemy with provided item and returns if player survives
53 if item == self.weakness:
54 print(f"You strike {self.name} down with {item}.")
55 return True
56 else:
57 print(f"{self.name} crushes you. Puny adventurer")
58 return False
59
60 def get_num_of_enemy():
61 return Enemy.num_of_enemy
Let’s investigate that method:
Code Explaination
def get_num_of_enemy():→ this creates the method.It doesn’t have
selfbecause it’s not linked to one object; it works for the whole class.
return Enemy.num_of_enemy→ this gives back the current number of enemies.The
Enemy.part tells Python to use the class variable from theEnemyclass.
Reduce Enemy Count¶
We can now count how many enemies there are and check that number, but we also need to lower the count when the player beats an enemy.
The fight method in the Enemy class already runs code when an enemy is defeated, so we just need to add one extra line there.
Stay in character.py and add the highlighted line below.
1# character.py
2
3class Character():
4
5 def __init__(self, name):
6 # initialises the character object
7 self.name = name
8 self.description = None
9 self.conversation = None
10
11 def describe(self):
12 # sends a description of the character to the terminal
13 print(f"{self.name} is here, {self.description}")
14
15 def talk(self):
16 # send converstation to the terminal
17 if self.conversation is not None:
18 print(f"{self.name}: {self.conversation}")
19 else:
20 print(f"{self.name} doesn't want to talk to you")
21
22 def hug(self):
23 # the character responds to a hug
24 print(f"{self.name} doesn't want to hug you")
25
26 def fight(self,item):
27 # the character response to a threat
28 print(f"{self.name} doesn't want to fight you")
29 return True
30
31class Friend(Character):
32
33 def __init__(self, name):
34 # initialise the Friend object by calling the character initialise
35 super().__init__(name)
36
37 def hug(self):
38 # the friend responds to a hug
39 print(f"{self.name} hugs you back.")
40
41class Enemy(Character):
42
43 num_of_enemy = 0
44
45 def __init__(self,name):
46 # initialise the Enemy object by calling the character initialise
47 super().__init__(name)
48 self.weakness = None
49 Enemy.num_of_enemy += 1
50
51 def fight(self, item):
52 # fights enemy with provided item and returns if player survives
53 if item == self.weakness:
54 print(f"You strike {self.name} down with {item}.")
55 Enemy.num_of_enemy -= 1
56 return True
57 else:
58 print(f"{self.name} crushes you. Puny adventurer")
59 return False
60
61 def get_num_of_enemy():
62 return Enemy.num_of_enemy
Save the code before we Investigate it:
Code Explaination
Line
53already checks if the player wins the fight.Enemy.num_of_enemy -= 1makes the class variable go down by one when an enemy is defeated.
Check for Victory¶
The player wins the game when every enemy has been defeated. When that happens, Enemy.num_of_enemy will be 0. So we need to choose the right spot in the code to check for this.
In main.py, line 89 is already where the game checks if the player wins, so that’s the best place to add our num_of_enemy check.
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
24# create characters
25ugine = Enemy("Ugine")
26ugine.description = "a huge troll with rotting teeth."
27ugine.weakness = "cheese"
28
29nigel = Friend("Nigel")
30nigel.description = "a burly dwarf with golden bead in woven through his beard."
31nigel.conversation = "Well youngan, what are you doing here?"
32
33# add characters to rooms
34armoury.character = ugine
35lab.character = nigel
36
37# create items
38cheese = Item("Cheese")
39cheese.description = "super smelly"
40
41chair = Item("Chair")
42chair.description = "designed to be sat on"
43
44elmo = Item("Elmo")
45elmo.description = "wanting to be tickled"
46
47# add items to rooms
48cavern.item = chair
49armoury.item = elmo
50lab.item = cheese
51
52'''
53# describe the rooms
54cavern.describe()
55armoury.describe()
56lab.describe()
57'''
58
59# initialise variables
60running = True
61current_room = cavern
62backpack = []
63
64# ----- MAIN LOOP -----
65while running:
66 current_room.describe()
67
68 command = input("> ").lower()
69
70 if command in ["north", "south", "east", "west"]:
71 current_room = current_room.move(command)
72 elif command == "talk":
73 if current_room.character is not None:
74 current_room.character.talk()
75 else:
76 print("There is no one here to talk to")
77 elif command == "hug":
78 if current_room.character is not None:
79 current_room.character.hug()
80 else:
81 print("There is no one here to hug")
82 elif command== "fight":
83 if current_room.character is not None:
84 weapon = input("What will you fight with? > ").lower()
85 available_weapons = []
86 for item in backpack:
87 available_weapons.append(item.name)
88 if weapon in available_weapons:
89 if current_room.character.fight(weapon):
90 if isinstance(current_room.character, Enemy):
91 current_room.character = None
92 if Enemy.get_num_of_enemy() == 0:
93 print("You have slain all the enemies. You are victorious!")
94 running = False
95 else:
96 running = False
97 else:
98 print(f"You don't have {weapon}")
99 print(f"{current_room.character.name} strikes you down.")
100 running = False
101 else:
102 print("There is no one here to fight")
103 elif command == "take":
104 if current_room.item is not None:
105 backpack.append(current_room.item)
106 print(f"You put {current_room.item.name} into your backpack")
107 current_room.item = None
108 else:
109 print("There is nothing here to take")
110 elif command == "backpack":
111 if backpack == []:
112 print("It is empty")
113 else:
114 print("You have:")
115 for item in backpack:
116 print(f"- {item.name.capitalize()}")
117 elif command == "quit":
118 running = False
119 else:
120 print("I don't understand.")
Investigating that code:
Code Explaination
Line
89makes sure this code only runs after the player defeats an enemy.if Enemy.get_num_of_enemy() == 0:checks if the class variable has reached0.print("You have slain all the enemies. You are victorious!")shows the win message.running = Falsestops the main loop so the game can end.
Testing¶
Now time to test our code.
Predict what you think will happen, then run your code. Make sure that you test that the player wins when they have defeated all the enemies.