Error when calling a method from separate Python file - python

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

Related

Menu for a turn based game

Our teacher has assigned us an assignment for doing a turned based game.
This only included name.strip() but this does not prompt player to input unique name:
def start():
print("\nNew game started...Setting up Player 1's team...\n")
for total_characters in range (1,4):
name = input('Enter a unique name for unit #'+str(total_characters)+'==> ')
if not name.strip():
print('Cant be blank name,please provide a unique name')
return start()
else:
role_selection()
def role_selection():
for total_characters in range (1):
role = input('Select unit #'+str(total_characters)+' type: (W)arrior, (T)anker, or Wi(Z)ard ==> ')
total_characters+=1
if role.upper() == 'W':
pass
elif role.upper() == 'T':
pass
elif role.upper() == 'Z':
pass
else:
print("I don't understand what are you typing.")
return role_selection()
There are things that doesn't make sense :
You have the exact same function twice :
def set_up(team_size)
def set_up(name)
You are doing :
for total_units in range(team_size):
[...]
invalid = True
[...]
while invalid: # Infinite loop
set_up() # What's this function ?
As you can see from the comments in the code above, you never set invalid to False, leading to the infinite loop.
Note: My recommendation is that you should check out some tutorial on python before moving on coding a complex project, because your homework is not that easy.
Edit :
From the new code you've posted, you could do something like this :
def new_game():
names = []
for unit_id in range(1,4):
print(f'Enter a unique name for unit #{unit_id} ->')
empty = True
while empty:
name = input('>')
if name == "":
continue
empty = False
if name in names:
print('Unit name must be unique.')
else:
print('Name looks good!')
names.append(name)
python menu
At first glance, this stood out to me:
if not name.strip():
print('Unit name could not be blank.')
invalid = True
Remember in python the indentation matters. You are setting invalid to True regardless of the if condition. Further down you have a while loop that checks it.
The other if conditions have invalid=True inside the condition. Plus you don't have invalid=False anywhere as far as I see, so you'll get an error if you don't declare it somewhere so it's always on the path before the while.
this doesn't seem like a specific problem, more an ask for general guidance for going about this kind of problem?
One thing to note is that your above script only uses functions (which store behaviour) whilst really for something like the turn based game, you need to store behaviour (attacks etc) and information (how much health is left etc).
I won't write the script for you, but here's an example of how you might define an rpg like entity, capable of attacking, being attacked by another entity etc:
class Entity:
"""Abstract class for any combat creature"""
def __init__(self, name, health):
self.name = name
self.health = health
self.is_alive = True
def attack(self, other):
dmg = random.randint(7, 12)
other.be_attacked(dmg)
def be_attacked(self, dmg):
self.health = self.health - dmg
if self.health <= 0:
self.die()
def die(self):
self.is_alive = False
def check_life(self):
return self.is_alive
You can then initialise a bunch of these to make up the 'team' you where talking about:
one_person = Entity('Lee', 34)
another_person = Entity('Someone Else', 21)
etc. Hope that helps a bit. Good luck with your project and have fun!

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.

How to properly call a class

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)

Python Referencing Object Inside Object Incorrectly

I have 2 python classes: Player, and Board. The board contains a dict with "A1" reference style for spaces.
player.py's Player class:
from board import Board
class Player:
def __init__(self):
self.name = input("Name: ")
self.board = Board(3, ["A", "B", "C"])
board.py's Board class:
class Board:
EMPTY = "0"
spaces = {}
def __init__(self, size, letters):
for let in letters:
for num in range(1, size + 1):
self.spaces["{}{}".format(let, num)] = self.EMPTY
def place_piece(self, spot):
self.spaces[spot] = "X"
def display_board(self):
for let in letters:
for num in range(1, size + 1):
print("\n" + self.spaces["{}{}".format(let, num)]
When Player is instantiated, it creates a Board object inside.
2 players are created, and each is added to the list players[]. Each player's turn is selected with a simple 1/0 variable called current_player.
from player import *
from board import *
current_player = 1
players = []
player_1 = Player()
player_2 = Player()
players.append(player_1)
players.append(player_2)
while True:
# Switches players
current_player = abs(current_player - 1)
# Prints the current player's name
print(players[current_player].name)
# Calls some method which should alter the current player's board
players[current_player].board.place_piece(input("> "))
# Calls some method which should show the current player's board
players[current_player].board.show_board()
Obviously, very simplified. The name prints out correctly every single time. The board, however, only uses the first player's board for both players. I know it's working because the players' name prints correctly.
The issue persists even if the boards are created separately and placed in their own list.
What am I doing wrong?
As it is written now the code posted shouldn't be working. The two methods in Board, place_piece and display_board, need to accept 'self' as a first argument.
Assuming this is a typo here's what's happening. The class Board is created with a class member spaces. Each time you're referencing self.spaces in an object, it is not found in the object is instead looked up in the class. Meaning you're using the same dict for all object of the class Board. Instead, to create a regular member place the declaration in the init method as you do in the Player class:
class Board:
EMPTY = "0"
# Remove spaces = {}
def __init__(self, size, letters):
self.spaces = {}
...
Finally, since you're using Python 2x please let me encourage you to always use new style classes (i.e. write class Board(object)). See What is the difference between old style and new style classes in Python?

How do I pass variables around in Python?

I want to make a text-based fighting game, but in order to do so I need to use several functions and pass values around such as damage, weapons, and health.
Please allow this code to be able to pass "weapons" "damage" "p1 n p2" throughout my code. As you can see I have tried using parameters for p1 n p2, but I am a little bit a newbie.
import random
def main():
print("Welcome to fight club!\nYou will be fighting next!\nMake sure you have two people ready to play!")
p1=input("\nEnter player 1's name ")
p2=input("Enter player 2's name ")
print("Time to get your weapons for round one!\n")
round1(p1,p2)
def randomweapons(p1,p2):
weapon=["Stick","Baseball bat","Golf club","Cricket bat","Knife",]
p1weapon=random.choice(weapon)
p2weapon=random.choice(weapon)
print(p1 +" has found a "+p1weapon)
print(p2 +" has found a "+p2weapon)
def randomdamage():
damage=["17","13","10","18","15"]
p1damage=random.choice(damage)
p2damage=random.choice(damage)
def round1(p1,p2):
randomweapons(p1,p2)
def round2():
pass
def round3():
pass
def weaponlocation():
pass
main()
There are a few options.
One is to pass the values as parameters and return values from your various functions. You're already doing this with the names of the two players, which are passed as parameters from main to round1 and from there on to randomweapons. You just need to decide what else needs to be passed around.
When the information needs to flow the other direction (from a called function back to the caller), use return. For instance, you might have randomweapons return the weapons it chose to whatever function calls it (with return p1weapon, p2weapon). You could then save the weapons in the calling function by assigning the function's return value to a variable or multiple variables, using Python's tuple-unpacking syntax: w1, w2 = randomweapons(p1, p2). The calling function could do whatever it wants with those variables from then on (including passing them to other functions).
Another, probably better approach is to use object oriented programming. If your functions are methods defined in some class (e.g. MyGame), you can save various pieces of data as attributes on an instance of the class. The methods get the instance passed in automatically as the first parameter, which is conventionally named self. Here's a somewhat crude example of what that could be like:
class MyGame: # define the class
def play(self): # each method gets an instance passed as "self"
self.p1 = input("Enter player 1's name ") # attributes can be assigned on self
self.p2 = input("Enter player 2's name ")
self.round1()
self.round2()
def random_weapons(self):
weapons = ["Stick", "Baseball bat", "Golf club", "Cricket bat", "Knife"]
self.w1 = random.choice(weapons)
self.w2 = random.choice(weapons)
print(self.p1 + " has found a " + self.w1) # and looked up again in other methods
print(self.p2 + " has found a " + self.w2)
def round1(self):
print("Lets pick weapons for Round 1")
self.random_weapons()
def round2(self):
print("Lets pick weapons for Round 2")
self.random_weapons()
def main():
game = MyGame() # create the instance
game.play() # call the play() method on it, to actually start the game

Categories