I am trying to call an object attribute with a variable based on user input. This is for a text game. The idea is the player types in 'hat', for example, and this function checks the player object's self.inventory = [] for Item objects named 'hat', and if such an object exists it will append the Item object to the player object's corresponding attribute, in this case self.helm = [].
To do this I am trying to have equipItem be a variable equal to the equipping item's class type which should be the same as one of the player objects' equipment attributes.
move = input("To equip, unequip, or an use item, type [item name]. To trade
in item for XP, type 't [item name]'. Type 'x' to exit inventory:
").lower().split()
print(move[0])
for i in currentPlayer.inventory:
print(i.name)
if i.name == move[0]:
print(i)
equipItem = i.itemClass
currentPlayer.equipItem.append(i)
currentPlayer.inventory.remove(i)
print(currentPlayer.equipItem)
But of course this throws an error because 'equipItem' in not a player attribute. So my question is how might I achieve the result I am after? Can I use a variable to call object attributes?
I understand this is all probably quite janky and I am not married to this approach by any means, so any suggestions other approaches are welcome as well!
Player class and Item class below:
class Player:
def __init__(self, name):
self.name = name
self.health = 10
self.maxHealth = 10
self.inventory = [Item(1, 1), Item(2, 2)]
self.weapon = [Item(0, 1)]
self.helm = [Item(1, 0)]
self.shield = [Item(5, 0)]
self.boots = [Item(3, 0)]
self.greaves = [Item(4, 0)]
self.gloves = [Item(6, 0)]
self.cuirass = [Item(2, 0)]
self.defaultPotion = []
self.attack = 5 + self.weapon[0].attack
armorClass = self.helm[0].defense + self.shield[0].defense +
self.boots[0].defense + self.greaves[0].defense +
self.gloves[0].defense
+ self.cuirass[0].defense
self.defense = 1 + armorClass
self.level = 1
self.experience = 0
self.offensiveMagic = 0
self.defenseiveMagic = 0
self.offensiveCombat = 0
self.weightClass = 10
def __str__(self):
return self.name
class Item:
def __init__(self, itemType, subType):
#denotes type of item (wepaon, gloves, etc)
self.itemType = allItems[itemType]
#denotes item name and stats (sword, attack value, etc)
self.subType = self.itemType[subType]
#denotes how item is used (euip, consume, etc)self.subType = 0:
if subType == 0:
self.itemClass = 'weapon'
elif subType == 1:
self.itemClass = 'helm'
elif subType == 2:
self.itemClass = 'cuirass'
elif subType == 3:
self.itemClass = 'boots'
elif subType == 4:
self.itemClass = 'greaves'
elif subType == 5:
self.itemClass = 'shield'
elif subType == 6:
self.itemClass = 'gloves'
self.name = self.subType['name']
self.attack = self.subType['attack']
self.defense = self.subType['defense']
# self.equip = 'no'
def __str__(self):
return self.itemType
return self.name
return self.attack
return self.defense
To get an object's attribute by name, use getattr builtin function. For example: getattr(currentPlayer, equipItem).append(i). To assign to an attribute, use setattr.
Related
players_list = [Ani, Paty, Felix, Alex]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
I tried to iterate over the list, but it always gives me an error: NameError: name 'Ani' is not defined
for player in players_list:
player = Player(str(player))
But doing all the process manually work:
Ani = Player("Ani"), etc
Is there any way that i can automate this process?
First of all the thing you should know, the players_list that you have declared are not containing strings, they are being considered as variables which you have not defined anywhere, and therefore the NameError.
Now, if you want to correct this, and if you actually intend to store objects of Player in players_list, then you can do the following:
players_list = ["Ani", "Paty", "Felix", "Alex"]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
for i in range(len(players_list)):
players_list[i]=Player(players_list[i])
This will store Player objects in the list you have declared just the thing that you expect to get.
You are having problems with the players not being defined. So players_list = [Ani, Paty, Felix, Alex] will throw an error because the objects Ani, Paty, Felizx, and Alex do not exist.
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
Now, we need to iterate through the list.
players_list = ['Ani', 'Paty', 'Felix', 'Alex']
players = [Player(player) for player in players_list]
Sounds like you're trying to dynamically create variables - write code that writes code.
You could try to use the exec built-in function.
players = ['Ani', 'Paty', 'Felix', 'Alex']
class Player:
def __init__(self, name):
self.name = name
def p_vote(self):
print(self.name + " voted.")
for player in players:
exec( "%s = Player( '%s' )" %(player, player) )
Ani.p_vote()
Although, general internet advice has two points to make:
Be cautious where you use exec.
The Pythonic way is to write out the variables, "explicit is better than implicit."
I am building a battle simulation program. Running into TypeError. Unable to resolve. Any help would be appreciated. I can't seem to get the iadd function working. I'm trying to add new Pokemon objects to the existing PokemonTrainer object by using the iadd function in python. Anyone has any ideas on how to execute this?
main.py
name = input("State your name: ")
player = PokemonTrainer(name)
player += Pokemon("Staryu", ElementType.WATER, [
Move("water blast", ElementType.WATER, 5),
Move("water cyclone", ElementType.WATER, 6)
])
pokemon_trainer.py
For the iadd, I'm using type-based dispatch to deal with the parameter. If it is of type Pokemon, call the add_pokemon method on self and then return the self object. If it is of type Item, call the add_item method on self and then return the self object. Otherwise, raise a TypeError.
from pokemon import Pokemon
class PokemonTrainer:
def __init__(self, name, pokemon = [], items = [], current_active_pokemon = None):
self.name = name
self.pokemon = pokemon
self.items = items
self.current_active_pokemon = current_active_pokemon
def __iadd__(self, other):
self.pokemon.append(other)
if (type(other) == type(Pokemon)):
self.add_pokemon(other)
elif (type(other) == type(Item)):
self.add_item(other)
else:
raise TypeError("Only Pokemon or Item type are allowed")
return self
def add_pokemon(self, pkmn):
self.pokemon.append(pkmn)
if (self.current_active_pokemon == None):
self.current_active_pokemon = pkmn
def add_item(self, item):
self.items.append(item)
pokemon.py
class Pokemon:
def __init__(self, name, pokemon_type, moves):
self.name = name
self.pokemon_type = pokemon_type
self.moves = moves
self.level = 1
self.exp = 0
self.max_hp = 100
self.current_hp = self.max_hp
self.attack_power = 1
self.defense_power = 1
self.fainted = False
I guess you want isinstance(other, Pokemon) instead of type(other) == type(Pokemon).
https://docs.python.org/3/library/functions.html#isinstance
Also relevant here: What are the differences between type() and isinstance()?
I've spent an hour or two collectively now trying to figure this problem out but I'm not getting any results. In my program when a defending animal is "killed" it should be deleted from it's registry, but no matter what I do I can't seem to get that to happen. In this instance if I were to initiate a hunter and a buffalo then attack() the buffalo with the hunter the buffalo should be killed and removed from it's classes registry but I can't get python to select that specific buffalo from the registry.
Any help is appreciated.
class IterRegistry(type):
def __iter__(cls):
return iter(cls._registry)
class Buffalo(object):
__metaclass__ = IterRegistry
_registry = []
hp = 1
price = 150
attacks = 0
regeneration = 2
def __init__(self, name):
self._registry.append(self)
self.name = name
def createBuffalo():
for i in range(len(Buffalo._registry),len(Buffalo._registry)+1):
varname = ("b" + str(i))
globals()[varname] = Buffalo("b" + str(i))
class Wolf:
__metaclass__ = IterRegistry
_registry = []
hp = 1
price = 0
attacks = 2
regeneration = 1.5
def __init__(self, name):
self._registry.append(self)
self.name = name
def createWolf():
for i in range(len(Wolf._registry),len(Wolf._registry)+1):
varname = ("w" + str(i))
globals()[varname] = Wolf("w" + str(i))
class Hunter:
__metaclass__ = IterRegistry
_registry = []
hp = 2
price = 0
attacks = 1
regeneration = 0
balance = 0
def __init__(self, name):
self._registry.append(self)
self.name = name
def createHunter():
for i in range(len(Hunter._registry),len(Hunter._registry)+1):
varname = ("h" + str(i))
globals()[varname] = Hunter("h" + str(i))
def attack(attacker, target):
if attacker.attacks >= 1:
target.hp -= 1
if target.hp == 0:
if type(attacker) == Hunter:
attacker.balance += 150
print(target)
if type(target) == Wolf:
del Wolf._registry[[n for n in Wolf._registry if n == target]]
if type(target) == Hunter:
del Hunter._registry[[n for n in Hunter._registry if n == target]]
if type(target) == Buffalo:
del Buffalo._registry[[n for n in Hunter._registry if n == target]]
One more note, the reason I have double brackets is because it was incorrect syntax with single brackets but the syntax was fine with doubles.
If you need any more code, ask in a comment below (I have not included all of it but it should be enough).
The issue you're trying to solve is caused by trying to use a list as an index to be removed from your list
[n for n in Wolf._registry if n == target]
All you're trying to get out of this list comprehension is the target, so just use that.
Wolf._registry.remove(target)
I have a list of objects. I would like to check some string if that string exists as a field value any object in the list. for example,
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
a = [animal1, animal2, animal3,animal4,animal5]
my problem to write a code in order to see if there is an object with given name. for example "chip".
You can iterate over the array of objects, and check with each object's getName function.
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
animals = [animal1, animal2, animal3,animal4,animal5]
searched_animal = 'rex'
for animal in animals:
if animal.getName() == searched_animal:
print('Found')
break
You can use any plus a comprehension:
any(animal.getName() == "chip" for animal in animals)
Iterating a list containing anything is quite simple really. Like so:
animal_to_find = "someAnimal"
for animal in animals:
if animal.getName() == animal_to_find:
print("Found a match for: " + animal)
You can use the getName method present in Ani class for this program
class Ani:
name = ''
def __init__(self, name):
self.name = name
def getName(self):
return self.name
animal1 = Ani('alica')
animal2 = Ani('rex')
animal3 = Ani('bobik')
animal4 = Ani('dobik')
animal5 = Ani('sobik')
animals = [animal1, animal2, animal3,animal4,animal5]
key = 'chip'
flag=0
for animal in animals:
if animal.getName() == key:
print('Found')
flag=1
break
if flag==0:
print("Not Found")
Im trying to write a python method that looks at Rarity and counts the different types and then returns what the smallest count is but i keep getting: 'MagicCard' object is not subscriptable. Im also wanting to check which colors are associated with the least rare cards. Any help would be appreciated:
Here is where the Json can be obtained from for testing: http://mtgjson.com/json/DTK.json
Card Object:
class MagicCard(object):
def __init__ (self, jsonCard):
self.name=jsonCard["name"]
if jsonCard.get("colors",""):
self.colors=jsonCard["colors"]
else:
self.colors=None
if jsonCard["rarity"]:
self.rarity=jsonCard["rarity"]
else:
self.rarity=None
def get_name(self):
"""Return the name of the card"""
return self.name
def get_colors(self):
"""Return the colors of the card"""
return self.colors
def get_rarity(self):
"""Return the rarity of the card"""
return self.rarity
Card Deck Object:
class MagicCardSet(object):
def __init__(self, DeckDict):
self.cardlist = [MagicCard(eachCard) for eachCard in DeckDict["cards"]]
def get_card_list(self):
Card_name_list=[]
for newCard in self.cardlist:
Card_name_list.append(newCard.get_name())
return(Card_name_list)
def get_card_color(self):
color_list=[]
for newCard in self.cardlist:
color_list.append(newCard.get_color())
return(color_list)
def get_card_rarity(self):
rarity_list=[]
for newCard in self.cardlist:
rarity_list.append(newCard.get_rarity())
return(rarity_list)
def get_rarest_card(self):
for eachCard in self.cardlist:
if eachCard["rarity"]=="Uncommon":
uncommon_counter = uncommon_counter + 1
elif eachCard["rarity"]=="Common":
common_counter=common_counter + 1
elif eachCard["rarity"]=="Rare":
rare_counter = rare_counter + 1
elif eachCard["rarity"]=="Mythic Rare":
mythic_rare_counter = mythic_rare_counter + 1
return(mythic_rare_counter)
error:
The
for eachCard in self.cardlist
returns a MagicCard instance. Call get_rarity() and get_name() and get_colors() on eachCard.
Also, to get the colors of the least rare (most common) cards:
unrare_colors = {}
for eachCard in self.cardlist:
if eachCard.get_rarity() == "Common":
for eachColor in eachCard.get_colors():
unrare_colors[eachColor] = 1
for color in unrare_colors.keys():
print(color)