My code thus far:
from random import randint
Dice1 = randint(1,6)
Dice2 = randint(1,6)
Dice3 = randint(1,6)
DiceRoll2 = Dice1 + Dice2
DiceRoll3 = Dice1 + Dice2 + Dice3
class Item(object):
def __init__(self, name, value, desc):
self.name = name
self.value = value
self.desc = desc
sword = Item("Sword", 2, "A regular sword.")
class Monster(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
monster = Monster("Monster", 50, DiceRoll2)
Damage = DiceRoll3 + sword.value
NewHealth = monster.health - Damage
print("You see a monster!")
while True:
action = input("? ").lower().split()
if action[0] == "attack":
print("You swing your", sword.name, "for", Damage, "damage!")
print("The", monster.name, "is now at", NewHealth, "HP!")
elif action[0] == "exit":
break
The intension is that with every time you enter "attack" you get a random result of DiceRoll3 (three random numbers from 1 to 6, that three times), add the value of the sword and substract that from the monster's starting health. This goes well until I enter "attack" a second time, which results in the same damage and the same reduced health being printed instead of using a new value. How can I properly do this?
You need to make the call to randint everytime. Below is one way to do it
def Dice1(): return randint(1,6)
def Dice2(): return randint(1,6)
def Dice3(): return randint(1,6)
This isn't great though because of all the repeated code. Here is a better way
class Dice(object):
def roll_dice(self):
return randint(1,6)
Dice1 = Dice()
Dice2 = Dice()
Dice3 = Dice()
Now in your code where ever you call Dice1, Dice2 or Dice3; instead call Dice1.roll_dice(), Dice2.roll_dice(), Dice3.roll_dice(). This abstract away the dice implementation and you are free to change it later without having to change your code.
If you need have dice with different number of faces, you only need to change your dice class
class Dice(object):
def __init__ (self, num_faces=6):
self.faces = num_faces
def roll_dice(self):
return randint(1,self.faces)
Dice1 = Dice() # 6 faced die
Dice2 = Dice(20) # 20 faced die
Put your dice-rolling into a separate function and calculate Damage and NewHealth inside your loop. (Also, update your Monster's health. :))
from random import randint
def dice_roll(times):
sum = 0
for i in range(times):
sum += randint(1, 6)
return sum
class Item(object):
def __init__(self, name, value, desc):
self.name = name
self.value = value
self.desc = desc
sword = Item("Sword", 2, "A regular sword.")
class Monster(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
monster = Monster("Monster", 50, dice_roll(2))
print("You see a monster!")
while True:
action = input("? ").lower().split()
if action[0] == "attack":
Damage = dice_roll(3) + sword.value
NewHealth = max(0, monster.health - Damage) #prevent a negative health value
monster.health = NewHealth #save the new health value
print("You swing your", sword.name, "for", Damage, "damage!")
print("The", monster.name, "is now at", NewHealth, "HP!")
elif action[0] == "exit":
break
if monster.health < 1:
print("You win!")
break
Related
New to Python and coding. This is my first project and I'm having trouble closing a loop once one of my classes reaches zero. Any help would be appreciated. Thank you.
# Space Warriors Game
import random
import time
class Spacecraft:
def __init__(self, type, health):
self.type = type
self.health = health
self.ship_destroyed = False
def __repr__(self):
return "This {type} spacecraft has {health} starting hit points ".format(type=self.type, health=self.health)
def ship_gone(self):
self.ship_destroyed = True
if self.health != 0:
self.health = 0
print("Your spacecraft has been destroyed!")
def ship_gone_def(self):
self.ship_destroyed = True
if self.health != 0:
self.health = 0
print("Your enemy spacecraft has been destroyed! YOU WON!!")
def lose_health(self, amount):
self.health -= amount
if self.health <= 0:
self.ship_gone()
else:
print("Your spacecraft now has {health} hit points remaining.".format(health=self.health))
def lose_health_def(self, amount):
self.health -= amount
if self.health <= 0:
self.health = 0
self.ship_gone_def()
else:
print("The enemy spacecraft now has {health} hit points remaining.".format(health=self.health))
def attack(self, enemy_ship):
while True:
damage_fighter = random.randrange(6, 14)
damage_defender = random.randrange(4, 10)
if self.type == "fighter":
#time.sleep(2)
print('Your {type} spacecraft attacked the enemy ship for {damage} damage!'.format(type=self.type, damage=damage_fighter))
#time.sleep(2)
enemy_ship.lose_health_def(damage_fighter)
#time.sleep(2)
print()
print('The enemy {enemy_ship} spacecraft attacked your ship for {damage2} damage!'.format(enemy_ship=enemy_ship.type, damage2=damage_defender))
#time.sleep(2)
self.lose_health(damage_defender)
print()
elif self.type == "defender":
#time.sleep(2)
print('Your {type} spacecraft attacked the enemy ship for {damage} damage!'.format(type=self.type, damage=damage_defender))
#time.sleep(2)
enemy_ship.lose_health_def(damage_defender)
#time.sleep(2)
print()
print('The enemy {enemy_ship} spacecraft attacked your ship for {damage2} damage!'.format(enemy_ship=enemy_ship.type, damage2=damage_fighter))
#time.sleep(2)
self.lose_health(damage_fighter)
print()
class Player:
def __init__(self, type):
self.type = type
self.current_type = 0
def attack_enemy_ship(self, enemy_ship):
my_ship = self.type[self.current_type]
their_ship = enemy_ship.type[enemy_ship.current_type]
my_ship.attack(their_ship)
a = Spacecraft("fighter", 40)
b = Spacecraft("defender", 50)
print()
player_name = input('''Welcome to SPACE WARRIORS! Please enter your name and hit enter. ''')
print('''
Welcome ''' + player_name + '''! Space Warriors is a game that allows you to chose one of two spacecrafts and battle it out with
the CPU! There are two classes: Fighter Class and a Defender Class. Each class is unique in it's own way.''')
print()
player_style = input('Please type in "Fighter" or "Defender" and press enter. ''').lower()
print()
if player_style == 'fighter':
print('You have selected the fighter class which has 40 life and does 6 - 12 damage. Goodluck!')
time.sleep(2)
elif player_style == 'defender':
print('You have selected the defender class which has 50 life and does 4 - 10 damage. Goodluck!')
time.sleep(2)
else:
print('Wrong selection. Restart the game')
raise SystemExit
player_selected = []
computer_selected = []
player_selected.append(a)
computer_selected.append(b)
player_selected.append(b)
computer_selected.append(a)
live_player = Player(player_selected)
computer_player = Player(computer_selected)
print()
print("Let's get ready to fight! Both ships are launched!")
print()
live_player.attack_enemy_ship(computer_player)
In the attack function each player does damage back and forth until one reaches 0. At that point it prints the enemy won or the player won. However, once the hit points reach 0 it continues to print the loser is defeated and the winner's damage. Any help on closing this loop would be great! Thank you.
I have built a simple "Higher or Lower" card game for two players using reference from Why is the same card being drawn in this while loop for card deck?. The game flow should be like this:
First player (Computer) to draw a card from the deck and show it
Each player place a guess whether the next card drawn will be higher or lower in value to the first card drawn
The second player (Player_1) draw a card and show it
Whoever guess is correct will get one point
After the last card of the deck is drawn, the points are to be tallied
import random
class Card(object):
def __init__(self, suit, value):
self.suit = suit
self.value = value
def show(self):
print("{} of {}".format(self.value, self.suit))
class Deck(object):
def __init__(self):
self.cards = []
self.build()
def build(self):
self.cards = []
for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
for v in range(1, 14):
self.cards.append(Card(s, v))
return self
#print("{} of {}". format(v, s))
def show(self):
for cards in self.cards:
print(cards.show())
def shuffle(self):
random.shuffle(self.cards)
return self
def draw_card(self):
return self.cards.pop()
def add(self, card):
return self.cards.append(card)
def size(self):
return len(self.cards)
class Player(object):
def __init__(self, name):
self.name = name
self.hand = Deck()
def draw(self, deck):
self.hand.add(deck.draw_card())
return self
def show_hand(self):
for card in self.hand:
card.show()
def play():
Player_1 = Player("Player 1")
Computer = Player("Computer")
Higher_or_lower = ["h", "l"]
player_1_score = 0
computer_score = 0
deck = Deck().build().shuffle()
Computer.draw(deck)
Computer.show_hand()
while deck.size() > 0:
answer = "?"
while answer not in "hl":
Player_guess = str(input("What is your guess: higher or lower (h or l)?\n".format(Player_1.hand.cards[-1]))).lower()
Computer_guess = random.choice(Higher_or_lower)
print("You guess " + str(Player_guess))
print("The computer guess " + str(Computer_guess))
Player_1.draw(deck)
Player_1.show_hand()
diff = Computer.hand.cards[-1].value-Player_1.hand.cards[-1].value
if diff <= 0 and answer == "h" or diff >= 0 and answer == "l":
if Player_guess == answer:
player_1_score += 1
print("You guessed correctly")
elif Computer_guess == answer:
computer_score += 1
print("Your guess is incorrect")
else:
if player_1_score > computer_score:
print("You are the winner! You scored " + str(player_1_score - computer_score) + "higher")
elif player_1_score == computer_score:
print("You have a draw game")
elif player_1_score < computer_score:
print("You have lost. You scored " + str(computer_score - player_1_score) + "lower")
play()
There are a few problems in this code. First, the deck was not iterable. But this has been resolved by editing show_hand(self).
Second, the deck has only one suit (Spades)
Third, codes after print("The computer guess " + str(Computer_guess)) is not being executed.
self.hand is the Deck object, in for card in self.hand you are trying to iterate over it. You want to iterate over its cards property
def show_hand(self):
for card in self.hand.cards:
card.show()
I'm making a basic battle program with a multi-sided dice class and a while loop. Basically, you and a dragon start with 100 health, and a 20 sided dice is randomly thrown to determine how much damage you each do. For example, if I rolled a six, and the dragon rolled an 8, then I would have 92 health left, and the dragon would have 94 health left. And this would continue until one health value reaches 0. Here's an example of my code below:
import random
class MSDie:
def __init__(self, num_sides):
self.num_sides = num_sides
self.current_value = self.roll()
def roll(self):
self.current_value = random.randrange(1,self.num_sides+1)
return self.current_value
def __int__(self):
return int(self.current_value)
def getValue(self):
return self.value
def setValue(self, value):
self.value = value
print("you are a legendary hero on a quest to save the kingdom from an evil dragon.")
print("You find him outside his lair and the two of you begin to battle.")
print("Both you and the dragon start with 100 health.")
print("You each will both randomly deal between 1-20 damage.")
print("The first whose health drops to 0 loses.")
playerHealth = 100
DragonHealth = 100
while(playerHealth > 0 or DragonHealth > 0):
print("You have ", playerHealth, "Health.")
print("The dragon has ", DragonHealth, "Health.")
myDamage = MSDie(20)
DragonDamage = MSDie(20)
playerHealth = playerHealth - DragonDamage
DragonHealth = DragonHealth - myDamage
print("")
print("You dealt ", myDamage, "to the dragon.")
print("The dragon dealth ", DragonDamage, "to you.")
print("")
However, each time I try to subtract the damage roll from the health, I keep getting this error:
File "C:\Users\Jacks\OneDrive\Documents\Python files\Ds files\monsterbattle.py", line 52, in <module>
playerHealth = playerHealth - DragonDamage
TypeError: unsupported operand type(s) for -: 'int' and 'MSDie'
DragonDamage is an instance of the MSDie class. Python won't convert it to an integer automatically, even though you implemented the __int__ method. You need to do this explicitly. Try playerHealth - int(DragonDamage).
import random
class MSDie:
def __init__(self, num_sides):
self.num_sides = num_sides
self.current_value = self.roll()
def roll(self):
self.current_value = random.randrange(1,self.num_sides+1)
return self.current_value
def __int__(self):
return int(self.current_value)
def getValue(self):
return self.value
def setValue(self, value):
self.value = value
print("you are a legendary hero on a quest to save the kingdom from an evil dragon.")
print("You find him outside his lair and the two of you begin to battle.")
print("Both you and the dragon start with 100 health.")
print("You each will both randomly deal between 1-20 damage.")
print("The first whose health drops to 0 loses.")
playerHealth = 100
DragonHealth = 100
while(playerHealth > 0 or DragonHealth > 0):
print("You have ", playerHealth, "Health.")
print("The dragon has ", DragonHealth, "Health.")
myDamage = MSDie(20)
DragonDamage = MSDie(20)
playerHealth = playerHealth - int(DragonDamage)
As #mcsoini suggested above, you need to explicitly convert to int.
I'd suggest you smiplify a lot your code. You need only one MSDie instance, not 2 at each loop iteration, and the dice may just provide values, it doesn't need an internal value . Also you may use and in your condition, to stop when one reach 0
class MSDie:
def __init__(self, num_sides):
self.num_sides = num_sides
def roll(self):
return random.randrange(1, self.num_sides + 1)
Using
player_health = 100
dragon_health = 100
multi_dice = MSDie(20)
while player_health > 0 and dragon_health > 0:
player_damage = multi_dice.roll()
dragon_damage = multi_dice.roll()
player_health -= dragon_damage
dragon_health -= player_damage
print("You dealt ", player_damage, "to the dragon, it now have", dragon_health)
print("The dragon dealth ", dragon_damage, "to you, you now have", player_health)
print("")
if player_health > dragon_health:
print(f"You won with {player_health}PV, dragon is dead")
else:
print(f"You loose, you're dead, dragon has {dragon_health}PV")
I am learning about classes in Python and tried to make a simple battle game. This code runs fine and as long as I print devin.battle() multiple times, but I want a while loop so that it will revert back to asking if the user would like to start a battle while also deducting the attack from the hit points.
start_battle = input("Would you like to start a battle? Y/N ===> ")
class People:
max_hit_points = 150
current_hit_points = 150
current_strength = 5
defence = 0
def __init__(self, name, current_hit_points):
self.name = name
self.current_hit_points
self.damage = 50
def battle(self):
if start_battle == "Y":
self.attacked()
elif start_battle == "N":
print("okay, nevermind then")
def attacked(self):
self.current_hit_points -= self.damage
print("You have been attacked")
if self.current_hit_points > 0:
print("Try again newb!")
else:
print("Your HP has reached 0, you are dead")
def __str__(self):
return f"{self. name} has {self.current_hit_points}HP remaining"
devin = People("Devin", 150)
devin.battle()
print(devin)
However, when I add one to the whole thing Python freezes up.
start_battle = input("Would you like to start a battle? Y/N ===> ")
class People:
max_hit_points = 150
current_hit_points = 150
current_strength = 5
defence = 0
def __init__(self, name, current_hit_points):
self.name = name
self.current_hit_points
self.damage = 50
while current_hit_points > 0:
def battle(self):
if start_battle == "Y":
self.attacked()
elif start_battle == "N":
print("okay, nevermind then")
def attacked(self):
self.current_hit_points -= self.damage
print("You have been attacked")
if self.current_hit_points > 0:
print("Try again newb!")
else:
print("Your HP has reached 0, you are dead")
def __str__(self):
return f"{self. name} has {self.current_hit_points}HP remaining"
continue
else:
print("You are dead")
devin = People("Devin", 150)
devin.battle()
print(devin)
If anyone can explain to me why its freezing up and how I can properly loop a battle, it would be greatly appreciated.
You have multiple issues here and its not super clear what you are trying to do but here is some direction according to your comment, make sure ot read the # code comments
class People:
max_hit_points = 150
current_hit_points = 150
current_strength = 5
defence = 0
def __init__(self, name, current_hit_points):
self.name = name
# you forgot to actually assign the hit points
self.current_hit_points = current_hit_points
self.damage = 50
def battle(self):
while self.current_hit_points > 0:
# you want to ask the user every round?
start_battle = input("Would you like to start a battle? Y/N ===> ")
if start_battle == "Y":
self.attacked()
# note that the user didnt get to attack back
# maybe print(self) here so the user can see his hp?
elif start_battle == "N":
print("okay, nevermind then")
break
else:
print("You are dead")
def attacked(self):
self.current_hit_points -= self.damage
print("You have been attacked")
if self.current_hit_points > 0:
print("Try again newb!")
else:
print("Your HP has reached 0, you are dead")
def __str__(self):
return f"{self. name} has {self.current_hit_points}HP remaining"
devin = People("Devin", 150)
devin.battle()
print(devin)
I'm trying to create a version of the game Snakeeyes, which will take in n at the start of the program, n being the number of players.
So far, I have managed to get this far:
import random
def rollDice():
dice = random.randint(1, 6)
print "You rolled a", dice
return dice
def addUser(name):
name = player()
print name, "is a player"
class player():
score = 0
players = []
def __init__(self):
score = 0
player.score = score
def addScore(self, dice1, dice2):
if dice1 == 1 or dice2 == 1:
player.score = 0
if dice1 == 1 and dice2 == 1:
print "SNAKE EYES"
else:
player.score += dice1
player.score += dice2
return player.score
def dispScore(self):
return player.score
numbp = int(input("Please enter number of players \n"))
plyarr = dict()
for x in range(numbp):
plyarr[x] = player()
plyarr[x].addScore(rollDice(),rollDice())
for x in range(numbp):
print plyarr[x].score
However,I can't get it to work because of my naivety with how python works and how classes (etc) can be used to speed this sort of programming up. The main issue is that often it overwrites the same spot in the dictionary (if I use a dictionary).
Re written player class:
class player():
def __init__(self):
self.score = 0
self.players = []
def addScore(self, dice1, dice2):
if dice1 == 1 or dice2 == 1:
player.score = 0
if dice1 == 1 and dice2 == 1:
print "SNAKE EYES"
else:
self.score += dice1
self.score += dice2
return self.score
def dispScore(self):
return self.score
def __str__(self):
return '<a description of the current object>'
From your comment, I assume you are inquring about the way to store the players in a dictionary; you could do it as follows (did a small change to your original code)
numbp = int(input("Please enter number of players \n"))
plyarr = dict()
for x in range(numbp):
current_player = player()
current_player.addScore(rollDice(),rollDice())
playarr[x] = current_player
And finally, display your players' scores:
for player_id, player in plyarr.items():
print player.dispScore()