# Import Modules
from Dice import dice
d10 = dice(10,1) #I use dice, but you could just as easily use random.randint()
d4 = dice(4,1)
d20 = dice(20,1)
# Assign Classes
class Player_Character:
inventory = []
def __init__(self, HP, MaxHP, AC, ToHitAdjustment, Surprise_Adjustment,
Initiative_Adjustment, Exp, \
MaxExp, Gold, Damage):
self.HP = int(HP)
self.MaxHP = int(MaxHP)
self.AC = int(AC)
self.ToHitAdjustment = int(ToHitAdjustment)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
self.Exp = int(Exp)
self.MaxExp = int(MaxExp)
self.Gold = int(Gold)
self.Damage = int(Damage)
this next section may be where the error is, although I doubt it because when I run through the code the character is assigned exp and gold and they seem to grow at the correct rate.
def attack(self, goblin, Player_Character):
Player_attack_roll = d20.die_roll() + Player_Character.ToHitAdjustment
if (Player_attack_roll >= goblin.AC):
print('you did', Player_Character.Damage, 'damage')
goblin.HP -= Player_Character.Damage
if (goblin.HP <= 0):
print("congratulations you killed the goblin")
Player_Character.Exp += goblin.ExpReward
if (Player_Character.Exp >= Player_Character.MaxExp):
print("Congratulations you have leveled up")
Player_Character.LevelUp()
print('you have', Player_Character.Exp, 'exp ')
Player_Character.Gold += goblin.Gold
print("you have", Player_Character.Gold, 'gold ')
del goblin
else:
print("You miss ")
def flee(self):
print("you run away ")
quit()
def heal(self, Player_Character):
Player_Character.HP += d10.die_roll()
if Player_Character.HP >= Player_Character.MaxHP:
Player_Character.HP = Player_Character.MaxHP
print("You have reached max HP ")
this may be where the error is, I expect it to assign the variable name 'MrHezy' which was previously assigned to Player_Character to FighterLvl1, but when I run the code it continuously says that I am leveling up, which I am unsure if that means that the character is remaining as Player_Character, or if there is something else wrong
def LevelUp(self):
MrHezy = FighterLvl1(25, 25, 15, 10, 2, 2, 25, 75, 20, d10.die_roll()+5)
This next section has code is where my question of inheritance comes into play. Even though FighterLvl1 has inherited from (Player_Character) my IDE says things like "unresolved attribute reference 'Exp' for FighterLvl1" Also I am unsure if adding the 'attack' method under FighterLvl1 does anything; I expect it to overwrite the 'attack' method from Player_Character
class FighterLvl1(Player_Character):
def attack(self, goblin, Player_Character):
Player_attack_roll = d20.die_roll() + Player_Character.ToHitAdjustment
if (Player_attack_roll >= goblin.AC):
print('you did', Player_Character.Damage, 'damage')
goblin.HP -= Player_Character.Damage
if (goblin.HP <= 0):
print("congratulations you killed the goblin")
FighterLvl1.Exp += goblin.ExpReward
if (FighterLvl1.Exp >= FighterLvl1.MaxExp):
print("Congratulations you have leveled up")
FighterLvl1.LevelUp()
print('you have', FighterLvl1.Exp, 'exp ')
FighterLvl1.Gold += goblin.Gold
print("you have", FighterLvl1.Gold, 'gold ')
del goblin
def LevelUp(self):
MrHezy = FighterLvl2(Player_Character)
class FighterLvl2(Player_Character):
def LevelUp(self):
MrHezy = FighterLvl3(Player_Character)
class FighterLvl3(Player_Character):
def MaxLevel(self):
print("Congratulations you are level 3, this is the highest programmed level in the game
")
class goblin:
def __init__(self, HP, MaxHP, AC, ToHitAdjustment, Surprise_Adjustment,
Initiative_Adjustment, \
ExpReward, Gold, Damage):
self.HP = int(HP)
self.MaxHP = int(MaxHP)
self.AC = int(AC)
self.ToHitAdjustment = int(ToHitAdjustment)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
self.ExpReward = int(ExpReward)
self.Gold = int(Gold)
self.Damage = int(Damage)
def attack(self, Player_Character, goblin):
if (goblin.HP <= 0):
print("the goblin is inert")
else:
goblin_attack_roll = d20.die_roll() + goblin.ToHitAdjustment
if (goblin_attack_roll >= Player_Character.AC):
goblin_damage = d4.die_roll()
print("you take", goblin_damage, 'damage')
Player_Character.HP -= goblin_damage
if (Player_Character.HP <= 0):
print("oh dear you have died")
del Player_Character
quit()
else:
print("the goblin misses ")
MrHezy = Player_Character(20, 20, 10, 5, 0, 0, 0, 25, 0, d10.die_roll())
def spawn_goblin(goblin):
G1 = goblin(5, 10, 8, 2, 0, 0, 25, 5, d4.die_roll())
return G1
goblin1 = spawn_goblin(goblin)
def battle(goblin1):
# user input
player_initiative_adjustment = MrHezy.Initiative_Adjustment
monster_initiative_adjustment = goblin1.Initiative_Adjustment
#define while loop for the battle
while True:
if (goblin1.HP <= 0):
print('oh dear looks like we need a new goblin')
break
#use random.randint(a,b) to generate player and monster base initiative
player_base_initiative = d10.die_roll()
monster_base_initiative = d10.die_roll()
#subtract the adjustment to get player and monster initiative
player_initiative = player_base_initiative - player_initiative_adjustment
monster_initiative = monster_base_initiative - monster_initiative_adjustment
#compare the initiatives and display the results
if (player_initiative < monster_initiative):
attack_flee_heal = input("congratulations you go first. Would you like to attack,
flee, or heal?")
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1, MrHezy)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
elif attack_flee_heal == 'flee':
MrHezy.flee()
else:
print("uhoh, the monsters go first, they attack!")
goblin1.attack(MrHezy, goblin1)
attack_flee_heal = input("Would you like to attack, flee, or heal? ")
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1, MrHezy)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy, goblin1)
elif attack_flee_heal == 'flee':
MrHezy.flee()
#main game loop
while True:
spawn_goblin(goblin)
battle(goblin1)
print("spawn another goblin")
goblin1.HP = 0
goblin1.HP += d10.die_roll()
This code runs perfectly well, please enter it into your IDE.
The problem that I have is a logic error, when a goblin is killed instead of leveling up the character first to level 1 then level 2 then level 3 instead the character levels up to level 1 over and over and over.
I agree with Danny Varod, in that there are very many improvements that need to be made, and I definitely recommend following his advice.
However if you are simply looking to make what you have work you need to specify in your level up methods that you are referencing the global MrHezy variable.
eg:
def LevelUp(self):
global MrHezy
MrHezy = FighterLvl2(Player_Character)
The level up replaces a variable in the object, what you should do, if you want to use a class per level (not necessarily a good idea) is:
Create a Character class.
In Character class define an implementation field.
Initialize implementation field e.g. implementation = SomeSpeciesLevel1().
To "level-up": implementation = implementation.level_up()
This way you have a constant wrapper that doesn't change which wraps the level-changing implementation.
A better design would be to have one class with functionality based on level-dependant formulas.
class CharImpl:
#abstractmethod
def can_level_up() -> bool:
return NotImplemented
#abstractmethod
def next_level() -> CharImpl:
return NotImplemented
pass
class Character:
def __init__(initial_impl: CharImpl=None):
self.impl = initial_impl.copy() if initial_impl else HumanLevel1()
pass
def level_up():
if self.impl.can_level_up():
self.impl = self.impl.next_level()
pass
pass
class Human(CharImpl):
pass
class HumanLevel1(Human):
def __init__(src: Human):
# TODO: copy relevant fields from src
pass
def can_level_up() -> bool:
return True
def next_level() -> CharImpl:
return HumanLevel2(self)
pass
class HumanLevel2(Human):
def __init__(src: Human):
# TODO: copy relevant fields
pass
def can_level_up() -> bool:
return False
def next_level() -> CharImpl:
return self
pass
Related
I have the following method of a certain class:
def make_payment(self, cost):
and the following at the main file:
print(money_machine.make_payment(drink.cost))
why is it returning this? (I am following a code-along session and everything seems to be fine with his code)
TypeError: MoneyMachine.make_payment() missing 1 required positional argument: 'cost'
MAIN:
from menu import Menu, MenuItem
from coffee_maker import CoffeeMaker
from money_machine import MoneyMachine
"""1print report
2check resources sufficies
process coins
check transaction successful
make coffee
"""
coffee_maker = CoffeeMaker()
menu = Menu()
money_machine = MoneyMachine
is_on = True
while is_on:
print(menu.get_items())
order = input("your order: ")
if order == 'off':
is_on = False
elif order == "report":
coffee_maker.report()
else:
drink = menu.find_drink(order)
if coffee_maker.is_resource_sufficient(drink):
if money_machine.make_payment(drink.cost):
coffee_maker.make_coffee(drink)
MONEY MACHINE:
class MoneyMachine:
CURRENCY = "$"
COIN_VALUES = {
"quarters": 0.25,
"dimes": 0.10,
"nickles": 0.05,
"pennies": 0.01
}
def __init__(self):
self.profit = 0
self.money_received = 0
def report(self):
"""Prints the current profit"""
print(f"Money: {self.CURRENCY}{self.profit}")
def process_coins(self):
"""Returns the total calculated from coins inserted."""
print("Please insert coins.")
for coin in self.COIN_VALUES:
self.money_received += int(input(f"How many {coin}?: ")) * self.COIN_VALUES[coin]
return self.money_received
def make_payment(self, cost):
"""Returns True when payment is accepted, or False if insufficient."""
print(self.money_received)
self.process_coins()
if self.money_received >= cost:
change = round(self.money_received - cost, 2)
print(f"Here is {self.CURRENCY}{change} in change.")
self.profit += cost
self.money_received = 0
return True
else:
print("Sorry that's not enough money. Money refunded.")
self.money_received = 0
return False
Per your comments, the issue is that you are not instantiating your class correctly.
Overall your instantiation code should be more like this, which is the correct way to instantiate a class:
money_machine = MoneyMachine()
then calling methods would insatiate it correctly and you pass self in, so money_machine.make_payment(drink.cost) would then work as expected.
Instantiating a class is essentially calling the class's __init__() method, this is also where you would define any required arguments if needed when creating a copy of the class. For example:
class MoneyMachine():
def __init__(self, currency_type):
# here you must instantiate with currency_type defined
self.currency_type = currency_type
self.profit = 0
self.money_received = 0
usa_money_machine = MoneyMachine(currency_type='USD')
I am trying to create the GUI code for my connect four boardgame but error's keep on coming up that I don't know how to correct. Can anyone help? The error:
TypeError: init() missing 1 required positional argument: 'buttns_list'
Code:
def __init__(self):
self.mw = tkinter.Tk()
self.mw.title = ("Connect Four")
self.rows = 6
self.cols = 7
self.buttons_2d_list = []
for i in range (self.rows):
self.rows = ['']*self.cols
self.buttons_2d_list.append(self.rows)
self.gboard = ConnectFourBoard()
p1 = HumanPlayer("X")
p2 = ComputerPlayer("O", self.buttns_list)
self.players_1st = (p1, p2)
self.currnt_player_index = 0
self.winner = False
def clicked_btn(self, x, y):
p = self.players_1st[self.currnt_player_index]
button = self.buttons_2d_list[x][y]
if button["text"] == "":
button["text"] = p.get_player_symbol()
self.gboard.MakeMove(x, y, p.get_player_symbol())
winner = self.gboard.CheckForWin()
is_full = self.gboard.FullBoard()
if winner == True:
win_message = ("Player %s is the winner!" %p.get_player_symbol())
messagebox.showinfo("Winner Info", win_messge)
self.mw.destroy()
exit()
elif is_full == True:
messagebox.showinfo("Winner Info", "The game is a draw")
self.mw.destroy()
exit()
else:
pass
if self.currnt_player_index == 1:
self.currnt_player_index = 0
else:
self.currnt_player_index += 1
p = self.players_1st[self.currnt_player_index]
p.play()
import random
class ComputerPlayer(Player):
def __init__(self, letter, buttns_list):
Player.__init__(self, letter)
self.buttons_2d_list = buttns_list
def play(self):
pass
It's not clear to me from the rest of the code exactly what you should be passing here, but your init calls for a letter, which you do have, and a buttns_list, which you don't:
def __init__(self, letter, buttns_list):
So the error comes from this line:
p2 = ComputerPlayer("O")
Either:
1) Pass in a buttns_list if your ComputerPlayer class needs it
p2 = ComputerPlayer("O", self.buttons_2d_list)` # in GameGUI init
2) Get rid of it if this was added by mistake:
class ComputerPlayer(Player):
def __init__(self, letter):
Player.__init__(self, letter)
I'm trying to print a variable in Python using the following code:
from time import sleep
import random
class Hero:
def __init__(self,name):
self.name = name
if name == "rock":
self.health = 50
self.attack = 10
elif name == "paper":
self.health = 70
self.attack = 7
elif name == "scissors":
self.health = 100
self.attack = 5
def dmg(self, other):
other.ehealth -= self.attack
start = 1
while start == 1:
name = input("Pick a class [rock/paper/scissors]")
if name != "rock" or "paper" or "scissors":
print ("That player does not exist. Try again.")
start = 1
else:
start = 1
player = Hero(name)
enemyName = ["erock", "epaper", "escissors"]
ename = random.choice(enemyName)
print ("Your character is", name, "which comes with", self.health, "health, and", self.attack, "attack.")
print("")
sleep(1)
print ("Your enemy is", ename, "which comes with", ehealth, "health, and", eattack, "attack.")
I can't figure out a way to access and print the variable "self.health" under the "Hero" class. I can access "name" just fine. Maybe it's the fact that it's under an if statement? Can someone help me out?
self is just a parameter name used inside the methods. Don't use it outside the method.
To access the variables refer to them using the object name (player) like this
player.health
The name variable you are printing "works" because it's not from the object. You should use the same notation to access that too:
player.name
ok so this is my program so far to operate as an ordering system of a cafe with multiple items. My goal is to calculate the price of an order, store that order to keep count of which coffee was ordered and how many of that coffee was ordered. Right now I am stuck on calculating the order total for an order. The main problem im stuck on is getting the coffee price of a coffee based on what the user wants, say if i want x coffee, i need to get the price of that coffee. I've stored instances of coffee in an array and right now I am not sure of how to get the price of a coffee to be used in the calculation of the total price
class Coffee(object):
def __init__ (self, coffee_type, price):
self.coffee_type = coffee_type
self.price = price
class Order(object):
def __init__(self, coffee_type, coffee_amount):
self.coffee_type = coffee_type
self.coffee_amount = coffee_amount
if name =="main":
coffee_available=[Coffee("1 : Flat White", 3.50),
Coffee("2 : Long Black", 3.50),
Coffee("3 : Cappuccino", 4.00),
Coffee("4 : Espresso", 3.25),
Coffee("5 : Latte", 3.50)]
ordering = 'Y'
total_cost = 0
while ordering == 'Y':
print("Coffee Type\t\tPrice")
print("-----------\t\t-----")
for coffee in coffee_available:
print("{}\t- - -\t$ {}".format(coffee.coffee_type,coffee.price))
print()
order_coffee = int(input("What is the number of the coffee you want? "))
order_amount = input("How many would you like to order? ")
new_order = None
if order_coffee >= 1 and order_coffee <=5:
coffee_choice = coffee_available[coffee.price]
new_order = Order(coffee_choice, order_amount)
total_cost = new_order.coffee_type * order_amount
else:
print ("Please enter a valid number")
dine_in = input('You like to dine in? (Y/N)')
dine_in = dine_in.upper()
if dine_in == 'Y' or 'YES':
total_cost = total_cost + (total_cost * 0.1)
print (total_cost)
Ordering = 'N'
elif dine_in == 'N' or 'No':
total_cost = total_cost
else:
print("Please enter a valid input")
continue
It's better to split the id of the coffee from the name:
class Coffee(object):
def __init__ (self, coffee_id, coffee_type, price):
self.coffee_id = coffee_id
self.coffee_type = coffee_type
self.price = price
Then when you create object use:
Coffee(1, "Flat White", 3.5)
And when you want the price use:
def get_price(coffee_available, coffee_id):
for coffee in coffee_available:
if coffee.coffee_id == coffee_id:
return coffee.price
return None
I am working on a simple text based battle game, and I have come across a(nother) problem. I have a main function and a battle function and in the battle function once you finish the battle, you gain a certain amount of XP, which is then (or should be) remembered by changing the value of player1.xp. Right after the battle sequence I set it so in the code if player1.xp >= 1 it will change the value of player1.level to "2". Though, whenever I run the code, for some reason the xp value gets lost when the battle function is finished. I know this because it prints out the value of player1.xp after the battle function, and it says "0". Here is the code:
import random
xp1 = random.randint(1,2)
class player:
def __init__ (self, name, health, strength, defense, potion, xp, level):
self.health = health
self.strength = strength
self.defense = defense
self.name = name
self.potion = potion
self.xp = xp
self.level = level
def changeHealth(self, h):
self.health = h
def addLevel(self):
self.level += 1
def subHealth(self, num):
self.health -= num
return self.health
def subPotion(self):
self.potion -= 1
return self.health
def addPotion(self, num1):
self.potion += num1
def addHealth(self):
self.health +=2
def addXP(self):
self.xp += xp1
def battle1(enemy, player1, name1):
player1 = player(name1, player1.health, player1.strength, player1.defense, player1.potion, player1.xp, player1.level)
enemy = player("Rat", enemy.health, enemy.strength, enemy.defense, player1.potion, enemy.xp, enemy.level)
print("Fight!")
s = 0
while s == 0:
attack =input("Type 1 to attack, type 2 to use a potion.")
if attack == "1":
enemy.subHealth(15)
elif attack == "2":
if player1.potion > 0:
print("You used a potion.")
elif player1.potion <= 0:
print("You don't have any potions! You are forced to attack.")
enemy.subHealth(15)
else:
print("Your life depends on this!")
if enemy.health <= 0:
print("Congratulations, you won! You recieved", xp1, "xp!")
player1.addXP()
s = 2
def main():
name1 = input("What would you like your name to be?")
print("Hello,", name1, "you are on a quest to save otis from the evil Dongus. You must slay him, or Otis will poop.")
player1 = player(name1, 10, 2, 1, 0, 0, 1)
enemy = player("Rat", 15, 0, 0, 0, 0, 0)
pick = input("You were walking along the path and found a potion! Press 'p' to pick it up.")
if pick == "p":
print("You added a potion to your inventory.")
player1.addPotion = 1
else:
print("You have no potions, you should probably pick this one up.")
print("You added a potion to your inventory.")
player1.addPotion = 1
battle1(enemy, player1, name1)
print(player1.xp)
if player1.xp >= 1:
print("You leveled up. You are now level 2.")
player1.addLevel()
else:
print("You have 0 xp.")
main()
Does anybody have a clue why this is happening? Thanks!
In main you create two player (should be Player) instances, and pass them to battle1:
player1 = player(name1, 10, 2, 1, 0, 1)
enemy = player("Rat", 15, 0, 0, 0, 0)
battle1(enemy, player1, name1)
In battle1 you create two new player instances, based on the two argument instances, modify the new instances, and don't return anything:
# take three parameters (one of which is unnecessary)
def battle1(enemy, player1, name1):
# replace two of the arguments with copies
player1 = player(name1, player1.health, player1.strength, player1.defense, player1.xp, player1.level)
enemy = player("Rat", enemy.health, enemy.strength, enemy.defense, enemy.xp, enemy.level)
# original arguments now inaccessible
It is not clear why you expected that this would work, but the minimal fix is to stop creating new instances in battle1. Also, it might be clearer if you moved xp1 = random.randint(1,2) inside battle1.