def __separateBonusMelds(tileString): """keep them separate. One meld per bonus tile. Others depend on that.""" result = [] if 'f' in tileString or 'y' in tileString: for pair in Pairs(tileString.replace(' ', '').replace('R', '')): if pair[0] in 'fy': result.append(Meld(pair)) tileString = tileString.replace(pair, '', 1) return result, tileString
def __computeDragonWindMelds(tileString): """returns lists with melds containing all (even single) dragons respective winds""" dragonMelds = [] windMelds = [] for split in tileString.split(): if split[0] == 'R': pairs = Pairs(split[1:]) for lst, tiles in ((windMelds, elements.wINDS), (dragonMelds, elements.dRAGONS)): for tile in tiles: count = pairs.count(tile) if count: lst.append(Meld([tile] * count)) elif split[0] in 'dD': dragonMelds.append(Meld(split)) elif split[0] in 'wW': windMelds.append(Meld(split)) return dragonMelds, windMelds
def __init__(self, ruleset, string, computedRules=None, robbedTile=None): """evaluate string using ruleset. rules are to be applied in any case. ruleset can be Hand, Game or Ruleset.""" # silence pylint. This method is time critical, so do not split it into smaller methods # pylint: disable=R0902,R0914,R0912,R0915 if isinstance(ruleset, Hand): self.ruleset = ruleset.ruleset self.player = ruleset.player self.computedRules = ruleset.computedRules elif isinstance(ruleset, Ruleset): self.ruleset = ruleset self.player = None else: self.player = ruleset self.ruleset = self.player.game.ruleset self.string = string self.robbedTile = robbedTile if computedRules is not None and not isinstance(computedRules, list): computedRules = list([computedRules]) self.computedRules = computedRules or [] self.__won = False self.mjStr = '' self.mjRule = None self.ownWind = None self.roundWind = None tileStrings = [] mjStrings = [] haveM = False splits = self.string.split() for part in splits: partId = part[0] if partId in 'Mmx': haveM = True self.ownWind = part[1] self.roundWind = part[2] mjStrings.append(part) self.__won = partId == 'M' elif partId == 'L': if len(part[1:]) > 8: raise Exception('last tile cannot complete a kang:' + self.string) mjStrings.append(part) else: tileStrings.append(part) if not haveM: raise Exception('Hand got string without mMx: %s', self.string) self.mjStr = ' '.join(mjStrings) self.__lastTile = self.__lastSource = self.__announcements = '' self.__lastMeld = 0 self.__lastMelds = [] self.hiddenMelds = [] self.declaredMelds = [] self.melds = [] tileString = ' '.join(tileStrings) self.bonusMelds, tileString = self.__separateBonusMelds(tileString) self.tileNames = Pairs(tileString.replace(' ', '').replace('R', '')) self.tileNames.sort() self.values = ''.join(x[1] for x in self.tileNames) self.suits = set(x[0].lower() for x in self.tileNames) self.lenOffset = self.__computeLenOffset(tileString) self.dragonMelds, self.windMelds = self.__computeDragonWindMelds( tileString) self.__separateMelds(tileString) self.hiddenMelds = sorted(self.hiddenMelds, key=meldKey) self.tileNamesInHand = sum((x.pairs for x in self.hiddenMelds), []) self.sortedMeldsContent = meldsContent(self.melds) if self.bonusMelds: self.sortedMeldsContent += ' ' + meldsContent(self.bonusMelds) self.usedRules = [] self.score = None oldWon = self.won self.__applyRules() if len(self.lastMelds) > 1: self.__applyBestLastMeld() if self.won != oldWon: # if not won after all, this might be a long hand. # So we might even have to unapply meld rules and # bonus points. Instead just recompute all again. # This should only happen with scoring manual games # and with scoringtest - normally kajongg would not # let you declare an invalid mah jongg self.__applyRules()