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