I made a class as you can see here.
class Player():
def __init__(self, name, maxhealth, base_attack, gold, weapon, curweapon, healing_potions):
player = Player('player', 100, 100, 5, 30, 'Normal Sword', 'Normal Sword', 0 )
self.name = name
self.maxhealth = maxhealth
self.health = self.maxhealth
self.base_attack = base_attack
self.gold = gold
self.weap = weapon
self.curweapon = curweapon
self.healing_potions = healing_potions
But then when I try and call on the healing_potions part like so
if question == '2':
player_in_diningroom = True
print("You enter the dining room")
print("")
print("You find a Potion Of healing on the table!")
print("")
healing_potions += 1
player_in_diningroom = False
Then it gives me this error
Traceback (most recent call last):
File "c:/Users/Isaiah/Desktop/All of my programs/Role playing game.py", line 179, in
healing_potions += 1
NameError: name 'healing_potions' is not defined
PS C:\Users\Isaiah\Desktop\All of my programs>
I don't quite understand why you initialize a player object inside your player class. This causes infinite recurison where you constantly create a player instance infinitely.
You most likely need to create it outside of your class. I've added a method to the class so we can increase the health potions using a method belonging to the instance. This is generally the recommended practice.
#player class
class Player():
def __init__(self, name, maxhealth, base_attack, gold, weapon, curweapon, healing_potions):
self.name = name
self.maxhealth = maxhealth
self.health = self.maxhealth
self.base_attack = base_attack
self.gold = gold
self.weap = weapon
self.curweapon = curweapon
self.healing_potions = healing_potions
def increase_health_potions(self):
self.healing_potions +=1
Then we initialize a player instance/object. I noticed you had one extra parameter in the instance you created, so I removed one to make it work
#create an instance called player
player = Player('player', 100, 100, 5, 'Normal Sword', 'Normal Sword', 0 )
question = '2'
if question == '2':
player_in_diningroom = True
print("You enter the dining room")
print("")
print("You find a Potion Of healing on the table!")
print("")
player.healing_potions += 1 #accesing and increasing variable belonging to instance
player.increase_health_potions() #call method belonging to instance that increases the variable
player_in_diningroom = False
print(player.healing_potions)
Take a notice at
player.healing_potions += 1
You have to reference the player, that you want to increase the health potions at.
Related
I am creating my first python program and have been struggling with a "TypeError: 'bool' object is not callable" error. I have only been studying for a few weeks so any assistance would be great! Also, if there are any tips on how to reduce some of the code that'd be great! Thanks!
import random
class Spacecraft:
def __init__(self, type, health):
self.type = type
self.health = health
self.ship_destroyed = False
def ship_destroyed(self):
self.ship_destroyed = True
if self.health != 0:
self.health = 0
print("Your spacecraft has been destroyed!")
def ship_destroyed_def(self):
self.ship_destroyed = True
if self.health != 0:
self.health = 0
print("Your enemy spacecraft has been destroyed! YOU WON!!")
def lose_health(self, amount):
self.health -= amount
if self.health <= 0:
self.ship_destroyed()
else:
print("Your spacecraft now has {health} hit points remaining.".format(health=self.health))
def lose_health_def(self, amount):
self.health -= amount
if self.health <= 0:
self.health = 0
self.ship_destroyed()
else:
print("The enemy spacecraft now has {health} hit points remaining".format(health=self.health))
print()
def attack(self, enemy_ship):
while True:
damage_fighter = random.randrange(2, 14)
damage_defender = random.randrange(4, 10)
if self.type == "fighter":
print(
'Your {type} spacecraft attacked the enemy ship for {damage} damage and the enemy {enemy_ship} spacecraft attacked your ship for {damage2} damage.'.format(
type=self.type,
damage=damage_fighter,
enemy_ship=enemy_ship.type,
damage2=damage_defender))
self.lose_health(damage_defender)
enemy_ship.lose_health_def(damage_fighter)
elif self.type == "defender":
print(
'Your {type} spacecraft attacked the enemy ship for {damage} damage and the enemy {enemy_ship} spacecraft attacked your ship for {damage2} damage.'.format(
type=self.type,
damage=damage_defender,
enemy_ship=enemy_ship.type,
damage2=damage_fighter))
self.lose_health(damage_fighter)
enemy_ship.lose_health_def(damage_defender)
class Player:
def __init__(self, type):
self.type = type
self.current_type = 0
def attack_enemy_ship(self, enemy_ship):
my_ship = self.type[self.current_type]
their_ship = enemy_ship.type[enemy_ship.current_type]
my_ship.attack(their_ship)
a = Spacecraft("fighter", 40)
b = Spacecraft("defender", 50)
print()
player_name = input('Welcome to Space Warriors! Please enter your name and hit enter. ')
player_style = input('''
Welcome ''' + player_name + '''! Space Warriors is a game that allows you to chose between two classes of spacecraft. If you select a
fighter spacecraft when you will fight again a defender spacecraft. If you choose a defender space craft
then you will fight a fighter spacecraft. Please select "Fighter" or "Defender" and press enter. ''').lower()
player_selected = []
computer_selected = []
if player_style == 'fighter':
player_selected.append(a)
computer_selected.append(b)
else:
player_selected.append(b)
computer_selected.append(a)
live_player = Player(player_selected)
computer_player = Player(computer_selected)
print()
print("Let's get ready to fight! Both ships are launched!")
print()
live_player.attack_enemy_ship(computer_player)
Once one of the two ships reaches zero hit points I am attempting to call ship_destroyed or ship_destroyed_def, to end the game; however the program stops once one of the ships hits "0". This is when I receive the error.
def ship_destroyed(self):
self.ship_destroyed = True
You're trying to make a function and an attribute that are both named ship_destroyed. You can't do that. Pick a different name for one of them.
I've been successfully able to "spellsiphon" (steal) a method from one class (darkMage) to give to the player class (Player).
However, the "stolen" method still seems to belong to the darkMage class--in other words, when the Player casts the stolen spell, it still reads (in all ways) as the darkMage casting the spell.
Can you help? I've done this:
Added the stolen darkMage() spell to the Player's spellbook (a list)
Successfully paired the "cast" command with items in the spellbook
I want to:
- Have the Player() casting the spell rather than the darkMage (when the stolen method is called, it's run as the darkMage rather than the Player)
class Player(livingThing):
def __init__(self,name="The Stranger", HP=10, MP=5, strength=1, intellect=1, spirit=1, luck=5, gil=6):
self.name = name
self.HP = HP
self.MP = MP
self.gil = gil
self.strength = strength
self.intellect = intellect
self.spirit = spirit
self.luck = luck
self.spellbook = []
def act(self, enemy):
actions = {
"a" : self.attack,
"heal" : self.heal,
"flee" : self.flee,
"cast" : self.cast,
"siphon" : self.spellsiphon
}
#Takes input from the player
self.safe = False
while ((self.HP > 0) and (enemy.HP > 0)) and (self.safe != True):
decision = input("What would you like to do? ")
#Sets the user's input as lower-case and checks for it within the dictionary
if decision.lower() in actions:
actions[decision.lower()](enemy)
if self.safe != True:
enemy.agreact(self)
self.printHP(enemy)
else:
print("That didn't workkkkkk! Try again.")
# Prints both player and enemy HP
def printHP(self, enemy):
print("{0}'s' HP: {1} \n{2}'s HP: {3}".format(self.name, self.HP, enemy.name, enemy.HP))
# Allows the player to attack an enemy (currently functional)
def attack(self, enemy):
enemy.HP -= self.strength
print("You strike {0} for {1} damage!".format(enemy.name, self.strength))
#player.printHP(enemy)
# Allows the player to heal a certain amount of health based on its "spirit" stat (currently functional)
def heal(self, enemy):
healed = randint(0, self.spirit)
self.HP += healed
print("You've healed for {0}!".format(healed))
#player.printHP(enemy)
#Allows the player to attempt to run away
def flee(self, enemy):
randluck = randint(0, self.luck)
if randluck > 3:
print("You successfully escaped!")
self.safe = True
else:
print("You weren't able to escape!")
def cast(self, enemy):
if len(self.spellbook) != 0:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](self)
else:
print("You don't have any spells to cast!")
### SPELLSIPHON IS CURRENTLY BROKEN; IT -DOES- SIPHON THE SPELL BUT ONLY ALLOWS THE DARK MAGE TO CONTINUE CASTING ###
def spellsiphon(self, enemy):
if len(enemy.spellbook) != 0:
randspell = randint(0, len(enemy.spellbook)-1)
stolenspell = darkMage().spellbook[randspell]
#(type(enemy).__name__).__init__(self, stolenspell)
self.spellbook.append(stolenspell)
print("You've successfully stolen {0} from {1}!".format("stolenspell", enemy.name))
else:
print("You can't steal a spell from {0}!".format(enemy.name))
# Anything that can act with/against the player
class Actor(livingThing):
def __init__(self, name="Unknown Entity", HP=10, MP=2, strength=1, intellect=1, spirit=3, gil=3):
self. name = name
self.HP = HP
self.MP = MP
self.gil = gil
self.strength = strength
self.intellect = intellect
self.spirit = spirit
self.abilities = [self.strike, self.heal]
def printabilities():
print(self.abilities)
# Chooses how your opponent will respond to your attack
def agreact(self, player):
choice = randint(0, len(self.abilities)-1)
self.abilities[choice](player)
# A basic "hit back" reaction from your opponent--everyone can do this
def strike(self, player):
player.HP -= self.strength
print("{0} hit {1} for {2}!".format(self.name, player.name, self.strength))
def heal(self, enemy):
healed = randint(0, self.spirit)
self.HP += healed
print("{0} healed for {1}!".format(self.name, healed))
### CURRENT VERSION SUPPORTS THE ADDITION OF NEW ABILITIES IN CHILD CLASSES VIA THE "super().__init__()" method! ###
class Enemy(Actor):
def __init__(self):
super().__init__()
self.abilities.append(self.cast)
self.name = "Unknown Enemy"
self.HP = 600
self.spellbook = []
def cast(self, opponent):
if len(self.spellbook) != 0:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](opponent)
class darkMage(Enemy):
def __init__(self):
super().__init__()
self.player = Player()
self.name = "Dark Mage"
self.spellbook.extend((self.fireball, self.icenova))
def fireball(cls, opponent):
choice = randint(cls.intellect*1, cls.intellect*2)
spellname = "Fireball"
opponent.HP -= choice
print("{0} casted fireball for {1} damage!".format(cls.name, choice))
def icenova(cls, opponent):
opponent.HP -= cls.intellect
choice = randint(0,1)
name = "Ice Nova"
if choice == 1:
frozen = True
else:
frozen = False
print("{0} casted ice nova for {1} damage!".format(cls.name, cls.intellect))
if frozen == True:
print("{0} has been frozen solid!".format(opponent.name))
It looks like you want the spells to be detached from the enemies/players. You can do this by making them static methods instead of instance methods (you're using def fireball(cls,..) but not using the #classmethod decorator, so they are really instance methods). Static methods don't automatically get passed the class/instance they are attached to like class/instance methods, so you can pass they can be 'stolen' and 'cast' (called) without remembering the original owner.
Here is a simple example:
class DarkMage:
def __init__(self, name):
self.name = name
self.spellbook = [self.fireball]
#staticmethod
def fireball(caster, target):
print("{} casted fireball on {} for 10 damage".format(caster.name, target.name))
class Player:
def __init__(self, name):
self.name = name
self.spellbook = []
def spellsiphon(self, enemy):
if enemy.spellbook:
spellchoice = randint(0, len(enemy.spellbook)-1)
self.spellbook.append(enemy.spellbook[spellchoice])
def cast(self, enemy):
if self.spellbook:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](self, enemy)
>>> dm = DarkMage('Bad Guy')
>>> p = Player('Do-Gooder')
>>> p.spellsiphon(dm)
>>> p.cast(e)
Do-Gooder casted fireball on Evildoer for 10 damage
>>> p.cast(dm)
Do-Gooder casted fireball on Bad Guy for 10 damage
You can also define the static methods outside the classes, which would let you share them between classes a bit easier, but I think the ideal way to do this would be to make spells their own python classes so that you can attach names and other attributes to them:
class Fireball:
name = 'fireball'
damage = 10
#classmethod
def cast(cls, caster, target):
print(
'{} cast {} on {} for {} damage!'.format(
caster.name,
cls.name,
target.name,
cls.damage,
)
)
class SuperFireball(Fireball):
name = 'super fireball'
damage = 50
class Player:
def __init__(self):
self.spellbook = [Fireball]
def list_spells(self):
for spell in self.spellbook:
print(spell.name)
def cast(self, enemy):
if self.spellbook:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice].cast(self, enemy)
I am quite new to python, having only toyed with it for a few days now. I am trying to cobble together a program to show off a battle system I had in mind. My issue is that I keep getting "None" produced when I try to print
import os
class Player():
def __init__(self, name, hp, maxhp, strength, intel, charm, level):
self.name = name
self.hp = hp
self.maxhp = maxhp
self.strength = 10
self.intel = intel
self.charm = charm
self.level = level
def attack(self, Enemy):
Enemy.hp -= self.strength
class Steve():
def __init__(self, name, hp, maxhp, strength, intel, charm, level):
self.name = name
self.hp = hp
self.maxhp = maxhp
self.strength = strength
self.intel = intel
self.charm = charm
self.level = level
class Barry():
def __init__(self, name, hp, maxhp, strength, intel, charm, level):
self.name = name
self.hp = hp
self.maxhp = maxhp
self.strength = strength
self.intel = intel
self.charm = charm
self.level = level
def Start():
Player.hp = 100
Player.maxhp = 200
Player.strength = 30
Player.intel = 10
Player.charm = 43
Player.level = 23
nameSelection()
def nameSelection():
os.system('cls')
Player.name = input("Please enter your name\n==>")
print("==>")
gameStart()
def gameStart():
os.system('cls')
global Enemy
print ("Player Name:",Player.name)
print ("Who would you like to fight?")
print ("1.)Steve")
print ("2.)Barry")
print ("3.)Change your name")
option = input("==>")
if option == "1":
Enemy = Steve("Steve", 100, 200, 10, 20, 30, 50)
fight()
elif option == "2":
Enemy = Barry("Barry", 100, 200, 10, 20, 30, 50)
fight()
elif option == "3":
nameSelection()
def attack():
Enemy.hp -= Player.strength
def fight():
os.system('cls')
while Enemy.hp > 0:
os.system('cls')
print(CharacterStats())
print ("1.) Attack")
print ("2.) Run")
option = input("==>")
if option == "1":
attack()
print (Enemy.hp)
print ("You did it! You have defeated", Enemy.name,"!")
gameStart()
def CharacterStats():
print ("You now face", Enemy.name)
print ("His current health is", Enemy.hp,"/",Enemy.maxhp)
print ("His strength is", Enemy.strength)
print ("His intelligence is", Enemy.intel)
print ("His charm is", Enemy.charm)
print ("He is level", Enemy.level)
Start()
When I get to a fight encoutner with one of the two options, I get
You now face Steve
His current health is 100 / 200
His strength is 10
His intelligence is 20
His charm is 30
He is level 50
None
1.) Attack
2.) Run
==>
I have read that return could fix it, but I can't seem to get return to give me the desired results I was looking for, both how it looks different went printed in to the player, and it only returns one of these lines of stats. I may be getting some of my terms wrong, I hope I am being clear on what my issue is.
You are getting None because you are printing the function, where you should just call the function, your function doesn't return anything and that is why you are getting None.
Change this line:
print(CharacterStats())
to:
CharacterStats()
In Python, when you call a function, that function does its work and then returns a value. For instance,
def add(x, y):
print("Working on it...")
answer = x + y
print("Got it!")
return answer
When called, this function will do four things. It will print "Working on it..." to the terminal. It will create a variable called answer, and assign it to the sum of x and y. It will print "Got it". And then, it will silently return that answer.
What does return mean? It means two things: it tells Python to return control to the place where the function was called, and it also says: wherever I was called, replace me with a certain value.
So if I write
print(add(2,3))
the function will be called and do its thinking, printing "working" and "got it" to the terminal. It will return 5, so now Python comes back to the print call and replaces add(2, 3) with 5:
print(5)
which will print 5. Similarly, I could do:
x = add(4,6) + add(5,2)
This would print:
Working on it...
Got it!
Working on it...
Got it!
And then x would be set to 10 + 7, or 17.
In your code, since you don't explicitly return anything from your function, Python uses the default, implicit return of None when it reaches the last line of your function. That means that
print(MyFunc())
actually is understood as, do the function, then
print(None)
Hope that clears things up!
As a side note, it will be more suitable if you use inheritance (use the Player class as base class eg: class Steve (Player):pass ) in your game : https://docs.python.org/2/tutorial/classes.html
I can't really copy over all of the code in both of these files since it is over 1000 lines, but essentially I am making a program that has the variables 'strength', 'endurance', 'strength', 'dexterity', 'intelligence', 'wisdom', and 'luck' (it's an rpg game) and I am trying to get the variable 'damage', which is an equation of 'strength' * 'dexterity' / 100, into another file. All of these variables are within the function character() in a file specifically for creating your character, and I'm trying to call over these variables again in another file for the main game, inside a variable called fight(). I've tried a multitude of things such as global variables, and using return, but nothing has worked for me. I'm sorry if I explained that poorly, comment if you have any questions.
The code in question.
character.py
def character():
#tons of stuff go here
global damage
damage = strength * dexterity / 100
game.py
def fight():
choice = input('(Type in the corresponding number to choose.) ')
global enemy_health
global damage
if choice == 1:
print ' '
print enemy_health,
enemy_health += -damage
print '-->', enemy_health
Thank you for your time.
I guess you could try importing character.py to game.py.
game.py: (edited)
import character
character_health = character.health
character_strength = character.strength
def fight():
...
But yeah, use classes.
Edit: example class
game.py:
class Character(object):
def __init__(self, health, strength):
self.health = health
self.strength = strength
self.alive = True
def check_dead(self):
self.alive = not(self.health)
def fight(self, enemy):
self.health -= enemy.strength
enemy.health -= self.strength
self.check_dead()
enemy.check_dead()
if __name__ == "__main__":
player = Character(300, 10) # health = 300, strength = 10
enemy = Character(50, 5) # health = 50, strength = 5
player.fight(enemy)
print("Player's health: {}\nIs he alive? {}\nEnemy's health: {}\nIs he alive? {}".format(player.health, player.alive, enemy.health, enemy.alive))
I'm working on a text based game, but I haven't found a very efficient solution to my fighting system yet. I currently have my statements set up sort of like this:
class Weapon1:
damage = 4
price = 5
class Weapon2:
damage = 4
price = 5
class Enemy1:
damage = 2
health = 5
class enemy2:
damage = 3
health = 6
def fight():
Weapon = raw_input("What weapon would you like to use?")
if Weapon == "Weapon 1":
if enemy = "Enemy1":
Enemy1.health -= Weapon1.damage
else:
Enemy2.health -= Weapon1.damage
else:
if enemy = "Enemy1":
pass
else:
pass
I have a lot more enemies and classes than that, so I would like to have a single statement that can reference classes' properties using variables. I decided not to upload the actual function due to it being over 100 lines long.
The pseudocode for what I'm after would look something like this:
class pistol:
damage = 4
price = 5
class cannon:
damage = 4
price = 5
class Enemy1:
damage = 2
health = 5
class enemy2:
damage = 3
health = 6
def fight():
Weapon = raw_input("What weapon would you like to use?")
enemy.health -= weapon.damage
You can use a simple dict, here with namedtuple to make the code easier to read:
from collections import namedtuple
Weapon = namedtuple('Weapon', ['damage', 'price'])
weapons = {
'pistol': Weapon(4, 5),
'cannon': Weapon(4, 5),
# ...
}
def fight():
weapon_name = raw_input("What weapon would you like to use?")
enemy.health -= weapons[weapon_name].damage
make the weapon,enemy class and initiate before doing fight()
class weapon:
def __init__(self,d,p):
self.damage = d
self.price = p
def initiate():
pistol = weapon(4,5)
#....