Python class attributes missing - python

I am making a game in python. I ran into some issues with the code. I defined my mobs as different classes, making it easy to edit later on. The issues I ran into is that I cannot call upon the health to deal damage on it.
class spaceStalker(object):
def __init__(self, name, hp):
self.name = name
self.hp = hp
mobList = [spaceStalker]
mob = random.choice(mobList)
killList = ["not killed the beast!", "killed the beast!"]
kill = random.choice(killList)
def game():
if mob == spaceStalker:
fleeAtt = input("A Space Stalker has appeared! Attack or flee? ")
if fleeAtt == "Attack":
hitPass = input("Attack or Pass? ")
if hitPass == "Attack":
spaceStalker.hp -= 50
print(spaceStalker.hp)
else:
print("1")```

Use an instance of the class
mobList = [SpaceStalker('some name', 54)]
And when you do the type of mob checking, you can do it with isinstance(object, classname) :
so instead of:
if mob == spaceStalker:
#dosomething
use:
if isinstance(mob, SpaceStalker):
#dosomething
I also suggest you to use getters and setters for your class:
class SpaceStalker(object):
def __init__(self, name, hp):
self.name = name
self.hp = hp
#property
def hp(self):
return self.__hp
#hp.setter
def hp(self, hp):
#some validation here
self.__hp = hp
Also, maybe you want to use the classname convention (camelcase) so I've written it as SpaceStalker

Related

Text-Based Pokemon Game: How do I implement an evolution system?

I have starting working on this Text-Based Pokemon game and I am stuck on trying to figure an evolution system that can change one class object into another class object, if that makes sense.
I've attempted to do this just by simply making the class object equal to the one I want to change:
# Trainer
new_trainer = Trainer('Trainer', 'Male')
# Test pokemon (the parameter is just a level value)
bulbasaur = Bulbasaur(10)
ivysaur = Ivysaur(20)
# Adding pokemon to party
new_trainer.add_pokemon(bulbasaur)
new_trainer.add_pokemon(ivysaur)
# Display pokemon lists
print(new_trainer.pokemon_list)
new_trainer.display_party()
# Attempting to 'evolve' bulbasuar
bulbasaur = Ivysaur(bulbasaur.lvl)
# Displaying results again to see if it worked
print(new_trainer.pokemon_list)
new_trainer.display_party()
But by looking at the output, it shows that nothing has happened:
Bulbasaur was added to your party!
Ivysaur was added to your party!
[<__main__.Bulbasaur object at 0x0000023587EDA080>, <__main__.Ivysaur object at 0x0000023587EDA0F0>]
1. Bulbasaur
2. Ivysaur
[<__main__.Bulbasaur object at 0x0000023587EDA080>, <__main__.Ivysaur object at 0x0000023587EDA0F0>]
1. Bulbasaur
2. Ivysaur
EDIT:
It turns that that the variable value DOES indeed change, but I simply need to update the Trainer's pokemon list. However, I am still unsure on how to do this.
The display_party function in the Trainer class looks like this:
def display_party(self): # Displays pokemon party list
if not self.pokemon_list:
return print("There are no pokemon in your party.")
else:
for pokemon in range(len(self.pokemon_list)):
print("{0}. {1}".format(pokemon + 1, self.pokemon_list[pokemon].name))
I was just thinking of adding an update_party function, which goes into the list, deletes the old value and inserts the new value, but how will it know what value to delete?
Perhaps there is a better way to do this? And sorry if my question doesn't include that much information, I will add more of my code if it doesn't make much sense already. This is my first time asking a question here :D
EDIT 2:
For those who don't understand how the code works, this is basically how it works so far:
# Formula used to calculate pokemon health
def health_stat_calculation(base_stat, lvl):
return int(((base_stat * 3 * lvl) / 100) + lvl + 10)
# Formula used to calculate pokemon stats
def stat_calculation(base_stat, lvl):
return int(((base_stat * 3 * lvl) / 100) + 5)
# Trainer class
class Trainer:
def __init__(self, name, gender):
self.name = name
self.gender = gender
self.pokemon_list = []
self.item_list = []
def add_badge(self, badge): # Gives player a badge
self.player_badges.append(badge)
def add_pokemon(self, pokemon): # Adds a pokemon to party
for poke in self.pokemon_list:
if pokemon is poke:
return print("You already have this pokemon in your party!")
if len(self.pokemon_list) > 5:
return print("You have too much pokemon in your party!")
else:
self.pokemon_list.append(pokemon)
return print("{} was added to your party!".format(pokemon.name))
def display_party(self): # Displays pokemon party list
if not self.pokemon_list:
return print("There are no pokemon in your party.")
else:
for pokemon in range(len(self.pokemon_list)):
print("{0}. {1}".format(pokemon + 1, self.pokemon_list[pokemon].name))
def add_item(self, item): # Adds an item to player's inventory
if len(self.item_list) > 50:
print("You have too much items in your inventory!")
else:
self.item_list.append(item)
print("{} was added to your inventory!")
# Generic pokemon class
class Pokemon:
def __init__(self, name, lvl, exp, id_number, health, attack, defence, sp_attack, sp_defense, speed):
self.name = name
self.lvl = lvl
self.exp = exp
self.id_number = id_number
self.health = health
self.attack = attack
self.defence = defence
self.sp_attack = sp_attack
self.sp_defense = sp_defense
self.speed = speed
def get_pokemon_name(self):
return self.name
# User friendly stat display
def display_stats(self):
print("\nStats for {}\n---------------".format(self.name))
print("Level: {}".format(self.lvl))
print("Index No.{}".format(self.id_number))
print("Health: {}".format(self.health))
print("Attack: {}".format(self.attack))
print("Defense: {}".format(self.defense))
print("Sp. Attack: {}".format(self.sp_attack))
print("Sp. Defense: {}".format(self.sp_defense))
print("Speed: {}\n".format(self.speed))
# Level up pokemon and show change in stats
def level_up(self):
self.display_stats()
self.lvl += 1
print("\n{} has leveled up!\n".format(self.name))
self.calculate_stats()
self.display_stats()
# Calculate generic pokemon stats
def calculate_stats(self):
self.health = health_stat_calculation(self.base_health, self.lvl)
self.attack = stat_calculation(self.base_attack, self.lvl)
self.defense = stat_calculation(self.base_defense, self.lvl)
self.sp_attack = stat_calculation(self.base_sp_attack, self.lvl)
self.sp_defense = stat_calculation(self.base_sp_defense, self.lvl)
self.speed = stat_calculation(self.base_speed, self.lvl)
# Bulbasaur class
class Bulbasaur(Pokemon):
def __init__(self, lvl, name="Bulbasaur"):
self.name = name
self.lvl = 16
self.exp = 0
self.id_number = 1
# Bulbasaur Base stats
self.base_health = 45
self.base_attack = 49
self.base_defense = 49
self.base_sp_attack = 65
self.base_sp_defense = 65
self.base_speed = 45
self.calculate_stats()
# Ivysaur class
class Ivysaur(Pokemon):
def __init__(self, lvl, name="Ivysaur"):
self.name = name
self.lvl = 16
self.exp = 0
self.id_number = 2
# Bulbasaur Base stats
self.base_health = 60
self.base_attack = 62
self.base_defense = 63
self.base_sp_attack = 80
self.base_sp_defense = 80
self.base_speed = 60
self.calculate_stats()
Casting from one class to another makes no sense in your case.
Just go with
class Pokemon():
def __init__(self, name, level=0):
self.level = level
self.name = name
def evolve(self):
self.level += 1
def __str__(self):
return 'Pokemon: {}, Level: {}'.format(self.name, self.level)
p1 = Pokemon('Bulbasaur')
p2 = Pokemon('Ivysaur')
print(p1)
print(p2)
p1.evolve()
p2.evolve()
print(p1)
print(p2)
You could turn the kind, Bulbasaur, Ivysaur, etc., into a component of the Pokemon class. The Bulbasaur has its next evolution stage as an attribute and in the evolve method of the Pokemon you can just set the kind to the next evolution stage.
class Pokemon:
def __init__(self, kind, level):
self.level = level
self.kind = kind # The kind is just a component now.
def evolve(self):
# Create a new instance of the next evolution stage
# and use it to replace the previous kind.
self.kind = self.kind.evolution_stage()
class Bulbasaur:
def __init__(self):
self.base_health = 45
# A reference to the next evolution stage class.
self.evolution_stage = Ivysaur
class Ivysaur:
def __init__(self):
self.base_health = 60
# self.evolution_stage = Venusaur
# Pass a Bulbasaur instance as the `kind` argument.
pokemons = [Pokemon(Bulbasaur(), 3)]
print(pokemons[0].kind, pokemons[0].kind.base_health)
pokemons[0].evolve() # Changes the .kind attribute.
print(pokemons[0].kind, pokemons[0].kind.base_health)
I don't know if this is the cleanest way, but somehow it worked when I added this function into the Pokemon class and used the dict dunder to update the contents of the old object to the new one. The temp_pos was used as a temporary placeholder for the current object's name so it didn't get changed when updating it to the new_pokemon object.
# Evolve function
def evolve(self, evln, trainer):
temp_name = self.name
new_pokemon = evln(self.lvl)
self.__dict__.update(new_pokemon.__dict__)
self.name = temp_name

Printing my Class attributes

these are 2 parts of my misbehaving text based adventure code that I'm trying to learn how to do with a youtube tutorial. I believe that most of my problems arise because the tutorial I'm pretty sure is using python2.something and I'm using 3.
My problem is I'm trying to list the "Player" class attributes on the start screen, which I have successfully done with Playername, but I'm having trouble getting the numbers listed as self.attack and self.health etc to print.
I downloaded python for the first time about 5 days ago, so bear with a noob if you can, please.
Let me know what I can change, and thank you in advance!
class Player:
def _init_(self, name):
self.name = name
self.maxhealth = 100
self.health = self.health
self.attack = 10
self.gold = 0
self.bandages = 0
def start1():
os.system("cls")
print("Name: %s" % (PlayerIG))
print("Attack: {}".format (PlayerIG.attack))
print('Health: {}/{}'.format(PlayerIG.health, PlayerIG.maxhealth))
print("Gold: %i") % PlayerIG.gold
print("Bandages: %i") % PlayerIG.bandages
A few things immediately:
def _init_ needs to be def __init__ (note the double underscores).
self.health = self.health doesn't make sense - whatever is on the right side of an = needs to exist before you can assign some other variable to it, and self.health doesn't exist until that line.
The variable PlayerIG was never assigned to anything, so none of the code in start1 will work (unless it was done somewhere else, that you haven't included in the question).
A working version of what you have in your question would be something like
class Player:
def __init__(self, name, maxhealth, health, attack, gold, bandages):
self.name = name
self.maxhealth = maxhealth
self.health = health
self.attack = attack
self.gold = gold
self.bandages = bandages
def start1():
PlayerIG = Player('foo', 100, 50, 10, 0, 0)
print('Name: {}'.format(PlayerIG.name))
print('Health: {}/{}'.format(PlayerIG.health, PlayerIG.maxhealth))
print('Attack: {}'.format(PlayerIG.attack))
print('Gold: {}'.format(PlayerIG.gold))
print('Bandages: {}'.format(PlayerIG.bandages))
start1()
There are many improvements you could make from there, like defining a __str__ function for Player or using keyword arguments in your __init__ method.

Can I 'import' information to a class object from a previously defined function?

So i'm trying to make a very simple text-based RPG as my semester project for my programming class. I just recently learned (which is probably pretty apparent by my code) how to define classes and felt they would work much better than a function.
However, i'm having trouble with the 'character' class. Instead of having the player name predefined, I want the user to be able input their own name, which i've done in the 'Intro' function. Now my problem is taking the variable 'pName' and setting as the player's name, which I havent been able to do.
My questions are:
1. Can I do this? (use a function variable as a class attribute?)
2. Is there a better, more efficient way of doing this? And
3. Is there any additional information you guys could give me about classes or about how I can go about finishing this program?
Anything is well-appreciated and thanks in advance for the help!
import random, time
#I'm not at all hellbent on keeping this same format, it's just
#the way i've been taught and i'm most comfortable with.
def Intro():
print('Welcome puny warrior, to my Dungeon of DOOM, and stuff.')
pName = input('Tell me your name, puny warrior: ')
playResponse = input('Do you want to begin puny warrior who calls himself ' + pName + '? Y/N: ')
playResponse = playResponse.upper()
if playResponse[0:1] == 'Y':
pass
else:
print('You die now', pName)
class character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
#this part obviously doesn't work, but I decided to leave it as a visual aid
player = character(pName, 25, 5)
#should I just make this class a child of the 'character' class?
class foes(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
zombie = foes('Zombie', 10, 3)
dragon = foes('Dragon',20, 5)
skeleton = foes('Skeleton', 8, 4)
You are trying to call internal Intro() variable - fast fix could be like this:
def Intro():
print('Welcome puny warrior, to my Dungeon of DOOM, and stuff.')
pName = input('Tell me your name, puny warrior: ')
playResponse = input('Do you want to begin puny warrior who calls himself ' + pName + '? Y/N: ')
playResponse = playResponse.upper()
if playResponse[0:1] == 'Y':
pass
else:
print('You die now', pName)
return pName
class character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
#this part obviously doesn't work, but I decided to leave it as a visual aid
player = character(Intro(), 25, 5)
#should I just make this class a child of the 'character' class?
class foes(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
zombie = foes('Zombie', 10, 3)
dragon = foes('Dragon',20, 5)
skeleton = foes('Skeleton', 8, 4)
Some Pointers
Take a look at PEP8, the Style Guide for Python.
Use the Character Class to define both the player, and foes.
Implement a main() method and use it appropriately. For more information about this topic, visit this discussion.
Make use of Python dictionaries, as they are very powerful.
#!/usr/bin/env python
"""Simple, text-based RPG."""
import random # Generate pseudo-random numbers.
import time # Time access and conversions.
class Character(object):
"""Define the character."""
def __init__(self, name, health, attack):
self.name = str(name) # Expecting a string.
self.health = int(health) # Expecting an integer.
self.attack = int(attack) # Expecting an integer.
def properties(self):
"""Returns dictionary containing the character properties."""
# Because using dictionaries is awesome.
characteristics = {
'name': self.name,
'health': self.health,
'attack': self.attack
}
return characteristics # Returns a dictionary
def get_player():
"""Acquire the name of the player, and begin the game."""
# Newline characters should improve readability on the command line.
print('\nWelcome puny warrior, to my Dungeon of DOOM, and stuff.\n')
# Variable names should be easy to read and understand.
player_name = input(
"""
Welcome puny warrior, to my Dungeon of DOOM... and stuff.
Tell me your name: """
)
# Get and store the player's response.
player_response = input(
"""
Do you want to begin puny warrior who calls himself %s? (Y/N): \
""" % player_name
)
if player_response.upper() == "Y":
pass
else:
print('\nYou die now\n', player_name)
return player_name
def score():
"""Assign a score between 1 and 100."""
return random.randint(1, 100)
def main():
"""Where the automagic happens."""
# Assuming you want random integers.
player = Character(get_player(), score(), score()).properties()
zombie = Character('Zombie', score(), score()).properties()
dragon = Character('Dragon', score(), score()).properties()
skeleton = Character('Skeleton', score(), score()).properties()
# Since you're working with a dictictionary, you can now do things like:
print(player['name'])
print(zombie['name'], zombie['health'])
print("%s: %s, %s" % (dragon['name'], dragon['health'], dragon['attack']))
# The correct methodology.
if __name__ == "__main__":
main()
I'm not really sure what your question is. There's no difference to Python between using a variable like pName and a string like "Zombie" in a class instantiation. The only thing wrong with your code
is that you're doing that instantiation outside Intro(), so pName is not defined.

'Character_Creation' object has no attribute 'choice'

I keep getting this error 'Character_Creation' object has no attribute 'choice' but i clearly defined choice as, choice = input(">") and made the object character creation. Any help on how to fix this?
class Character_Creation():
def __init__(self):
print("""Character Creation
Whats your name?""")
Name = input(">")
print("""Chose your career
Type b for Blacksmith, a weapon-smith
Type bo for BodyBuilder, a Russian strong man
Type m for Merchant , a man with strong trade skills
""")
choice = input(">")
class Classes():
def Blacksmith():
health = 100
attack = 30
defence = 10
money = 100
def Bodybuilder():
health = 150
attack = 10
defense = 30
money = 100
def Merchant():
health = 100
attack = 5
defence = 5
money = 500
class Stats():
def __init__(self):
if c.choice == "m":
cl.Merchant()
print(attack)
t=Title_Screen()
c=Character_Creation()
cl=Classes()
s=Stats()
JBernardo is correct that you aren't using self correctly. More broadly, though, your use of classes is a bit odd. CharacterCreation seems better suited to a class method than a whole class, and having a class Classes with instance methods that define then discard local variables is a bit odd. I think want you are trying to do looks more like:
class Character(object):
def __init__(self, name, health, attack, defence, money):
self.name = name
self.health = health
self.attack = attack
self.defence = defence
self.money = money
#classmethod
def create(cls, name):
characters = {"bodybuilder": (150, 10, 30, 100), ...}
return cls(name, *characters[name])
...
if choice.lower() == "bo":
character = Character.create("bodybuilder")
If you need the different types of Character to have different instance methods and attributes, use inheritance:
def Blacksmith(Character):
def hammer_metal(self):

python: setting attributes from module to module

Im teaching myself python and I've come upon a snag in a simple game project I'm working on.
I would like to keep the players stats in a different module from the rooms that are being run by the game engine. Problem is when I try to set a Playerattribute from a different module, it doesn't save the new attribute and instantiates the original attribute.
here is the Playerclass in the entities module
class Player(object):
def __init__(self):
self.name = ' '
self.hp = 0
self.current_hp = 0
self.strength = 0
self.dexterity = 0
self.constitution = 0
And here is how im trying to manipulate and test the attributes in the rooms module
class CharacterCreation(Scene):
def enter(self):
character = entities.Player()
character.hp = 10
print character.hp
return 'barracks'
class Barracks(Scene):
def enter(self):
character = entities.Player()
print character.hp
return 'shop'
When I test this with the rest of my code, here is what I get.
-------------------------------------------------------------------------------
10
-------------------------------------------------------------------------------
0
-------------------------------------------------------------------------------
So what am I missing here? I thought I could set that attribute using =but it seems I'm mistaken? the first time I did it, it worked, but then how do i get python to set the new value of hp to 10?
You're creating a new Player object in each scene, changing its attributes, and then throwing it away.
You should be explicitly passing one single player into each scene:
def enter(self, player):
... do something with player ...
It looks like you're creating a new Player instance on every enter method...
If you're going to have only one player in the game, you could have it as a global variable (usually not very good idea) or even better, as a singleton class:
http://blog.amir.rachum.com/post/21850841339/implementing-the-singleton-pattern-in-python
I made some tweakings to the code. It adds the PlayerPool class (which is more like a cache, actually). It may give you some ideas :)
#!/usr/bin/env python
#http://stackoverflow.com/questions/14629710/python-setting-attributes-from-module-to-module/14629838#14629838
class Player(object):
def __init__(self):
self.name = ' '
self.hp = 0
self.current_hp = 0
self.strength = 0
self.dexterity = 0
self.constitution = 0
class PlayerPool(object):
_players = dict()
#classmethod
def getPlayerByName(cls, name):
if not name in cls._players:
newPlayer = Player()
newPlayer.name = name
cls._players[newPlayer.name] = newPlayer
return cls._players[name]
class Scene(object):
pass
class CharacterCreation(Scene):
def enter(self):
character = PlayerPool.getPlayerByName("foobar-hero")
character.hp = 10
print "%s has %s points of hp" % (character.name, character.hp)
return 'barracks'
class Barracks(Scene):
def enter(self):
character = PlayerPool.getPlayerByName("foobar-hero")
print "%s has %s points of hp" % (character.name, character.hp)
return 'shop'
if __name__ == "__main__":
step1 = CharacterCreation()
if step1.enter() == "barracks":
step2 = Barracks()
step2.enter()
That outputs:
borrajax#borrajax-comp:~/Tests/Python/Stack Overflow$ python ./players.py
foobar-hero has 10 points of hp
foobar-hero has 10 points of hp
Welcome to python. I'm sure you'll find it has really cool features... such as the ability to return functions, or pass functions as parameters, inspect the classes defined in any module... Looks like things you could find useful.

Categories