class Session: def __init__(self, w, h, owner): self.sid = sha1(str(time.time())).hexdigest() self.clients = [owner] owner.player = 1 self.player_counter = 2 self.state = STATE_JOINING self.board = Board(w, h) self.turn = owner owner.send(Msg('newgame', self.sid, w, h).encode()) owner.send(Msg('turn', self.turn.player).encode()) def __str__(self): return '<Session %s state=%d size=%dx%d>' % \ (self.sid, self.state, self.board.w, self.board.h) def click_wall(self, client, x, y, direction): check(self.turn is client, 'not your turn') check(self.state < STATE_FINISHED, 'already finished') self.state = STATE_PLAYING occupied = self.board.click_wall(x, y, direction, client.player) self.bcast('clickwall', x, y, direction) if occupied: for x, y in occupied: self.bcast('occupy', x, y, client.player) if self.board.is_finished(): scores = self.board.scores() for player in xrange(1, self.player_counter): scores.setdefault(player, 0) scores = scores.items() scores.sort(key=lambda (player, score): score, reverse=True) self.state = STATE_FINISHED self.bcast('finish', *['%d:%d' % s for s in scores]) else: index = (self.clients.index(self.turn) + 1) % len(self.clients) self.turn = self.clients[index] self.bcast('turn', self.turn.player) def bcast(self, mtype, *args): encoded = Msg(mtype, *args).encode() for client in self.clients: client.send(encoded) def join(self, client): client.player = self.player_counter self.player_counter += 1 self.bcast('join', client.player) client.send(Msg('newgame', self.sid, self.board.w, self.board.h, client.player).encode()) client.send(Msg('turn', self.turn.player).encode()) for other in self.clients: client.send(Msg('join', other.player).encode()) self.clients.append(client) def leave(self, client): self.clients.remove(client) self.bcast('leave', client.player) if self.state == STATE_PLAYING: self.bcast('cancel', 'a player has quit before the game ended') elif client is self.turn: self.turn = self.clients[0] self.bcast('turn', self.turn.player) def is_dead(self): return not self.clients