I'm trying to create two subclasses based on the same parent class, so that they each have their own versions of the same variables defined in the parent object. However I realized that changing these variables in one of these subclasses will cause the versions in the other subclass to change as well. I know I am probably not fully understanding the idea of Inheritance. Please help!
import random
class PlayerParent():
id = 1
# Cooperate: True; Betrayal: False
opponent_moves_history = {}
self_moves_history = {}
def append_opponent_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.opponent_moves_history[round_num] = c_true
def append_self_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.self_moves_history[round_num] = c_true
score = int(0)
def score_keeper(self, round_num):
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == False):
self.score += 7
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == True):
self.score += 5
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == True):
self.score += 1
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == False):
self.score += 2
def get_score(self):
return self.score
class TitForTat(PlayerParent):
def rule(self, round_num):
if len(self.opponent_moves_history) == 0:
return True
else:
return self.opponent_moves_history[round_num - 1]
class Random(PlayerParent):
def rule(self, round_num):
random_num = random.uniform(0, 1)
if random_num >= 0.5:
return True
else:
return False
Random = Random()
Random.id = 1
TitForTat = TitForTat()
TitForTat.id = 2
def match(a, b):
game_counter = 1
# while game_counter <= 10:
#a_result = a.rule(game_counter)
# b_result = b.rule(game_counter)
# print(a_result, b_result)
# a.append_self_history(game_counter, a_result)
# b.append_opponent_history(game_counter, a_result)
# b.append_self_history(game_counter, b_result)
# a.append_opponent_history(game_counter, b_result)
# a.score_keeper(game_counter)
# b.score_keeper(game_counter)
# game_counter += 1
# print(a.get_score(), b.get_score())
a.self_moves_history[1] = True
print(a.self_moves_history, '\n', b.self_moves_history)
match(Random, TitForTat)
Resulting a.self_moves_history and b.self_moves_history is identical even though no alteration has been done to the b class variable.
I commented out chunks of the codes just to test where went wrong.
You are making opponent_moves_history a class variable, so naturally any change to it is class-wide.
In your case you should make opponent_moves_history, along with self_moves_history and id instance variables instead, so that changes made to them are specific to the instances.
class PlayerParent():
def __init__(self):
self.id = 1
self.opponent_moves_history = {}
self.self_moves_history = {}
So I am designing a battleship backend system that will be running on google apps engine... I just started yesterday and designed a framework for the game.
Unfortunately for me, I have not coded too much in python so I am not too familiar with the specifics of the language. I keep getting the following error when I try to run the program:
File "C:\Users\Shlomo\Desktop\eclipse\plugins\org.python.pydev_2.7.5.2013052819\pysrc\pydev_runfiles.py", line 432, in __get_module_from_str
mod = __import__(modname)
File "C:\Users\Shlomo\workspace\battleship\Battleship.py", line 222, in <module>
battleship = BattleshipGame("Shlomo",1,1,4,1,1,2,5,2,1,3,3,3,1,4,2,4,1,5,5,5,"John",1,1,4,1,1,2,5,2,1,3,3,3,1,4,2,4,1,5,5,5)
File "C:\Users\Shlomo\workspace\battleship\Battleship.py", line 210, in __init__
field = self.player1_field.getField()
AttributeError: 'NoneType' object has no attribute 'getField'
ERROR: Module: Battleship could not be imported (file: C:\Users\Shlomo\workspace\battleship\Battleship.py).
So I translated this error as the variable field is not getting initialized with the PlayerField object...
Here is my code:
import random
class Player:
player_name = None
player_id = None
game_id = None
your_turn = False
player_field = None
hit_field = None
opponent = None
def __init__(self,name,player_field,hit_field,opponent):
self.player_name = name
self.player_field = player_field
self.hit_field = hit_field
self.opponent = opponent
def getPlayerField(self):
return self.player_field
def performHit(self,x,y):
mark = None
hit = self.opponent.getPlayerField.hitAt(x,y)
if hit:
mark = 'X'
else:
mark = 'O'
self.hit_field.markHitField(x,y,mark)
class HitField:
hit_field = None
def __init__(self):
hit_field = [[0 for i in xrange(10)] for i in xrange(10)]
def markHitField(self,x,y,mark):
self.hitfield[x][y] = mark
class PlayerField:
player_field = [[0 for i in xrange(10)] for i in xrange(10)]
shipsOnField = []
goodToGo = False
def __init__(self,battleship,aircraft,destroyer,submarine,patrol):
if self.validPlacement(battleship)and self.validPlacement(aircraft)and self.validPlacement(destroyer) and self.validPlacement(submarine) and self.validPlacement(patrol):
self.placeShip(battleship)
self.placeShip(aircraft)
self.placeShip(destroyer)
self.placeShip(submarine)
self.placeShip(patrol)
self.shipsOnField.append(battleship)
self.shipsOnField.append(aircraft)
self.shipsOnField.append(destroyer)
self.shipsOnField.append(submarine)
self.shipsOnField.append(patrol)
self.goodToGo = True
else:
print "some pieces have been placed incorrectly"
def validPlacement(self,ship):
hx = ship.getHeadX;
hy = ship.getHeadY;
tx = ship.getTailX;
ty = ship.getTailY;
if not hx > 0 and not hx < 11:
return False
return True
def placeShip(self,ship):
hx = ship.getHeadX();
hy = ship.getHeadY();
tx = ship.getTailX();
ty = ship.getTailY();
for y in range(ty,hy):
for x in range(tx,hx):
self.player_field[x][y] = ship.getShipID
def hitAt(self,x,y):
hitPos = self.player_field[x][y]
if not hitPos == 0 and not hitPos == 'X':
self.getShipByID(hitPos).removeHealth
self.player_field[x][y] = 'X'
return True
def getShipByID(self,ID):
for ship in self.shipsOnField:
if ship.getShipID == ID:
return ship
def getField(self):
return self.player_field
class Ship(object):
ship_id = None
ship_name = None
max_health = None
remaining_health = None
head_pos_x = None
head_pos_y = None
tail_pos_x = None
tail_pos_y = None
def __init__(self,id,name,max,hx,hy,tx,ty):
self.ship_id = id
self.max_health = max
self.remaining_health = max
self.ship_name = name
self.head_pos_x = hx
self.head_pos_y = hy
self.tail_pos_x = tx
self.tail_pos_y = ty
self.remaining_health = max
def removeHealth(self):
self.remaining_health -= 1
def getHeadX(self):
return self.head_pos_x
def getHeadY(self):
return self.head_pos_y
def getTailX(self):
return self.tail_pos_x
def getTailY(self):
return self.tail_pos_y
def getRemainingHealth(self):
return self.remaining_health
def getShipID(self):
return self.ship_id
class Battleship(Ship):
def __init__(self,hx,hy,tx,ty):
Ship.__init__(self,1,"Battle Ship",4,hx,hy,tx,ty)
class AircraftCarrier(Ship):
def __init__(self,hx,hy,tx,ty):
Ship.__init__(self,2,"Aircraft Carrier",5,hx,hy,tx,ty)
class Destroyer(Ship):
def __init__(self,hx,hy,tx,ty):
Ship.__init__(self,3,"Destroyer",3,hx,hy,tx,ty)
class Submarine(Ship):
def __init__(self,hx,hy,tx,ty):
Ship.__init__(self,4,"Submarine",3,hx,hy,tx,ty)
class PatrolBoat(Ship):
def __init__(self,hx,hy,tx,ty):
Ship.__init__(self,5,"Patrol Boat",2,hx,hy,tx,ty)
class BattleshipGame:
current_turn = None
player1 = None
player2 = None
player1_field = None
player1_opponent = player2
player2_field = None
player2_opponent = player1
def firstTurn(self):
rand = random.randint(1,2)
if rand==1:
return self.player1
else:
return self.player2
def printGameBoard(self):
field = self.player1_field.getField()
for y in range(1,10):
for x in range(1,10):
print field[x][y]
print '\n'
def __init__(self,p1name,p1bshx,p1bshy,p1bstx,p1bsty
,p1dhx,p1dhy,p1dtx,p1dty
,p1shx,p1shy,p1stx,p1sty
,p1pbhx,p1pbhy,p1pbtx,p1pbty
,p1achx,p1achy,p1actx,p1acty
,p2name,p2bshx,p2bshy,p2bstx,p2bsty
,p2dhx,p2dhy,p2dtx,p2dty
,p2shx,p2shy,p2stx,p2sty
,p2pbhx,p2pbhy,p2pbtx,p2pbty
,p2achx,p2achy,p2actx,p2acty):
player1_field = PlayerField(Battleship(p1bshx,p1bshy,p1bstx,p1bsty),
AircraftCarrier(p1achx,p1achy,p1actx,p1acty),
Destroyer(p1dhx,p1dhy,p1dtx,p1dty),
Submarine(p1shx,p1shy,p1stx,p1sty),
PatrolBoat(p1pbhx,p1pbhy,p1pbtx,p1pbty))
player2_field = PlayerField(Battleship(p2bshx,p2bshy,p2bstx,p2bsty),
AircraftCarrier(p2achx,p2achy,p2actx,p2acty),
Destroyer(p2dhx,p2dhy,p2dtx,p2dty),
Submarine(p2shx,p2shy,p2stx,p2sty),
PatrolBoat(p2pbhx,p2pbhy,p2pbtx,p2pbty))
player1 = Player(p1name,self.player1_field,HitField(),self.player2)
player2 = Player(p2name,self.player2_field,HitField(),self.player1)
self.current_turn = self.firstTurn()
battleship = BattleshipGame("Player1",1,1,4,1,1,2,5,2,1,3,3,3,1,4,2,4,1,5,5,5,"Player2",1,1,4,1,1,2,5,2,1,3,3,3,1,4,2,4,1,5,5,5)
battleship.printGameBoard()
Sorry about the sytax, I had trouble pasting it in the code format. This code probably has a few problems but I have not been able to get passed this problem yet...
What am I doing wrong?
In your __init__, you're assigning to a local variable player1_field rather than to instance data. Instead of:
player1_field = PlayerField(...
You want:
self.player1_field = PlayerField(...
Without that, you're trying to deference your class's value for player1_field, which is None.
Python isn't Java or whatever language you are trying to write. These mutable class attributes are unlikely to do what you think they do.
class PlayerField:
player_field = [[0 for i in xrange(10)] for i in xrange(10)]
shipsOnField = []
goodToGo = False