def nextHand(self, dummyResults): """next hand: maybe rotate""" if not self.running: return DeferredBlock.garbageCollection() for block in DeferredBlock.blocks: if block.table == self: logError('request left from previous hand: %s' % block.outstandingStr()) token = self.game.handId.prompt( withAI=False) # we need to send the old token until the # clients started the new hand rotateWinds = self.game.maybeRotateWinds() if self.game.finished(): self.server.removeTable(self, 'gameOver', i18nE('Game <numid>%1</numid> is over!'), self.game.seed) if Debug.process and os.name != 'nt': logDebug('MEM:%s' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) return self.game.sortPlayers() playerNames = list((x.wind, x.name) for x in self.game.players) self.tellAll(None, Message.ReadyForHandStart, self.startHand, playerNames=playerNames, rotateWinds=rotateWinds, token=token)
def _clientDiscarded4(self, dummyResults, msg, dangerousText, mustPlayDangerous): """client told us he discarded a tile. Continue, check for dangerous game""" block = DeferredBlock(self) player = msg.player if dangerousText: if mustPlayDangerous and not player.lastSource.isDiscarded: if Debug.dangerousGame: tile = Tile(msg.args[0]) logDebug( '%s claims no choice. Discarded %s, keeping %s. %s' % (player, tile, ''.join( player.concealedTiles), ' / '.join(dangerousText))) player.claimedNoChoice = True block.tellAll(player, Message.NoChoice, tiles=TileList(player.concealedTiles)) else: player.playedDangerous = True if Debug.dangerousGame: tile = Tile(msg.args[0]) logDebug( '%s played dangerous. Discarded %s, keeping %s. %s' % (player, tile, ''.join( player.concealedTiles), ' / '.join(dangerousText))) block.tellAll(player, Message.DangerousGame, tiles=TileList(player.concealedTiles)) if msg.answer == Message.OriginalCall: player.isCalling = True block.callback(self.clientMadeOriginalCall, msg) else: block.callback(self._askForClaims, msg)
def clientMadeOriginalCall(self, dummyResults, msg): """first tell everybody about original call and then treat the implicit discard""" msg.player.originalCall = True if Debug.originalCall: logDebug('server.clientMadeOriginalCall: %s' % msg.player) block = DeferredBlock(self) block.tellAll(msg.player, Message.OriginalCall) block.callback(self.askForClaims)
def initGame(self): """ask clients if they are ready to start""" game = self.preparedGame game.saveNewGame() block = DeferredBlock(self) for player in game.players: block.tellPlayer(player, Message.ReadyForGameStart, tableid=self.tableid, gameid=game.gameid, shouldSave=player.shouldSave, wantedGame=game.wantedGame, source=list((x.wind, x.name) for x in game.players)) block.callback(self.startGame)
def claimMahJongg(self, msg): """a player claims mah jongg. Check this and if correct, tell all. Otherwise abort game, kajongg client is faulty""" if not self.running: return player = msg.player concealedMelds = MeldList(msg.args[0]) withDiscard = Tile(msg.args[1]) if msg.args[1] else None lastMeld = Meld(msg.args[2]) if self.game.ruleset.mustDeclareCallingHand: assert player.isCalling, '%s %s %s says MJ but never claimed: concmelds:%s withdiscard:%s lastmeld:%s' % ( self.game.handId, player.hand, player, concealedMelds, withDiscard, lastMeld) discardingPlayer = self.game.activePlayer lastMove = next(self.game.lastMoves(withoutNotifications=True)) robbedTheKong = lastMove.message == Message.DeclaredKong if robbedTheKong: player.robsTile() withDiscard = lastMove.meld[0].concealed lastMove.player.robTileFrom(withDiscard) msgArgs = player.showConcealedMelds(concealedMelds, withDiscard) if msgArgs: self.abort(*msgArgs) return player.declaredMahJongg(concealedMelds, withDiscard, player.lastTile, lastMeld) if not player.hand.won: msg = i18nE('%1 claiming MahJongg: This is not a winning hand: %2') self.abort(msg, player.name, player.hand.string) return block = DeferredBlock(self) if robbedTheKong: block.tellAll(player, Message.RobbedTheKong, tile=withDiscard) if (player.lastSource is TileSource.LivingWallDiscard and self.game.dangerousFor(discardingPlayer, player.lastTile) and discardingPlayer.playedDangerous): player.usedDangerousFrom = discardingPlayer if Debug.dangerousGame: logDebug('%s wins with dangerous tile %s from %s' % (player, self.game.lastDiscard, discardingPlayer)) block.tellAll(player, Message.UsedDangerousFrom, source=discardingPlayer.name) block.tellAll(player, Message.MahJongg, melds=concealedMelds, lastTile=player.lastTile, lastMeld=lastMeld, withDiscardTile=withDiscard) block.callback(self.endHand)
def proposeGameId(self, gameid): """server proposes an id to the clients ands waits for answers""" while True: with Transaction(): query = Query('insert into game(id,seed) values(?,?)', list([gameid, 'proposed']), mayFail=True) if query.success: break gameid += random.randrange(1, 100) block = DeferredBlock(self) for player in self.preparedGame.players: if player.shouldSave and isinstance(player.remote, User): # do not ask robot players, they use the server data base block.tellPlayer(player, Message.ProposeGameId, gameid=gameid) block.callback(self.collectGameIdAnswers, gameid)
def endHand(self, dummyResults=None): """hand is over, show all concealed tiles to all players""" if not self.game: return if self.game.playOpen: self.saveHand() else: block = DeferredBlock(self) for player in self.game.players: # there might be no winner, winner.others() would be wrong if player != self.game.winner: # the winner tiles are already shown in claimMahJongg block.tellOthers(player, Message.ShowConcealedTiles, show=True, source=player.concealedTileNames) block.callback(self.saveHand)
def claimTile(self, player, claim, meldTiles, nextMessage): """a player claims a tile for pung, kong or chow. meldTiles contains the claimed tile, concealed""" if not self.running: return lastDiscard = self.game.lastDiscard # if we rob a tile, self.game.lastDiscard has already been set to the # robbed tile hasTiles = Meld(meldTiles[:]) discardingPlayer = self.game.activePlayer hasTiles = hasTiles.without(lastDiscard) meld = Meld(meldTiles) if len(meld) != 4 and not (meld.isPair or meld.isPungKong or meld.isChow): msg = i18nE('%1 wrongly said %2 for meld %3') self.abort(msg, player.name, claim.name, str(meld)) return if not player.hasConcealedTiles(hasTiles): msg = i18nE( '%1 wrongly said %2: claims to have concealed tiles %3 but only has %4' ) self.abort(msg, player.name, claim.name, ' '.join(hasTiles), ''.join(player.concealedTiles)) return # update our internal state before we listen to the clients again self.game.discardedTiles[lastDiscard.exposed] -= 1 self.game.activePlayer = player if lastDiscard: player.lastTile = lastDiscard.exposed player.lastSource = TileSource.LivingWallDiscard player.exposeMeld(hasTiles, lastDiscard) self.game.lastDiscard = None block = DeferredBlock(self) if (nextMessage != Message.Kong and self.game.dangerousFor(discardingPlayer, lastDiscard) and discardingPlayer.playedDangerous): player.usedDangerousFrom = discardingPlayer if Debug.dangerousGame: logDebug('%s claims dangerous tile %s discarded by %s' % (player, lastDiscard, discardingPlayer)) block.tellAll(player, Message.UsedDangerousFrom, source=discardingPlayer.name) block.tellAll(player, nextMessage, meld=meld) if claim == Message.Kong: block.callback(self.pickKongReplacement) else: block.callback(self.moved)
def divided(self, dummyResults=None): """the wall is now divided for all clients""" if not self.game: return block = DeferredBlock(self) for clientPlayer in self.game.players: allPlayerTiles = [] for player in self.game.players: bonusTileNames = tuple(x.element for x in player.bonusTiles) if player == clientPlayer or self.game.playOpen: playerTiles = player.concealedTileNames else: playerTiles = ('Xy',) * 13 allPlayerTiles.append((player.name, playerTiles + bonusTileNames)) block.tellPlayer(clientPlayer, Message.SetConcealedTiles, source=allPlayerTiles) block.callback(self.dealt)
def sendVoiceData(self, requests, voiceDataRequests): """sends voice sounds to other human players""" self.processAnswers(requests) block = DeferredBlock(self) for voiceDataRequester, voiceFor in voiceDataRequests: # this player requested sounds for voiceFor voice = voiceFor.voice content = voice.archiveContent if content: if Debug.sound: logDebug('server got voice data %s for %s from client' % (voiceFor.voice, voiceFor.name)) block.tell(voiceFor, voiceDataRequester, Message.VoiceData, md5sum=voice.md5sum, source=content) elif Debug.sound: logDebug('server got empty voice data %s for %s from client' % ( voice, voiceFor.name)) block.callback(self.assignVoices)
def sendVoiceIds(self): """tell each player what voice ids the others have. By now the client has a Game instance!""" humanPlayers = [x for x in self.game.players if isinstance(x.remote, User)] if len(humanPlayers) < 2 or not any(x.remote.voiceId for x in humanPlayers): # no need to pass around voice data self.assignVoices() return block = DeferredBlock(self) for player in humanPlayers: if player.remote.voiceId: # send it to other human players: others = [x for x in humanPlayers if x != player] if Debug.sound: logDebug('telling other human players that %s has voiceId %s' % ( player.name, player.remote.voiceId)) block.tell(player, others, Message.VoiceId, source=player.remote.voiceId) block.callback(self.collectVoiceData)
def nextHand(self, dummyResults): """next hand: maybe rotate""" if not self.game: return DeferredBlock.garbageCollection() for block in DeferredBlock.blocks: if block.table == self: logError('request left from previous hand: %s' % block.outstandingStr()) token = self.game.handId() # we need to send the old token until the # clients started the new hand rotateWinds = self.game.maybeRotateWinds() if self.game.finished(): self.close('gameOver', m18nE('The game is over!')) return self.game.sortPlayers() playerNames = list((x.wind, x.name) for x in self.game.players) self.tellAll(None, Message.ReadyForHandStart, self.startHand, source=playerNames, rotateWinds=rotateWinds, token=token)
def collectVoiceData(self, requests): """collect voices of other players""" if not self.game: return block = DeferredBlock(self) voiceDataRequests = [] for request in requests: if request.answer == Message.ClientWantsVoiceData: # another human player requests sounds for voiceId voiceId = request.args[0] voiceFor = [x for x in self.game.players if isinstance(x.remote, User) \ and x.remote.voiceId == voiceId][0] voiceFor.voice = Voice(voiceId) if Debug.sound: logDebug('client %s wants voice data %s for %s' % (request.player.name, request.args[0], voiceFor)) voiceDataRequests.append((request.player, voiceFor)) if not voiceFor.voice.oggFiles(): # the server does not have it, ask the client with that voice block.tell(voiceFor, voiceFor, Message.ServerWantsVoiceData) block.callback(self.sendVoiceData, voiceDataRequests)
def sendVoiceIds(self): """tell each player what voice ids the others have. By now the client has a Game instance!""" humanPlayers = [ x for x in self.game.players if isinstance(self.remotes[x], User) ] if len(humanPlayers) < 2 or not any(self.remotes[x].voiceId for x in humanPlayers): # no need to pass around voice data self.assignVoices() return block = DeferredBlock(self) for player in humanPlayers: remote = self.remotes[player] if remote.voiceId: # send it to other human players: others = [x for x in humanPlayers if x != player] if Debug.sound: logDebug( 'telling other human players that %s has voiceId %s' % (player.name, remote.voiceId)) block.tell(player, others, Message.VoiceId, source=remote.voiceId) block.callback(self.collectVoiceData)
def collectVoiceData(self, requests): """collect voices of other players""" if not self.running: return block = DeferredBlock(self) voiceDataRequests = [] for request in requests: if request.answer == Message.ClientWantsVoiceData: # another human player requests sounds for voiceId voiceId = request.args[0] voiceFor = [ x for x in self.game.players if isinstance(self.remotes[x], User) and self.remotes[x].voiceId == voiceId ][0] voiceFor.voice = Voice(voiceId) if Debug.sound: logDebug('client %s wants voice data %s for %s' % (request.user.name, request.args[0], voiceFor)) voiceDataRequests.append((request.user, voiceFor)) if not voiceFor.voice.oggFiles(): # the server does not have it, ask the client with that # voice block.tell(voiceFor, voiceFor, Message.ServerWantsVoiceData) block.callback(self.sendVoiceData, voiceDataRequests)
def assignVoices(self, dummyResults=None): """now all human players have all voice data needed""" humanPlayers = [ x for x in self.game.players if isinstance(self.remotes[x], User) ] block = DeferredBlock(self) block.tell(None, humanPlayers, Message.AssignVoices) block.callback(self.startHand)
def claimMahJongg(self, msg): """a player claims mah jongg. Check this and if correct, tell all.""" # pylint: disable=R0912 # too many branches if not self.game: return player = msg.player concealedMelds, withDiscard, lastMeld = msg.args if self.game.ruleset.mustDeclareCallingHand: assert player.isCalling, '%s: concmelds:%s withdiscard:%s lastmeld:%s' % ( player, concealedMelds, withDiscard, lastMeld) discardingPlayer = self.game.activePlayer # pylint: disable=E1103 # (pylint ticket 8774) lastMove = self.game.lastMoves(without=[Message.PopupMsg]).next() robbedTheKong = lastMove.message == Message.DeclaredKong if robbedTheKong: player.lastSource = 'k' withDiscard = lastMove.source[0].capitalize() lastMove.player.robTile(withDiscard) lastMeld = Meld(lastMeld) msgArgs = player.showConcealedMelds(concealedMelds, withDiscard) if msgArgs: self.abort(*msgArgs) # pylint: disable=W0142 player.declaredMahJongg(concealedMelds, withDiscard, player.lastTile, lastMeld) if not player.hand.won: msg = m18nE('%1 claiming MahJongg: This is not a winning hand: %2') self.abort(msg, player.name, player.hand.string) return block = DeferredBlock(self) if robbedTheKong: block.tellAll(player, Message.RobbedTheKong, tile=withDiscard) if (player.lastSource == 'd' and self.game.dangerousFor(discardingPlayer, player.lastTile) and discardingPlayer.playedDangerous): player.usedDangerousFrom = discardingPlayer if Debug.dangerousGame: logDebug('%s wins with dangerous tile %s from %s' % \ (player, self.game.lastDiscard, discardingPlayer)) block.tellAll(player, Message.UsedDangerousFrom, source=discardingPlayer.name) block.tellAll(player, Message.MahJongg, source=concealedMelds, lastTile=player.lastTile, lastMeld=list(lastMeld.pairs), withDiscard=withDiscard) block.callback(self.endHand)
def pickTile(self, dummyResults=None, deadEnd=False): """the active player gets a tile from wall. Tell all clients.""" if not self.game: return player = self.game.activePlayer try: tile = player.pickedTile(deadEnd) except WallEmpty: self.endHand() else: tileName = tile.element self.game.lastDiscard = None block = DeferredBlock(self) block.tellPlayer(player, Message.PickedTile, source=tileName, deadEnd=deadEnd) if tileName[0] in 'fy' or self.game.playOpen: block.tellOthers(player, Message.PickedTile, source=tileName, deadEnd=deadEnd) else: block.tellOthers(player, Message.PickedTile, source= 'Xy', deadEnd=deadEnd) block.callback(self.moved)
def clientMadeOriginalCall(self, dummyResults, msg): """first tell everybody about original call and then treat the implicit discard""" msg.player.originalCall = True if Debug.originalCall: logDebug('server.clientMadeOriginalCall: %s' % msg.player) block = DeferredBlock(self) block.tellAll(msg.player, Message.OriginalCall) block.callback(self._askForClaims, msg)
def claimTile(self, player, claim, meldTiles, nextMessage): """a player claims a tile for pung, kong or chow. meldTiles contains the claimed tile, concealed""" if not self.game: return lastDiscard = self.game.lastDiscard claimedTile = lastDiscard.element hasTiles = meldTiles[:] discardingPlayer = self.game.activePlayer hasTiles.remove(claimedTile) meld = Meld(meldTiles) if len(meldTiles) != 4 and meld.meldType not in [PAIR, PUNG, KONG, CHOW]: msg = m18nE('%1 wrongly said %2 for meld %3') + 'x:' + str(meld.meldType) + meld.joined self.abort(msg, player.name, claim.name, str(meld)) return if not player.hasConcealedTiles(hasTiles): msg = m18nE('%1 wrongly said %2: claims to have concealed tiles %3 but only has %4') self.abort(msg, player.name, claim.name, ' '.join(hasTiles), ''.join(player.concealedTileNames)) return # update our internal state before we listen to the clients again self.game.discardedTiles[claimedTile.lower()] -= 1 self.game.activePlayer = player if claimedTile: player.lastTile = claimedTile.lower() player.lastSource = 'd' player.exposeMeld(hasTiles, claimedTile) self.game.lastDiscard = None block = DeferredBlock(self) if (nextMessage != Message.Kong and self.game.dangerousFor(discardingPlayer, lastDiscard) and discardingPlayer.playedDangerous): player.usedDangerousFrom = discardingPlayer if Debug.dangerousGame: logDebug('%s claims dangerous tile %s discarded by %s' % \ (player, lastDiscard, discardingPlayer)) block.tellAll(player, Message.UsedDangerousFrom, source=discardingPlayer.name) block.tellAll(player, nextMessage, source=meldTiles) if claim == Message.Kong: block.callback(self.pickKongReplacement) else: block.callback(self.moved)
def _clientDiscarded3(self, dummyResults, msg, dangerousText, mustPlayDangerous): """client told us he discarded a tile. Continue, check for calling""" block = DeferredBlock(self) player = msg.player if self.game.ruleset.mustDeclareCallingHand and not player.isCalling: if player.hand.callingHands: player.isCalling = True block.tellAll(player, Message.Calling) block.callback(self._clientDiscarded4, msg, dangerousText, mustPlayDangerous)
def _clientDiscarded2(self, dummyResults, msg, dangerousText, mustPlayDangerous, violates): """client told us he discarded a tile. Continue, check for violating original call""" block = DeferredBlock(self) player = msg.player if violates: if Debug.originalCall: tile = Tile(msg.args[0]) logDebug('%s just violated OC with %s' % (player, tile)) player.mayWin = False block.tellAll(player, Message.ViolatesOriginalCall) block.callback(self._clientDiscarded3, msg, dangerousText, mustPlayDangerous)
def joinTable(self, user, tableid): """user joins table""" table = self._lookupTable(tableid) table.addUser(user) block = DeferredBlock(table) block.tell(None, self.srvUsers, Message.TableChanged, source=table.asSimpleList()) if len(table.users) == table.maxSeats(): if Debug.table: logDebug('Table %s: All seats taken, starting' % table) def startTable(dummy): """now all players know about our join""" table.readyForGameStart(table.owner) block.callback(startTable) else: block.callback(False) return True
def pickTile(self, dummyResults=None, deadEnd=False): """the active player gets a tile from wall. Tell all clients.""" if not self.running: return player = self.game.activePlayer try: tile = player.pickedTile(deadEnd) except WallEmpty: self.endHand() else: self.game.lastDiscard = None block = DeferredBlock(self) block.tellPlayer(player, Message.PickedTile, tile=tile, deadEnd=deadEnd) showTile = tile if tile.isBonus or self.game.playOpen else Tile.unknown block.tellOthers(player, Message.PickedTile, tile=showTile, deadEnd=deadEnd) block.callback(self.moved)
def initGame(self): """ask clients if they are ready to start""" game = self.game game.saveStartTime() block = DeferredBlock(self) for player in game.players: block.tellPlayer(player, Message.ReadyForGameStart, tableid=self.tableid, gameid=game.gameid, shouldSave=player.shouldSave, wantedGame=game.wantedGame, playerNames=list( (x.wind, x.name) for x in game.players)) block.callback(self.startGame)
def proposeGameId(self, gameid): """server proposes an id to the clients ands waits for answers""" while True: query = Query('insert into game(id,seed) values(?,?)', (gameid, 'proposed'), mayFail=True, failSilent=True) if not query.failure: break gameid += random.randrange(1, 100) block = DeferredBlock(self) for player in self.game.players: if player.shouldSave and isinstance(self.remotes[player], User): # do not ask robot players, they use the server data base block.tellPlayer(player, Message.ProposeGameId, gameid=gameid) block.callback(self.collectGameIdAnswers, gameid)
def divided(self, dummyResults=None): """the wall is now divided for all clients""" if not self.running: return block = DeferredBlock(self) for clientPlayer in self.game.players: for player in self.game.players: if player == clientPlayer or self.game.playOpen: tiles = player.concealedTiles else: tiles = TileList(Tile.unknown * 13) block.tell(player, clientPlayer, Message.SetConcealedTiles, tiles=TileList(chain(tiles, player.bonusTiles))) block.callback(self.dealt)
def endHand(self, dummyResults=None): """hand is over, show all concealed tiles to all players""" if not self.running: return if self.game.playOpen: self.saveHand() else: block = DeferredBlock(self) for player in self.game.players: # there might be no winner, winner.others() would be wrong if player != self.game.winner: # the winner tiles are already shown in claimMahJongg block.tellOthers(player, Message.ShowConcealedTiles, show=True, tiles=TileList(player.concealedTiles)) block.callback(self.saveHand)
def leaveTable(self, user, tableid, message=None, *args): """user leaves table. If no human user is left on a new table, remove it""" if tableid in self.tables: table = self.tables[tableid] if user in table.users: if len(table.users) == 1 and not table.suspendedAt: # silent: do not tell the user who left the table that he # did self.removeTable(table, 'silent', message, *args) else: table.delUser(user) if self.srvUsers: block = DeferredBlock(table) block.tell(None, self.srvUsers, Message.TableChanged, source=table.asSimpleList()) block.callback(False) return True
def clientDiscarded(self, msg): """client told us he discarded a tile. Check for consistency and tell others.""" if not self.running: return player = msg.player assert player == self.game.activePlayer tile = Tile(msg.args[0]) if tile not in player.concealedTiles: self.abort('player %s discarded %s but does not have it' % (player, tile)) return dangerousText = self.game.dangerousFor(player, tile) mustPlayDangerous = player.mustPlayDangerous() violates = player.violatesOriginalCall(tile) self.game.hasDiscarded(player, tile) block = DeferredBlock(self) block.tellAll(player, Message.Discard, tile=tile) block.callback(self._clientDiscarded2, msg, dangerousText, mustPlayDangerous, violates)
def sendVoiceData(self, requests, voiceDataRequests): """sends voice sounds to other human players""" self.processAnswers(requests) block = DeferredBlock(self) for voiceDataRequester, voiceFor in voiceDataRequests: # this player requested sounds for voiceFor voice = voiceFor.voice content = voice.archiveContent if content: if Debug.sound: logDebug('server got voice data %s for %s from client' % (voiceFor.voice, voiceFor.name)) block.tell(voiceFor, voiceDataRequester, Message.VoiceData, md5sum=voice.md5sum, source=content) elif Debug.sound: logDebug('server got empty voice data %s for %s from client' % (voice, voiceFor.name)) block.callback(self.assignVoices)
def tellOthers(self, player, command, callback=None, **kwargs): """tell something about player to all other players""" block = DeferredBlock(self) block.tellOthers(player, command, **kwargs) block.callback(callback) return block
def assignVoices(self, dummyResults=None): """now all human players have all voice data needed""" humanPlayers = [x for x in self.game.players if isinstance(x.remote, User)] block = DeferredBlock(self) block.tell(None, humanPlayers, Message.AssignVoices) block.callback(self.startHand)
def clientDiscarded(self, msg): """client told us he discarded a tile. Check for consistency and tell others.""" # pylint: disable=R0912 # too many branches player = msg.player game = self.game if not game: return assert player == game.activePlayer tile = msg.args[0] if tile not in player.concealedTileNames: self.abort('player %s discarded %s but does not have it' % (player, tile)) return txt = game.dangerousFor(player, tile) mustPlayDangerous = player.mustPlayDangerous() block = DeferredBlock(self) game.hasDiscarded(player, tile) block.tellAll(player, Message.Discard, tile=tile) if player.violatesOriginalCall(): if Debug.originalCall: logDebug('%s just violated OC with %s' % (player, player.discarded[-1])) player.mayWin = False block.tellAll(player, Message.ViolatedOriginalCall) if game.ruleset.mustDeclareCallingHand and not player.isCalling: if player.hand.callingHands(mustBeAvailable=True): player.isCalling = True block.tellAll(player, Message.Calling) if txt: if mustPlayDangerous and player.lastSource not in 'dZ': if Debug.dangerousGame: logDebug('%s claims no choice. Discarded %s, keeping %s. %s' % \ (player, tile, ''.join(player.concealedTileNames), ' / '.join(txt))) player.claimedNoChoice = True block.tellAll(player, Message.HasNoChoice, tile=player.concealedTileNames) else: player.playedDangerous = True if Debug.dangerousGame: logDebug('%s played dangerous. Discarded %s, keeping %s. %s' % \ (player, tile, ''.join(player.concealedTileNames), ' / '.join(txt))) block.tellAll(player, Message.PlayedDangerous, tile=player.concealedTileNames) if msg.answer == Message.OriginalCall: block.callback(self.clientMadeOriginalCall, msg) else: block.callback(self.askForClaims)
def tellAll(self, player, command, callback=None, **kwargs): """tell something about player to all players""" block = DeferredBlock(self) block.tellAll(player, command, **kwargs) block.callback(callback) return block