Getting functions to interact with each other - python

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.

Related

[textRPG]How to keep random creating of class and class atrributes every time i run a program[Python]

I am trying some text based rpg game as a beginner in python. But i am struggling to get done one thing.
If i use while loop to run program 5 times. So i want repeat killing monster but without saving his attributes.
If you run this code, character kills a monster in couple of moves and appends his experience to himself and monster hp decreases to <= 0 and dies.
Looping whole program does not work, randomly created monster is still the same, i just want to create new monster with new random attributes every time i loop program. It is possible? I am new to this and can't figure it out at this moment. Some tips ?
Here is some code but without while loop: final output is to loop this menu and fight simulator to gain exp and items from random monsters.
import random
import time
# List of items to drop
normal_items = ['Copper ore', 'Apple', 'Animal skin', 'Stone', 'Feather', 'Rotten egg', 'Bag of sand', "Simple dagger", "Blue flower"]
rare_items = ['Energized wand', 'Staff of purity', 'Enhanced gloves', 'Adamant chest plate']
legendary_items = ['Crown of Immortality', 'Robe of fire-dragon']
drop_chance_dice = random.randint(1, 100)
# Simple drop chance function
def dice():
if drop_chance_dice <= 70:
random_choice = (random.choice(normal_items))
print(f"You got: {random_choice} ")
if 70 <= drop_chance_dice <= 98:
random_choice = (random.choice(rare_items))
print(f"You got: {random_choice} ")
if 99 <= drop_chance_dice <= 100:
random_choice = (random.choice(legendary_items))
print(f"Congratulations! You got an legendary item: {random_choice}")
# Instances and mobs
rat_nest= ['Rat', 'Giant Rat', 'Leader of Rats']
northern_forest = ['Snake', 'Wolf', 'Witch']
# My Character Class
class YourCharacter:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Creating my character(preset)
my_character = YourCharacter("Your character \n", 'FroGres', 16, 0, 1, 100)
# Introduction
def introduction_of_player(my_character):
print(f"{my_character.intro}")
print(f"{my_character.name}")
print(f"Attack: {my_character.attack}")
print(f"Experience: {my_character.exp}")
print(f"Level: {my_character.level}")
print(f"HP: {my_character.hp}")
# Monsters class build
class Monster:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Monsters attributes + list of mobs (for testing - to be upgraded)
# rat nest
rat = Monster("You fight vs: \n", "Rat", random.randint(4, 6), random.randint(8, 14), random.randint(1, 3),
random.randint(50, 100))
giant_rat = Monster("You fight vs: \n", "Giant Rat", random.randint(6, 8), random.randint(10, 18), random.randint(2, 4),
random.randint(80, 130))
rat_boss = Monster("You fight vs: \n", "Leader of Rats", random.randint(4, 6), random.randint(8, 14),
random.randint(1, 3),
random.randint(50, 100))
# northern forest
#Witch = Monster("You fight vs: \n", "Witch", random.randint(8, 12), random.randint(12, 20), random.randint(3, 6), random
# .randint(120, 200))
list_of_mobs = [rat, giant_rat, rat_boss]
event_mob = random.choice(list_of_mobs) # Random pick monster , USED in function
# Introduction of Monster
def introduction_of_monster_ratnest(list_of_mobs):
print(f"{list_of_mobs.intro}")
print(f"{list_of_mobs.name}")
print(f"Attack: {list_of_mobs.attack}")
print(f"Experience: {list_of_mobs.exp}")
print(f"Level: {list_of_mobs.level}")
print(f"HP: {list_of_mobs.hp}")
def escape_or_fight():
take_input = input("[a]ttack or [r]un?")
if take_input == 'a':
return attack()
if take_input == 'r':
print("You run as fast as possible.. ")
print("You returning to your hideout..")
else:
print("Something wrong")
# Menu of actions
def menu_dungs():
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
if event_mob == rat:
introduction_of_monster_ratnest(rat)
escape_or_fight()
elif event_mob == giant_rat:
introduction_of_monster_ratnest(giant_rat)
escape_or_fight()
elif event_mob == rat_boss:
introduction_of_monster_ratnest(rat_boss)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
elif asking == "2":
print("You entering northern forest.. good luck!\n")
print("Dungeon unavailable at this moment, try another one")
pass
# Not in use
else:
print("Try again and choose correct location\n")
menu_dungs()
def attack():
gain_exp = event_mob.exp + my_character.exp
rounds = 0
while event_mob.hp > 0:
event_mob.hp = event_mob.hp - my_character.attack
rounds += 1
print(f"You hit with: {my_character.attack} damage. Enemy HP is {event_mob.hp}")
print(f"Enemy HP after your attack is {event_mob.hp}", "\n")
if event_mob.hp <= 0:
print(f"{event_mob.name} has died..")
print(f"It tok you: {rounds} moves to kill that creature! \n")
print("Congratulations! Here is your loot")
dice()
print(f"You got: {event_mob.exp} experience from that fight.")
print(f"Your experience is now: {gain_exp}")
menu_dungs()
I tried: to create new unique monster with new randomly created attributes every time i run program. I used while loop but monster is not "respawning"
I expect: Some sort of simulator, after i kill monster, program creates new one and my character gains experience and items every fight.
I wonder: If there is some method to makes this class unique every loop.
Here is HOW-TO to achieve all goals in your question:
each time generate monsters with different parameters
respawn monsters
First you create 3 sepreate functions that would return a new monster - the class of returned value is always the same (Monster) but they return new instances on each call:
def get_rat():
return Monster("You fight vs: \n", "Rat", ...)
def get_giant_rat():
return Monster(...)
def get_rat_boss():
reutrn Monster(...)
You will also need to modify how you select monsters. I would suggest to create list of functions - so instead of selecting a monster you select a function, that generates monster:
# This should replace the list_of_mob
list_of_mob_generators = [get_rat, get_giant_rat, get_rat_boss]
And the last - you should select monster on each loop interation in main menu (so the monster could respawn). The shortest way is to change your global variable:
event_mob = None # we change event_mob initially to None - we will select in later
def menu_dungs():
global event_mob # this is new
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
event_mob_generator = random.choice(list_of_mob_generators) # get one of the functions
event_mob = event_mob_generator() # call the function to get monster
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
# and this condition has changed, since we do not have one instance of each monster anymore
if event_mob.name == 'Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Giant Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Rat Boss':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
... # and so on
and of course do not forget a while loop for main menu =)
while True:
menu_dungs()
Thanks for help, program works as i wanted but still shows me 8 yellow errors in attack() function. Cannot find reference 'hp' in 'None' etc.
maybe because this event_mob = None ?
Could you run this code and see what is going on ? very likely i did put something in wrong place..
import random
import time
# List of items to drop
normal_items = ['Copper ore', 'Apple', 'Animal skin', 'Stone', 'Feather', 'Rotten egg', 'Bag of sand', "Simple dagger", "Blue flower"]
rare_items = ['Energized wand', 'Staff of purity', 'Enhanced gloves', 'Adamant chest plate']
legendary_items = ['Crown of Immortality', 'Robe of fire-dragon']
drop_chance_dice = random.randint(1, 100)
# Simple drop chance function
def dice():
if drop_chance_dice <= 70:
random_choice = (random.choice(normal_items))
print(f"You got: {random_choice} ")
if 70 <= drop_chance_dice <= 98:
random_choice = (random.choice(rare_items))
print(f"You got: {random_choice} ")
if 99 <= drop_chance_dice <= 100:
random_choice = (random.choice(legendary_items))
print(f"Congratulations! You got an legendary item: {random_choice}")
# Instances and mobs
rat_nest= ['Rat', 'Giant Rat', 'Leader of Rats']
#not in use
northern_forest = ['Snake', 'Wolf', 'Witch']
# My Character Class
class YourCharacter:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Creating my character(preset)
my_character = YourCharacter("Your character \n", 'FroGres', 16, 0, 1, 100)
# Introduction
def introduction_of_player(my_character):
print(f"{my_character.intro}")
print(f"{my_character.name}")
print(f"Attack: {my_character.attack}")
print(f"Experience: {my_character.exp}")
print(f"Level: {my_character.level}")
print(f"HP: {my_character.hp}")
# Monsters class build
class Monster:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Monsters getting functions
# rat nest
def get_rat():
return Monster("You fight vs: \n", "Rat", random.randint(4, 6), random.randint(8, 14), random.randint(1, 3),
random.randint(50, 100))
def get_giant_rat():
return Monster("You fight vs: \n", "Giant Rat", random.randint(6, 8), random.randint(10, 18), random.randint(2, 4),
random.randint(80, 130))
def get_rat_boss():
return Monster("You fight vs: \n", "Rat Boss", random.randint(4, 6), random.randint(8, 14),random.randint(1, 3),
random.randint(50, 100))
# northern forest
# def get_witch():
# return Monster("You fight vs: \n", "Witch", random.randint(8, 12), random.randint(12, 20), random.randint(3, 6), random
# .randint(120, 200))
list_of_mobs_generators = [get_rat, get_giant_rat, get_rat_boss]
def escape_or_fight():
take_input = input("[a]ttack or [r]un?")
if take_input == 'a':
return attack()
if take_input == 'r':
print("You run as fast as possible.. ")
print("You returning to your hideout..")
else:
print("Something wrong")
# Menu of actions
event_mob = None
def menu_dungs():
global event_mob
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
event_mob_generator = random.choice(list_of_mobs_generators)
event_mob = event_mob_generator()
def introduction_of_monster_ratnest(event_mob):
print(f"{event_mob.intro}")
print(f"{event_mob.name}")
print(f"Attack: {event_mob.attack}")
print(f"Experience: {event_mob.exp}")
print(f"Level: {event_mob.level}")
print(f"HP: {event_mob.hp}")
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
if event_mob.name == 'Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Giant Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Rat Boss':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
elif asking == "2":
print("You entering northern forest.. good luck!\n")
print("Dungeon unavailable at this moment, try another one")
pass
# Not in use
else:
print("Try again and choose correct location\n")
def attack():
gain_exp = event_mob.exp + my_character.exp
rounds = 0
while event_mob.hp > 0:
event_mob.hp = event_mob.hp - my_character.attack
rounds += 1
print(f"You hit with: {my_character.attack} damage. Enemy HP is {event_mob.hp}")
print(f"Enemy HP after your attack is {event_mob.hp}", "\n")
if event_mob.hp <= 0:
print(f"{event_mob.name} has died..")
print(f"It tok you: {rounds} moves to kill that creature! \n")
print("Congratulations! Here is your loot")
dice()
print(f"You got: {event_mob.exp} experience from that fight.")
print(f"Your experience is now: {gain_exp}")
while True:
menu_dungs()

Pop from Empty List error during Black Jack

Ok, so I'm experiencing a weird error, and unfortunately, I don't know that I can show both examples here.
Take a look at the following code (apologies for the length):
import random
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8,
'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
class Card():
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
## Attributes listed in the __init__ statement do not have to
## correlate to called objects (ie: suit,rank)
self.value = values[rank]
## Values represents the integer value of each card as compared
## to it's string (word) based rank
def __str__(self):
return self.rank + " of " + self.suit
## Allows for printing in the form of X of Y, or Two of Hearts as an example
# Deck will be a compilation of all card objects to a single list
# that can then be shuffled, dealt from, etc.
class Deck():
def __init__(self):
## All cards starts off with a blank list
self.all_cards = []
## For each suit in suits
for suit in suits:
### For each rank in ranks
for rank in ranks:
#### Create the Card object equal to the suit and rank of the card
#### ie: Two of spades, three of clubs, etc.
created_card = Card(suit,rank)
#### Then append each card created to the self.all_cards list.
self.all_cards.append(created_card)
def shuffle(self):
## Method call to randomize the self.all_cards list internally
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop()
game_deck = Deck()
game_deck.shuffle()
## Checking to make sure the deck is full before continuing
print(len(game_deck.all_cards))
## Attempt without watching tutorial
class Player():
def __init__(self,name):
self.name = name
self.player_hand = []
self.balance = 100
self.bet = 0
def deposit(self,dep_amt):
self.balance += dep_amt
print(f'{dep_amt} added to balance. New balance is: ${self.balance}')
def withdraw(self,wit_amt):
self.balance -= wit_amt
print(f'{wit_amt} subtracted from balance. New balance is: ${self.balance}')
def player_bet(self,bet_amt = 0):
while True:
bet_amt = int(input("How much would you like to bet? \n"))
if bet_amt > self.balance:
print("Sorry, you don't have enough money, try again.")
elif bet_amt < 1:
print('Sorry, you must bet at least $1')
else:
print(f'Thanks, your bet is ${bet_amt}')
self.balance -= bet_amt
print(f'Your remaining balance is ${self.balance}')
break
## May need to be adjusted to clear the hand entirely, unsure
def remove_one(self):
return self.player_hand.pop(0)
# NOTE: The most cards a player can hold without busting is 11
def add_cards(self,new_cards):
### Single card object
self.player_hand.append(new_cards)
def __str__(self):
return f'{self.name} has a balance of ${self.balance}.'
## Attempt without watching tutorial
class Dealer():
def __init__(self,name):
self.name = name
self.player_hand = []
self.balance = 500
def deposit(self,dep_amt):
self.balance += dep_amt
print(f'{dep_amt} added to balance. New balance is: ${self.balance}')
def withdraw(self,wit_amt):
self.balance -= wit_amt
print(f'{wit_amt} subtracted from balance. New balance is: ${self.balance}')
def remove_one(self):
return self.player_hand.pop(0)
def add_cards(self,new_cards):
### Single card object
self.player_hand.append(new_cards)
def __str__(self):
return f'{self.name} has a balance of ${self.balance}.'
## Full Game Code
game_on = True
playing = False
while game_on == True:
game_check = input('Would you like to play Black Jack, Y/N? ').lower()
if game_check == 'y':
round_counter = 0
dealer_name = 'Klaus the Dealer'
dealer = Dealer(dealer_name)
player_name = input("Player One, what is your name? ")
player_one = Player(player_name)
print(f"Nice to meet you {player_name}, you'll be playing against {dealer_name}\n")
print(player_one)
print(dealer)
print("Let's play Black Jack!\n")
playing = True
else:
print('Ok, have a nice day')
game_on = False
break
while playing == True:
round_counter +=1
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
So when I run this code all at once, at the very last 2 lines, I get an index error when the code hits the player_one.add_cards(game_deck.deal_one()) stating IndexError: pop from empty list
The thing is, if I run this code in separate lines in a Jupiter notebook, and separate out the class calls from the rest of the game code, the player_one.add_cards(game_deck.deal_one()) works just fine.
Can anyone tell me what is causing this error?
You are running out of cards... :)
the line you reference is inside of an infinite loop.
while playing == True:
round_counter +=1
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
suggestion: while you are troubleshooting, just pop a little print statement in the deal_one() function to see what is being dealt and then delete it later.
Ok, so thanks to Jeff H for pointing out that the call for the card deal was inside an infinite loop, even though I couldn't fix the problem by breaking the loop itself, I did figure out how to start off the initial deal by absorbing it into the game_check statement above, like so:
while game_on == True:
game_check = input('Would you like to play Black Jack, Y/N? ').lower()
if game_check == 'y':
round_counter = 0
dealer_name = 'Klaus the Dealer'
dealer = Dealer(dealer_name)
player_name = input("Player One, what is your name? ")
player_one = Player(player_name)
print(f"Nice to meet you {player_name}, you'll be playing against {dealer_name}\n")
print(player_one)
print(dealer)
print("Let's play Black Jack!\n")
playing = True
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
This won't account for having to deal cards into the hand later while in another while loop, but it will fix the first issue.

Trying to recreate a Dice Game called "Going to Boston" in Python

I'm trying to develop "Going to Boston" in python. A lot of the rules are explained in the code, as well as a lot of the code being explained in the comments. I'll answer any questions, but I'm having some issues with my output. Here is what I have.
# This code aims to recreate the game "Going to Boston" for four players.
# Rules:
# - Each player rolls three dice.
# – Each player keeps their highest die and sets it aside.
# – The remaining two dice are re-rolled and the highest of the two is set aside.
# – The last die is rolled and the final score is the sum of the three dice.
# ----------------------------------------------------------------------------------------------------------------------
# We'll use the random module for the dice.
import random
# This variable is just to count rounds
RoundCount = 0
# These global variables are being used to save the score of each player.
Score1 = 0
Score2 = 0
Score3 = 0
Score4 = 0
FinalScore = [] # We'll use this to decide the winner(s).
# Here is our class for player.
class Player:
def __init__(self, name):
self.name = name # Storing their name, just to more easily identify each player.
d1 = random.randint(1,6) # Randomly choosing a number from 1-6 to simulate a dice.
d2 = random.randint(1,6)
d3 = random.randint(1,6)
self.dice = [d1, d2, d3]
self.SavedDice = [] # We'll be using this variable to save dice.
def score(self):
# here is where dice are actually coded and saved.
# Here, we'll save the max value in dice.
self.SavedDice.append(max(self.dice))
self.dice.remove(max(self.dice)) # We're removing the max value, and maintaining the previous two dice.
for i in self.dice:
i = random.randint(1,6)
self.dice.append(i)
#return print(self.name,"\b's score is:",sum(self.SavedDice))
return(self.dice)
def __str__(self): # Here is where we return the saved dice.
return print(self.name,'Saved Dice:',self.SavedDice)
# Here is where we actually play.
# First, we setup the players.
Player1 = Player('Player 1')
Player2 = Player('Player 2')
Player3 = Player('Player 3')
Player4 = Player('Player 4')
# We'll use a loop to manage rounds.
while RoundCount < 3:
RoundCount += 1
# We use the __str__ method to show the currently saved dice.
Player1.__str__()
Player2.__str__()
Player3.__str__()
Player4.__str__()
# We'll assign values for scoring, to be used later, here
FScore1 = Player1.score()
FScore2 = Player2.score()
FScore3 = Player3.score()
FScore4 = Player4.score()
# Here is where we'll score each player.
# We'll first append all the final scores of each player to be compared.
FinalScore.append(FScore1, FScore2, FScore3, FScore4)
WinningScore = max(FinalScore)
if FScore1 == WinningScore:
print('Player 1 Won!')
if FScore2 == WinningScore:
print('Player 2 Won!')
if FScore3 == WinningScore:
print('Player 3 Won!')
if FScore4 == WinningScore:
print('Player 4 Won!')
# Just cleanly exiting the code.
print(' ')
exit('End of Game')
I end up getting an output like this, and I'm not sure why. I also need to keep def str(self): and use it.
Player 1 Saved Dice: []
Player 2 Saved Dice: []
Player 3 Saved Dice: []
Player 4 Saved Dice: []
Seems like it isn't looping all the way through or being cancelled somehow, and the values aren't being saved to self.SavedDice or SavedDice.
You're infinite-looping on the following block:
for i in self.dice:
i = random.randint(1,6)
self.dice.append(i)
Try replacing with SavedDice:
for i in self.dice:
i = random.randint(1,6)
self.SavedDice.append(i)
import random
# Here is our class for player.
class Player:
def __init__(self, name):
self.name = name # Storing their name, just to more easily identify each player.
d1 = random.randint(1,6) # Randomly choosing a number from 1-6 to simulate a dice.
d2 = random.randint(1,6)
d3 = random.randint(1,6)
self.dice = [d1, d2, d3]
self.saved_dice = [] # We'll be using this variable to save dice.
def roll(self):
# here is where dice are actually coded and saved.
# Here, we'll save the max value in dice.
max_dice = max(self.dice)
self.saved_dice.append( max_dice )
self.dice.remove( max_dice ) # We're removing the max value, and maintaining the previous two dice.
self.dice = [ random.randint(1,6) for _ in self.dice ] # recreate list with size of remained values
#property
def score(self):
return sum(self.saved_dice)
def __str__(self): # Here is where we return the saved dice.
return f'{self.name} Saved Dice: { self.saved_dice }'
def main():
max_players = 4
round_count = 0
# Create set of players
players = { Player(f'Player { i + 1 }') for i in range(max_players) }
while round_count < 3:
round_count += 1
for player in players:
# Roll each player per each round
player.roll()
print(player)
# Choosing winner player
winner = max( players, key=lambda p: p.score )
print(f'{winner.name} Won!')
print(' ')
exit('End of Game')
if __name__ == '__main__':
main()

In python, steal a class B method AND use it as an instance of class A from within a class A method

I've been successfully able to "spellsiphon" (steal) a method from one class (darkMage) to give to the player class (Player).
However, the "stolen" method still seems to belong to the darkMage class--in other words, when the Player casts the stolen spell, it still reads (in all ways) as the darkMage casting the spell.
Can you help? I've done this:
Added the stolen darkMage() spell to the Player's spellbook (a list)
Successfully paired the "cast" command with items in the spellbook
I want to:
- Have the Player() casting the spell rather than the darkMage (when the stolen method is called, it's run as the darkMage rather than the Player)
class Player(livingThing):
def __init__(self,name="The Stranger", HP=10, MP=5, strength=1, intellect=1, spirit=1, luck=5, gil=6):
self.name = name
self.HP = HP
self.MP = MP
self.gil = gil
self.strength = strength
self.intellect = intellect
self.spirit = spirit
self.luck = luck
self.spellbook = []
def act(self, enemy):
actions = {
"a" : self.attack,
"heal" : self.heal,
"flee" : self.flee,
"cast" : self.cast,
"siphon" : self.spellsiphon
}
#Takes input from the player
self.safe = False
while ((self.HP > 0) and (enemy.HP > 0)) and (self.safe != True):
decision = input("What would you like to do? ")
#Sets the user's input as lower-case and checks for it within the dictionary
if decision.lower() in actions:
actions[decision.lower()](enemy)
if self.safe != True:
enemy.agreact(self)
self.printHP(enemy)
else:
print("That didn't workkkkkk! Try again.")
# Prints both player and enemy HP
def printHP(self, enemy):
print("{0}'s' HP: {1} \n{2}'s HP: {3}".format(self.name, self.HP, enemy.name, enemy.HP))
# Allows the player to attack an enemy (currently functional)
def attack(self, enemy):
enemy.HP -= self.strength
print("You strike {0} for {1} damage!".format(enemy.name, self.strength))
#player.printHP(enemy)
# Allows the player to heal a certain amount of health based on its "spirit" stat (currently functional)
def heal(self, enemy):
healed = randint(0, self.spirit)
self.HP += healed
print("You've healed for {0}!".format(healed))
#player.printHP(enemy)
#Allows the player to attempt to run away
def flee(self, enemy):
randluck = randint(0, self.luck)
if randluck > 3:
print("You successfully escaped!")
self.safe = True
else:
print("You weren't able to escape!")
def cast(self, enemy):
if len(self.spellbook) != 0:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](self)
else:
print("You don't have any spells to cast!")
### SPELLSIPHON IS CURRENTLY BROKEN; IT -DOES- SIPHON THE SPELL BUT ONLY ALLOWS THE DARK MAGE TO CONTINUE CASTING ###
def spellsiphon(self, enemy):
if len(enemy.spellbook) != 0:
randspell = randint(0, len(enemy.spellbook)-1)
stolenspell = darkMage().spellbook[randspell]
#(type(enemy).__name__).__init__(self, stolenspell)
self.spellbook.append(stolenspell)
print("You've successfully stolen {0} from {1}!".format("stolenspell", enemy.name))
else:
print("You can't steal a spell from {0}!".format(enemy.name))
# Anything that can act with/against the player
class Actor(livingThing):
def __init__(self, name="Unknown Entity", HP=10, MP=2, strength=1, intellect=1, spirit=3, gil=3):
self. name = name
self.HP = HP
self.MP = MP
self.gil = gil
self.strength = strength
self.intellect = intellect
self.spirit = spirit
self.abilities = [self.strike, self.heal]
def printabilities():
print(self.abilities)
# Chooses how your opponent will respond to your attack
def agreact(self, player):
choice = randint(0, len(self.abilities)-1)
self.abilities[choice](player)
# A basic "hit back" reaction from your opponent--everyone can do this
def strike(self, player):
player.HP -= self.strength
print("{0} hit {1} for {2}!".format(self.name, player.name, self.strength))
def heal(self, enemy):
healed = randint(0, self.spirit)
self.HP += healed
print("{0} healed for {1}!".format(self.name, healed))
### CURRENT VERSION SUPPORTS THE ADDITION OF NEW ABILITIES IN CHILD CLASSES VIA THE "super().__init__()" method! ###
class Enemy(Actor):
def __init__(self):
super().__init__()
self.abilities.append(self.cast)
self.name = "Unknown Enemy"
self.HP = 600
self.spellbook = []
def cast(self, opponent):
if len(self.spellbook) != 0:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](opponent)
class darkMage(Enemy):
def __init__(self):
super().__init__()
self.player = Player()
self.name = "Dark Mage"
self.spellbook.extend((self.fireball, self.icenova))
def fireball(cls, opponent):
choice = randint(cls.intellect*1, cls.intellect*2)
spellname = "Fireball"
opponent.HP -= choice
print("{0} casted fireball for {1} damage!".format(cls.name, choice))
def icenova(cls, opponent):
opponent.HP -= cls.intellect
choice = randint(0,1)
name = "Ice Nova"
if choice == 1:
frozen = True
else:
frozen = False
print("{0} casted ice nova for {1} damage!".format(cls.name, cls.intellect))
if frozen == True:
print("{0} has been frozen solid!".format(opponent.name))
It looks like you want the spells to be detached from the enemies/players. You can do this by making them static methods instead of instance methods (you're using def fireball(cls,..) but not using the #classmethod decorator, so they are really instance methods). Static methods don't automatically get passed the class/instance they are attached to like class/instance methods, so you can pass they can be 'stolen' and 'cast' (called) without remembering the original owner.
Here is a simple example:
class DarkMage:
def __init__(self, name):
self.name = name
self.spellbook = [self.fireball]
#staticmethod
def fireball(caster, target):
print("{} casted fireball on {} for 10 damage".format(caster.name, target.name))
class Player:
def __init__(self, name):
self.name = name
self.spellbook = []
def spellsiphon(self, enemy):
if enemy.spellbook:
spellchoice = randint(0, len(enemy.spellbook)-1)
self.spellbook.append(enemy.spellbook[spellchoice])
def cast(self, enemy):
if self.spellbook:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice](self, enemy)
>>> dm = DarkMage('Bad Guy')
>>> p = Player('Do-Gooder')
>>> p.spellsiphon(dm)
>>> p.cast(e)
Do-Gooder casted fireball on Evildoer for 10 damage
>>> p.cast(dm)
Do-Gooder casted fireball on Bad Guy for 10 damage
You can also define the static methods outside the classes, which would let you share them between classes a bit easier, but I think the ideal way to do this would be to make spells their own python classes so that you can attach names and other attributes to them:
class Fireball:
name = 'fireball'
damage = 10
#classmethod
def cast(cls, caster, target):
print(
'{} cast {} on {} for {} damage!'.format(
caster.name,
cls.name,
target.name,
cls.damage,
)
)
class SuperFireball(Fireball):
name = 'super fireball'
damage = 50
class Player:
def __init__(self):
self.spellbook = [Fireball]
def list_spells(self):
for spell in self.spellbook:
print(spell.name)
def cast(self, enemy):
if self.spellbook:
spellchoice = randint(0, len(self.spellbook)-1)
self.spellbook[spellchoice].cast(self, enemy)

I am having problems with my elif statements

I'm programming a game to try and improve my skills in python. In this part of the code I am trying to program a shop with a money system testing one variable against 5 different possible answers
while True:
choice=str(input("What would you like to buy? (Type in 'nothing' when you don't want anymore items) "))
if choice!="health potion" and "strength potion" and "strength booster" and "armour piece" and "nothing":
print()
next_line=input("I do not understand what you wrote. Try again please ")
print()
elif choice=="nothing":
next_line=input("The merchant says 'Thanks for business' ")
print()
break
elif choice=="health potion":
gold=gold-10
if gold<0:
gold=gold+10
next_line=input("Sorry but you don't have enough gold ")
print()
else:
next_line=input("You bought a health potion ")
health_potions=health_potions+1
next_line=input("You now have "+str(gold)+" gold coins ")
print()
elif choice=="strength potion":
gold=gold-15
if gold<0:
gold=gold+15
next_line=input("Sorry but you don't have enough gold ")
print()
else:
next_line=input("You bought a strength potion ")
strength_potions=strength_potions+1
next_line=input("You now have "+str(gold)+" gold coins ")
print()
elif choice=="strength booster":
gold=gold-45
if gold<0:
gold=gold+45
next_line=input("Sorry but you don't have enough gold ")
print()
else:
next_line=input("You boosted your strength ")
strength_booster=strength_booster+1
next_line=input("You now have "+str(gold)+" gold coins ")
print()
elif choice=="armour piece":
gold=gold-30
if gold<0:
gold=gold+30
next_line=input("Sorry but you don't have enough gold ")
print()
else:
next_line=input("You bought an armour piece ")
armour=armour+1
next_line=input("You now have "+str(gold)+" gold coins ")
print()
When you input health potion the code goes on like normal but with the other inputs it goes to this part of the code
if choice!="health potion" and "strength potion" and "strength booster" and "armour piece" and "nothing":
print()
next_line=input("I do not understand what you wrote. Try again please ")
print()
For fun, here is a significantly more advanced version.
Don't worry if it doesn't all make sense right away; try tracing through it and figuring out how it works. Once you fully understand it you will have a much better grasp of Python!
class Character:
def __init__(self, name, health=50, strength=20, gold=200, inventory=None):
"""
Create a new character
inventory is a list of items (may have repeats)
"""
self.name = name
self.health = health
self.strength = strength
self.gold = gold
self.inventory = [] if inventory is None else list(inventory)
def buy(self, item):
"""
Buy an item
"""
if self.gold >= item.cost:
print(item.buy_response.format(name=item.name, cost=item.cost)) # print acceptance
self.gold -= item.cost # pay gold
item.buy_action(self) # apply purchased item to character
return True
else:
print("Sorry but you don't have enough gold.")
return False
class Item:
def __init__(self, name, cost, buy_response="You bought a {name} for {cost} GP", buy_action=None):
# store values
self.name = name
self.cost = cost
# what to print on a successful purchase
self.buy_response = buy_response
# apply a purchased item to the character
self.buy_action = self.make_buy_action() if buy_action is None else buy_action
def make_buy_action(self):
def buy_action(char):
"""
Purchase default action: add item to character inventory
"""
char.inventory.append(self)
return buy_action
#staticmethod
def buy_strength_booster(char):
"""
Purchase strength booster action: increase character strength
"""
char.strength += 1
def __str__(self):
return self.name
class Shop:
def __init__(self, name, *inventory):
"""
Create a shop
inventory is a list of (num, item); if num is None the store has an unlimited supply
"""
self.name = name
self.inventory = {item.name:(num, item) for num,item in inventory}
def visit(self, char):
"""
Serve a customer
"""
print("\nHowdy, {}, and welcome to {}!".format(char.name, self.name))
while True:
print("\nWhat would you like to buy today? (type 'list' to see what's available or 'done' to leave)")
opt = input("{} GP> ".format(char.gold)).strip().lower()
if opt == 'done':
print("Have a great day, and c'mon back when you've got more gold!")
break
elif opt == 'list':
item_names = sorted(name for name, (num, item) in self.inventory.items() if num is None or num > 0)
if item_names:
print(", ".join(item_names))
else:
print("Huh - looks like we're all sold out. Try again next week!")
break
elif opt in self.inventory:
num, item = self.inventory[opt]
if num is None or num > 0:
yn = input("That's {} GP. You want it? [Y/n]".format(item.cost)).strip().lower()
if yn in {'', 'y', 'yes'}:
if char.buy(item) and num is not None:
self.inventory[opt] = (num - 1, item)
else:
print("(scowling, the proprietor stuffs the {} back under the counter)".format(item.name))
else:
print("'Fraid we're all out of those.")
else:
print("Sorry, hain't had one o' those around in a coon's age!")
def main():
# stock the store
shop = Shop("Dwarven Dave's Delving Deal Depot",
(6, Item("health potion", 10)),
(6, Item("strength potion", 15)),
(3, Item("strength booster", 45, "You boosted your strength!", Item.buy_strength_booster)),
(None, Item("armor piece", 30)) # unlimited stock
)
# create a buyer
jeff = Character("Jeff")
# visit the store
shop.visit(jeff)
if __name__ == "__main__":
main()
Your issue is with this statement:
if choice!="health potion" and "strength potion" and "strength booster" and "armour piece" and "nothing":
Comparing strings like this doesn't work. You need to make sure it isn't in an array of the strings
if choice not in ("health potion","strength potion","strength booster","armour piece","nothing"):
Otherwise it will always be true, so the first statement will always execute.

Categories