Yahtzee, using a dictionary instead of list of attributes - python

So my issue is that currently I have code for my yahtzee (I will not post all of the code, but the important stuff is looking like this (and it works):
from terminaltables import AsciiTable
class Player:
def __init__(self,name):
self.name=name
self.ones=0
self.twos=0
self.threes=0
self.fours=0
self.fives=0
self.sixs=0
self.abovesum=0
self.bonus=0
self.onepair=0
self.twopair=0
self.threepair=0
self.fourpair=0
self.smalladder=0
self.bigladder=0
self.house=0
self.chance=0
self.yatzy=0
self.totalsum=0
def welcome():
global spelarlista
spelarlista=[]
print("Welcome to the yahtzee game!")
players = int(input("How many players: "))
rounds=0
while not players==rounds:
player=input("What is your name?: ")
rounds=rounds+1
spelarlista.append(Player(player))
table_data = [["Name"] + spelarlista,
['Ones'] + [player.ones for player in spelarlista],
['Twos'] + [player.twos for player in spelarlista],
['Threes'] + [player.threes for player in spelarlista],
['Fours'] + [player.fours for player in spelarlista],
['Fives'] + [player.fives for player in spelarlista],
['Sixs'] + [player.sixs for player in spelarlista]]
table = AsciiTable(table_data)
table.inner_row_border = True
print(table.table)
spelarlista[0].add()
welcome()
The issue right now is that I want to add a dictionary instead of all those self.ones, self.twos etc. If you take a look at my welcome method, you can see that I have [player.ones for player in spelarlista]and I need this to assign the players points, how can I fix so this work for a dictionary instead? The dictionary is neccesary for my next method, add, if you were curious!
Thanks in advance!

dict_names = ['ones', 'twos', ..., 'totalsum']
self.dict = {name:0 for name in dict_names}
and to access you'd use player.dict['fours'] instead if player.fours

Related

How to take away health points when using a class?

I'm working on a game in python and I can't figure out how to take away health once attack function has taken place. I can run the program and the attack function works fine, it shows a random integer between 1 and 50 but doesn't actually take away health from castlehealth = 100
Underneath print("You attacked for " + str(self.attack)) I left the next line blank because I don't know what to type in, I tried a lot of different things and just can't get the attack to take away from castlehealth.
Here is my code:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
You want the following:
self.castlehealth -= attack
Try something like self.castlehealth -= attack. I also fixed some potential indentation issues for you.
Your full code sample could look this this:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
self.castlehealth -= attack
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
Explanation: self.castlehealth is an instance variable of your GameActions class. The function GameActions.attack() creates a new attack variable as a random integer and then subtracts that value from the instance variable self.castlehealth of the GameActions class. Now self.castlehealth will be the updated value. Consider also tracking the various attacks and resulting healths in a data structure, since every time you have a new attack self.castlehealth and self.attack will change values and you will lose the ability to access the previous values.

How can I store data inside python?

I'm making a game in which the player works for a certain amount of money. But I'm running the code on a discord server which means that there will be multiple users? If I can get a unique ID for each user then how can I store information for each user?
This is some code I made that basically reflects my other one. How can I store money as well as returning money if they enter a username that's been used before.
def start():
name = input("What is your name?")
main()
def main():
print('1. New Player')
print('2. Work')
answer = input()
if answer == '1':
start()
if answer == '2':
work()
def work():
print("You work for $100")
money += 100
main()
main()
(Sorry if my question is too broad... ask any questions if want more details.)
A simple suggestion would be to create a class that describes a player, their attributes and any functions associated with the player. For example:
class Player:
def __init__(self, id):
self.money = 0
self.items = []
self.level = 1
# Initialize other player attributes here
def add_money(self, amount_added):
self.money += amount_added
def main():
player_1 = Player(id=1)
player_1.add_money(100)
player_2 = Player(id=2)
This is a very generic example, but defining a class for a player will allow you to easily create an object for which you can associate each player. If you add 100 to player 1's money then that will be completely independent of player 2's money. I suggest searching up tutorials/examples on classes and you'll get a feel!

Updating the value of an attribute on an instance of a class

I was not sure how to word this problem I'm having and after 4 hours of searching I am left here to ask. So i will lay out my problem and hope for the best!
I have completed every step of this program and have gotten it to run, but my brain can not wrap around how to solve this problem.
Here is the instructions:
Match Coins: Create a coin toss game with two players.
Each player starts with 20 coins. Rules:
each player tosses their own coin
If the coins match,
Player1 gets Player2’s coin.
If not, the Player2 gets the coin from Player1.
Whoever has the most coins wins.
In main(), create a while loop that asks to user to continue play.
In each loop, report the results … coins matched?
Total coins for each player?
The loop should toss the coins at least once.
A ‘Coin’ class is needed. The class requires:
The methods __init__(), toss(), get_sideup(), get_amount(), set_amount()
The class needs the attributes ’__amount’, initialized to 20, and ’__sideup’
initialized to one of two values, ‘Heads’ or ‘Tails’.
‘toss()’ method : generates a random value of ‘0’ or ‘1’, assigning ‘Heads’ or ‘Tails’ accordingly.
‘get_sideup()’ method : returns the current value of __sideup.
‘set_amount()’ method : passes a +1 or -1 to change __amount, depending on the results of the toss.
‘get_amount()’ method : returns the current value of __amount.
I have most of this working but I can not figure out how to add coins to one instance and subract from the next.
(I put self.get_amount as filler in the function im having problems with)
Here is my code:
import random
class Coin (object):
def __init__ (self, __amount = 20, __sideup = "Heads"):
self.__amount = __amount
self.__sideup = __sideup
def toss (self):
val = random.randint(0,1)
if val == 0:
self.__sideup = "Heads"
else:
self.__sideup = "Tails"
def get_sideup (self):
return self.__sideup
def get_amount(self,):
return self.__amount
def set_amount (self, __amount):
self.get_amount
c1 = Coin()
c2 = Coin()
play = input ("Do you want to play? (Y/N): ")
while play == "Y" or "y":
c1.toss()
c2.toss()
if c1.get_sideup() == c2.get_sideup():
c1.set_amount(+1)
c2.set_amount(-1)
print("player 1 wins")
else:
c1.set_amount(-1)
c2.set_amount(+1)
print("player 2 wins")
print(" player1: " + str(c1.get_amount()) + " and player2: " + str(c2.get_amount()))
play = input("Do you want to play? (y/n): ")
Thank you to anyone who reaches out. If the answer to my question is on here please link it. I'm a beginner and not sure how to word my questions very well.
You just need to update the self.__amount property of your coin object by rebinding it to the sum of __amount and self.__amount in your coin's set_amount method.
def set_amount (self, __amount):
self.__amount = self.__amount + __amount
or a little more succinctly,
def set_amount (self, __amount):
self.__amount += __amount

Adding a combat system to a text adventure game; confused by the structure of the code I'm using

Through some educational materials I've been tasked to use the below structure (the classes) for a text adventure game and am required to add a simple combat system for battle between a hero and an enemy.
Currently I am able to have an enemy created in each room and move between the start room(corridor) to the bathroom and back, but at this point I'm stuck. I can't determine where I should be creating my 'hero' or how I'd communicate the changes I'd need to make to the health attributes etc.
If I could structure the code in another way, I would be able to complete the game, but as it is there is a gap in my understanding of how to enable various sections of code communicate with each other.
Thanks,
Dave
# text based adventure game
import random
import time
from sys import exit
class Game(object):
def __init__(self, room_map):
self.room_map = room_map
def play(self):
current_room = self.room_map.opening_room()
while True:
next_room_name = current_room.enter()
current_room = self.room_map.next_room(next_room_name)
class Character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
class Hero(Character):
def __init__(self, name):
super(Hero, self).__init__(name, 10, 2)
def __str__(self):
rep = "You, " + self.name + ", have " + str(self.health) + " health and " + \
str(self.attack) + " attack."
return rep
class Enemy(Character):
ENEMIES = ["Troll", "Witch", "Ogre", "Jeremy Corbyn"]
def __init__(self):
super(Enemy, self).__init__(random.choice(self.ENEMIES),
random.randint(4, 6), random.randint(2, 4))
def __str__(self):
rep = "The " + self.name + " has " + str(self.health) + \
" health, and " + str(self.attack) + " attack."
return rep
class Room(object):
def __init__(self):
self.commands = ["yes", "no"]
self.rooms = ["\'corridor\'", "\'bathroom\'", "\'bedroom\'"]
self.enemy = Enemy()
def command_list(self):
print("Commands: ", ", ".join(self.commands))
def enter_room_question(self):
print("Which room would you like to enter?")
print("Rooms:", ", ".join(self.rooms))
def leave_room_question(self):
print("Do you want to leave this room?")
print("Commands:", ", ".join(self.commands))
class Bathroom(Room):
def enter(self):
print("You enter the bathroom. But, wait! There is an", \
self.enemy.name, "!")
print(self.enemy)
print("You are in the bathroom. Need to take a dump? ")
self.command_list()
response = input("> ")
while response not in self.commands:
print("Sorry I didn't recognise that answer")
print("You are in the bathroom. Need to take a dump?")
self.command_list()
response = input("> ")
if response == "yes":
print("Not while I'm here!")
return "death"
elif response == "no":
print("Good.")
self.leave_room_question()
response = input("> ")
if response == "yes":
return "corridor"
else:
return "death"
class Bedroom(Room):
def enter(self):
pass
class Landing(Room):
def enter(self):
pass
class Corridor(Room):
def enter(self):
print("You are standing in the corridor. There are two rooms available to enter.")
self.enter_room_question()
response = input("> ")
if response == "corridor":
print("You're already here silly.")
else:
return response
class Death(Room):
QUIPS = ["Off to the man in sky. You are dead",
"You died, no-one cried.",
"Lolz. You're dead!"]
def enter(self):
time.sleep(1)
print(random.choice(Death.QUIPS))
exit()
class Map(object):
ROOMS = {"corridor": Corridor(),
"bathroom": Bathroom(),
"death": Death(),
"landing": Landing(),
"bedroom": Bedroom()}
def __init__(self, start_room):
self.start_room = start_room
self.hero = hero
def next_room(self, room_name):
return Map.ROOMS.get(room_name)
def opening_room(self):
return self.next_room(self.start_room)
a_hero = Hero("Dave")
a_map = Map("corridor")
a_game = Game(a_map, a_hero)
a_game.play()
If I were you, I would set out a game schema. You could find out asking yourself questions like this:
What are the really important entities?
In your case, as you have done, I would consider Character, Enemy, Room and Map, inheriting when it would be appropiate, like Character-> Hero and Enemy, and several types of room from Room as Bathroom, Corridor, ...
If I were you a consider using a data structure to represent the Map. For example, if you are considering do a text game adventure, you could think in different rooms as different states in your game. If you are in the bathroom, you could be attacked by an enemy and if you are in the bedroom, you can retrieve your hitpoints (life) so these places can be thought as different states.
As an example, you would an array for group all your different rooms (states)
rooms = ["bedroom", "bathroom", "corridor", "kitchen", "living_room"]
and other rooms that you can think about.
(there is probably a better example, more efficient and so on, so this example is to help you about not giving up when you gets stuck about an problem.
According to this example, if you use an array, you can assign a value to each room (equal to each position in the array)
Moreover, you will need to know the hero's position, so you could assign a random value to it using rand(). You can read links below for more information:
random docs python
stackoverflow answer
At last, you also would find useful to compare the hero's position, which would have a random assigned value previously with every position of your array or rooms
In this cases, you could use a if... elif.. elif... to compare those values and do something according to the room where your hero would be.
I hope this answer will be useful for you.
Let me know if you have any doubt about my answer.
Cheers

Python New to Object Oriented Programming

I was wondering how to fix this problem I am having with my first piece of OOP code. The problem lies within the attack method of the Snake class. I have two snakes in the game and am trying to get the snake to attack the other one. At the moment I am using two variables to note which Snake's turn it is, then use this to try and attack the other snake. However this is not working. Anyone have any idea how to solve this? Thank you so much.
class Snake:
hp=100
attack=25
defense=1
def set_name(self, name):
self.name=name
def shed(self):
self.defense=self.defense+1
def attack(self, opposite, current):
opposite.hp=opposite.hp-(current.attack-opposite.defense)
def eat(self):
self.attack=self.attack+5
print(str(self.name) + " eats a rat!")
print(str(self.name) + "'s attack dmg is now " + str(self.attack))
def sleep(self):
print (str(self.name) + " goes to sleep")
self.hp=self.hp+10
if self.hp>100:
self.hp=100
print (str(self.name) + " wakes up with " + str(self.hp) + "hp")
##initialises the snakes
alpha=Snake()
beta=Snake()
## gives the snakes names of the user's choice
alpha_name=raw_input("What would you like to name your snake? ")
alpha.set_name(alpha_name)
beta_name=raw_input("What would you like to name the other snake? ")
beta.set_name(beta_name)
##starts the game
turn=True
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
if action=="sleep":
alpha.sleep()
if action=="eat":
alpha.eat()
if action=="shed":
alpha.shed()
turn=False
except IOError:
print("Please chose only one action, exaclty how it is typed")
while turn==False:
opposite="alpha"
current="beta"
if beta.hp<15:
beta.sleep()
elif alpha.hp>75:
beta.attack()
else:
index=random.randint(1, 3)
if index==1:
beta.shed()
elif index==2:
beta.eat()
else:
beta.attack(opposite, current)
turn=True
in "attack" you try to access "opposite.hp", but this method is called with a string instead of an object:
opposite="alpha"
current="beta"
=> change this to
opposite=alpha
current=beta
also, there is a field and a method with the same name in the class: attack. I suggest renaming the field to "attackpoints" or something.
additionaly, you call "beta.attack()". you forgot the method arguments there.
I see two problems. The first is you're passing the name of the variable instead of the variable itself.
change this:
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
to this:
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite=beta
current=alpha
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
Additionally, you have the attack field defined twice in the Snake class.
class Snake:
attack=25
def attack(self, opposite, current):
Here's what I came up with after playing with your code:
import random
class Snake:
hp=100
attack_skill=25
defense=1
def set_name(self, name):
self.name=name
def shed(self):
self.defense=self.defense+1
def attack(self, opposite):
opposite.hp = opposite.hp - (self.attack_skill - opposite.defense)
def eat(self):
self.attack_skill += 5
print(str(self.name) + " eats a rat!")
print(str(self.name) + "'s attack dmg is now " + str(self.attack_skill))
def sleep(self):
print (str(self.name) + " goes to sleep")
self.hp=self.hp+10
if self.hp>100:
self.hp=100
print (str(self.name) + " wakes up with " + str(self.hp) + "hp")
##initialises the snakes
alpha=Snake()
beta=Snake()
## gives the snakes names of the user's choice
alpha_name=raw_input("What would you like to name your snake? ")
alpha.set_name(alpha_name)
beta_name=raw_input("What would you like to name the other snake? ")
beta.set_name(beta_name)
##starts the game
turn=True
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(beta)
if action=="sleep":
alpha.sleep()
if action=="eat":
alpha.eat()
if action=="shed":
alpha.shed()
turn=False
except IOError:
print("Please chose only one action, exaclty how it is typed")
while turn==False:
opposite="alpha"
current="beta"
if beta.hp<15:
beta.sleep()
elif alpha.hp>75:
beta.attack(alpha)
else:
index=random.randint(1, 3)
if index==1:
beta.shed()
elif index==2:
beta.eat()
else:
beta.attack(alpha)
turn=True
When you beta attack, you are calling the attack() method without any parameters. I assume you want beta.attack(alpha,beta)
But you could probably refactor the method to only require the opponent as a parameter (since you know who is attacking (it's the object calling the attack method))
def attack(self, opposite):
opposite.hp -= self.attack-opposite.defense

Categories

Resources