OO style advice

D

DomF

I have been putting together a little text chess program and have run into a
style issue when integrating my chess clock with my chessboard generator.
Basically, I would like to be able to manipulate the clock independently of
the board but also want the clock time as displayed by the board to change
automatically.

I am passing in a clock object to the board in __init__ to achieve this.
However, means that the clock object can be changed via the board object and
the clock object. Is this good style or should I be designing in a totally
different way?

I previously had them separate but that led to lots of ugly board.time1 =
clock.time1 statements.

Chopped up for brevity but tested code below.

Thanks for looking,

Dom Fitzpatrick

#-------#
import time

class ChessBoard:

def __init__(self,clock):
'''Pass in a clock object with time1 and time2 attributes.'''
self.clock = clock

def testforpost(self):
print self.clock.time1
print self.clock.time2

class ChessClock:

defaulttime = 7200

def __init__(self,startvalue1=defaulttime,startvalue2=defaulttime):
'''set up the clock for the start of a game'''
ChessClock.defaulttime = startvalue1
self.time1 = startvalue1
self.time2 = startvalue2
self.state = 'Stopped'


def reset(self,value1=defaulttime,value2=defaulttime):
'''reset the chess clock with optional new game length'''
self.time1 = value1
self.time2 = value2
self.state = 'Stopped'


def clockgen(self):
'''generator for clock events, uses self.state to control what
happens'''
currenttimeleft = time.time()

while 1:
yield self.time1
if self.state == 'Player1':
self.time1 = self.time1 - int(time.time() - currenttimeleft)
currenttimeleft = time.time()

elif self.state == 'Player2':
self.time2 = self.time2 - int(time.time() - currenttimeleft)
currenttimeleft = time.time()
else:
currenttimeleft = time.time()



if __name__ == "__main__":

gameclock = ChessClock()
gameclockgen = gameclock.clockgen()
gameclockgen.next()

board = ChessBoard(gameclock)
board.testforpost()

gameclock.state = 'Player1'
time.sleep(3)
gameclockgen.next()

board.testforpost()
#-----------#
 
S

Sean Ross

DomF said:
I have been putting together a little text chess program and have run into a
style issue when integrating my chess clock with my chessboard generator.
Basically, I would like to be able to manipulate the clock independently of
the board but also want the clock time as displayed by the board to change
automatically.

Hi.
My first thought is to make a Clock object that has a time attribute and
start() and stop() methods

Then have one instance of Clock for each player (and perhaps an independent
one for the board?)

If you have Player objects, perhaps they could have a clock instance. In
that way
you could do something like:

# suppose the players are maintained by the board in a list
# and you have a turn variable for accessing the player whose turn it is to
play
while board.state != STALEMATE and board.state != CHECKMATE:
player = player[turn]
player.clock.start()
player.move()
player.clock.stop()
turn.next() # adjust turn index to let other player move next round


you could even have player.clock.start() and player.clock.stop() at the
start
and end of the inside of player.move() so your code looks more like this

while board.state != STALEMATE and board.state != CHECKMATE:
player[turn].move()
turn.next()


Just an idea,
Sean
 
A

Alan Gauld

I am passing in a clock object to the board in __init__ to achieve this.
However, means that the clock object can be changed via the board object and
the clock object. Is this good style or should I be designing in a totally
different way?

In OO objects communicate via messages. Thus think about the
messages that can be sent to the clock. Do not think about the
data inside the clock, that should be treated as private (even
though Python does not enforce this).

Now you have a single clock object but referenced both inside and
outside the board. Is that really what you want or do you want
the oard to have its own clock instance internally? If it is a
single object then its perfectly reasonable that both internal
and external objects can send it messages. If its an internal
object then only the board can conceptually see it.
If you need to initialise the internal clock you may want to take
a time parameter to the board and use that to set the clock
initial values, rather than passing a functioning clock object as
the parameter.

Also as somebody else said you may want to use multiple clock
objects...
I previously had them separate but that led to lots of ugly board.time1 =
clock.time1 statements.

Rather than access the data I'd provide a method, say
synchronise?

board.synchronise(myClock)

Which internally sets the board clock to the same time as the
parameter clock, something like:

def synchronise(self, aClock):
self.clock.setTime(aClock.time())

Whether you think that looks any less ugly than the assignments
you had is a moot point!

Alan G.
Author of the Learn to Program website
http://www.freenetpages.co.uk/hp/alan.gauld
 
A

A. Lloyd Flanagan

DomF said:
I have been putting together a little text chess program and have run into a
style issue when integrating my chess clock with my chessboard generator.
Basically, I would like to be able to manipulate the clock independently of
the board but also want the clock time as displayed by the board to change
automatically.

I am passing in a clock object to the board in __init__ to achieve this.
However, means that the clock object can be changed via the board object and
the clock object. Is this good style or should I be designing in a totally
different way?
As long as the clock is one conceptual object, you should definitely
have only one instance. You're just passing a handle to the board to
give the board permission to read/update the clock.
The method of having the time in the board and the clock, and
synchronizing, has a fatal flaw. You would have two instances
modeling the exact same object, and that _would_ be bad design. I
think you've got the right answer here.
 
D

DomF

Alan Gauld said:
In OO objects communicate via messages. Thus think about the
messages that can be sent to the clock. Do not think about the
data inside the clock, that should be treated as private (even
though Python does not enforce this).

Now you have a single clock object but referenced both inside and
outside the board. Is that really what you want or do you want
the oard to have its own clock instance internally? If it is a
single object then its perfectly reasonable that both internal
and external objects can send it messages. If its an internal
object then only the board can conceptually see it.
If you need to initialise the internal clock you may want to take
a time parameter to the board and use that to set the clock
initial values, rather than passing a functioning clock object as
the parameter.

Also as somebody else said you may want to use multiple clock
objects...


Rather than access the data I'd provide a method, say
synchronise?

board.synchronise(myClock)

Which internally sets the board clock to the same time as the
parameter clock, something like:

def synchronise(self, aClock):
self.clock.setTime(aClock.time())

Whether you think that looks any less ugly than the assignments
you had is a moot point!

There isn't only one way to do this then :)

Thanks for the reply, points taken. I think the final decision will depend
on whether I need to use the clock instance outside of the board or not. At
the moment I reckon I will for match and player classes but maybe not!
 
M

Magnus Lyck?

DomF said:
I have been putting together a little text chess program and have run into a
style issue when integrating my chess clock with my chessboard generator.
Basically, I would like to be able to manipulate the clock independently of
the board but also want the clock time as displayed by the board to change
automatically.

I am passing in a clock object to the board in __init__ to achieve this.
However, means that the clock object can be changed via the board object and
the clock object. Is this good style or should I be designing in a totally
different way?

So, just pass in a bound method to view the clock output then!
Likewise, player objects can get buttons to play with. Methods
are also objects that can be passed around, you know... E.g:

import time

class ChessClock:
WHITE, BLACK = False, True

def __init__(self):
self.last_start = None
self.total = [0.0,0.0]
self.running = None

def white_press_button(self):
if self.running is None:
self.running = self.BLACK
self.last_start = time.time()
else:
self.press_button(self.WHITE)

def black_press_button(self):
self.press_button(self.BLACK)

def press_button(self, color):
if self.running == color:
self.running = not color
self.total[color] += time.time() - self.last_start
self.last_start = time.time()
else:
print "Not your turn!"

def display(self):
times = self.total[:]
txt = ['STOPPED','RUNNING']
if not self.running is None:
times[self.running] += time.time() - self.last_start
for color, COLOR in [('White', self.WHITE), ('Black', self.BLACK)]:
print "%s: %d min %02d sec %s" %(
(color, times[COLOR]//60, times[COLOR]%60, txt[COLOR]))


class ChessGame:
def __init__(self, clock_display):
self.clock_display = clock_display
...

...
self.clock_display()
...


class ChessPlayer:
def __init__(self, colour, press_clock_button):
self.press_clock_button = press_clock_button
...

...
self.press_clock_button()
...

....

clk = ChessClock()
game = ChessGame(clk.display)
w = ChessPlayer('White', clk.white_press_button)
b = ChessPlayer('Black', clk.black_press_button)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,966
Members
47,515
Latest member
Harvey7327

Latest Threads

Top