Python Jumpstart by Building 10 Apps Transcripts
Chapter: App 7: Wizard Battle App
Lecture: Adding behaviors to the wizard

Login or purchase this course to watch this video and the rest of the course contents.
0:00 It's time to add some behavior to our objects, now let's work with attack first. We'll just implement these 3 behaviors, attack run away and look.
0:10 So attack I think is the most interesting, we'll start there. Now, the first thing we are going to need, remember,
0:16 is the game said a creature of such and such type appears, or has come out of the forest and what do you want to do to it,
0:23 so that part is not here yet, we do have our creatures they are up here but I need to get one and randomly selecting one
0:31 seems like the ideal thing to do, so we can come down here and say something like active creature is something.
0:39 Now, in many languages you can get random numbers, random integers and so on, and you know that if I had a random integer,
0:46 I could come over here and say if I had randomly selected an index I can come over here and say creatures some index and pull that out,
0:53 but in true Python fashion, Python has a better way to do that. It still involves a random module, so we'll start there.
1:01 Add that at top and then we'll say choice, so we can go over here and say I have a set of items, I would like to randomly get one so we'll say
1:13 I would like to just randomly select a creature so let's do a little print statement to just say what that creature is.
1:19 We'll say a { } so you know, and then the name of the creature or something, has appeared from a dark and foggy forest, something like that.
1:32 Now, I want to add the levels so we'll say of level that's very important to know whether we should attack it,
1:40 so then we can say .format active creature.name and active creature.level, let's just add a little extra space here,
1:51 so let's go and run it to make sure this randomly choosing a creature is working for us, yes,
1:57 so this part up here we could probably get rid of that all right, here is our game, oh a bat of level 3 has appeared from a dark and foggy forest
2:05 do you want to attack, run away or look around. And it didn't really matter what we press, it's just going to go around and around.
2:12 You can see each time through it's randomly selecting an item so the sort of activating the random creature for a particular round is working,
2:20 now next thing to do is work on what we do when we actually attack it, how we do this, there is a couple of ways depending
2:29 on how you want the features at this game to evolve, there is maybe one way of doing it that's better than another.
2:35 But I think the simplest and straightforward one is to assume that only wizards can attack creatures and maybe other wizards
2:43 but creatures don't initiate the attack they don't have this concept of being an attacking creature they can just have,
2:49 they can be in a battle but they are not the one who initiates it. And if that's the case, which I am going to say
2:55 for this little game since I am writing it, that's the case. Putting some kind of attack behavior on the wizard
3:00 so the wizard knows how to attack creatures is the way to go, so we'll come over here and we want to say something like hero. and then
3:08 you can see we have our level and our name that we created in the init method and we want to add not just data but behavior.
3:15 so let's go over here to our actors where we have our wizard and we'll define just like any other method we are going to define a method called attack,
3:24 these instance methods they always take the self parameter, when you invoke them from the outside
3:30 you don't specify the self or anything like that not explicitly anyway, but when you define them they do, that's just how Python classes work,
3:39 and then you can pass the actual arguments that appear to the color so the thing we want to pass is some kind of creature
3:43 and we'll just print something like and we want to refer to the name of the wizard
3:49 that is the particular instance the object that was generated from this class that would be the self parameter, right,
3:56 so we'll say self.name and then the creature also has a name and a level so we'll go like that. So let's go over here now and say .attack,
4:04 now we have our data and our behavior. And we'll come down here attack the creature, so that will be active creature,
4:13 now we still have a lot of work to do to determine whether they win, to figure out even what the algorithm is for winning or losing or fighting,
4:19 but we should be able to at least test this out. Ok a bat of level 3 has appeared form the dark and foggy forest,
4:25 let's attack it, why not, so the wizard Gandolf attacks bat, so let's go finish our attack method.
4:32 Now, PyCharm has some really cool ways to navigate around, I can come over here and if I hit command B
4:37 it will actually take me over to that method wherever it happens to be defined, right, there is only two files it's pretty straightforward to find it
4:43 but in real projects you might have 50 files and where did this beast come form, that can be really tricky so that is a super helpful feature,
4:51 you can also hold down command and then all of these things basically become hyper links,
4:55 so I'll click over here and it will take us straight to attack. So, this print part, this is going well,
5:00 now what we want to do is decide on the algorithm and my simple algorithm I am going to use for this game
5:06 is the level of the creature and the level of the wizard are going to be factored into this
5:11 and we are going to have what would be more geeky in dungeon and dragon then a 12 sided dice, so you are going to roll 12 sided dice,
5:17 multiply it by your level and then whoever rolls the higher number is going to win that battle, so that will go something like this,
5:25 I'm just calling my roll = now I want a random number between 0 and 12 so we'll say random and just like before we'll import this,
5:34 and we'll say rand int and we are going to give it 1 to 12 and then I am going to multiply that by the wizard
5:40 because this is the wizard's throw by the level. Similarly, we are going to have creature roll, and it's going to be the creature's level.
5:51 And then we are just going to compare but first before we do so you get some visibility
5:56 into what's happening let's do a print statement, you roll some number, my roll and then we'll say the creature like bat or toad or whatever rolls,
6:06 then finally we are going to do a test to see who rolled the higher number, and I am going to assume if the creature and the wizard tie
6:17 because the wizard has the element of surprise, he is going to win. So that would look something like this,
6:22 if my roll is greater than or equal to creature roll, then let's return true to say that we won, on the other hand we could return false here,
6:35 now we also want to give a little visibility like print the wizard had handily defeated whatever it was, right, so we'll say .format creature.name
6:48 so down here we can say the wizard has been defeated, let's change it so we don't need to use the same words, they triumphed over, ok.
6:59 There is a couple of things going on here that are not fantastic. One of them is that this attack method really should be performing the attack,
7:10 it should be doing this algorithm here and it should be doing sort of this decision here determining whether or not you won or the creature has won.
7:20 But it's also doing this kind of UI management stuff, now this is simple game we are just going to leave it here
7:27 but in a real application you want to somehow separate if possible the UI piece from the core logic of our game
7:36 so we are kind of violating that rule here but just because we are just getting started with classes let's just keep it simple and roll with this.
7:44 All right, let's test our attack method, ok, a tiger of level 12 has appeared out of the forest,
7:51 let's go ahead and attack since well, that's the only thing we've done, and it looks like I forgot something in my print string,
7:58 so notice here there is one, two place holders but only one value provided, let's go fix that really quick. Ok, now let's try it again.
8:11 All right, this time, that same tiger has appeared, let's attack it. Ok the wizard Gandolf attacks tiger and you roll 375, the tiger 24.
8:21 So the wizard has handily defeated the tiger. Now, something more serious has happened, a dragon of level 50 let's give that thing a shot, OH NO!!!,
8:30 now we only got 75 the dragon did 100 and we have been defeated. Now there is really no consequence for us to be defeated
8:38 and if we look around we haven't implemented that part yet, but if we did, you would see that all the creatures are still there
8:44 even though they have been defeated. Let's do a little work on the consequences of being defeated.
8:49 So over here we'll say if when the hero attack the creature they win, what we should probably do is remove that creature from the game.
8:56 This creatures list holds all the living creatures, so we can do something really simple like this creatures.remove
9:02 and just give it the creature, active creature. On the other hand if the hero loses, there is two possibilities here,
9:13 one could be that's it, the game is over you are done, the other one is maybe the hero wasn't killed all the way,
9:20 they are just defeated so they have to go rest and recover. It's pretty straightforward to say print game over break without the semicolon,
9:29 break so let's look at what we might do if we want to make it pause. So to make it sort of appear to pause, we'll come over here and we'll say time
9:40 and I imported just the import time above, and I say time.sleep and that's a number of seconds it takes
9:48 a floating point number so I could do like 0.001 for milliseconds, something like that and let's say you are going to sleep for 5 seconds,
9:55 and we'll say something like this print, like this and then we can print, the wizard returns revitalized
10:05 and let's just add a new line down here at the end of all this so there is some space so here is the consequence
10:12 of either winning or losing this attack round, so when the hero attacks the creature is removed from the game when the hero loses,
10:20 we have decided that actually the game is not over, but that the hero has to go rest for a while, so let's try that,
10:27 ok again a tiger of level 12 we have seen we have a good chance against that let's go, all right,
10:32 so we have beaten the tiger, now but you can't really tell, like us we haven't verified it yet, is we haven't implemented look around,
10:40 so let's do that really quick, just so we can see that our creatures are going away. So what we are going to do is just say something like
10:47 wizard so and so takes in the surroundings and sees then I want to loop over each of the creatures so I'll just say remember our for in loop,
10:59 so we'll say for c in creatures we'll print out maybe a little sort of place holder thing like this and we'll say a name of level such and such
11:09 and again a format would be nice here so we'll say c.name c.level and maybe that fits on one line, ok. Ok, let's try this again,
11:18 now we can see if our remove is working ok so the tiger again, every single time it's the tiger, all right tiger attack oh we definitely defeated him,
11:28 oh oh, a dragon of level 50, it's not so good, so we'll look around and apparently we are going to need to put something there
11:34 a toad of level 1, a bat of level 3, a dragon and an evil wizard. Well, the dragon is away, the toad is out, we can attack it and beat it of course,
11:43 we look around again, now the toad and the tiger gone, let's attack the bat- again, we defeated it, now it's just the dragon and the evil wizard,
11:52 it's kind of getting a little bit harder for us here, I still got to fix this but let's go and do this attack,
11:57 what are we going to attack- the dragon, maybe we can beat that. Oh, we have won, ok now it's just down to the evil wizard,
12:04 there is almost no chance we are going to win here but let's give it a shot. Oh no the wizard has been defeated,
12:10 he runs and hides, taking time recovering. Now notice, it took actually stopped for that five seconds and then it went on,
12:16 let's do it again I am sure we'll lose, 1, 2, 3, 4, 5, counting up and there we go. So that's our time.sleep.
12:24 Excellent, let's just get out of here for now. You can see we forgot our format here, hero.name well the very last thing to implement is just run away
12:35 and that is super easy to do let's just say print the wizard has become unsure of his power and flees.
12:46 All right so let's look around, oops, focus focus focus- look around, so the wizard is looking around he sees all this things,
12:54 oh my gosh this toad is frightening, run away, all right so the wizard has become unsure of his power and flees,
12:59 and now a tiger appears, oh let's attack it, excellent, we defeated it, now if we look the tiger is gone, I think our game is very nearly done,
13:08 there are a couple of things we are going to come back and look at because the way we have written it here while it works in this simple scenario
13:15 is not maybe the best way to model things so we are going to do one more pass on this and make sure we have everything just right.


Talk Python's Mastodon Michael Kennedy's Mastodon