I'm having a foray into OOP in python,
This project is creating some randomly generated RPG characters
The problem I have run into is I am creating a list of these randomly generated characters, and want to print out there stats.
Here is how the characters are randomly generated:
def generateCharacters():
classes = ["B", "E", "W", "D", "K"]
choice = random.choice(classes)
if choice == "B":
return barbarian(70, 20, 50)
elif choice == "E":
return elf(30, 60, 10)
elif choice == "W":
return wizard(50, 70, 30)
elif choice == "D":
return dragon(90, 40, 50)
elif choice == "K":
return knight(60, 10, 60)
and here is the barbarian class, all the other classes are more or less identical:
class barbarian(character):
def __init__(self, charPower, charSAttackPwr, charSpeed):
# Getting the properties from the inheritted character Base Class
character.__init__(self, "B", 100)
self.power = charPower
self.sAttackPwr = charSAttackPwr
self.speed = charSpeed
# Method for getting and returning all the stats of the character
def getStats(self):
# Creating a string to hold all the stats, using concatenation
stats = "Name: %s, Type: %s, Health: %s, Power: %s, Special Attack
Power: %s, Speed: %s" % (self.name, self.type, self.health,
self.power, self.sAttackPwr, self.speed)
# Returns stats to the the function that called
return stats
I've created a method called getStats, which using string concatenation to make a string that shows all the stats:
# Method for getting and returning all the stats of the character
def getStats(self):
# Creating a string to hold all the stats, using concatenation
stats = "Name: %s, Type: %s, Health: %s, Power: %s, Special Attack Power: %s, Speed: %s" % (self.name, self.type, self.health, self.power, self.sAttackPwr, self.speed)
# Returns stats to the the function that called
return stats
When I run the code, it calls main(), which in turn calls menu():
def menu(gameChars):
print("Welcome to the RPG Character Simulator")
print("Here is your randomly generated team: ")
for x in gameChars:
print(x.getStats)
def main():
gameChars = []
for x in range(10):
y = generateCharacters()
gameChars.insert(x, y)
#z = generateCharacters()
menu(gameChars)
#print(z.getStats)
The output I was expecting from the print(x.getStats) would've been, using examples:
Name: bob, Type: barbarian, Health: 100, Power: 70, Special Attack Power: 20, Speed: 20
but instead, I get this:
<bound method barbarian.getStats of <__main__.barbarian object at 0x000001F56A195668>>
What am I missing with this? and how could I get the intended output?
Thanks in advance for any help
Replace this :
print(x.getStats)
With this :
print(x.getStats())
another version would be to use the #property decorator:
class Barbarian(Character):
#property
def getStats(self):
return 'Name: {.name}'.format(self)
which would allow:
bob = Barbarian('bob', …)
print(bob.getStats)
to work as you expect
Related
Here I have to create a class student with following member attributes: roll no, name, age and total marks. Create suitable methods for reading and printing member variables also to overload ‘==’ operator to print the details of students having same marks. Here I can't find way how to overload == operator for marks. Here I have got error.
class Student():
def __init__(self,r_no,name,age,marks):
self.r_no = r_no
self.name = name
self.age = age
self.marks = marks
def displayStudent(self):
print ("Roll no : ", self.r_no, "Name : ", self.name, ", Age: ", self.age, ", Marks: ", self.marks)
def __str__(self):
return "({0},{1},{3},{4})".format(self.r_no,self.name,self.age,self.marks)
def __eq__(self,other):
if(self.marks==other.marks):
return self.marks==other.marks
stu = []
for i in range (1,3):
print("Enter Details for Students %d" % (i))
r_no = int(input("Enter Roll no:"))
name = input("Enter Name:")
age = int(input("Enter Age:"))
marks = input("Enter Marks:")
stu.append(Student(r_no,name,age,marks))
for s in stu:
s.displayStudent()
To report that two students are equal given that they have the same marks the __eq__ function should look like this:
def __eq__(self, other):
return self.marks == other.marks
It returns True if the marks are the same and False otherwise
Then this code returns True and False respectively.
print(Student(1, 'test1', 20, 4) == Student(2, 'test2', 30, 4)) # True
print(Student(3, 'test3', 0, 1) == Student(3, 'test3', 0, 2)) # False
Code screenshot
Instead of def __eq__, you need to use an if condition, like
if(stu[0].marks==stu[1].marks):
print("marks of ",stu[0].name,"&",stu[1].name," is same")
else:
print("not same")
Or, if you have more data than just two students, you can use a for loop as well. For more details, check out the image I've linked at the top here.
I have created a class called Dog_card. With this, I created player_card and computer_card. I am trying to compare the same attribute from both of these objects. There are more values to each than friendliness, but I have removed them so it is easier to test. I keep getting the error:
NameError: name 'player_card' is not defined
Here is my code:
class Dog_card:
def __init__(self):
self.name = ""
self.friendliness = ""
def printing_card(self):
prnt_str = "Name: %s \nIntelligence: %s" %(self.name, self.friendliness)
return prnt_str
def printing_player_card():
player_card = Dog_card()
player_card.name = dogs_list_player[0]
player_card.friendliness = random.randint(1,101)
def printing_computer_card():
computer_card = Dog_card()
computer_card.name = dogs_list_computer[0]
def choose_category():
user_choice_category = input("Please choose a category: ")
if user_choice_category not in ["1", "2", "3", "4"]:
print("Please choose from the options above")
choose_category()
else:
if user_choice_category == "1":
if player_card.friendliness > computer_card.friendliness:
print("Player has won the round!")
elif player_card.friendliness == computer_card.friendliness:
print("It is a Draw!")
Any help would be appreciated
The problem is as it's stated in the error. Basically you are trying to use player_card when it is not defined inside the definition of choose_category(). I suggest you pass the value of player_card to the function like the following
def choose_category(player_card):
or you can define it as an attribute so that it can be accessed by the methods of the same class.
you need to initialize play_card before using it. Maybe you call printing_player_card in order to intnialize before, but as you don't return anything from that function, the created object and the variable player_card only lives in scope of the function. When that function finished, player_card object variable is unknown and the object is destroyed.
if you want player_card (as well as computer_card) survice its function, you need to return it an save it to a variable outside the function code.
Furthermore your function name "printing" is bad, as you don't print anything. You just initialize your object.
Maybe that's what you are aiming at.
class Dog_card:
def __init__(self, name, friendliness=1):
self.name = name
self.friendliness = friendliness
def __str__(self):
return "Name: %s \nIntelligence: %s" %(self.name, self.friendliness)
player_card = Dog_card(dogs_list_player[0], random.randint(1,101))
computer_card = Dog_card(dogs_list_copmuter[0])
def choose_category():
user_choice_category = input("Please choose a category: ")
if user_choice_category not in ["1", "2", "3", "4"]:
print("Please choose from the options above")
choose_category()
else:
if user_choice_category == "1":
if player_card.friendliness > computer_card.friendliness:
print("Player has won the round!")
elif player_card.friendliness == computer_card.friendliness:
print("It is a Draw!")
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
The project: Write a program in python in which the virtual dealer Jake plays against the virtual players: Mike and Will. Mike and Will are free to bet on different outcomes with different payout ratios. This will allow the comparison of various strategies. You should keep track of each player's bank roll (including the dealer)
The game is played with a 7 faced die with numbers [0 - 6] numbers[1, 2, 3] are blue and numbers [4, 5, 6] are green.
Correct Parity Pays: 2/1
Correct Colour Pays: 2/1
Exact Number Pays: 5/1
Here is the first draft with the modifications #Harvey Summer suggested. Comments on how I can improve the code's structure and performance are appreciated.
from random import choice
from random import randint
class die_face():
# This class is used to define the properties linked to each outcome on the dice.
def __init__(self, num, colour, parity):
self.num = num
self.colour = colour
self.parity = parity
# Determine the properties linked to each outcome on the dice.
zero = die_face(0, 'none', 'none')
one = die_face(1, 'blue', 'odd')
two = die_face(2, 'blue', 'even')
three = die_face(3, 'blue', 'odd')
four = die_face(4, 'green', 'even')
five = die_face(5, 'green', 'odd')
six = die_face(6, 'green', 'even')
options = [zero, one, two, three, four, five, six,]
class bet():
# Define the bets
def __init__(self, bet_type, odds):
self.bet_type = bet_type
self.odds = odds
num_bet = bet('num', 5)
colour_bet = bet('colour', 2)
parity_bet = bet('parity', 2)
class broker():
# Define the properties of the broker.
def __init__(self, name, balance):
self.name = name
self.balance = balance
def __str__(self):
result = "Name: {} \n" \
"Balance: {}" .format(self.name, self.balance)
return result
def modify_balance(self, amount):
self.balance += amount
main_broker = broker('Main',1e3)
def random_strategy():
# Bet a random amount on a random game with a random guess.
guess = 'empty'
game_mode= choice([num_bet, colour_bet, parity_bet])
if game_mode == num_bet:
guess = randint(0,6)
elif game_mode == colour_bet:
guess = choice(['blue','green'])
elif game_mode == parity_bet:
guess = choice(['even','odd'])
value = randint(1,10)
return game_mode , value, guess
class player():
# This class defines each player
def __init__(self, name, strategy, bank_roll):
self.name = name
self.strategy = strategy
self.bank_roll = bank_roll
def modify_balance(self, amount):
self.bank_roll += amount
def __str__(self):
result = "Name: {} \n" \
"Bank Roll: {}" .format(self.name, self.bank_roll)
return result
def play(self):
return self.strategy()
# Add the players
Will = player("Will",random_strategy,100)
def dealer(type, bet_value, guess):
#Roll the dice
correct = choice(options)
#Return amount based on Win or Lose
if type == num_bet.bet_type:
if correct.num == guess:
return num_bet.odds * bet_value - bet_value
else:
return -bet_value
if type == colour_bet.bet_type:
if correct.colour == guess:
return colour_bet.odds * bet_value - bet_value
else:
return -bet_value
if type == parity_bet.bet_type:
if correct.parity == guess:
return parity_bet.odds * bet_value - bet_value
else:
return -bet_value
def main_play(player):
# Collect the bets from the players
bets = player.play()
# Roll and return bets
amount = dealer(bets[0].bet_type, bets[1], bets[2])
# Distribute the money
main_broker.modify_balance(amount*-1)
player.modify_balance(amount)
print(player)
print(main_broker)
I would create a bettingtable as a broker where money is put at risk and the outcome to the dealer and players are exchanged based on the play outcome, and allow players and dealer to place bet and collect winnings. Encapsulate betting logic to the players and abstracted it from a game rules class. Each player should have a risk tolerance or game play style (lame, aggressive, cheater, etc.)
If you build this right, it shouldn't matter what the game is: dice, cards, etc. should basically play the same.
I've written a simple script to help me better understand using classes. It generates a random character for a game. I defined the object and then call a function on that object that prints out the generated character. At the end of the printed block, there is an extraneous "None" that I'm not sure where it's coming from nor why it's being printed. Here's the sample output:
ted
Strength : 20
Dexterity : 17
Hit Points: 100
Aura : 100
Weapon :
Spell :
Item :
Element :
--------------------
None
In my code, the last line of player.stats() is print "-" * 20 which is displayed right above "None". Here's the code that defines the object:
class Player(object):
def __init__(self, name):
self.name = name
self.strength = randint(15, 20)
self.dexterity = randint(15, 20)
self.hit_points = 100
self.aura = 100
self.weapon = " "
self.spell = " "
self.item = " "
self.element = " "
def stats(self):
print "\n"
print self.name
print "Strength : %d" % self.strength
print "Dexterity : %d" % self.dexterity
print "Hit Points: %d" % self.hit_points
print "Aura : %d" % self.aura
print "Weapon : %s" % self.weapon
print "Spell : %s" % self.spell
print "Item : %s" % self.item
print "Element : %s" % self.element
print "-" * 20
The object is then instanced using this:
name = raw_input("Name your character: ")
player = Player(name)
print player.stats()
The complete code can be read here at Pastebin if necessary.
print player.stats()
Is the culprit. player.stats() == None
You want just:
player.stats()
You'd do better to name your function player.printStats().
Another option would be to make it return a string:
def stats(self):
return '\n'.join([
self.name
"Strength : %d" % self.strength,
"Dexterity : %d" % self.dexterity,
"Hit Points: %d" % self.hit_points,
"Aura : %d" % self.aura,
"Weapon : %s" % self.weapon,
"Spell : %s" % self.spell,
"Item : %s" % self.item,
"Element : %s" % self.element,
"-" * 20
])
And then print player.stats() would behave as expected
The stats() method does not return anything. A function that doesn't return anything evaluates to None. Which is what you print.
So, don't print the return value of the function. Just call it. Now, you should rename the function as printStats() to make it clear what it does. And then just call it like this:
def printStats(self):
....
player = Player(name)
player.printStats()
Naming is a really important part of programming. A slightly poor choice of name often leads to confusion like this.
You print the return value of player.stats():
print player.stats()
but the .stats() method does not have a return statement. The default return value of any function or method in python is None, if no return statement has been given:
>>> def foo():
... pass
...
>>> print foo()
None
Either remove the print before the method call, or have stats() return a string to print instead of doing all the printing in the method.