Skip to content

Commit 20442f1

Browse files
committed
stage 8 reworked
1 parent 35a95e1 commit 20442f1

31 files changed

+483
-341
lines changed

_static/custom.css

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,24 @@ h4 {
5454
}
5555

5656
/* Sidebar background (covers gutter left of nav) */
57+
body:not([data-theme="dark"]) {
58+
background: #ffdfb4 !important;
59+
}
60+
body:not([data-theme="dark"]) .page {
61+
background: #ffdfb4 !important;
62+
}
63+
.main,
64+
.main-content,
65+
.content,
66+
.article {
67+
background: #ffffff !important;
68+
}
69+
body[data-theme="dark"] .main,
70+
body[data-theme="dark"] .main-content,
71+
body[data-theme="dark"] .content,
72+
body[data-theme="dark"] .article {
73+
background: transparent !important;
74+
}
5775
.sidebar-drawer,
5876
.sidebar,
5977
.sidebar-container,
@@ -117,17 +135,14 @@ h4 {
117135
) !important;
118136
}
119137

120-
/* Override base background (left gutter) while keeping content white */
121-
html,
122-
body {
123-
background: #ffdfb4 !important;
124-
}
125-
.page {
126-
background: #ffdfb4 !important; /* ensure outer layout uses the gutter color */
138+
/* Sidebar subtitle via pseudo-element */
139+
.sidebar-brand-text::after {
140+
content: "Object Orentated Python";
141+
display: block;
142+
font-size: 0.9rem;
143+
color: var(--color-foreground-muted);
144+
margin-top: 0.1rem;
127145
}
128-
.main,
129-
.main-content,
130-
.content,
131-
.article {
132-
background: #ffffff !important; /* keep center content area white */
146+
.sidebar-brand-text {
147+
color: #000000 !important;
133148
}

build/.buildinfo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Sphinx build info version 1
22
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
3-
config: 18f0f6d15f8fe781a14a84e8cb0397cc
3+
config: 17e558abee438519930b4a4f55f41399
44
tags: 645f666f9bcd5a90fca523b33c5a78b7

build/.buildinfo.bak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Sphinx build info version 1
22
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
3-
config: b66cfdc9d94f3475b7b891ac0a6eab11
3+
config: f7ef413303263d410bc28d1a0d115a6d
44
tags: 645f666f9bcd5a90fca523b33c5a78b7

build/.doctrees/environment.pickle

179 Bytes
Binary file not shown.

build/.doctrees/stage_7.doctree

2.74 KB
Binary file not shown.

build/.doctrees/stage_8.doctree

3.38 KB
Binary file not shown.

build/_sources/stage_7.md.txt

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,48 @@
11
# Stage 7 - Victory Conditions
22

3-
```{topic} In this lesson you will:
4-
5-
- Count the number of enemies
6-
- Create victory conditions
3+
```{topic} Learning Intentions
4+
In this lesson you will:
5+
* Know the difference between class variables and normal (instance) variables in an OOP programme.
6+
* Understand how objects can share information by using a class variable.
7+
* Know when and where to put if-statements inside methods so an object can make decisions.
8+
* Create and change class variables so objects can share the same data.
9+
* Write methods that use if-statements to change what an object does based on what is happening in the programme.
710
```
811

912
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/hTGv542obJo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
1013

1114
## Introduction
1215

13-
We are close to finishing our text-based adventure game. We now have a dungeon in which the user can move around, collect different items, interact with different characters and have the result of those interactions determined by the character type.
16+
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.
1417

15-
In this stage we will look at establishing victory conditions for the game.
18+
In this stage, you’re going to set up how the player wins the game.
1619

17-
We will do this by:
20+
You will do this by:
1821

19-
- keeping a count of the number of enemies
20-
- reducing the enemy count when each enemy is defeated
21-
- declare the player victorious when there are no enemies left
22+
* counting how many enemies exist
23+
* lowering that count each time an enemy is defeated
24+
* checking when the count reaches zero so the player wins the game
2225

2326
### Class Diagram
2427

25-
Look to our class diagram for this stage and you will notice something new.
28+
Have a look at the class diagram for this stage and you’ll see something new.
2629

27-
The `Enemy` class has a new:
30+
The `Enemy` class now has:
2831

29-
- `num_of_enemy` attribute
30-
- `get_num_of_enemy` method
32+
* a `num_of_enemy` attribute
33+
* a `get_num_of_enemy` method
3134

3235
![lesson 7 class diagram](./assets/lesson_7_class_diagram.png)
3336

34-
Notice the `num_of_enemy` attribute is underlined. This indicates that this is a **class variable**. This means that the variable is shared across to all instances of that class. Each instance of that class can access and modify the variable, and any changes will be shared with other classes.
37+
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.
3538

36-
In our example, the `num_of_enemy` will be shared with all the `Enemy` objects we create in our game.
39+
In this game, `num_of_enemy` keeps track of how many `Enemy` objects exist, and every enemy you create will share that same number.
3740

3841
## Count Number of Enemies
3942

40-
To keep track of the number of `Enemy` objects in the game, we need to add a **class variable** to the `Enemy` class.
43+
To keep track of how many `Enemy` objects are in the game, we need to add a **class variable** to the `Enemy` class.
4144

42-
So we need to open the **character.py** file, and add the highlighted code below.
45+
Open **character.py** and add the highlighted code shown below.
4346

4447
```{code-block} python
4548
:linenos:
@@ -108,13 +111,14 @@ Save the code, and **run** it to ensure there are no errors.
108111

109112
**Investigating** the code:
110113

111-
- `num_of_enemy = 0` &rarr; creates our **class variable**
112-
- important to note the location and the indent level of **class variables**:
113-
- need to be placed before the `__init__` method
114-
- indented once &rarr; same level as method definitions
115-
- also note that, unlike the other attributes, `num_of_enemy` does start with `self` because it is a **class variable**
116-
- `Enemy.num_of_enemy += 1` &rarr; increases `num_of_enemy` by one each time a new `Enemy` object is created.
117-
- since `__init__` runs each time a new enemy is made, the value of `num_of_enemy` will increase
114+
```{admonition} Code Explaination
115+
* `num_of_enemy = 0` &rarr; this creates the **class variable**.
116+
* Class variables must be written **before** the `__init__` method.
117+
* They are indented once, at the same level as the methods.
118+
* It does **not** use `self` because it belongs to the whole class, not to one object.
119+
* `Enemy.num_of_enemy += 1` &rarr; this adds 1 to `num_of_enemy` every time a new `Enemy` is created.
120+
* Because `__init__` runs whenever you make a new enemy, the total number of enemies goes up each time.
121+
```
118122

119123
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
120124

@@ -188,18 +192,20 @@ class Enemy(Character):
188192

189193
Let's investigate that method:
190194

191-
- `def get_num_of_enemy():` &rarr; defines the method
192-
- there is no `self` argument &rarr; this method is not tied to a particular instance, but rather the whole class.
193-
- `return Enemy.num_of_enemy` &rarr; provides the current value of `num_of_enemy`
194-
- notice the `Enemy.` &rarr; tells Python this is a **class variable** of the `Enemy` class
195+
```{admonition} Code Explaination
196+
* `def get_num_of_enemy():` &rarr; this creates the method.
197+
* It doesn’t have `self` because it’s not linked to one object; it works for the whole class.
198+
* `return Enemy.num_of_enemy` &rarr; this gives back the current number of enemies.
199+
* The `Enemy.` part tells Python to use the **class variable** from the `Enemy` class.
200+
```
195201

196202
## Reduce Enemy Count
197203

198-
So we have a count of the number of enemies, and we can retrieve that value, now we need to reduce the enemy count when the player defeats an enemy.
204+
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.
199205

200-
The `Enemy` class `fight` method already has code that is executed when the player defeats the enemy, so we just need to add to that.
206+
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.
201207

202-
Still in **character.py** go to insert the highlighted line below:
208+
Stay in **character.py** and add the highlighted line below.
203209

204210
```{code-block} python
205211
:linenos:
@@ -270,14 +276,16 @@ class Enemy(Character):
270276

271277
Save the code before we **Investigate** it:
272278

273-
- line `53` &rarr; already determines if the player beats the enemy
274-
- `Enemy.num_of_enemy -= 1` &rarr; reduces the value of the **class variable** by one.
279+
```{admonition} Code Explaination
280+
* Line `53` already checks if the player wins the fight.
281+
* `Enemy.num_of_enemy -= 1` makes the class variable go down by one when an enemy is defeated.
282+
```
275283

276284
## Check for Victory
277285

278-
The player will be victorious when they have defeated all the enemies in the dungeon. When all the enemies have been defeated the `Enemy.num_of_emeny` will be `0`. So we need to find the best place to check this.
286+
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.
279287

280-
Let's look back at **main.py**. Line `89` is where Python decides if they player wins, so it makes sense to put out `num_of_enemy` check around here.
288+
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.
281289

282290
Add the highlighted code below:
283291

@@ -408,10 +416,12 @@ while running:
408416

409417
**Investigating** that code:
410418

411-
- line `89` &rarr; already established that our new code will only run when the player defeats an enemy
412-
- `if Enemy.get_num_of_enemy() == 0:` &rarr; checks if the **class variable** is `0`
413-
- `print("You have slain all the enemies. You are victorious!")` &rarr; displays a victory message
414-
- `running = False` &rarr; readies to finish the game by exiting the main loop.
419+
```{admonition} Code Explaination
420+
* Line `89` makes sure this code only runs after the player defeats an enemy.
421+
* `if Enemy.get_num_of_enemy() == 0:` checks if the class variable has reached `0`.
422+
* `print("You have slain all the enemies. You are victorious!")` shows the win message.
423+
* `running = False` stops the main loop so the game can end.
424+
```
415425

416426
## Testing
417427

build/_sources/stage_8.md.txt

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
# Stage 8 - Useability
22

3-
```{topic} In this lesson you will:
4-
5-
- Improve the code useabilty
3+
```{topic} Learning Intentions
4+
In this lesson you will:
5+
* understand why making something easy to use is important for the person using it
6+
* know what UI and UX mean and why they matter when people use a program
7+
* understand how comments and neat code make a program easier to read and fix
8+
* improve a program by adding features that help the user, like a help option or clearer messages
9+
* tidy up a program by removing code you don’t need and organising it so it’s easier to read and use
610
```
711

812
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/lHSCfn0U45k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
913

1014
## Introduction
1115

12-
Our dungeon is complete. We have a fully functioning game, but before we sign-off we need to improve the useability of our program and tidy up our code.
16+
Our dungeon works, but before we finish we need to make it easier to use and clean up the code.
17+
18+
We will:
1319

14-
To do this we will:
20+
* add a **help** command
21+
* make the program easier to read and use
22+
* add a goodbye message at the end
23+
* write more comments in the code
24+
* delete code we don’t need
25+
* make our spacing neat and consistent
1526

16-
- Create a **help** command
17-
- Improve the user experience and user interface
18-
- Add a farewell message
19-
- Add some in-code comments
20-
- Remove unused code
21-
- Standardise our white-space
2227

2328
## Help command
2429

25-
We know all the commands we can use because we wrote the code. Someone else might not know what they can say. In addition, if they don't enter one of the commands, the program only says `I don't understand.`, which is far from helpful.
30+
We know the commands because we wrote the code. A new player won’t know what they’re allowed to type. Right now, if they type something wrong, the program just says I dont understand,” which isn’t very helpful.
2631

27-
To make life easier for new players, we should create a **help** command which lists all the commands. But how will the player know about the **help** command, without using the **help** command? Simple, we change the catch-all event handler (under the `else:`) to inform the user about the help command.
32+
To fix this, we should add a **help** command that shows all the commands. But players won’t know the help command exists unless we tell them. So we update the final `else:` section to remind them to type “help” when they get something wrong.
2833

29-
To implement this, add the highlighted code below to **main.py**:
34+
Now add the highlighted code to **main.py**.
3035

3136
```{code-block} python
3237
:linenos:
@@ -161,23 +166,25 @@ while running:
161166
print("Enter 'help' to list the copmmands.")
162167
```
163168

164-
By now this code should be familiar and makes sense to you.
169+
You’ve seen this kind of code many times now, so you should already understand how it works without investigating it.
165170

166171
## Improving the UI and UX
167172

168-
Although our program is visually very simple, the user stills interacts with it, which means we need to consider the UI and the UX.
173+
Even though our program looks simple, people still have to use it, so we need to think about the UI and UX &mdash; how it looks and how easy it is to use.
174+
169175

170176
```{admonition} UI and UX
171-
UI stands for User Interface, which is basically what you see on your screen when you use an app or a website. This includes things like buttons, menus, icons, and colors. UI design focuses on making things look good and easy to use.
177+
:class: note
178+
UI means **User Interface**. It’s the stuff you actually see on the screen when you use an app or website — things like buttons, menus, icons, and colours. UI is about making everything look clear and easy to use.
172179

173-
UX stands for User Experience, which is how you feel when you use an app or a website. It's about how easy it is to use, how it makes you feel, and whether it helps you achieve what you're trying to do. UX design focuses on making things easy and enjoyable to use.
180+
UX means **User Experience**. Its about what it *feels* like to use the app — if it’s easy, confusing, fun, or annoying. UX is about making sure the user has a smooth and enjoyable time using the program.
174181
```
175182

176-
We have already addressed some UI and UX problems by adding the **help** command. Play the game and see if you can identify anything else.
183+
We’ve already fixed some UI and UX issues by adding the **help** command. Now play the game and see if you can spot anything else that feels confusing.
177184

178-
Did you notice that after entering a command, the game responds and then quickly describes the room again. It's really easy to loose the command response in this quick action. Let's change that by writing the response and then asking the user to press a key to proceed.
185+
You might notice that after you type a command, the game shows the response and then instantly prints the room description again. This makes it easy to miss what the game just told you. To fix that, we’ll show the response and then make the user press a key before the game continues.
179186

180-
I implement this, add the highlighted code below.
187+
To do this, add the highlighted code below.
181188

182189
```{code-block} python
183190
:linenos:
@@ -317,16 +324,18 @@ Save the file, **predict** and then **run** the code.
317324

318325
How does that work? Let's **investigate**:
319326

320-
- `input("\nPress <Enter> key to continue")` &rarr; this is a hack. That is we are using `input` in an unconventional way to achieve our desired outcome.
321-
- the normal operation of `input` is to wait for the user response &rarr; addresses the pausing of the game
322-
- normally the user enters their response by pressing the Enter key &rarr; stops the pausing
323-
- the value the user enters is **not** assigned to a variable, so it just disappears
327+
```{admonition} Code Explaination
328+
* `input("\nPress <Enter> key to continue")` is basically a little trick. We’re using `input` in a way it’s not normally meant to be used.
329+
* Normally, `input` waits for the user to type something, which is why it pauses the game.
330+
* The user presses **Enter** to continue, which ends the pause.
331+
* We don’t save what the user types, so whatever they enter is ignored and disappears.
332+
```
324333

325334
## Farewell message
326335

327-
When the game ends, it just stops. Whether the player won or lost it just exits the the Shell prompt. To make things a little more polite, we should add an farewell message.
336+
When the game ends, it just shuts off straight away. No message, even if you win or lose. To make the ending feel a bit nicer, we should add a goodbye message.
328337

329-
To include a farewell message add the highlighted code below
338+
Add the highlighted code below to include the farewell message.
330339

331340
```{code-block} python
332341
:linenos:
@@ -465,7 +474,13 @@ print("Thank you for playing Deepest Dungeon")
465474

466475
## In-code comments
467476

468-
We already have some in-code comment that helps structure our code, but we have missed much of the main loop. We should add some comment to the main loop to make our code more readable and therefore maintainable.
477+
We already have a few comments in the code to help explain what parts do, but most of the main loop doesn’t have any. Adding comments there will make the code easier to read and easier to fix later.
478+
479+
480+
```{admonition} Code maintainability
481+
:class: note
482+
Code maintainability means making your code easy to understand, fix, and update later. If your code is neat, well-organised, and has clear comments, you or someone else can quickly figure out how it works. This makes it easier to find bugs, add new features, and change things without breaking the program.
483+
```
469484

470485
Let's first start with **main.py**
471486

@@ -613,7 +628,7 @@ while running:
613628
print("Thank you for playing Deepest Dungeon")
614629
```
615630

616-
When you create classes your should really have a comment that explains what each method does. If you look at the classes in our **room.py**, **item.py** and **character.py** files you will see that we have already done this.
631+
When you make classes, it’s a good idea to add a comment explaining what each method does. If you check the classes in **room.py**, **item.py**, and **character.py**, you’ll see we’ve already done this there.
617632

618633
## Remove unused code
619634

@@ -764,7 +779,7 @@ print("Thank you for playing Deepest Dungeon")
764779

765780
## Final code
766781

767-
White space is the blank lines between our code. You can use this to help structure your code.
782+
Whitespace is the empty lines in your code. You can use it to break your code into clear sections and make it easier to read.
768783

769784
Finalise your code by adjusting it so to look the same as the following code:
770785

@@ -1035,8 +1050,8 @@ class Item():
10351050

10361051
## Final Make
10371052

1038-
The tutorials are now over. It is time to make this dungeon yours by adding new features. The Extensions Ideas page has some suggestions.
1053+
The tutorials are finished. Now it’s your turn to make the dungeon your own by adding new features. You can check the Extension Ideas page for inspiration.
10391054

1040-
The current code does have a couple of logical errors, but you will have to test it to find out what they are and then try and solve them. Don't forget to use your debugger to help you with this.
1055+
There are a few logic mistakes in the code, but you’ll need to test the game to find them and work out how to fix them. Make sure you use your debugger to help.
10411056

1042-
Good luck. May your adventure be long and fruitful.
1057+
Good luck on your adventure.

0 commit comments

Comments
 (0)