How to properly call a class - python

I'm a Python (and programming in general) newbie and I'm trying to make a text-based, endless rpg with random rooms/encounters based on a list. This code is (of course) not completed yet, It's just for testing. Note that I imported Enemies from another .py file:
import Enemies
import random
class Room:
# template definition to define all rooms
def __init__(self, intro):
self.intro = intro
class VsRoom(Room):
# room with an enemy
def __init__(self, enemy):
self.enemy = random.choice(Enemy_List)
super().__init__(intro = "There's an enemy here!")
class NullRoom(Room):
# empty, boring room
def __init__(self):
super().__init__(intro = "Nothing Interesting here.")
Rooms = [VsRoom, NullRoom] # All future room "types" will go here
def print_room():
# Tells the player which kind of room they are
print("You enter the next room...")
Gen_Room = random.choice(Rooms)
print(Gen_Room.intro)
I wanted print room() to print "You enter on the next room...", randomly pick a room from the list, and print its intro, but when I try to run it I get this:
You enter the next room...
[...]
print(Gen_Room.intro)
AttributeError: type object 'NullRoom' has no attribute 'intro'
Process finished with exit code 1
I'm trying to learn how classes work and any help would be great for me. I tried to follow PEP8 as much as I could, and I also tried to find similar questions, without success.

From what I observe you have a list of where you choose the enemies, so you do not need to enter that parameter:
class VsRoom(Room):
# room with an enemy
def __init__(self):
self.enemy = random.choice(Enemy_List)
super().__init__(intro = "There's an enemy here!")
To create an instance you must do it as follows:
{class name}()
So you must change:
Gen_Room = random.choice(Rooms)
To:
Gen_Room = random.choice(Rooms)()
Complete code:
import Enemies
import random
class Room:
# template definition to define all rooms
def __init__(self, intro):
self.intro = intro
class VsRoom(Room):
# room with an enemy
def __init__(self):
self.enemy = random.choice(Enemy_List)
super().__init__(intro = "There's an enemy here!")
class NullRoom(Room):
# empty, boring room
def __init__(self):
super().__init__(intro = "Nothing Interesting here.")
Rooms = [VsRoom, NullRoom] # All future room "types" will go here
def print_room():
# Tells the player which kind of room they are
print("You enter the next room...")
Gen_Room = random.choice(Rooms)()
print(Gen_Room.intro)

Related

Error when calling a method from separate Python file

I am trying to make a Tic Tac Toe game in Python, where I use two separate files. Each has different code and separate classes, which I am trying to call. However, each time I try to do so, I receive this error:
def __init__(self, letter): super().__init__(letter)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
Why does this happen? I have imported the right files (as below) and used the code (under that) to call it.
from player import NormalPlayer, ComputerPlayer
--
if __name__ == "__main__":
x_player = NormalPlayer("X")
o_player = ComputerPlayer("O")
ttt = TicTacToe()
play(ttt,
x_player,
o_player,
print_game = True)
I haven't included it, but if you need me to provide all my code from both files, please let me know. If you know what my error is from this code, however, please let me know. Thank you!
# Recognise the player as an object, with a specific letter (X or O)
class Player:
# Set the player's letter (noughts or crosses)
def __init__(self, letter): self.letter = letter
# Turn-based system
def get_move(self, game): pass
# Use the inheritance of classes to create a computer player that uses the 'Player' class
class ComputerPlayer:
# Set the computer's letter with teh super class
def __init__(self, letter): super().__init__(letter)
# Turn-based system, get a random move from all open possibilities
def get_move(self, game):
choice = random.choice(game.open_moves())
return choice
# Use the inheritance of classes for the user object that uses the 'Player' class
class NormalPlayer:
# Set the user's letter with the super class
def __init__(self, letter): super().__init__(letter)
# Turn-based system, get the player's movement choice
def get_move(self, game):
# Player's choice must first be verified
verified = False
# The spot value of the move the player wants to make
value = None
# Ask for the player's move
while not verified:
choice = input(self.letter + "\s turn. Which spot do you want to play? ")
# Check if the player's choice is valid...
try:
# Turn the input into an integer
value = int(choice)
# If the spot value is not available, catch the error and tell the player
if value not in game.open_moves():
raise ValueError
# ...if it is, then announce it
except ValueError:
# If the choice was invalid, have the player decide their move again
print("The spot value is not valid. Please choose another spot.")
return value
You're not specifying which class you are inheriting from. To use inheritance, you do class ClassName(ClassToInheritFrom).
So your file would look like:
# Recognise the player as an object, with a specific letter (X or O)
class Player:
# Set the player's letter (noughts or crosses)
def __init__(self, letter): self.letter = letter
# Turn-based system
def get_move(self, game): pass
# Use the inheritance of classes to create a computer player that uses the 'Player' class
class ComputerPlayer(Player):
# Set the computer's letter with teh super class
def __init__(self, letter): super().__init__(letter)
# Turn-based system, get a random move from all open possibilities
def get_move(self, game):
choice = random.choice(game.open_moves())
return choice
# Use the inheritance of classes for the user object that uses the 'Player' class
class NormalPlayer(Player):
# Set the user's letter with the super class
def __init__(self, letter): super().__init__(letter)
# Turn-based system, get the player's movement choice
def get_move(self, game):
# Player's choice must first be verified
verified = False
# The spot value of the move the player wants to make
value = None
# Ask for the player's move
while not verified:
choice = input(self.letter + "\s turn. Which spot do you want to play? ")
# Check if the player's choice is valid...
try:
# Turn the input into an integer
value = int(choice)
# If the spot value is not available, catch the error and tell the player
if value not in game.open_moves():
raise ValueError
# ...if it is, then announce it
except ValueError:
# If the choice was invalid, have the player decide their move again
print("The spot value is not valid. Please choose another spot.")
return value

Game with turns, need a way to receive a fuction's return in another turn

I'm making a game where I can gather resources or build when I send Workers, but I can't think of a way to receive those resources or finish building depending on the turn and the time(turns) it takes to finish those actions.
I've already made a Worker class, and it has a method to gather and it gives a random value that I save in a Player class. Also, my Game class keeps track of the turn I and the computers are.
class Game:
def __init__(self, player = None):
self.player = player
self.turn = 1
class Player:
def __init__(self):
self.workers = [Worker(), Worker(), Worker()]
self.resourcers = 0
class Worker:
def __init__(self):
self.hp = 100
def gather(self):
return randint(MIN_CANTIDAD_RECURSO, MAX_CANTIDAD_RECURSO)
player = Player()
game = Game()
game.player = player
for worker in player.workers:
player.resources += worker.gather
game.turn +=1
Gathering should give the result the next turn and build should give it depending on the building.
In a general sense, you store the values you need in the relevant object and pass them as parameters to whatever method requires those values. For example, you would need to store the turn duration of an action in the return value of that action, e.g in class Worker
def gather(self):
# Some code that determines gather_value and duration...
return [gather_value, duration]
and then the resource usage would look something like
def use_gather(gather, turn): # Pass in (return value from gather, game.turn)
# Use parameters...
With such a vague question, it's hard to say anything more.

Python Attribute Error in Blackjack game

I am working on am assignment for my programming class in which we have to take a blackjack program and add the option to bet.
This is the original program:
http://courses.ischool.berkeley.edu/i90/f11/resources/chapter09/blackjack.py
This works with no problems.
In the class BJ_Game I have added some code to collect bets
class BJ_Game(object):
def __init__(self, names):
self.players = []
for name in names:
player = BJ_Player(name)
self.players.append(player)
self.dealer = BJ_Dealer("Dealer")
self.deck = BJ_Deck()
self.deck.populate()
self.deck.shuffle()
# betting
def placing_bets (self, names):
self.total_bets=10
for name in names:
yes_no=input("The dealer bets 10.", name, "would you like to bet on this round? (y/n)")
if yes_no=="y":
player_bet=input(int("How much would you like to bet?:"))
else:
break
self.total_bets=player_bet+self.total_bets
return self.total_bets
(Sorry about the formatting, I'm new at this. In real life it's indented just like in the link)
The only other change I made was to add the bottom two lines to print the bets that the winner has won:
def win(self):
print(self.name, "wins.")
# awarding bets
print("You win $", self.total_bets)
When I run this, I get an error:
AttributeError: 'BJ_Game' object has no attribute '_BJ_Game__additional_cards'
I am not understanding how the changes I made caused this issue. Help is greatly appreciated.
Is this line:
def __additional_cards(self, player):
still in your program? If not, you have your answer. If yes, have a closer look at the code directly above this line.

How to re-initialize a class object

I'm making the typical text game program and I'm stuck on the restart function. I want to restart the room instances, but when I try to delete the object I get AttributeError: room1. Here's some pseudo-ish code:
class Room:
inventory = []
__init__(self, itemsInRoom, doors):
#makes a room instance and puts some items and doors into the room
self.roomItems = []
self.roomDoor = []
for item in itemsInRoom:
#puts initial items into the room
self.roomItems.append(item)
for eachDoor in doors:
#tells the instance what doors there are
self.roomDoor.append[doors]
Def functionsBlahBlah():
Pass
class RoomNumber:
room1 = Room(['stool', 'tavern wench', 'bar keep'], ['north', 'east'])
room2 = Room(so on and so forth)
def functionsBlahBlah():
Pass
def restartFunction():
del RoomNumber.room1
del RoomNumber.room2
startGame()
def startGame():
RoomNum()#initializes rooms
main()
startGame()
So anyway, I try to delete RoomNumber.room1 in the restart function so I can turn around and initialize it again with it's original items and stuff. As I said though, I get an error. Any ideas on where I'm going wrong?

Can I 'import' information to a class object from a previously defined function?

So i'm trying to make a very simple text-based RPG as my semester project for my programming class. I just recently learned (which is probably pretty apparent by my code) how to define classes and felt they would work much better than a function.
However, i'm having trouble with the 'character' class. Instead of having the player name predefined, I want the user to be able input their own name, which i've done in the 'Intro' function. Now my problem is taking the variable 'pName' and setting as the player's name, which I havent been able to do.
My questions are:
1. Can I do this? (use a function variable as a class attribute?)
2. Is there a better, more efficient way of doing this? And
3. Is there any additional information you guys could give me about classes or about how I can go about finishing this program?
Anything is well-appreciated and thanks in advance for the help!
import random, time
#I'm not at all hellbent on keeping this same format, it's just
#the way i've been taught and i'm most comfortable with.
def Intro():
print('Welcome puny warrior, to my Dungeon of DOOM, and stuff.')
pName = input('Tell me your name, puny warrior: ')
playResponse = input('Do you want to begin puny warrior who calls himself ' + pName + '? Y/N: ')
playResponse = playResponse.upper()
if playResponse[0:1] == 'Y':
pass
else:
print('You die now', pName)
class character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
#this part obviously doesn't work, but I decided to leave it as a visual aid
player = character(pName, 25, 5)
#should I just make this class a child of the 'character' class?
class foes(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
zombie = foes('Zombie', 10, 3)
dragon = foes('Dragon',20, 5)
skeleton = foes('Skeleton', 8, 4)
You are trying to call internal Intro() variable - fast fix could be like this:
def Intro():
print('Welcome puny warrior, to my Dungeon of DOOM, and stuff.')
pName = input('Tell me your name, puny warrior: ')
playResponse = input('Do you want to begin puny warrior who calls himself ' + pName + '? Y/N: ')
playResponse = playResponse.upper()
if playResponse[0:1] == 'Y':
pass
else:
print('You die now', pName)
return pName
class character(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
#this part obviously doesn't work, but I decided to leave it as a visual aid
player = character(Intro(), 25, 5)
#should I just make this class a child of the 'character' class?
class foes(object):
def __init__(self, name, health, attack):
self.name = name
self.health = health
self.attack = attack
zombie = foes('Zombie', 10, 3)
dragon = foes('Dragon',20, 5)
skeleton = foes('Skeleton', 8, 4)
Some Pointers
Take a look at PEP8, the Style Guide for Python.
Use the Character Class to define both the player, and foes.
Implement a main() method and use it appropriately. For more information about this topic, visit this discussion.
Make use of Python dictionaries, as they are very powerful.
#!/usr/bin/env python
"""Simple, text-based RPG."""
import random # Generate pseudo-random numbers.
import time # Time access and conversions.
class Character(object):
"""Define the character."""
def __init__(self, name, health, attack):
self.name = str(name) # Expecting a string.
self.health = int(health) # Expecting an integer.
self.attack = int(attack) # Expecting an integer.
def properties(self):
"""Returns dictionary containing the character properties."""
# Because using dictionaries is awesome.
characteristics = {
'name': self.name,
'health': self.health,
'attack': self.attack
}
return characteristics # Returns a dictionary
def get_player():
"""Acquire the name of the player, and begin the game."""
# Newline characters should improve readability on the command line.
print('\nWelcome puny warrior, to my Dungeon of DOOM, and stuff.\n')
# Variable names should be easy to read and understand.
player_name = input(
"""
Welcome puny warrior, to my Dungeon of DOOM... and stuff.
Tell me your name: """
)
# Get and store the player's response.
player_response = input(
"""
Do you want to begin puny warrior who calls himself %s? (Y/N): \
""" % player_name
)
if player_response.upper() == "Y":
pass
else:
print('\nYou die now\n', player_name)
return player_name
def score():
"""Assign a score between 1 and 100."""
return random.randint(1, 100)
def main():
"""Where the automagic happens."""
# Assuming you want random integers.
player = Character(get_player(), score(), score()).properties()
zombie = Character('Zombie', score(), score()).properties()
dragon = Character('Dragon', score(), score()).properties()
skeleton = Character('Skeleton', score(), score()).properties()
# Since you're working with a dictictionary, you can now do things like:
print(player['name'])
print(zombie['name'], zombie['health'])
print("%s: %s, %s" % (dragon['name'], dragon['health'], dragon['attack']))
# The correct methodology.
if __name__ == "__main__":
main()
I'm not really sure what your question is. There's no difference to Python between using a variable like pName and a string like "Zombie" in a class instantiation. The only thing wrong with your code
is that you're doing that instantiation outside Intro(), so pName is not defined.

Categories