Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Introduce Critical Hit Damage

00:00 The next stretch goal reads to introduce double-damage critical hits that occur when an attack value is a multiple of three. That’s a little throwback to the previous challenge where you had to calculate the factors of a number.

00:16 Maybe this already gives you a hint of how you can solve this. You probably already did solve it, but let’s see how I’m going to go ahead and do that. We want to mess with the damage, right, and give a chance for both the user, the player, as well as the monster to do double damage. Actually, one thing I want to do in here, just to make it a little bit more readable for myself, I’m going to say that here starts the player’s turn, and then down here starts the monster’s turn.

00:47 So both for the player and the monster, I want to introduce this critical hit chance. It’s two places where I have to do something, and that can be okay, but generally it’s a good idea to generalize this into a function.

01:05 I want to not write this logic twice, but instead I’m going to define a function that I’ll call is_factor_of_three(), and then it’s going to take a number as an input.

01:18 The code logic you’ll write for this function will look similar to the code you wrote for your first challenge that was about finding the factors of a number.

01:25 How beautiful, it’s all connected and coming together. I’m going say if number module % 3 == 0 then this function should return True and else I’ll make it return False.

01:44 So, now I can use this function to figure out whether any number is a factor of three. Is that really enough for me? No, I think I want another function because I’m still calculating the damage twice at the moment. I’m doing it here, and I’m doing it at the monster’s turn, line 58 currently.

02:06 So let’s also take that out into a function, and I’m going to call that one

02:13 calculate_damage_dealt_by() and then the attacker. I’m going to take that as an input for us to decide which formula to apply, basically.

02:27 So I’m going to say if the attacker is "player", so I’m just going to input a string here for now that says either "player" or "monster", the damage is going to be

02:44 random.randint(10, 15).

02:50 else it’ll be the "monster", then the damage is going to be, oh, let’s copy that one from line 64 … 15 to 20.

03:04 And now that gives me a chance to edit both of these damages. Well, I’m going to call that damage as well in that case. Then I’m going to call is_factor_of_three() on it.

03:17 So I’m going to say if is_factor_of_three()

03:23 and then input the damage as an argument that I just calculated up here, then I want to say, damage = damage * 2, double damage. And with that, we’re ready to return the damage.

03:43 So now I’ve added two functions. One I’m going to use to calculate the damage that the player or the monster attack, and in there I use another helper function that I called is_factor_of_three() that figures out whether a number is divisible by three without a remainder, and if it is, then it’s going to be double damage. Okay, now I just need to replace where I calculate the damage here.

04:12 Damage is calculate_damage_dealt_by(), and then I’ll input "player". This is the player. And down here, monster_damage is going to be calculate_damage_dealt_by("monster").

04:28 Just give "monster" as an input string here. In that case, this will go to the else statement. You could use an elif statement, but it’s nice to catch, maybe you wanna add other attackers in this game, and then you could expand this calculate_damage_dealt_by(). All right, that looks nice, but does it work? Let’s give it a go.

04:55 Okay, “Welcome to the game. Do you want to (A)ttack, (H)eal, or (R)un away?” I want to attack. I attacked the monster for 30. The monster attacked you for 30 damage.

05:03 So I believe that means it worked because the monster should otherwise only do between 15 and 20. So it looks like it rolled 15 and then did double damage.

05:16 But I’m not entirely satisfied with the information I get back here. So I want to add a print() call in here. I’m going to say

05:27 print("Critical hit") and maybe also how much it is to make it easier to understand.

05:39 And let’s also say who did it. attacker.capitalize()

05:46 just to get the first letter big

05:53 "scored a critical hit of" that much "damage". Okay, so I have a bit of information so that I better know what’s happening.

06:07 And let’s try this once more. F5. Attack. All right, there you go. The Monster scored a critical hit of 36 damage. Ay ay ay, I’ll try again. You attacked the monster. Oh no, they have another critical hit.

06:23 I’ve totally got to heal. Heal, heal, and then I’ll try again. 11, 17 Oh no, the monster scored another critical hit of 30, and then I was defeated by the monster. All right, so this is working.

06:42 I never actually got a critical hit, but that was just bad luck in that case. Both of our damage gets calculated the same way. So if mine was multiple of three, then I would also get double damage.

06:55 Great. Also, I made this a bit more generalized because now I created these two functions that I’m using in the two respective places where I need to calculate any sort of damage, and this makes it easier to extend.

07:12 So if I wanted to have another player or another monster, I could just add that in and hook them up with the calculate_damage_dealt_by() function, which itself uses the is_factor_of_three() function to figure out whether they should multiply damage or not. All right, I’m pretty happy with that.

07:31 I’ll check off the stretch goal and move on to the next lesson.

Become a Member to join the conversation.