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, 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 _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 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 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 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 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 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 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 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