I'm making a program where you're firing a 'blaster', and I have 5 ammo. I'm blasting an alien who has 5 health. At the end I instantiate the player and make him blast 6 times to check that the program works correctly. But the way I've done it makes it so that the amount won't decrease. Is there an easy fix to this, or do I just have to make a new attribute for ammo and health? Here's what I have:
class Player(object):
""" A player in a shooter game. """
def blast(self, enemy, ammo=5):
if ammo>=1:
ammo-=1
print "You have blasted the alien."
print "You have", ammo, "ammunition left."
enemy.die(5)
else:
print "You are out of ammunition!"
class Alien(object):
""" An alien in a shooter game. """
def die(self, health=5):
if health>=1:
health-=1
print "The alien is wounded. He now has", health, "health left."
elif health==0:
health-=1
print "The alien gasps and says, 'Oh, this is it. This is the big one. \n" \
"Yes, it's getting dark now. Tell my 1.6 million larvae that I loved them... \n" \
"Good-bye, cruel universe.'"
else:
print "The alien's corpse sits up momentarily and says, 'No need to blast me, I'm dead already!"
# main
print "\t\tDeath of an Alien\n"
hero = Player()
invader = Alien()
hero.blast(invader)
hero.blast(invader)
hero.blast(invader)
hero.blast(invader)
hero.blast(invader)
hero.blast(invader)
raw_input("\n\nPress the enter key to exit.")
Think about it: the amount of ammunition available is part of a player's state. An object's state is best represented as instance variables of that object. So you should not have ammo as an argument to blast -- it should be self.ammo in that method, initialized to 5 or whatever in the __init__ you forgot to code;-).
It's not a matter of seeking for fancy workarounds to hide and stash that state somewhere else -- it's a matter of doing things in the simplest, most straightforward, most effective way. Why would you ever want anything but such a way?!
You need to keep track of the alien's health. All you're doing now is decrementing the "health" local variable in the Alien.die function.
Here's a little snippet that should help get you going in the right direction:
class Alien(object):
def __init__(self):
self.health = 5
def do_damage(self, amount):
self.health -= amount
Similar tracking required for player's ammo.
I just modify the above program by making 2 attributes named ammo and health.
I think they make program so easy. Try it for various outcomes by changing attributes' initial values.
class Player(object):
""" A player in a shooter game. """
def __init__(self, ammo):
self.ammo = ammo
def blast(self, enemy):
if enemy.health > 0:
if self.ammo > 0:
print "The player has blasted the alien.\n"
print "The player has", self.ammo, "ammunition left."
enemy.die()
elif self.ammo == 0:
print "The player can't blast the alien because he is out of ammunition.\n"
self.ammo -= 1
class Alien(object):
""" An alien in a shooter game. """
def __init__(self, health):
self.health = health
def die(self):
if self.health > 0:
self.health -= 1
print "The alien is wounded. He now has", self.health, "health left.\n"
if self.health == 0:
self.health -= 1
print "The alien gasps and says, 'Oh, this is it. This is the big one. \n"\
"Yes, it's getting dark now. Tell my 1.6 million larvae that I "\
"loved them...\nGood-bye, cruel universe.'\n"
elif self.health < 0:
print "The alien's corpse sits up momentarily and says, 'No need to blast me, I'm dead already!"
print "\t\tDeath of an Alien\n"
hero = Player(6)
invader = Alien(3)
blast = int(raw_input("How many times do you want to blast the alien? "))
for cnt in range(blast - 1):
hero.blast(invader)
Probably you want to do something like this:
class Player:
def __init__(self, ammo=5):
self.ammo=ammo
def blast(self, enemy):
if self.ammo>0:
self.ammo-=1
enemy.die(5)
else:
print "U are out of ammunition!"
You need to use self.health for the alien as well.
In class Player in the method named blast() your references to to ammo are incorrect. You want to refer to self.ammo in all cases within that function/method definition.
Furthermore you should probably (almost certainly) define an __init__ method to set the starting ammunition value to 5 (and perhaps later provide a reload() method to set self.ammo back up to 5 ... and so on.
Related
This code is in the main function:
Player and Computer are lists in this format:
player = ["name", 10, 20, 30]
10 is the health, 20 is the strength, and 30 is the dexterity
# Get the character for the user and the computer.
player = character_choices.get_and_remove_character(choice)
computer = character_choices.get_random_character()
# Preparation for the battle
print ("You have picked a " + player.name)
print ("The computer picked " + computer.name)
print ("Let's battle!\n")
# Battle Loop
rnd = 1
while (player.hit_points > 0 and computer.hit_points > 0):
print ("Round: " + str(rnd))
player.attack (computer)
computer.attack (player)
This is the function:
def attack (self, enemy):
self.player = [self]
if self.player[3] == enemy[3]:
I do not know how to call the player variable within the attack function in this format I can not change the attributes and I do not know how to get the player list items to compare to the enemies list items and fight.
self is a variable commonly related to objects in python by convention.
In your case, to make use of self, you should read up on python object oriented programming.
https://realpython.com/python3-object-oriented-programming/
Go through the tutorial in the link and once you are done, you will have a better understanding of what you want to achieve using your code. Have fun!
I am currently working through the book Learn Python 3 The Hard Way.
I have reached exercise 43 where a small text adventure game is written to practice Object Oriented programming.
I completed typing in the code for the program and got it working without any errors. Then in the additional study section, the author asked for a simple combat system to be added to the script.
The full script can be seen at this link, I did not want to paste the whole script for ex43 into this question.
https://github.com/ubarredo/LearnPythonTheHardWay/blob/master/ex43.py
I created the following script as a combat system:
import random
import time
class Player:
def __init__(self, hit_points, sides):
self.hit_points = hit_points
self.sides = sides
def take_hit(self):
self.hit_points -= 2
def roll(self):
return random.randint(1, self.sides)
class Combat(Player):
def combat_start():
p = Player(hit_points = 10, sides = 6)
e = Player(hit_points = 8, sides = 6)
battle = 1
while battle != 0:
human = p.roll() + 6
print("Your hit score: ", human)
monster = e.roll() + 6
print("Enemy hit score: ", monster)
if human > monster:
e.take_hit()
print("Your hit points remaining: ", p.hit_points)
print("Enemy hit points remaining:", e.hit_points)
if e.hit_points == 0:
battle = 0
print("The Enemy is Dead!!!")
time.sleep(2)
elif human < monster:
p.take_hit()
print("Your hit points remaining: ", p.hit_points)
print("Enemy points remaining: ", e.hit_points)
if p.hit_points == 0:
battle = 0
print("You died in Battle!!!")
time.sleep(2)
Combat.combat_start()
This works fine on its own and I wanted to use it in the script from the book.
I attempted to call it from the CentralCorridor class. After the player types in "shoot" I called the script I had written by adding:
Combat.combat_start()
What I hoped would happen is the Combat class I had written would start, then when the player won it would continue to the next scene, and if the player lost it would return the Death class.
After much trying and failing, I changed the Combat class to:
class Combat(Scene, Player):
With this added the script ran then breaks out of the loop.
Your hit score: 12
Enemy hit score: 12
Your hit score: 10
Enemy hit score: 11
Your hit points remaining: 8
Enemy points remaining: 4
Your hit score: 10
Enemy hit score: 10
Your hit score: 12
Enemy hit score: 7
Your hit points remaining: 8
Enemy hit points remaining: 2
Your hit score: 7
Enemy hit score: 9
Your hit points remaining: 6
Enemy points remaining: 2
Your hit score: 7
Enemy hit score: 8
Your hit points remaining: 4
Enemy points remaining: 2
Your hit score: 9
Enemy hit score: 10
Your hit points remaining: 2
Enemy points remaining: 2
Your hit score: 10
Enemy hit score: 9
Your hit points remaining: 2
Enemy hit points remaining: 0
The Enemy is Dead!!!
Traceback (most recent call last):
File "ex43.py", line 220, in <module>
a_game.play()
File "ex43.py", line 24, in play
next_scene_name = current_scene.enter()
AttributeError: 'NoneType' object has no attribute 'enter'
If the enemy players score is higher the loop break after one or two rounds.
I'm struggling to find a solution to this and would really appreciate some pointers of where I'm going wrong.
Looking through other answers, I have seen some comment that this is not an ideal way of writing OOP in Python.
In the book it shows:
class Scene(object):
And from what I have read this is the Python 2 style of OOP. I have seen that the Author is more of a Python 2 fan than Python 3.
I do enjoy the exercises he has put into the book and want to continue onto his next one.
Any help as always will be very much appreciated.
----UPDATE----
this is the Play method as requested:
def play(self):
current_scene = self.scene_map.opening_scene()
last_scene = self.scene_map.next_scene('finished')
while current_scene != last_scene:
next_scene_name = current_scene.enter()
current_scene = self.scene_map.next_scene(next_scene_name)
# be sure to print out the last scene
current_scene.enter()
I fixed the issue. After writing,
Combat.combat_start()
I needed to enter:
return 'laser_weapon_armory'
without that the program was crashing as it had no-where to go next.
Also fixed the logic in the Combat class.
Thanks for the help with this.
I am trying to create a simple game in Python using the OOP style.
The parent class is set up and there are two sub-classes, one for the hero and one for the ork.
Basically, when the hero attacks the ork (or vice versa) I want the health to be updated based on the damage done (damage is the amount of power the attacking character has). Currently, every time it loops it resets the health values back to the original of 100.
What is the best way of doing this using OOP? I can figure out how to do it in my own procedural and messy way, but I would like to see how it should be done.
class Character:
'''Blueprint for game characters'''
def __init__(self):
#default values
self.character = ""
self.speed = 0
self.power = 0
self.health = 100
def attack(self, attackObj):
self.attacker = self.character
self.attackerPower = self.power
self.victim = attackObj.character
self.victimHealth = attackObj.health
self.newHealth = self.victimHealth - self.attackerPower
print(self.character, "you have chosen to attack", self.victim)
print(self.victim, "you have suffered", self.attackerPower, "damage and your health is now", self.newHealth)
class Hero(Character):
'''Inherits from character to create hero'''
def __init__(self):
Character.__init__(self)
self.character = "Hero"
self.speed = 8
self.power = 9
print(self.character, "you have",self.speed, "speed,", self.power, "power and", self.health, "health.")
class Ork(Character):
'''Inherits from character to create ork'''
def __init__(self):
Character.__init__(self)
self.character = "Ork"
self.speed = 2
self.power = 8
print(self.character, "you have",self.speed, "speed,", self.power, "power and", self.health, "health.")
def main():
charclass = Character()
hero = Hero()
ork = Ork()
endLoop = False
while endLoop == False:
print("Please choose your character by typing the corresponding key: ")
print("H for hero")
print("O for ork")
charChoice = input()
if charChoice in ("H", "h", "hero", "Hero"):
charChoice = hero
enemy = ork
hero = Hero()
elif charChoice in ("O", "o", "ork", "Ork"):
charChoice = ork
enemy = hero
print("Please choose an action by typing the corresponding key: ")
print("A to attack")
actionChoice = input()
if actionChoice in ("A", "a"):
charChoice.attack(enemy)
else:
print("Nothing chosen!")
finishedYN = input("Have you finished? Y/N ")
if finishedYN in ("Y", "y", "Yes", "yes", "YES"):
print("You have chosen to end the game...")
endloop = True
break
else:
pass
if __name__ == "__main__":
main()
A quick fix to your code. Remove all these unecessary attributes, e.g. self.attacker (that's just self), self.attackPower (that's just self.power). self.victim = attackObj.character just gives your object a new attribute that is the same string as whatever attackObj.character is. Similarly, this:self.newHealth = self.victimHealth - self.attackerPower just creates a new attribute each time the method is called that will always be 100 - self.attack
def attack(self, attackObj):
attackObj.health -= self.power
print(self.character, "you have chosen to attack", attackObj.character)
print(attackObj.character, "you have suffered", self.power, "damage and your health is now", attackObj.health)
Really, an even better way is to add methods that mutate your object, that will be used as an interface with how your object interacts with other objects. So, for example:
class Character:
'''Blueprint for game characters'''
def __init__(self):
#default values
self.character = ""
self.speed = 0
self.power = 0
self.health = 100
def attack(self, victim):
victim.receive_damage(self.power)
def receive_damage(raw_damage):
self.health -= raw_damage
This improves the extensibility of your code. You could more easily implement a "buffs" system, or add an "armor" element, that affects how you recieve damage, without ever having to change the code in attack. You can override these methods in subclasses. So, perhaps you want all orks to have "thickskin", and in Ork:
def receive_damage(raw_damage):
self.health -= raw_damage*self.thickskin_modifier
Where self.thickskin_modifier was set in the Ork class __init__. It could be something like 0.9.
I've been learning python and I was creating a mini-game and did good so far. I need ideas to give each player a turn to attack, First here is the code:
from random import randint
class Dragon:
def __init__(self,name,health):
self.name = name
self.health = health
def kill(self,target):
while target.health >= 0:
if target.health <= 50:
hit = randint(1,20)
target.health -= hit
print '%s hits %s for %s' %(self.name,target.name,hit)
elif target.health <= 0:
print '%s has killed %s' %(self.name,target.name)
else:
hit = randint(1,50)
if hit >= 40:
target.health -= hit
print "%s critically hits %s for %s" %(self.name,target.name,hit)
else:
target.health -= hit
print "%s hits %s for %s" %(self.name,target.name, hit)
def Dead(self):
if self.health <= 0:
print "%s is dead" %self.name
class Hero:
def __init__(self,name,health):
self.name = name
self.health = health
Diet = Dragon('Diet',200)
Pizza = Hero('Pizza', 100)
if __name__ == '__main__':
Diet.kill(Pizza)
I will add more methods to the hero class once I figure out how to give turns to each player and my second problem is that the block that prints out the death of a player is not working, I've tried to nest it under each if function and it worked. But I think I shouldn't repeat the same code over and over and there must be a better way to do it.
Take the kill method out of a while loop, make it so each time the method is called it is just a single attack, rather than going till the other person is dead.
Then stick the entire game in a while loop, with some sentinel value for the end condition, e.g.:
GameIsRunning = True
while GameIsRunning:
#heros action
#enemies action
if EndConditionIsMet():
GameIsRunning = False
At the end of each loop check if the game is over, e.g. if all enemies are dead or the hero is dead, and set GameIsRunning to false.
Edit:
Dead option 1
As is, the Dead method just prints a message. You can't use this for much other than showing the user that so-and-so is dead. But if you want it like this, call it somewhere in either the attackers kill method. Or in the game loop. If you want this to get automatically called when the instance dies, then I would wrap up any damage dealing in a method:
def DealDamage(self, damage):
self.health -= damage
self.Dead()
Then use
def Kill(self, target):
#damage picking logic stays the same
target.DealDamage(damage)
Dead option 2
If you want said Dead method to mean that thing do or don't happen, it ought to have a boolean signature, e.g.:
def IsDead(self):
# Stick in a display message here if you like, or let the game do it
if self.health <= 0:
return True
else:
return False
Then you can let the game decide what to do about the fact that this person is dead. If you want to start adding multiple enemies then (as most games ultimately will), you might consider sticking them in a collection (a list or a dictionary), looping through this to take each enemies' turn if they're still alive, and removing them if they're dead. Then you're end condition can just be
if Hero.IsDead() or len(Enemies) == 0:
return True
This way gives you an easy way to spawn more enemies mid-game as well.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Ok I'm trying to make a program where I have a certain health and ammo for the alien and the human. I need them to go ten rounds. I want them to go the ten rounds randomly. I'm new to python, so I have some of it figured out but I don't have all of it figured out. I need to know what exactly am I doing wrong and how to do it.
class Alien(object):
"""Time to shoot the Player"""
def __init__(self,name,health,ammo):
self.name = name
name = input("What would you like to name your Alien?:")
self.health = 75
self.ammo = 50
def _str_(self):
return self.name
def blast(self,enemy):
import random
ammunition = random.randrange(5)
if ammunition >2
self.ammo(health)
print(self.name,"has shot the Player.")
print("He has",self.ammo,"ammo left.")
elif self.ammo == 0:
print(self.name,"is out of ammo.")
def health(self,health):
import random
shoot = random.randrange(10)
if shoot > 5
self.health(ammo)
if self.health >0:
print(self.name,"has been shot down. He has",self.health,"health left.")
elif self.health == 0
print("Im already dead. There's no way you can kill me again!!!")
class Player(object):
"""Time to shoot the Alien"""
def __init__(self,ammo,health,name):
self.name = name
name = input("What would you like to name your player?:")
self.ammo = 50
self.health = 75
def _str_(self):
return self.name
def blast(self,enemy):
import random
ammunition = random.randrange(5)
if ammuntion >2
self.ammo(health)
print (self.name,"has shot the alien.")
print ("He has",self.ammo,"ammo left.")
elif self.ammo == 0:
print(self.name,"is out of ammo.")
def health(self,health):
import random
shoot = random.randrange(10)
if shoot > 5
self.health(ammo)
if self.health >0:
print(self.name,"has been wounded. He has",self.health,"health left.")
elif self.health == 0:
print("I'm already dead. There's no way you can kill me again!!!")
These are my two classes for it.
I think i know what you are looking for. I remember writing a similar program for my sophomore school year and hope this helps.
class Player(object):
""" A player in a shooter game. """
def __init__(self,ammo):
self.ammo = ammo
self.lose = False
def blast(self, enemy):
if self.lose:
print "You were unsuccessful and did not kill the alien!\nNow the Earth was destroyed thanks to you."
else:
print "The player blasts an enemy."
if self.ammo > 0:
self.ammo -= 1
print "Your ammunition count is reduced by 1."
print "The alien took 1 damage! You've done it!\n"
enemy.die()
else:
if enemy.health == 0:
print "They're already dead, yo."
else:
self.lose = True
print "The alien has more health than you have ammo."
print "You run out of ammo and die!"
class Alien(object):
""" An alien in a shooter game. """
def __init__(self, health):
self.health = health
def die(self):
if self.health > 1:
self.health -= 1
print "Is that all you've got??\n"
elif self.health == 1:
self.health -= 1
print "Oh no im gonna die"
else:
print "The alien is already dead. What you're doing is unneccessary."
# main
print "\tThe Death of an Alien\n"
#same health and ammo
print "\n-----You have 6 counts of ammo.-----"
print "-----The alien has 6 health.-----\n"
hero = Player(6)
invader = Alien(6)
for i in range(6):
hero.blast(invader)
#lower health than ammo
print "\n-----You have 6 counts of ammo.-----"
print "-----The alien has 5 health.-----\n"
hero = Player(6)
invader = Alien(5)
for i in range(6):
hero.blast(invader)
#lower ammo than health
print "\n-----You have 5 counts of ammo.-----"
print "-----The alien has 6 health.-----\n"
hero = Player(5)
invader = Alien(6)
for i in range(6):
hero.blast(invader)
raw_input("\n\nPress the enter key to exit.")