Trying to make a class to define enemies - python

I don't really know how to word this other than: does this work, and could I add more to it like the bush statement?
class Enemy():
def __init__(self, name, HP, skills, attack, defense, loot, expget, flvrtxt):
self.name = name
self.HP = health
self.skills = skills
self.attack = attack
self.defense = defense
self.loot = loot
self.expget = expget
self.flvrtxt = text
bush = Enemy()
bush.name = "Bush"
bush.HP = 10
bush.skills = "none"
bush.attack = 0
bush.defense = 5
bush.loot = "A stick"
bush.expget = 50
bush.flvrtxt = "Just a bush, it cannot attack"
And by adding more, I mean can I basically copy paste the bush definitions, change the stats around and make a brand new enemy?
For example, could I add this?:
imp = Enemy():
imp.name = "Imp"
imp.HP = 50
imp.skills = "none"
imp.attack = 10
imp.defense = 10
imp.loot = "gold"
imp.expget = 150
imp.flvrtxt = "Cliche RPG enemy"

Off the top of my head, I can think of two ways that you could go about this depending on what you are trying to achieve.
The way that you have your code structured now, you can create instances of the Enemy class, that are defined by their arguments. As #Patrick Haugh pointed out in the comments section, you could explicitly set all of the attributes of Enemy at construction if you update your method to be titled __init__(self, name, HP, skills, attack, defense, loot, expget, flvrtxt):
class Enemy(object):
def __init__(self, name, HP, skills, attack, defense, loot, expget, flvrtxt):
self.name = name
self.HP = HP
self.skills = skills
self.attack = attack
self.defense = defense
self.loot = loot
self.expget = expget
self.flvrtxt = flvrtext
bush = Enemy("Bush", 10, "none", 0, 5, "A Stick", 50, "Just a bush, it cannot attack")
imp = Enemy("Imp", 50, "none", 10, 10, "gold", 150, "Cliche RPG enemy")
Alternately, if you intend to instantiate specific types of Bushes and Imps, you might want to create them as their own classes that sub-class the Enemy class but have their own default implementations for their associated fields:
class Bush(Enemy):
def __init__(self):
super(Bush, self).__init__("Bush", 10, "none", 0, 5, "A Stick", 50, "Just a bush, it cannot attack")
class Imp(Enemy):
def __init__(self):
super(Imp, self).__init__("Imp", 50, "none", 10, 10, "gold", 150, "Cliche RPG enemy")
This way would allow you to write code like the following, to instantiate a Bush that would come pre-poulated with all of the fields that you define for a Bush in its class:
bush = Bush();

Related

How can I assign new classes to each item in a list by iterating over a dictionary's key/value pairs based on a matched attribute in python?

Every existing object in this list needs to be replaced with an instance of a specific class. Each existing object already has a .type which should pair with a key in a dictionary to produce the appropriate class (value in dict). Objects then also need to regain their original .name from before class assignment.
I can't find a way to do this that doesn't involve nested for-loops, but nested for loops are basically assigning to EVERY member of a class the same name (the last name saved to a temporary variable).
I've dug through all of the basic literature and understand the fundamental logic surrounding loops, dictionaries, and lists, I'm just (sure that I'm) executing something improperly or nesting something the wrong way.
class gameObject(object):
def __init__(self):
self.name = name
#Class given to any living thing in the game; confers basic stats
class livingThing(gameObject):
def __init__(self, name="Living Thing", HP = 0):
self.name = name
self.HP = HP
self.alive = True
self.safe = True
self.listready = False
# After livingThing, classes narrow into more specific groups that have unique traits, abilities, and roles in the game
class Animal(livingThing):
def __init__(self):
super().__init__()
self.truename = ""
self.type = ""
self.listready = False
self.type = "Test"
self.truetype = ""
self.hasatype = False
class Reptile(Animal):
def __init__(self):
super().__init__()
self.therm = "ecto"
self.type = "Game Reptile"
class Amphibian(Animal):
def __init__(self):
super().__init__()
self.therm = "ecto"
self.type = "Game Amphibian"
class Bird(Animal):
def __init__(self):
super().__init__()
self.therm = "endo"
self.type = "Game Bird"
class Mammal(Animal):
def __init__(self):
super().__init__()
self.therm = "endo"
self.type = "Game Mammal"
class Fungus(Animal):
def __init__(self):
super().__init__()
self.therm = "none"
self.type = "Game Fungus"
class Fungus(Animal):
def __init__(self):
super().__init__()
self.therm = "none"
self.type = "Game Fungus"
class Ascomycetes(Animal):
def __init__(self):
super().__init__()
self.therm = "none"
self.type = "Game Ascomycetes"
somereptile = Reptile()
somereptile.type = "Reptiles"
somereptile.name = "Some Reptile"
somefrog = Amphibian()
somefrog.type = "Amphibians"
somefrog.name = "Some frog"
somefungus = Fungus()
somefungus.type = "Fungi"
somefungus.name = "Some Fungus"
secondfrog = Amphibian()
secondfrog.type = "Amphibians"
secondfrog.name = "Second Frog"
thirdfrog = Amphibian()
thirdfrog.type = "Amphibians"
thirdfrog.name = "Third Frog"
secondfungus = Fungus()
secondfungus.type = "Fungi"
secondfungus.name = "Second Fungus"
dummypop = [somereptile, somefrog, somefungus, secondfrog, thirdfrog, secondfungus]
### PROBLEM FUNCTION ###
def givetype(poplist):
typedict = {
"Reptiles" : Reptile(),
"Amphibians" : Amphibian(),
"Birds" : Bird(),
"Mammals" : Mammal(),
"Fungi" : Fungus(),
"Ascomycetes" : Ascomycetes()
}
holderlist = []
tempnames = []
i = 0
for org in poplist:
holderlist.append(org)
tempnames.append(org.name)
for key in typedict.keys():
if (holderlist[i].type.lower() in key.lower()):
holderlist[i] = typedict[key]
holderlist[i].name = tempnames[i]
print(holderlist[i].name,
holderlist[i].type)
i+=1
return holderlist
dummymaster = (givetype(dummypop))
for animal in dummymaster:
print(animal.name, animal.type)
I expect to produce:
Some Reptile Game Reptile
Some Frog Game Frog
Third Frog Game Frog
Second Frog Game Frog
etc
What I'm getting is:
Some Reptile Game Reptile
Third Frog Game Frog
Third Frog Game Frog
Third Frog Game Frog
etc
Thanks for your help!
You only ever create one instance of each class (which happens when you create typedict), so all references to that instance (which is what holderlist is populated with, as opposed to distinct instances) will certainly all have the same name.
Try not instantiating classes in typedict, and instead doing the instantiation when you need it in the for loop:
typedict = {
"Reptiles" : Reptile,
"Amphibians" : Amphibian
...
}
...
holderlist[i] = typedict[key]()

Python and variable inside Variables

I have this object Troll.
I made a random selection for his 'weapon'.
Every time he appears his weapon will change.
Under his object status section, I have a variable 'base_att' I want it to be the damage variable from his 'weapon'
How can I have the base_att variable get updated by the 'weapon' variable random.choice
note that I listed all my 'Weapons' in a different .PY file hence the items.weapon_for_troll calling.
class stick:
name = 'Wooden Stick'
damage = range (0,3)
effect = None
class rocks:
name = 'Rocks'
damage = range (0,5)
effect = None
class troll:
name = 'Troll'
class equipment:
weapon = random.choice(items.weapon_for_troll)
class inventory:
loot = None
class status:
level = 1
exp_point = 30
hp_point = 30
base_att =
base_def = 2
bonus_def = 0
You need to distinguis between ("static") class variables and ("non static") instance variables.
You are declaring all things static - thats great for things that are shared between all Trolls (like a "type" of monster - aka Troll) - not so great for things all "have" but are not "the same" - say like an inventory.
Try this approach:
import random
class Weapon: # no need to make each weapon its own class
def __init__(self,name,damage,effect):
self.name = name
self.damage = damage
self.effect = effect
# create some troll weapons to choose from
troll_weapons = [ Weapon("Wooden Stick", range(3), None), Weapon("Rocks",range(5), None) ]
class Equipment:
def __init__(self):
# every time you instantiate a new equipment, generate a random weapon
# for this instance you just created. They are not static, they differ
# between each Troll (who instantiates its own Equipment)
self.weapon = random.choice(troll_weapons)
class Troll:
name = 'Troll'
def __init__(self):
self.equipment = Equipment() # get a new instance of Eq for this troll
# instance
self.weapon = self.equipment.weapon # "link" the troll weapon to its equipment
# as shortcut - do smth similar to an
# instance of your "Stat" block
def __str__(self):
return f"Troll with: {self.weapon.name}"
# create a troll army
trolls = [Troll() for _ in range(10)]
for t in trolls:
print(t)
Output:
Troll with: Rocks
Troll with: Wooden Stick
Troll with: Rocks
Troll with: Rocks
Troll with: Wooden Stick
Troll with: Rocks
Troll with: Wooden Stick
Troll with: Wooden Stick
Troll with: Wooden Stick
Troll with: Wooden Stick
Reads to check:
Classes
Class variables vs Instance variables
Sidenotes:
there are convention about naming schemes, classes start with a Capital, members lowercase

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):

Categories