Mar-12-2021, 11:56 PM
I’m learning OOP. Derek Banas is the instructor in the online (self directed, non-credit) Udemy course titled, “Python Programming Bootcamp” that I am taking. He demonstrates OOP well with a CLI game where two warriors with 100 health take turns attacking each other, reducing health by 20-50 points at each turn. The first warrior that reaches 0 health, loses. I am able to follow along and understand the basic principles of OOP demonstrated by the instructor. But for the fun of it and as an exercise, I decided to port the script from class methods/attributes to functions/variables as a personal challenge.
My script works but only sometimes. Here is some sample output:
Above, that output is expected. However below, the output is wrong:
This is wrong because Ironman’s health is less than Loki’s yet the winner is declared to be Ironman. How might you people alter my script to better account for this discrepancy?
Here is my script:
I see that the instructor’s OOP demo (below) is more dynamic and feature rich. It’s easier to read and follow along too. OOP is clearly the better way to go in this situation. But how might you people improve my attempt at implementing this game via functions/variables (above)?
Here is the instructor’s original:
Here is some output from running the instructor's scritp:
My script works but only sometimes. Here is some sample output:
Quote:$ python script.py
Ironman's health is: 30
Loki's health is: -2
The winner is: Ironman with 30 health remaining
Above, that output is expected. However below, the output is wrong:
Quote:$ python script.py
Ironman's health is: -28
Loki's health is: -12
The winner is: Ironman with -28 health remaining
This is wrong because Ironman’s health is less than Loki’s yet the winner is declared to be Ironman. How might you people alter my script to better account for this discrepancy?
Here is my script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import random import math health = 100 attack_max = 50 first_warrior = "Ironman" second_warrior = "Loki" def attack(attack_max): attack_amount = attack_max * (random.random() + . 5 ) return attack_amount def fight(first_warrior_health, second_warrior_health): while True : warrior_A_attack_amount = attack(attack_max) warrior_B_attack_amount = attack(attack_max) damage_to_warrior_B = math.ceil(warrior_A_attack_amount) damage_to_warrior_A = math.ceil(warrior_B_attack_amount) first_warrior_health = health - damage_to_warrior_A second_warrior_health = health - damage_to_warrior_B first_warrior_health = first_warrior_health - damage_to_warrior_A second_warrior_health = second_warrior_health - damage_to_warrior_B print ( f "{first_warrior}'s health is: {first_warrior_health}" ) print ( f "{second_warrior}'s health is: {second_warrior_health}" ) if second_warrior_health < = 0 : print ( f "The winner is: {first_warrior} with {first_warrior_health} health remaining" ) break elif first_warrior_health < = 0 : print ( f "The winner is: {second_warrior} with {second_warrior_health} health remaining" ) break def main(): fight( 100 , 100 ) main() |
Here is the instructor’s original:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
''' This original script was provided by Derek Banas in his Udemy course in Section 19 - Classes and Objects. Derek provided two scripts, demonstrating how to model classes of a video game. I have ventured to re-write the functionality of this OOP script but using functions/variables instead of class methods/objects ''' # We will create classes for both a Warrior and a Battle class # The Warrior class will simulate both the attributes and capabilities of a Warrior # The Battle class will however simulate the actions that occur in a battle such as starting the fight and getting the results import random import math # Warriors will have names, health, and attack and block maximums # They will have the capabilities to attack and block random amounts class Warrior: def __init__( self , name = "warrior" , health = 0 , attk_max = 0 , block_max = 0 ): self .name = name self .health = health self .attk_max = attk_max self .block_max = block_max def attack( self ): # Randomly calculate the attack amount # random() returns a value from 0.0 to 1.0 attk_amt = self .attk_max * (random.random() + . 5 ) return attk_amt def block( self ): # Randomly calculate how much of the attack was blocked block_amt = self .block_max * (random.random() + . 5 ) return block_amt # The Battle class will have the capability to loop until 1 Warrior dies # The Warriors will each get a turn to attack each turn class Battle: def start_fight( self , warrior1, warrior2): # Continue looping until a Warrior dies switching back and # forth as the Warriors attack each other while True : if self .get_attack_result(warrior1, warrior2) = = "Game Over" : print ( "Game Over" ) break if self .get_attack_result(warrior2, warrior1) = = "Game Over" : print ( "Game Over" ) break # A function will receive each Warrior that will attack the other # Have the attack and block amounts be integers to make the results clean # Output the results of the fight as it goes # If a Warrior dies return that result to end the looping in the # above function # Make this method static because we don't need to use self @staticmethod def get_attack_result(warriorA, warriorB): warrior_a_attk_amt = warriorA.attack() warrior_b_block_amt = warriorB.block() damage_2_warrior_b = math.ceil(warrior_a_attk_amt - warrior_b_block_amt) warriorB.health = warriorB.health - damage_2_warrior_b print ( "{} attacks {} and deals {} damage" . format (warriorA.name, warriorB.name, damage_2_warrior_b)) print ( "{} is down to {} health" . format (warriorB.name,warriorB.health)) if warriorB.health < = 0 : print ( "{} has Died and {} is Victorious" . format (warriorB.name, warriorA.name)) return "Game Over" else : return "Fight Again" def main(): # Create 2 Warriors Batman = Warrior( "Batman" , 100 , 40 , 10 ) Joker = Warrior( "Joker" , 100 , 40 , 10 ) # Create Battle object battle = Battle() # Initiate Battle battle.start_fight(Batman, Joker) main() |
Quote:› python re-written-v1.py
Ironman's health is: -28
Loki's health is: -12
The winner is: Ironman with -28 health remaining
gnull at gnosis in [~/dev/projects/python/2018-and-2020/learning-classes-Derek-Banas-Udemy/video-game] on git:master ✗ d8f0a68 "Initialize Derek Banas script"
18:36:42 › python original.py
Batman attacks Joker and deals 31 damage
Joker is down to 69 health
Joker attacks Batman and deals 27 damage
Batman is down to 73 health
Batman attacks Joker and deals 14 damage
Joker is down to 55 health
Joker attacks Batman and deals 48 damage
Batman is down to 25 health
Batman attacks Joker and deals 34 damage
Joker is down to 21 health
Joker attacks Batman and deals 40 damage
Batman is down to -15 health
Batman has Died and Joker is Victorious
Game Over