How to create a new instance using a class method - python

I am trying to write a method for a class which will create a new instance of an already existing instance of a class. The problem is that I cannot access the new instance in the console when I try new_handname.
This is for creating a blackjack game in python. The idea of the code is when the hand is split a new instance will be created to create a new hand
import random
class Card(object):
def __init__(self, value, suit,nvalue):
self.value = value
self.suit = suit
self.nvalue = nvalue
suit = ['Hearts','Spades','Clubs','Diamonds']
value = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
nvalue = [2,3,4,5,6,7,8,9,10,10,10,10,11]
class Hand(object):
def __init__(self,current_hand):
self.current_hand = current_hand
def hand_total(self):
current_sum = 0
for i in range(0,len(self.current_hand)):
current_sum += self.current_hand[i].nvalue
return current_sum
def hand_type(self):
if self.current_hand[0].value == self.current_hand[1].value:
return('pair')
elif self.current_hand[0].value == 'A' or self.current_hand[1].value == 'A':
return('soft')
else:
return('hard')
def append(self,current_hand,some_card):
self.current_hand = self.current_hand + some_card
def hit(self):
self.current_hand.append(deck[0])
deck.pop(0)
def double(self,new_handname):
new_handname = Hand(self)
def deal_start_hand():
player_hand.append(deck[0])
deck.pop(0)
dealer_hand.append(deck[0])
deck.pop(0)
player_hand.append(deck[0]) #### player gets two cards ### assuming europe no hole card rules
deck.pop(0)
def gen_deck():
for v,n in zip(value,nvalue):
for s in suit:
deck.append(Card(v,s,n))
### variable initiation ###
deck = []
player_hand = []
dealer_hand = []
##program start ##
gen_deck()
random.shuffle(deck)
deal_start_hand()
p1 = Hand(player_hand)
p1.double('p2')
p2 ### I expect p2 to return an instance but does not
>>> p1
<__main__.Hand object at 0x00000006A80F0898>
>>> p2
Traceback (most recent call last):
File "<pyshell#182>", line 1, in <module>
p2
NameError: name 'p2' is not defined
Note: current_hand is a list of the cards objects.
I expect p2 to return an instance of the class but instead the variable p2 is not defined

Your split routine could look like the following, in which a new instance of the class is returned:
class Hand(object):
def __init__(self, current_hand):
self.current_hand = current_hand
def split(self):
return Hand(self.current_hand)
Simply create an instance, then split it later:
# You need to define "some_default" somewhere
myhand = Hand(some_default)
second_hand = myhand.split()
However, your split routine needs to take into account what cards have already been played, and what cards are still in the deck(s), none of which your code considers. I might advise mapping out the "states" of the game (think of it as a state machine), draw that out on paper, then consider how to code up each state and transition. A card game like this is more complicated to code than it might seem at first glance.

Related

Nested Class - How can I use outer class variables for inner class

I created a super simple Character and Buildable class for a miniature game I am developing and I have created a nested class where Character is for the outer class and Buildable is the inner class. I am trying to loop through resources from Character inside my upgradeBuildable function within Buildable.
class Character:
# Constructor -- Also why do comments use # and not // -_-
def __init__(self):
self.name = "Pickle"
self.health = 100
self.resources = ["Fire", "Coal"]
self.buildObj = self.Buildable() # Object for nested 2nd class
# Function to display character info
def characterInfo(self):
print("CharacterInfo --> " + "Name:", self.name, "| Health:", self.health, "| Resources:", self.resources)
def printRes(self):
print(self.resources)
# Function for collecting resources
def collectResource(self, newResource):
self.resources.append(newResource)
class Buildable:
def __init__(self):
self.buildings = ["Fire 1"]
self.upgradeStatus = 0
self.outer = Character()
def displayBuildable(self):
print("Buildables -->", self.buildings)
def createBuildable(self, newBuilding):
self.buildings.append(newBuilding)
def upgradeBuildable(self, replaceBuilding):
if self.upgradeStatus == 0:
# Update selected building
for i in range(len(self.buildings)):
if self.buildings[i] == replaceBuilding:
self.buildings[i] = "2x"
break
print(Character.resources)
self.upgradeStatus = self.upgradeStatus + 1
print(self.upgradeStatus)
When I try to access print the resource attribute from Character in upgradeBuildable I get a recursion error "RecursionError: maximum recursion depth exceeded" which is confusing to me.
All I am trying to do is try and print the resources the character has inside my inner Buildable class. Any help is much appreciated !!
My main is followed below:
from BW_Classes import Character
pick = Character()
pick.characterInfo()
# Object created for inner class -- Buildable()
build = pick.buildObj
build.displayBuildable()
print()
print("Building......")
build.createBuildable("Fire 2")
build.createBuildable("Coal Mine")
build.createBuildable("Coal Supreme")
build.createBuildable("Ocean")
build.displayBuildable()
print()
print("Upgrading....")
build.upgradeBuildable("Fire 2")
build.displayBuildable()
I believe what you are look for is Inheritance. Inheritance basically means that a class inherits the properties and methods of another class, which I am assuming you are looking for when you say nested classes.
The error is being thrown because when you initialize the character, the function initializes the buildable. When the buildable is initialized, it initializes the character. See the loop?
Your code will probably look something like this:
class Character(Buildable):
def __init__(self):
self.name = "Pickle"
self.health = 100
self.resources = ["Fire", "Coal"]
#initialize the buildable class
super().__init__()
# Function to display character info
def characterInfo(self):
print("CharacterInfo --> " + "Name:", self.name, "| Health:", self.health, "| Resources:", self.resources)
def printRes(self):
print(self.resources)
# Function for collecting resources
def collectResource(self, newResource):
self.resources.append(newResource)
class Buildable():
def __init__(self):
self.buildings = ["Fire 1"]
self.upgradeStatus = 0
def displayBuildable(self):
print("Buildables -->", self.buildings)
def createBuildable(self, newBuilding):
self.buildings.append(newBuilding)
def upgradeBuildable(self, replaceBuilding):
if self.upgradeStatus == 0:
# Update selected building
for i in range(len(self.buildings)):
if self.buildings[i] == replaceBuilding:
self.buildings[i] = "2x"
break
print(Character.resources)
self.upgradeStatus = self.upgradeStatus + 1
print(self.upgradeStatus)

Can't append a set of values from a Class

I am doing a card game.
The class is called Card:
It can give a random value with the deal() method to display a random card from the numbers 1-13
The other file will import the file name that contains the Class Card. It will call the class 5 times and be able to store it by appending it on a list and displaying it in another def called display_hand
Here is the class file:
import random
class Card:
def __init__(self):
self.__value = 0
def deal(self):
self.__value = random.randint(1, 13)
def set_value(self, value):
self.__value = value
def get_value(self):
return self.__value
def find_face_value(self):
faces = ['Joker','Ace','Two','Three','Four','Five','Six',
'Seven','Eight','Nine','Ten','Jack','Queen','King']
return faces[self.__value]
def __str__(self):
return self.find_face_value()
The program is too big so this is the def for calling the function 5 times:
def deal_hand():
# Create an empty list to append the cards.
hand = []
deal_hand = classcard3.Card()
for i in range(1, 6):
deal_hand = classcard3.Card()
deal_hand.deal()
# Create a new object in memory and assign it to the
# hand variable
w = classcard3.Card(deal_hand)
# add it to the list
hand.append(w)
return hand
Here is the display function:
def display_hand(hand):
print ("The 5-card hand is: ")
for item in hand:
print(hand)
This is not showing anything except for the print inside the loop. How can I pass it to the display hand to show the cards?
This is the only thing that shows whenever I use the print function inside the loop. I'm trying to use it outside and I have no idea what I'm doing wrong. My apologies if I'm not explaining this too well. I'm a beginner at python and new to this website. Thanks
deal Four
deal Three
deal Five
deal Six
deal Queen
The only error that I'm getting from this is:
line 274, in deal_hand
w = classcard3.Card(deal_hand)
TypeError: __init__() takes 1 positional argument but 2 were given
This doesn't make sense, because I'm doing it just as the book says and is not willing to display the values

How to access a list outside a class?

So I generated a bunch of places with the Place class, then in the Player class I tried to make a method that looks at the current location and look at the connected locations through the places list I made to travel west, however since I am very new the OOP I am not sure how to give access to the Player function to the list made in main()
def main():
import random
places = []
places.append(Place("Boston", "Sunny - 55°F", ("Worcester", None), "645,966", "Marty Walsh"))
places.append(Place("Worcester", "Sunny - 64°F", ("Springfield", "Boston"), "182,544", "Joseph Petty"))
places.append(Place("Springfield", "Sunny - 67°F", ("Pittsfield", "Worcester"), "153,703", "Domenic Sarno"))
places.append(Place("Pittsfield", "Sunny - 63°F", (None, "Springfield"), "44,057", "Linda Tyer"))
This is where the player is generated in main() as well:
player = Player(name, random.choice(places))
Here is the Place class constructor:
class Place(object):
def __init__(self, name, weather, cl, pop, mayor):
self.name = name
self.weather = weather
self.connectedLocation = cl
self.population = pop
self.mayor = mayor
Here is the Player class constructor:
class Player(object):
def __init__(self, name, curLoc):
self.name = name
self.curLoc = curLoc
Later in the Player class I attempted to make this method to no avail, since to my dismay the class cannot access the list of places made in main()
def goWest(self):
for place in places:
if self.curLoc.connectedLocation[0] == place.name:
self.curLoc = place
You need to pass the places list to the goWest function by adding a places parameter to it. It would look something like this:
def go_west(self, places):
for place in places:
if self.cur_loc.connected_location[0] == place.name:
self.cur_loc = place
break
I added the break statement because I am assuming that once you find the current location you don't need to keep iterating of the list.

How to create and keep a set of variables in python?

I'm developing an application that reads a message input from telegram with a set of variables, and then starts a game with the user. So I created a class that represents an instance of the game, making one game per chat possible:
class Battle:
def __init__(self, mainchat):
self.mainchat = mainchat
print('Instance of battle started on chat %s' % self.mainchat)
pcount = 0
team1 = []
team2 = []
p1 = ()
p2 = ()
p1score = 0
p2score = 0
battlechoicep1 = -1
battlechoicep2 = -1
so, as soon as I get a message, I start an instance of a battle based on user inputes, e.g.
battle = Battle(chat_id)
battle.p1 = 'Paul'
battle.battlechoicep1 = 4
...
this way has been working fine right now, but every time I want to reset the battle, I go through a function that does this:
battle.pcount = 0
battle.team1 = []
battle.team2 = []
battle.p1 = ()
battle.p2 = ()
battle.p1score = 0
battle.p2score = 0
battle.battlechoicep1 = -1
battle.battlechoicep2 = -1
save() # outside function that saves the scores into a pickle file
return
So, I would like to make it so this is a function inside my class, so everytime I call battle.reset it would call something like this
def reset():
battle.pcount = 0
battle.team1 = []
battle.team2 = []
battle.p1 = ()
battle.p2 = ()
battle.p1score = 0
battle.p2score = 0
battle.battlechoicep1 = -1
battle.battlechoicep2 = -1
save() # outside function that saves the scores into a pickle file
return
I don't know how is the right approach to this problem, I don't even know if what I've been doing up to now is 'correct' (it is working at least).
Creating the function inside the class (like def reset(self):) seems to have no effect.
You're on the right track with def reset(self). You just need to change the instances of battle to self in the method itself. NOTE: This needs to be a method of the Battle class.
def reset(self):
self.pcount = 0
... # etc
save() # outside function that saves the scores into a pickle file
When you pass in self as the first parameter of a class method, it allows the method to work on the instance of the class that you've called it on. If you just do def reset(self) without changing the battle to self, it will try to modify a variable in the current scope called battle, which in this case probably doesn't exist.
The other thing you could do if you just want reset to create a completely new object without preserving any of the attributes, you can just do:
def reset(self):
return Battle()
You're almost there!
class Battle:
def __init__(self, mainchat):
self.mainchat = mainchat
print('Instance of battle started on chat %s' % self.mainchat)
self.reset()
def reset(self):
self.team1, self.team2 = [], []
self.p1 = self.p2 = () #New tuples will be assigned and overwritten
self.pcount = self.p1score = self.p2score = 0
self.battlechoicep1 = self.battlechoicep2 = -1
save() # outside function that saves the scores into a pickle file
So when you need to reset, just call battle.reset()! Maybe the save function can also be a class method as well, just follow the same format.

Modifying a function from another in python

For an online course in python, I'm making a basic text-based adventure game in python.
Right now, I have a rudimentary inventory system that works through booleans for if the user has an object or not, and integers for limited items, such as ammo and whatnot.
Here is the code for the inventory system
def Inventory(self): #The inventory for the game. I don't know how to program it properly, so this is my testing ground.
#This will hold the boolean values to if the player has the items or not. Another will be used to show the user the items
street_clothes = False
pistol = False
ammo = 0
phone = False
And this is the code where I am trying to modify the inventory function above
#Eric's apartment
def Eric_Apartment(self):
print "type in grab your gun"
action = raw_input("> ")
if action == "grab":
self.Inventory(CR97) = True
# self.CR97_ammo += 15
# print CR97_ammo
# print self.CR97_ammo
exit(1)
Attempting to run this program gets me this error:
python ex43.py
File "ex43.py", line 78
self.Inventory(CR97) = True
SyntaxError: can't assign to function call
Is there something else I'm supposed to do? I'm very new to python, and this is my first project on my own.
Here is the entire code, for reference
from sys import exit #allows the program to use the exit(1) code
from random import randint #allows the program to use a random number
class Game(object):
#quotes that pop up if the person dies, and also defines the start and self variables
def __init__(self, start):
self.quips = [
"You lose!"
]
self.start = start
def Inventory(self): #The inventory for the game.
#This will hold the boolean values to if the player has the items or not.
street_clothes = False
pistol = False
ammo = 0
phone = False
#this function launches the game, and helps with the room transfer
def play(self):
next = self.start
while True:
print "\n---------"
room = getattr(self, next)
next = room( )
#if the user dies, or fails at the game, this is the function that is ran
def death(self):
print self.quips[randint(0, len(self.quips)-1)]
exit(1)
#Welcome screen to the game
def welcome_screen(self):
print " place holder"
return 'intro_screen'
#Intro screen to the game
def intro_screen(self):
print "place holder"
action = raw_input("> Press any key to continue ")
return 'Eric_Apartment'
#Eric's apartment
def Eric_Apartment(self):
print "type in grab your gun"
action = raw_input("> ")
if action == "grab":
self.Inventory(CR97) = True
# self.CR97_ammo += 15
# print CR97_ammo
# print self.CR97_ammo
exit(1)
a_game = Game("welcome_screen")
a_game.play()
That's an amazingly perverse way to go about it. Why are you using a function to store data?
Just have a player object, with an inventory array.
I'd recommend using objects to model items too. Good use for for a class hierarchy. COuld have a base Item, with Subclasses SingleItem and StackableItem, etc.
Instead of using a function, try using a class -
class Player:
def __init__(self):
self.street_clothes = False
self.pistol = False
self.ammo = 0
self.phone = False
def give_street_clothes(self):
self.street_clothes = True
# etc
But personally, instead of using each item as a boolean, I'd use a list of items:
class Player:
def __init__(self):
self.inventory = []
# add code for ammo/pistol
def has_item(self, item):
return item in self.inventory
def give_item(self, item):
self.inventory.add(item)
def remove_item(self, item):
self.inventory.remove(item)
# etc

Categories

Resources