def isSanQi(self): """是否三七边""" # 1,2,3 拿出来,剩下的能不能胡 # 7,8,9 拿出来 剩下的能不能胡 handTile = copy.deepcopy( self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) handTile.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) if MTile.getValue(self.winTile) == 7 and self.winTile < 30 and ( self.winTile + 1) in handTile and (self.winTile + 2) in handTile: handTile.remove(self.winTile) handTile.remove(self.winTile + 1) handTile.remove(self.winTile + 2) res, _ = MWin.isHu(handTile) ftlog.debug('weihai_one_result.isSanQi result: ', res) return res elif MTile.getValue(self.winTile) == 3 and self.winTile < 30 and ( self.winTile - 1) in handTile and self.winTile - 2 in handTile: handTile.remove(self.winTile) handTile.remove(self.winTile - 1) handTile.remove(self.winTile - 2) res, _ = MWin.isHu(handTile) ftlog.debug('weihai_one_result.isSanQi result: ', res) return res else: ftlog.debug('weihai_one_result.isSanQi result: False') return False
def isDadiaoche(self, tiles): """ 大吊车:胡牌时自己手上只有一张牌,且胡的是二五八 """ handTile = tiles[MHand.TYPE_HAND] huTile = tiles[MHand.TYPE_HU][0] handTile.extend(tiles[MHand.TYPE_HU]) if len(handTile) == 2 and huTile < MTile.TILE_DONG_FENG and ( MTile.getValue(huTile) == 2 or MTile.getValue(huTile) == 5 or MTile.getValue(huTile) == 8): return True, [handTile] return False, []
def chooseBestDropTile(self, tiles, leftTiles, mostColor): ''' 从若干最小分值的牌中选择一个最合适的 附加权重: 1)自身权重 1、9的本身附加权重为0 2,8的附件权重为1 3,4,5,6,7的附件权重为2 2)剩余牌数权重 剩余牌数的附件权重每张为1 3)花色权重 花色之间的比较,花色较多的一方去加权重为1,花色较少的一方附件权重为0 ''' if len(tiles) == 1: return tiles[0] tiles.sort() values = [0 for _ in tiles] minTile = 0 minValue = 0 for index in range(len(tiles)): tile = tiles[index] if (MTile.getValue(tile) == 1) or (MTile.getValue(tile) == 9): values[index] += 0 elif (MTile.getValue(tile) == 2) or (MTile.getValue(tile) == 8): values[index] += 1 else: values[index] += 2 tileCount = 0 for _t in leftTiles: if _t == tile: tileCount += 1 values[index] += tileCount if MTile.getColor(tile) == mostColor: values[index] += 1 if (minTile == 0) or (minValue > values[index]): minTile = tile minValue = values[index] ftlog.debug('chooseBestDropTile tiles:', tiles, ' leftTiles:', leftTiles, ' mostColor:', mostColor, ' values:', values, ' minTile:', minTile, ' minValue:', minValue) return minTile
def isSanQi(self, winTile=None): for wn in self.winNodes: if wn['winTile'] == self.winTile: patterns = wn['pattern'] ftlog.debug('MJixiOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns) for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue if (self.winTile in p) and (p.index(self.winTile) == 0) and MTile.getValue( self.winTile) == 7: return True if (self.winTile in p) and (p.index(self.winTile) == 2) and MTile.getValue( self.winTile) == 3: return True # 宝牌情况处理 if self.isMagicTile(): for wn in self.winNodes: winTile = wn['winTile'] patterns = wn['pattern'] for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue if (winTile in p) and (p.index(winTile) == 0) and MTile.getValue(winTile) == 7: return True if (winTile in p) and (p.index(winTile) == 2) and MTile.getValue(winTile) == 3: return True return False
def isZhangYiSe(self, seatId): tiles = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) if len(tiles) % 2 > 0: tiles.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) for tile in tiles: if (tile >= MTile.TILE_DONG_FENG) or (MTile.getValue(tile) % 3 != 2): return False return True
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): ftlog.debug(self.TAG, '.isHu tiles:', tiles, ' tile:', tile, ' isTing:', isTing, ' getTileType:', getTileType, ' magicTiles:', magicTiles, ' tingNodes:', tingNodes, ' winSeatId:', winSeatId) # 平度麻将即可以听也可以不听,听牌后,校验tingNodes即可,无其他限制条件 if isTing: #[{'winTile': 16, 'winTileCount': 0, 'pattern': [[16, 17, 18], [12, 12]]}, {'winTile': 19, 'winTileCount': 0, 'pattern': [[17, 18, 19], [12, 12]]}] for tingNode in tingNodes: if tingNode['winTile'] == tile: pattern = tingNode['pattern'] return True, pattern # 检查2,5,8将 # 平度麻将允许胡七对 resultQiDui, patternQiDui = MWin.isQiDui(tiles[MHand.TYPE_HAND]) if resultQiDui: for pattern in patternQiDui: tile = pattern[0] if tile > MTile.TILE_NINE_TIAO: continue if MTile.getValue(pattern[0]) % 3 == 2: return True, patternQiDui return False, [] # 挑出2,5,8将,看剩下的牌是否能胡牌 jiangPatterns = [[MTile.TILE_TWO_WAN, MTile.TILE_TWO_WAN], [MTile.TILE_FIVE_WAN, MTile.TILE_FIVE_WAN], [MTile.TILE_EIGHT_WAN, MTile.TILE_EIGHT_WAN], [MTile.TILE_TWO_TONG, MTile.TILE_TWO_TONG], [MTile.TILE_FIVE_TONG, MTile.TILE_FIVE_TONG], [MTile.TILE_EIGHT_TONG, MTile.TILE_EIGHT_TONG], [MTile.TILE_TWO_TIAO, MTile.TILE_TWO_TIAO], [MTile.TILE_FIVE_TIAO, MTile.TILE_FIVE_TIAO], [MTile.TILE_EIGHT_TIAO, MTile.TILE_EIGHT_TIAO]] for jiangPat in jiangPatterns: result, pattern = MWin.isHuWishSpecialJiang( tiles[MHand.TYPE_HAND], jiangPat) if result: return result, pattern return False, []
def isDuanYao(self, tableConfig): ''' 判断手牌是否为断幺 ''' # 房间配置为0,则没有全幺九 if not tableConfig.get(MFTDefine.DUANYAOJIU_DOUBLE, 0): ftlog.debug('MSiChuanTilePattern.isDuanYao False because roomConfig') return False tiles = MHand.copyAllTilesToListButHu(self.playerAllTiles) ftlog.debug('MSiChuanTilePattern.isDuanYao tiles:', tiles) for tile in tiles: tileValue = MTile.getValue(tile) if tileValue == 1 or tileValue == 9: ftlog.debug('MSiChuanTilePattern.isDuanYao : False') return False ftlog.debug('MSiChuanTilePattern.isDuanYao: True') return True
def isDadiaoche(self): """ 大吊车:胡牌时自己手上只有一张牌,且胡的是二五八 """ handTile = copy.deepcopy( self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) if len(handTile) % 3 != 2: handTile.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) huTile = self.playerAllTiles[self.winSeatId][MHand.TYPE_HU][0] ftlog.debug('MYantaiOneResult.isDadiaoche handTile:', handTile, ' huTile:', huTile) if (len(handTile) == 2) and (huTile < MTile.TILE_DONG_FENG) and ( MTile.getValue(huTile) % 3 == 2): ftlog.debug('MYantaiOneResult.isDadiaoche result: True') return True ftlog.debug('MYantaiOneResult.isDadiaoche result: False') return False
def isDadiaoche(self): """ 大吊车:胡牌时自己手上只有一张牌,且胡的是二五八 """ handTile = copy.deepcopy(self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) if len(handTile) % 3 != 2: handTile.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) huTile = self.playerAllTiles[self.winSeatId][MHand.TYPE_HU][0] ftlog.debug('MYantaiOneResult.isDadiaoche handTile:', handTile , ' huTile:', huTile) if (len(handTile) == 2): if self.tableTileMgr.tableConfig.get(MTDefine.ONLY_JIANG_258, 0) == 1: if (huTile < MTile.TILE_DONG_FENG) and (MTile.getValue(huTile) % 3 == 2): return True else: return False else: return True ftlog.debug('MYantaiOneResult.isDadiaoche result: False') return False
def isBian(self): """是否夹牌""" if not self.isWinTile(): return False for wn in self.winNodes: if wn['winTile'] == self.winTile: patterns = wn['pattern'] ftlog.debug('MHaerbinOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns) for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue # 三七边 if (self.winTile in p) \ and (p.index(self.winTile) == 0) \ and (MTile.getValue(p[1]) == 8) \ and (MTile.getValue(p[2]) == 9): ftlog.debug('MHaerbinOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 7 bian') return True if (self.winTile in p) \ and (p.index(self.winTile) == 2) \ and (MTile.getValue(p[0]) == 1) \ and (MTile.getValue(p[1]) == 2): ftlog.debug('MHaerbinOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 3 bian') return True # 宝牌情况处理 if self.isMagicTile(): for wn in self.winNodes: winTile = wn['winTile'] patterns = wn['pattern'] for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue # 三七边 if (winTile in p) \ and (p.index(winTile) == 0) \ and (MTile.getValue(p[1]) == 8) \ and (MTile.getValue(p[2]) == 9): ftlog.debug('MHaerbinOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 7 bian') return True if (winTile in p) \ and (p.index(winTile) == 2) \ and (MTile.getValue(p[0]) == 1) \ and (MTile.getValue(p[1]) == 2): ftlog.debug('MHaerbinOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 3 bian') return True return False
def hasExtendMao(cls, tiles, alreadyHave = 0): extendMaos = [] if alreadyHave & MTDefine.MAO_DAN_DNXBZFB: es = [] for tile in tiles: if MTile.isFeng(tile) or MTile.isArrow(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_DNXBZFB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_DNXBZFB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_DNXB: es = [] for tile in tiles: if MTile.isFeng(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_DNXB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_DNXB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_ZFB: es = [] for tile in tiles: if MTile.isArrow(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_ZFB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_ZFB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_YAO: es = [] for tile in tiles: if MTile.getValue(tile) == 1: es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_YAO faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_YAO_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_JIU: es = [] for tile in tiles: if MTile.getValue(tile) == 9: es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_JIU faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_JIU_NAME extendMaos.append(faNode) return extendMaos
def isSanQi(self, winTile=None): if winTile == None: winTile = self.winTile if MTile.getValue(winTile) == 3 or MTile.getValue(winTile) == 7: return True return False
def checkMao(cls, pattern, maoType, maoDanSetting): ftlog.debug('MMao.checkMao pattern:', pattern , ' maoType:', maoType , ' maoDanSetting:', maoDanSetting) values = [] if maoType & MTDefine.MAO_DAN_DNXBZFB: #乱锚 if not maoDanSetting & MTDefine.MAO_DAN_DNXBZFB: return False for tile in pattern: if MTile.isArrow(tile) or MTile.isFeng(tile): values.append(tile) #取消对相同牌的检查 else: return False elif maoType & MTDefine.MAO_DAN_DNXB: if not maoDanSetting & MTDefine.MAO_DAN_DNXB: return False for tile in pattern: if MTile.isFeng(tile): if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_ZFB: if not maoDanSetting & MTDefine.MAO_DAN_ZFB: return False for tile in pattern: if MTile.isArrow(tile): if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_YAO: if not maoDanSetting & MTDefine.MAO_DAN_YAO: return False for tile in pattern: if MTile.getValue(tile) == 1: if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_JIU: if not maoDanSetting & MTDefine.MAO_DAN_JIU: return False for tile in pattern: if MTile.getValue(tile) == 9: if tile not in values: values.append(tile) continue else: return False ftlog.debug('MMao.checkMao pattern:', pattern , ' maoType:', maoType) return len(values) >= 3
def isBu(cls, tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB): """判断某个花色是否是三朴,缺的牌从癞子中获取,如果没有癞子牌了,也形不成三朴,和牌失败""" if 0 == cls.getCardNumByType(tileArr, tileType): # 这个花色没有牌 return True, hasJiang #ftlog.debug('check card:', MTile.traverseTile(tileType)) for tileIndex in MTile.traverseTile(tileType): if tileArr[tileIndex] == 0: continue if tileArr[tileIndex] >= 3: # 刻,没有占用癞子 tileArr[tileIndex] -= 3 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append([tileIndex, tileIndex, tileIndex]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 3 if (tileArr[tileIndex] == 2) and (len(magicArr) >= 1): # 对子,尝试加一张癞子组成刻 tileArr[tileIndex] -= 2 mTile = magicArr.pop(-1) # ftlog.debug('[11M]magicArr pop:', mTile, ' after pop:', magicArr) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append([tileIndex, tileIndex, mTile]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 2 magicArr.append(mTile) # ftlog.debug('[11M]magicArr push:', mTile, ' after push:', magicArr) if (tileArr[tileIndex] == 1) and (len(magicArr) >= 2): # 单张,尝试加两张癞子组成刻 tileArr[tileIndex] -= 1 mTile1 = magicArr.pop(-1) mTile2 = magicArr.pop(-1) # ftlog.debug('[1MM] magicArr pop1:', mTile1, ' pop2:', mTile2, ' after pop:', magicArr) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append([tileIndex, mTile1, mTile2]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 1 magicArr.append(mTile1) magicArr.append(mTile2) # ftlog.debug('[1MM] magicArr push1:', mTile1, ' push2:', mTile2, ' after push:', magicArr) if not hasJiang and \ tileArr[tileIndex] > 0 and \ (tileArr[tileIndex] + len(magicArr) >= 2): tileArr[tileIndex] -= 1 isMagicJiang = False jiangTile = tileIndex if tileArr[tileIndex] > 0: tileArr[tileIndex] -= 1 else: isMagicJiang = True jiangTile = magicArr.pop(-1) # ftlog.debug('[1M] magicArr pop:', jiangTile, ' after pop:', magicArr) oldJiang = hasJiang resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, True, allowZFB) if resultTmp: resultArr.append([tileIndex, jiangTile]) hasJiang = True return True, hasJiang else: # 还原将牌标记 hasJiang = oldJiang # 还原手牌 tileArr[tileIndex] += 1 if isMagicJiang: magicArr.append(jiangTile) # ftlog.debug('[1M] magicArr append:', jiangTile, ' after append:', magicArr) else: tileArr[tileIndex] += 1 #是否允许中发白作为顺牌,暂时没有考虑赖子的情况,后续可以修改添加 if not allowZFB: if tileIndex >= MTile.TILE_DONG_FENG: # 风箭牌不能组成顺 return False, hasJiang else: if tileIndex == MTile.TILE_HONG_ZHONG: if tileArr[tileIndex] > 0 and tileArr[ tileIndex + 1] > 0 and tileArr[tileIndex + 2] > 0: pattern = [tileIndex, tileIndex + 1, tileIndex + 2] tileArr[tileIndex] -= 1 tileArr[tileIndex + 1] -= 1 tileArr[tileIndex + 2] -= 1 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append(pattern) return True, hasJiang elif tileIndex >= MTile.TILE_DONG_FENG: return False, hasJiang # 提取顺牌组合 if tileArr[tileIndex] > 0 and tileType != MTile.TILE_FENG: # 测试顺子 0 1 2 if MTile.getValue(tileIndex) <= 7: tile0 = tileIndex needMagic = 0 is1Magic = False is2Magic = False if tileArr[tileIndex + 1] == 0: needMagic += 1 is1Magic = True if tileArr[tileIndex + 2] == 0: needMagic += 1 is2Magic = True if needMagic <= len(magicArr): pattern = [tile0, None, None] tileArr[tileIndex] -= 1 if is1Magic: pattern[1] = (magicArr.pop(-1)) else: pattern[1] = (tileIndex + 1) tileArr[tileIndex + 1] -= 1 if is2Magic: pattern[2] = (magicArr.pop(-1)) else: pattern[2] = (tileIndex + 2) tileArr[tileIndex + 2] -= 1 # if is1Magic and is2Magic: # ftlog.debug('[1MM] magicArr pop1:', pattern[1], ' pop2:', pattern[2], ' after pop:', magicArr) # elif is1Magic: # ftlog.debug('[1M3] magicArr pop1:', pattern[1], ' after pop:', magicArr) # elif is2Magic: # ftlog.debug('[12M] magicArr pop2:', pattern[2], ' after pop:', magicArr) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append(pattern) return True, hasJiang # 还原手牌 tileArr[tileIndex] += 1 if is1Magic: magicArr.append(pattern[1]) else: tileArr[tileIndex + 1] += 1 if is2Magic: magicArr.append(pattern[2]) else: tileArr[tileIndex + 2] += 1 # if is1Magic and is2Magic: # ftlog.debug('[1MM] magicArr append1:', pattern[1], ' append2:', pattern[2], ' after append:', magicArr) # elif is1Magic: # ftlog.debug('[1M3] magicArr append1:', pattern[1], ' after append:', magicArr) # elif is2Magic: # ftlog.debug('[12M] magicArr append2:', pattern[2], ' after append:', magicArr) # 测试顺子 -1 0 1 if MTile.getValue(tileIndex) <= 8 and MTile.getValue( tileIndex) >= 2: tile1 = tileIndex needMagic = 0 is0Magic = False is2Magic = False if tileArr[tileIndex - 1] == 0: needMagic += 1 is0Magic = True if tileArr[tileIndex + 1] == 0: needMagic += 1 is2Magic = True if needMagic <= len(magicArr): pattern = [None, tile1, None] tileArr[tileIndex] -= 1 if is0Magic: pattern[0] = (magicArr.pop(-1)) else: pattern[0] = (tileIndex - 1) tileArr[tileIndex - 1] -= 1 if is2Magic: pattern[2] = (magicArr.pop(-1)) else: #猜测有问题,导致pattern 长度为4 包含None #pattern.append(tileIndex + 1) pattern[2] = (tileIndex + 1) tileArr[tileIndex + 1] -= 1 # if is0Magic and is2Magic: # ftlog.debug('[M1M] magicArr pop0:', pattern[0], ' pop2:', pattern[2], ' after pop:', magicArr) # elif is0Magic: # ftlog.debug('[M23] magicArr pop1:', pattern[0], ' after pop:', magicArr) # elif is2Magic: # ftlog.debug('[12M] magicArr pop2:', pattern[2], ' after pop:', magicArr) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append(pattern) return True, hasJiang # 还原手牌 tileArr[tileIndex] += 1 if is0Magic: magicArr.append(pattern[0]) else: tileArr[tileIndex - 1] += 1 if is2Magic: magicArr.append(pattern[2]) else: tileArr[tileIndex + 1] += 1 # if is0Magic and is2Magic: # ftlog.debug('[M1M] magicArr append0:', pattern[0], ' append2:', pattern[2], ' after append:', magicArr) # elif is0Magic: # ftlog.debug('[M23] magicArr append0:', pattern[0], ' after append:', magicArr) # elif is2Magic: # ftlog.debug('[12M] magicArr append2:', pattern[2], ' after append:', magicArr) # 测试顺子 -2 -1 0 if MTile.getValue(tileIndex) >= 3: tile2 = tileIndex needMagic = 0 is0Magic = False is1Magic = False if tileArr[tileIndex - 2] == 0: needMagic += 1 is0Magic = True if tileArr[tileIndex - 1] == 0: needMagic += 1 is1Magic = True if needMagic <= len(magicArr): pattern = [None, None, tile2] tileArr[tileIndex] -= 1 if is0Magic: pattern[0] = (magicArr.pop(-1)) else: pattern[0] = (tileIndex - 2) tileArr[tileIndex - 2] -= 1 if is1Magic: pattern[1] = (magicArr.pop(-1)) else: pattern[1] = (tileIndex - 1) tileArr[tileIndex - 1] -= 1 # if is0Magic and is1Magic: # ftlog.debug('[MM3] magicArr pop0:', pattern[0], ' pop1:', pattern[1], ' after pop:', magicArr) # elif is0Magic: # ftlog.debug('[M23] magicArr pop0:', pattern[0], ' after pop:', magicArr) # elif is1Magic: # ftlog.debug('[1M3] magicArr pop1:', pattern[1], ' after pop:', magicArr) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang, allowZFB) if resultTmp: resultArr.append(pattern) return True, hasJiang # 还原手牌 tileArr[tileIndex] += 1 if is0Magic: magicArr.append(pattern[0]) else: tileArr[tileIndex - 2] += 1 if is1Magic: magicArr.append(pattern[1]) else: tileArr[tileIndex - 1] += 1 # if is0Magic and is1Magic: # ftlog.debug('[MM3] magicArr append0:', pattern[0], ' append1:', pattern[1], ' after append:', magicArr) # elif is0Magic: # ftlog.debug('[M23] magicArr append0:', pattern[0], ' after append:', magicArr) # elif is1Magic: # ftlog.debug('[1M3] magicArr append1:', pattern[1], ' after append:', magicArr) # 无和牌可能 return False, hasJiang
def hasChi(self, tiles, tile): """是否有吃牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待吃的牌 """ if tile >= MTile.TILE_DONG_FENG: return [] #是否允许会牌参与,如果不允许,删除会牌 tilesForChi = copy.deepcopy(tiles[MHand.TYPE_HAND]) if not self.tableTileMgr.allowMagicChiPengGang(): magicTile = self.tableTileMgr.getMagicTile() while magicTile in tilesForChi: tilesForChi.remove(magicTile) chiSolutions = MChi.hasChi(tilesForChi, tile) magicTiles = self.tableTileMgr.getMagicTiles(False) if len(magicTiles) == 0: return chiSolutions if not self.tableTileMgr.canUseMagicTile(MTableState.TABLE_STATE_CHI): return chiSolutions magicTile = magicTiles[0] tileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND]) magicCount = tileArr[magicTile] tileArr[magicTile] = 0 ftlog.debug('MChiRule.hasChi tile:', tile, ' magicCount:', magicCount) if magicCount == 0 or (tileArr[tile] == 0): return chiSolutions if MTile.getValue(tile) <= 7: # +1[-] +2[+] ==> [tile, magic, tile+2] if tileArr[tile + 1] == 0 and tileArr[tile + 2] > 0: chiSolutions.append([tile, magicTile, tile + 2]) # +1[+] +2[-] ==> [tile, tile + 1, magicTile] if tileArr[tile + 1] > 0 and tileArr[tile + 2] == 0: chiSolutions.append([tile, tile + 1, magicTile]) if (tileArr[tile + 1] + tileArr[tile + 2]) == 0 and magicCount >= 2: chiSolutions.append([tile, magicTile, magicTile]) if MTile.getValue(tile) >= 3: # -2[+] -1[-] ==> [tile - 2, magicTile, tile] if tileArr[tile - 2] > 0 and tileArr[tile - 1] == 0: chiSolutions.append([tile - 2, magicTile, tile]) # -2[0] -1[+] ==> [magicTile, tile - 1, tile] if tileArr[tile - 2] == 0 and tileArr[tile - 1] > 0: chiSolutions.append([magicTile, tile - 1, tile]) if (tileArr[tile - 2] + tileArr[tile - 1]) == 0 and magicCount >= 2: chiSolutions.append([magicTile, magicTile, tile]) if MTile.getValue(tile) >= 2 and MTile.getValue(tile) <= 8: # -1[-] 1[+] ==> magicTile, tile, tile + 1 if tileArr[tile - 1] == 0 and tileArr[tile + 1] > 0: chiSolutions.append([magicTile, tile, tile + 1]) # -1[+] 1[-] ==> [tile - 1, tile, magicTile] if tileArr[tile - 1] > 0 and tileArr[tile + 1] == 0: chiSolutions.append([tile - 1, tile, magicTile]) if (tileArr[tile + 1] + tileArr[tile - 1]) == 0 and magicCount >= 2: chiSolutions.append([magicTile, tile, magicTile]) return chiSolutions
def isTeDaJia(self, winPattern, tingNodes, tiles, currWintile, curSeatId): winCount = 0 isJiaCount = 0 bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) for wn in tingNodes: winTile = wn['winTile'] winCount = winCount + 1 patterns = wn['pattern'] ftlog.debug('MWinRuleJixi.isTaDaJia winTile:', winTile, ' winPatterns:', patterns) for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue # 夹牌 if (wn['winTile'] in p) and len(p) == 3 and p[0] != p[1]: if (p[1] == winTile) or (bianMulti and (MTile.getValue(winTile) == 3 or MTile.getValue(winTile) == 7)): isJiaCount = isJiaCount + 1 #只能是夹牌 并且不能作为他用 if winCount > 1 or isJiaCount <= 0: ftlog.debug('MWinRuleJixi.isTaDaJia winTile:', winTile, 'winCount:', winCount, 'isJiaCount:', isJiaCount) return False # 他人的碰牌 isInOtherPeng = False for (seatId, playerTiles) in self.allPlayerTiles.items(): if seatId != curSeatId: playerPengTiles = playerTiles[MHand.TYPE_PENG] for pattern in playerPengTiles: if pattern[0] == currWintile: isInOtherPeng = True break isInSelfKe = False playerPengTiles = tiles[MHand.TYPE_PENG] for pattern in playerPengTiles: if pattern[0] == currWintile: isInSelfKe = True break #自己的手牌 if not isInSelfKe: playerHandTiles = tiles[MHand.TYPE_HAND] winTileInHandCount = 0 for tile in playerHandTiles: if tile == currWintile: winTileInHandCount = winTileInHandCount + 1 if winTileInHandCount == 3: isInSelfKe = True break if not (isInSelfKe or isInOtherPeng): ftlog.debug('MWinRuleJixi.isTaDaJia winTile:', currWintile, 'isInSelfKe:', isInSelfKe, 'isInOtherPeng:', isInOtherPeng) return False return True
def hasMao(cls, tiles, maoDanSetting, alreadyHave = 0): ftlog.debug('MMao.hasMao tiles:', tiles , ' maoDanSetting:', maoDanSetting , ' alreadyHave:', alreadyHave) maos = [] if (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB) and (not (alreadyHave & MTDefine.MAO_DAN_DNXBZFB)): pattern = [] values = [] for tile in tiles: if MTile.isFeng(tile) or MTile.isArrow(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: luanMao = {} luanMao['type'] = MTDefine.MAO_DAN_DNXBZFB luanMao['pattern'] = values luanMao['name'] = MTDefine.MAO_DAN_DNXBZFB_NAME maos.append(luanMao) if (maoDanSetting & MTDefine.MAO_DAN_DNXB) and \ (not (alreadyHave & MTDefine.MAO_DAN_DNXB) and \ (not (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB))): pattern = [] values = [] for tile in tiles: if MTile.isFeng(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: fengMao = {} fengMao['type'] = MTDefine.MAO_DAN_DNXB fengMao['pattern'] = values fengMao['name'] = MTDefine.MAO_DAN_DNXB_NAME maos.append(fengMao) if (maoDanSetting & MTDefine.MAO_DAN_ZFB) and \ (not (alreadyHave & MTDefine.MAO_DAN_ZFB)) and \ (not (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB)): pattern = [] values = [] for tile in tiles: if MTile.isArrow(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: arrowMao = {} arrowMao['type'] = MTDefine.MAO_DAN_ZFB arrowMao['pattern'] = values arrowMao['name'] = MTDefine.MAO_DAN_ZFB_NAME maos.append(arrowMao) if (maoDanSetting & MTDefine.MAO_DAN_YAO) and (not (alreadyHave & MTDefine.MAO_DAN_YAO)): pattern = [] values = [] for tile in tiles: if MTile.getValue(tile) == 1: pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: yaoMao = {} yaoMao['type'] = MTDefine.MAO_DAN_YAO yaoMao['pattern'] = values yaoMao['name'] = MTDefine.MAO_DAN_YAO_NAME maos.append(yaoMao) if (maoDanSetting & MTDefine.MAO_DAN_JIU) and (not (alreadyHave & MTDefine.MAO_DAN_JIU)): pattern = [] values = [] for tile in tiles: if MTile.getValue(tile) == 9: pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: jiuMao = {} jiuMao['type'] = MTDefine.MAO_DAN_JIU jiuMao['pattern'] = values jiuMao['name'] = MTDefine.MAO_DAN_JIU_NAME maos.append(jiuMao) ftlog.debug('MMao.hasMao tiles:', tiles , ' maoDanSetting:', maoDanSetting , ' maos:', maos) return maos
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): ftlog.debug(self.TAG, '.isHu tiles:', tiles, ' tile:', tile, ' isTing:', isTing, ' getTileType:', getTileType, ' magicTiles:', magicTiles, ' tingNodes:', tingNodes, ' winSeatId:', winSeatId) # 平度麻将即可以听也可以不听,听牌后,校验tingNodes即可,无其他限制条件 if isTing: #[{'winTile': 16, 'winTileCount': 0, 'pattern': [[16, 17, 18], [12, 12]]}, {'winTile': 19, 'winTileCount': 0, 'pattern': [[17, 18, 19], [12, 12]]}] for tingNode in tingNodes: if tingNode['winTile'] == tile: pattern = tingNode['pattern'] return True, pattern # 烟台麻将允许胡七对 resultQiDui, patternQiDui = MWin.isQiDui(tiles[MHand.TYPE_HAND]) if resultQiDui: if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug('MWinRuleYantai.isHu checkQiDui with 258') for pattern in patternQiDui: tile = pattern[0] if tile > MTile.TILE_NINE_TIAO: continue if MTile.getValue(pattern[0]) % 3 == 2: return True, patternQiDui return False, [] return True, patternQiDui # 烟台麻将允许胡十三幺 self.tilePatternChecker.setPlayerAllTiles(tiles) if self.tilePatternChecker.isShisanyao(): if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug( 'MWinRuleYantai.isHu isShisanyao with 258, return False') return False, [] return True, tiles[MHand.TYPE_HAND] # 烟台麻将允许胡风一色 allTiles = MHand.copyAllTilesToList(tiles) allArr = MTile.changeTilesToValueArr(allTiles) colorCount = MTile.getColorCount(allArr) resultFeng, patternFeng = MWin.isLuanFengyise(tiles[MHand.TYPE_HAND], colorCount) if resultFeng: if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug( 'MWinRuleYantai.isHu isLuanFengyise with 258, return False' ) return False, [] return True, patternFeng # 挑出2,5,8将,看剩下的牌是否能胡牌 if self.tableConfig[MTDefine.ONLY_JIANG_258]: jiangPatterns = [[MTile.TILE_TWO_WAN, MTile.TILE_TWO_WAN], [MTile.TILE_FIVE_WAN, MTile.TILE_FIVE_WAN], [MTile.TILE_EIGHT_WAN, MTile.TILE_EIGHT_WAN], [MTile.TILE_TWO_TONG, MTile.TILE_TWO_TONG], [MTile.TILE_FIVE_TONG, MTile.TILE_FIVE_TONG], [MTile.TILE_EIGHT_TONG, MTile.TILE_EIGHT_TONG], [MTile.TILE_TWO_TIAO, MTile.TILE_TWO_TIAO], [MTile.TILE_FIVE_TIAO, MTile.TILE_FIVE_TIAO], [MTile.TILE_EIGHT_TIAO, MTile.TILE_EIGHT_TIAO]] ftlog.debug('MWinRuleYantai.isHu with 258') for jiangPat in jiangPatterns: result, pattern = MWin.isHuWishSpecialJiang( tiles[MHand.TYPE_HAND], jiangPat) if result: return result, pattern return False, [] else: result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND]) return result, pattern
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if handCount < 5: return False, [] isTing, tingResults = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('MTingMudanjiangRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) # [{'dropTile': 11, 'winNodes': [{'winTile': 1, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [1, 2, 3]]}, {'winTile': 2, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [3, 4, 5], [2, 2]]}, {'winTile': 4, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [2, 3, 4]]}, {'winTile': 5, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [5, 5], [2, 3, 4]]}, {'winTile': 7, 'winTileCount': 1, 'pattern': [[6, 6], [5, 6, 7], [5, 6, 7], [2, 3, 4]]}, {'winTile': 8, 'winTileCount': 1, 'pattern': [[6, 7, 8], [6, 6, 6], [5, 5], [2, 3, 4]]}]}] if not isTing: return False, [] chiCount = len(tiles[MHand.TYPE_CHI]) pengCount = len(tiles[MHand.TYPE_PENG]) gangCount = len(tiles[MHand.TYPE_GANG]) mingGangCount = 0 anGangCount = 0 #计算明杠个数,因为暗杠不算开门 if gangCount != 0: mingGangCount, anGangCount = MTile.calcGangCount( tiles[MHand.TYPE_GANG]) ftlog.debug('MTingMudanjiangRule.gang tiles:', tiles[MHand.TYPE_GANG], ' mingGangCount=', mingGangCount, ' anGangCount=', anGangCount) #daKouConfig = self.getTableConfig(MTDefine.DA_KOU, 0) daKouConfig = 1 ftlog.debug('.canTing daKouConfig:', daKouConfig) if daKouConfig != 1: if (chiCount + pengCount + mingGangCount) == 0: return False, [] # 检查刻,刻的来源,碰牌/明杠牌/手牌 keCount = pengCount + mingGangCount + anGangCount # 必须有顺牌 shunCount = chiCount newTingResults = [] for tingResult in tingResults: newWinNodes = [] winNodes = tingResult['winNodes'] for winNode in winNodes: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tingResult['dropTile']) newTiles[MHand.TYPE_HAND].append(winNode['winTile']) tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToList(newTiles)) # ftlog.debug( 'MTingMudanjiangRule.canTing tileArr:', tileArr ) # 清一色不可以听牌/和牌 if self.getTableConfig(MTDefine.YISE_CAN_TING, 0) != 1: newTileArr = copy.deepcopy(tileArr) newTileArr[MTile.TILE_HONG_ZHONG] = 0 colorCount = MTile.getColorCount(newTileArr) if colorCount == 1: # 清一色不能和牌 ftlog.debug('MTingMudanjiangRule.canTing colorCount:', colorCount, ' can not win, continue....') continue # 检查牌中的幺/九 # 1软 听牌可以没有19,只要胡牌带19就可以 # 2硬 听牌时就要有19 RuanYaoJiuConfig = self.getTableConfig(MTDefine.RUAN_YAO_JIU, 1) if RuanYaoJiuConfig == 0: #硬幺九 :听牌必须有19 #tileArr 减去 winNode['winTile'] 后判断 tileArr[winNode['winTile']] -= 1 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingMudanjiangRule.canTing : YING yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) <= 0: continue else: #软幺九 :只要胡牌有19就行 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingMudanjiangRule.canTing : RUAN yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) == 0: continue patterns = winNode['pattern'] winTile = winNode['winTile'] #夹起步(顺牌只能和夹和3,7) 除单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: hasJia = False bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) if bianMulti: if MTile.getValue( winTile ) == 3 and winTile < MTile.TILE_DONG_FENG: newTilesBian = copy.deepcopy(newTiles) # 1,2,3 if ((winTile - 2) in newTilesBian[MHand.TYPE_HAND]) and ( (winTile - 1) in newTilesBian[MHand.TYPE_HAND]): newTilesBian[MHand.TYPE_HAND].remove(winTile - 2) newTilesBian[MHand.TYPE_HAND].remove(winTile - 1) newTilesBian[MHand.TYPE_HAND].remove(winTile) newTilesBian[MHand.TYPE_CHI].append( [winTile - 2, winTile - 1, winTile]) rBian, rPattern = self.winRuleMgr.isHu( newTilesBian, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rBian: ftlog.debug( 'MTingMudanjiangRule isJia 3 Bian : ', newTilesBian, ' patterns:', rPattern) hasJia = True if not hasJia and MTile.getValue( winTile ) == 7 and winTile < MTile.TILE_DONG_FENG: newTiles37 = copy.deepcopy(newTiles) # 7,8,9 if ((winTile + 1) in newTiles37[MHand.TYPE_HAND]) and ( (winTile + 2) in newTiles37[MHand.TYPE_HAND]): newTiles37[MHand.TYPE_HAND].remove(winTile + 1) newTiles37[MHand.TYPE_HAND].remove(winTile + 2) newTiles37[MHand.TYPE_HAND].remove(winTile) newTiles37[MHand.TYPE_CHI].append( [winTile, winTile + 1, winTile + 2]) rQi, qiPattern = self.winRuleMgr.isHu( newTiles37, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rQi: ftlog.debug( 'MTingMudanjiangRule isJia 7 Bian : ', newTiles37, ' pattern:', qiPattern) hasJia = True danDiaoJia = self.tableConfig.get(MTDefine.DAN_DIAO_JIA, 1) if not hasJia and danDiaoJia: newTilesDan = copy.deepcopy(newTiles) ftlog.debug( 'MTingMudanjiangRule isJia in >> danDiao : ', newTilesDan) # 5,5 if winTile in newTilesDan[MHand.TYPE_HAND]: rDan, danPattern = MWin.isHuWishSpecialJiang( newTilesDan[MHand.TYPE_HAND], [winTile, winTile], magicTiles) if rDan: ftlog.debug( 'MTingMudanjiangRule isJia danDiao : ', newTilesDan, ' winTile:', winTile, ' pattern:', danPattern) hasJia = True if not hasJia: newTilesJia = copy.deepcopy(newTiles) # 2,3,4 if ((winTile - 1) in newTilesJia[MHand.TYPE_HAND]) and ( (winTile + 1) in newTilesJia[MHand.TYPE_HAND]): newTilesJia[MHand.TYPE_HAND].remove(winTile + 1) newTilesJia[MHand.TYPE_HAND].remove(winTile - 1) newTilesJia[MHand.TYPE_HAND].remove(winTile) newTilesJia[MHand.TYPE_CHI].append( [winTile - 1, winTile, winTile + 1]) rJia, jiaPattern = self.winRuleMgr.isHu( newTilesJia, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rJia: ftlog.debug('MTingMudanjiangRule isJia : ', newTilesJia, ' pattern:', jiaPattern) hasJia = True # winNodes中的patterns只是胡牌的一种方式,不是全部的胡牌解,判断夹牌,只使用patterns的组合会有遗漏的情况 # 合理的做法是先把夹拿出来,在判断剩下的牌是否能胡。 if not hasJia: ftlog.debug( 'MTingMudanjiangRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) checkShunCount = shunCount + self.getShunCount(patterns) ftlog.debug('MTingMudanjiangRule.canTing checkKeCount:', checkKeCount, ' checkShunCount:', checkShunCount) if checkKeCount and checkShunCount: newWinNodes.append(winNode) if len(newWinNodes) > 0: newTingResult = {} newTingResult['dropTile'] = tingResult['dropTile'] newTingResult['winNodes'] = newWinNodes newTingResults.append(newTingResult) return len(newTingResults) > 0, newTingResults
def checkMao(cls, pattern, maoType, maoDanSetting): ftlog.debug('MMao.checkMao pattern:', pattern , ' maoType:', maoType , ' maoDanSetting:', maoDanSetting) values = [] if maoType & MTDefine.MAO_DAN_DNXBZFB: #乱锚 if not maoDanSetting & MTDefine.MAO_DAN_DNXBZFB: return False for tile in pattern: if MTile.isArrow(tile) or MTile.isFeng(tile): values.append(tile) #取消对相同牌的检查 else: return False elif maoType & MTDefine.MAO_DAN_DNXB: if not maoDanSetting & MTDefine.MAO_DAN_DNXB: return False for tile in pattern: if MTile.isFeng(tile): if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_ZFB: if not maoDanSetting & MTDefine.MAO_DAN_ZFB: return False for tile in pattern: if MTile.isArrow(tile): if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_YAO: if not maoDanSetting & MTDefine.MAO_DAN_YAO: return False for tile in pattern: if MTile.getValue(tile) == 1: if tile not in values: values.append(tile) continue else: return False elif maoType & MTDefine.MAO_DAN_JIU: if not maoDanSetting & MTDefine.MAO_DAN_JIU: return False for tile in pattern: if MTile.getValue(tile) == 9: if tile not in values: values.append(tile) continue else: return False ftlog.debug('MMao.checkMao pattern:', pattern , ' maoType:', maoType) return len(values) >= 3
def isJia5(self): """是否夹五""" res = self.isJia() and (MTile.getValue(self.winTile) == 5) and (self.winTile < 30) ftlog.debug('weihai_one_result.isJia5 result: ', res) return res
def calcWin(self): """ 鸡西算番规则: """ scoreBase = self.tableConfig.get(MTDefine.WIN_BASE, 1) ftlog.debug('MJixiOneResult.calcWin scoreBase:', scoreBase) self.results['type'] = MOneResult.KEY_TYPE_NAME_HU name = '' index = 0 score = [0 for _ in range(self.playerCount)] fanPattern = [[] for _ in range(self.playerCount)] winMode = [MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount)] # 在和牌时统计自摸,点炮,最大番数 resultStat = [[] for _ in range(self.playerCount)] isBaoPei = False # 是否包赔,如果是包赔 那么兑奖也要包赔 resultStat[self.winSeatId].append({MOneResult.STAT_WIN: 1}) # 正常和牌 if not self.wuDuiHu: isZiMo = (self.lastSeatId == self.winSeatId) if isZiMo: resultStat[self.winSeatId].append({MOneResult.STAT_ZIMO: 1}) isJia = self.isJia() isBian = self.isBian() isDanDiao = self.isDanDiao() isMagic = self.isMagicTile() isQiDui = self.isQiDui(isMagic) isPiao = self.isPiao() isQingYiSe = self.isQingYiSe() isTeDaJia = self.isTeDaJia(isJia, isBian) isSanQi = self.isSanQi() ftlog.debug('MJixiOneResult.calcWin isJia:', isJia, ' isBian:', isBian, ' isDanDiao', isDanDiao, ' isQiDui:', isQiDui, ' isPiao:', isPiao, ' isQingYiSe:', isQingYiSe, ' isSanQi:', isSanQi) self.clearWinFanPattern() # 高级番型处理(清一色 通宝 宝中宝) isBaoZhongBao = False isTongBao = False if self.magicAfertTing: # 听牌之后是宝牌 直接和牌 # 宝中宝 宝夹 bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) if (isBian and isSanQi and bianMulti and len(self.winNodes) == 1): isBaoZhongBao = True elif isJia: # 如果是摸的宝是winNodes里面的夹,就是宝中宝,否则是宝边 magicTileInJia = False for wn in self.winNodes: patterns = wn['pattern'] for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue if (self.winTile in p) and (p.index( self.winTile)) == 1: magicTileInJia = True if magicTileInJia: isBaoZhongBao = True else: isTongBao = True elif isDanDiao: # 如果是摸的宝是winNodes里面的对子,就是宝中宝,否则是宝边 magicTileInPair = False for wn in self.winNodes: patterns = wn['pattern'] for p in patterns: if len(p) != 2: continue if p[0] == p[1] and (self.winTile in p): magicTileInPair = True if magicTileInPair: isBaoZhongBao = True else: isTongBao = True # 通宝 宝边 else: ftlog.debug('MJixiOneResult.calcWin isTongBao = True:') isTongBao = True if isBaoZhongBao: nameBaoZhongBao = self.fanXing[self.BAOZHONGBAOJIA]['name'] indexBaoZhongBao = self.fanXing[self.BAOZHONGBAOJIA]['index'] self.addWinFanPattern(nameBaoZhongBao, indexBaoZhongBao) index += self.fanXing[self.BAOZHONGBAOJIA]['index'] ftlog.debug('MJixiOneResult.calcWin MagicAfertTing name:', nameBaoZhongBao, ' index:', indexBaoZhongBao) elif isTongBao: nameTongBao = self.fanXing[self.BAOBIAN]['name'] indexTongBao = self.fanXing[self.BAOBIAN]['index'] self.addWinFanPattern(nameTongBao, indexTongBao) index += self.fanXing[self.BAOBIAN]['index'] # 计算基本番型 name, tempindex = self.calcBaseFan(isTeDaJia, False, False, False, isQiDui, isPiao) index += tempindex ftlog.debug('MJixiOneResult.calcWin BaseFan name:', name, ' index:', index) elif isZiMo: # 自摸番型处理(自摸 摸宝[2番] 杠开 ) if isMagic: index += self.fanXing[self.MOBAO]['index'] self.addWinFanPattern(self.fanXing[self.MOBAO]['name'], self.fanXing[self.MOBAO]['index']) resultStat[self.winSeatId].append( {MOneResult.STAT_MOBAO: 1}) else: index += self.fanXing[self.ZIMO]['index'] # 计算基本番型 name, tempindex = self.calcBaseFan(isTeDaJia, isJia, isBian, isDanDiao, isQiDui, isPiao) index += tempindex ftlog.debug('MJixiOneResult.calcWin ZiMoFan index:', index) elif isZiMo == False: # 点炮胡 # 计算基本番型 name, tempindex = self.calcBaseFan(isTeDaJia, isJia, isBian, isDanDiao, isQiDui, isPiao) index += tempindex ftlog.debug('MJixiOneResult.calcWin 点炮胡 index:', index) if isQingYiSe: if isTeDaJia or isQiDui or isPiao or isBaoZhongBao: nameQingYiSe = self.fanXing[self.QINGYISE_1]['name'] indexQingYiSe = self.fanXing[self.QINGYISE_1]['index'] self.addWinFanPattern(nameQingYiSe, indexQingYiSe) index += self.fanXing[self.QINGYISE_1]['index'] else: nameQingYiSe = self.fanXing[self.QINGYISE]['name'] indexQingYiSe = self.fanXing[self.QINGYISE]['index'] self.addWinFanPattern(nameQingYiSe, indexQingYiSe) index += self.fanXing[self.QINGYISE]['index'] ftlog.debug('MJixiOneResult.calcWin QingYiSeFan name:', nameQingYiSe, ' index:', indexQingYiSe) if self.bankerSeatId == self.winSeatId: index += 1 ftlog.debug('MJixiOneResult.calcWin name:', name, ' index:', index, ' type:', type, ' bankerSeatId:', self.bankerSeatId, ' winSeatId:', self.winSeatId) scoreIndex = self.tableConfig.get( MTDefine.FAN_LIST, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ftlog.debug('MJixiOneResult.calcWin scoreIndex:', scoreIndex) biMenFanConfig = self.tableConfig.get(MTDefine.BI_MEN_FAN, 0) # 当前局番型处理 # 输赢模式 输家番型统计 for seatId in range(self.playerCount): if seatId == self.winSeatId: winModeValue = MOneResult.WIN_MODE_PINGHU # 自摸 if self.lastSeatId == self.winSeatId: winModeValue = MOneResult.WIN_MODE_ZIMO if isMagic and (not self.magicAfertTing): winModeValue = MOneResult.WIN_MODE_mobao if isBaoZhongBao: winModeValue = MOneResult.WIN_MODE_baozhongbao if self.magicAfertTing: if self.tableConfig.get(MTDefine.DUI_BAO, 0) == 1: winModeValue = MOneResult.WIN_MODE_LOUHU if self.gangKai: winModeValue = MOneResult.WIN_MODE_GANGKAI self.addWinFanPattern( self.fanXing[self.GANGKAI]['name'], self.fanXing[self.GANGKAI]['index']) if self.qiangGang: winModeValue = MOneResult.WIN_MODE_QIANGGANGHU self.addWinFanPattern( self.fanXing[self.QIANGGANG]['name'], self.fanXing[self.QIANGGANG]['index']) if self.daFeng: winModeValue = MOneResult.WIN_MODE_guadafeng winMode[seatId] = winModeValue fanPattern[self.winSeatId] = self.winFanPattern elif seatId == self.lastSeatId: winModeValue = MOneResult.WIN_MODE_DIANPAO winMode[seatId] = winModeValue resultStat[seatId].append({MOneResult.STAT_DIANPAO: 1}) fanPattern[seatId] = [] # 点炮包庄 if self.tingState[seatId] == 0: winModeValue = MOneResult.WIN_MODE_DIANPAO_BAOZHUANG winMode[seatId] = winModeValue # 闭门 if self.menState[seatId] == 1 and biMenFanConfig: looseFanName = self.fanXing[self.BIMEN]['name'] looseFanIndex = self.fanXing[self.BIMEN]['index'] fanPattern[seatId].append( [looseFanName.strip(), str(looseFanIndex) + "番"]) else: fanPattern[seatId] = [] # 闭门 if self.menState[seatId] == 1 and biMenFanConfig: looseFanName = self.fanXing[self.BIMEN]['name'] looseFanIndex = self.fanXing[self.BIMEN]['index'] fanPattern[seatId].append( [looseFanName.strip(), str(looseFanIndex) + "番"]) if not self.tianHu: score = [index for _ in range(self.playerCount)] if self.lastSeatId != self.winSeatId: if self.tingState[self.lastSeatId]: ftlog.debug( 'MJixiOneResult.calcWin dianpao index is zero becouse is Ting' ) else: # 改成点炮都不翻倍 # score[self.lastSeatId] += 1 ftlog.debug('MJixiOneResult.calcWin dianpao score:', score) if self.bankerSeatId != self.winSeatId: score[self.bankerSeatId] += 1 ftlog.debug( 'MJixiOneResult.calcWin zhuangjia double score:', score, ' bankerSeatId:', self.bankerSeatId, ' winSeatId:', self.winSeatId) for seatId in range(len(self.menState)): if biMenFanConfig and self.menState[ seatId] == 1 and seatId != self.winSeatId: score[seatId] += 1 ftlog.debug( 'MJixiOneResult.calcWin menqing double score:', score, ' menState:', self.menState) winScore = 0 for seatId in range(len(score)): if seatId != self.winSeatId: newIndex = score[seatId] score[seatId] = -scoreIndex[newIndex] winScore += scoreIndex[newIndex] score[self.winSeatId] = winScore ftlog.debug('MJixiOneResult.calcWin score before baopei:', score) if self.lastSeatId != self.winSeatId: if self.tingState[self.lastSeatId] == 0: isBaoPei = True # 包赔 for seatId in range(len(score)): if seatId != self.winSeatId and seatId != self.lastSeatId: s = score[seatId] score[seatId] = 0 score[self.lastSeatId] += s ftlog.debug( 'MJixiOneResult.calcWin dianpaobaozhuang score:', score, ' lastSeatId:', self.lastSeatId, ' winSeatId:', self.winSeatId, ' tingState:', self.tingState) else: index = self.fanXing[self.TIANHU]['index'] score = [index for _ in range(self.playerCount)] scoreIndex = self.tableConfig.get( MTDefine.FAN_LIST, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ftlog.debug('MJixiOneResult.calcWin scoreIndex:', scoreIndex) winScore = 0 for seatId in range(len(score)): if seatId != self.winSeatId: newIndex = score[seatId] score[seatId] = -scoreIndex[newIndex] winScore += scoreIndex[newIndex] score[self.winSeatId] = winScore # fanPattern = [[] for _ in range(self.playerCount)] winMode = [ MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount) ] winMode[self.winSeatId] = MOneResult.WIN_MODE_TIANHU resultStat[self.winSeatId].append( {MOneResult.STAT_ZUIDAFAN: index}) else: name = self.fanXing[self.WUDUIHU]['name'] index = self.fanXing[self.WUDUIHU]['index'] self.addWinFanPattern(name, index) fanPattern[self.winSeatId] = self.winFanPattern score = [10 for _ in range(self.playerCount)] winScore = 0 for seatId in range(len(score)): if seatId != self.winSeatId: loseScore = score[seatId] score[seatId] = -loseScore winScore += loseScore score[self.winSeatId] = winScore # fanPattern = [[] for _ in range(self.playerCount)] winMode = [ MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount) ] winMode[self.winSeatId] = MOneResult.WIN_MODE_WUDUIHU # 最高128分封顶 for seatId in range(len(score)): if seatId != self.winSeatId: if abs(score[seatId]) > self.MAX_SCORE_LIMIT: ftlog.debug('MJixiOneResult.calcWin limit max score :', score[seatId], ' seatId:', seatId) score[self.winSeatId] = score[self.winSeatId] - ( abs(score[seatId]) - self.MAX_SCORE_LIMIT) score[seatId] = -self.MAX_SCORE_LIMIT # 兑奖 awardInfos = [] awardScores = [0 for _ in range(self.playerCount)] awardTiles = self.awardTiles if len(awardTiles) == 0: ftlog.debug('MJixiOneResult.calcWin award tile is zero') else: awardScore = 0 for awardTile in awardTiles: tileValue = MTile.getValue(awardTile) realScore = 0 if tileValue == 1 or awardTile == MTile.TILE_HONG_ZHONG: realScore = 10 awardScore += realScore else: realScore = tileValue awardScore += realScore awardInfo = {'awardTile': awardTile, 'awardScore': realScore} awardInfos.append(awardInfo) for seatId in range(len(score)): if seatId != self.winSeatId: if isBaoPei: # 兑奖包赔处理 score[self.lastSeatId] -= awardScore awardScores[self.lastSeatId] -= awardScore else: score[seatId] -= awardScore awardScores[seatId] = -awardScore score[self.winSeatId] += awardScore awardScores[self.winSeatId] += awardScore # 单局最佳统计(分数) resultStat[self.winSeatId].append( {MOneResult.STAT_ZUIDAFAN: score[self.winSeatId]}) self.results[self.KEY_TYPE] = '和牌' self.results[self.KEY_NAME] = name ftlog.debug('MJixiOneResult.calcWin result score:', score) self.results[self.KEY_SCORE] = score ftlog.debug('MJixiOneResult.calcWin result winMode:', winMode) self.results[self.KEY_WIN_MODE] = winMode self.results[self.KEY_STAT] = resultStat ftlog.debug('MJixiOneResult.calcWin result fanPattern:', fanPattern) self.results[self.KEY_FAN_PATTERN] = fanPattern self.results[self.KEY_AWARD_INFO] = awardInfos self.results[self.KEY_AWARD_SCORE] = awardScores
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): ftlog.debug(self.TAG, '.isHu tiles:', tiles, ' tile:', tile, ' isTing:', isTing, ' getTileType:', getTileType, ' magicTiles:', magicTiles, ' tingNodes:', tingNodes, ' winSeatId:', winSeatId) if self.tableTileMgr.isPassHuTileBySeatId(winSeatId, tile): return False, [] # 济南麻将允许胡七对 qiduiTiles = copy.deepcopy(tiles) resultQiDui, patternQiDui = MWin.isQiDui(qiduiTiles[MHand.TYPE_HAND]) if resultQiDui: if self.tableConfig[MTDefine.ONLY_JIANG_258]: for pattern in patternQiDui: tile = pattern[0] if tile > MTile.TILE_NINE_TIAO: continue # 选了258将判断这里,而且不能是风牌 if (MTile.getValue(pattern[0]) % 3 == 2) and pattern[0] < MTile.TILE_DONG_FENG: return True, patternQiDui return False, [] else: return resultQiDui, patternQiDui # 花胡 if getTileType == MWinRule.WIN_BY_MYSELF: flowerTiles = copy.deepcopy(tiles) resFlowerHu, patternFlowerHu = MWin.isFlowerHu(flowerTiles) if resFlowerHu: return resFlowerHu, patternFlowerHu # 全将 jiangTiles = copy.deepcopy(tiles) resQuanj, patternQuanj = MWin.isQuanJiang(jiangTiles) if resQuanj: return resQuanj, patternQuanj # 十三不靠 if not self.tableConfig[MTDefine.ONLY_JIANG_258]: bukaoTiles = copy.deepcopy(tiles) res13Bukao, pattern13Bukao = MWin.is13BuKao( bukaoTiles[MHand.TYPE_HAND]) if res13Bukao: return res13Bukao, pattern13Bukao # 挑出2,5,8将,看剩下的牌是否能胡牌 if self.tableConfig[MTDefine.ONLY_JIANG_258]: jiangPatterns = [[MTile.TILE_TWO_WAN, MTile.TILE_TWO_WAN], [MTile.TILE_FIVE_WAN, MTile.TILE_FIVE_WAN], [MTile.TILE_EIGHT_WAN, MTile.TILE_EIGHT_WAN], [MTile.TILE_TWO_TONG, MTile.TILE_TWO_TONG], [MTile.TILE_FIVE_TONG, MTile.TILE_FIVE_TONG], [MTile.TILE_EIGHT_TONG, MTile.TILE_EIGHT_TONG], [MTile.TILE_TWO_TIAO, MTile.TILE_TWO_TIAO], [MTile.TILE_FIVE_TIAO, MTile.TILE_FIVE_TIAO], [MTile.TILE_EIGHT_TIAO, MTile.TILE_EIGHT_TIAO]] jiangTiles = copy.deepcopy(tiles) for jiangPat in jiangPatterns: result, pattern = MWin.isHuWishSpecialJiang( jiangTiles[MHand.TYPE_HAND], jiangPat) if result: return result, pattern else: newTiles = copy.deepcopy(tiles) result, pattern = MWin.isHu(newTiles[MHand.TYPE_HAND]) return result, pattern return False, []
def isBian(self): """是否夹牌""" for wn in self.winNodes: if wn['winTile'] == self.winTile: patterns = wn['pattern'] ftlog.debug('MMudanjiangOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns) for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue # 三七边 if (self.winTile in p) \ and (p.index(self.winTile) == 0) \ and (MTile.getValue(p[1]) == 8) \ and (MTile.getValue(p[2]) == 9): ftlog.debug('MMudanjiangOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 7 bian') return True if (self.winTile in p) \ and (p.index(self.winTile) == 2) \ and (MTile.getValue(p[0]) == 1) \ and (MTile.getValue(p[1]) == 2): ftlog.debug('MMudanjiangOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 3 bian') return True # 宝牌情况处理 hongZongBaoConfig = self.tableConfig.get(MTDefine.HONG_ZHONG_BAO, 0) ftlog.debug('MMudanjiangOneResult.isBian checkMagic, isMagicTile:', self.isMagicTile(), ' isHongZhong:', self.isHongZhong(), ' hongZongBaoConfig:', hongZongBaoConfig, ' daFeng:', self.daFeng, ' magicAfertTing:', self.magicAfertTing) if self.isMagicTile() or (self.isHongZhong() and hongZongBaoConfig ) or self.daFeng or self.magicAfertTing: for wn in self.winNodes: winTile = wn['winTile'] patterns = wn['pattern'] for p in patterns: if len(p) == 2: continue if p[0] == p[1]: continue # 三七边 if (winTile in p) \ and (p.index(winTile) == 0) \ and (MTile.getValue(p[1]) == 8) \ and (MTile.getValue(p[2]) == 9): ftlog.debug('MMudanjiangOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 7 bian') return True if (winTile in p) \ and (p.index(winTile) == 2) \ and (MTile.getValue(p[0]) == 1) \ and (MTile.getValue(p[1]) == 2): ftlog.debug('MMudanjiangOneResult.isBian winTile:', self.winTile, ' winPatterns:', patterns, ' 3 bian') return True return False
def hasMao(cls, tiles, maoDanSetting, alreadyHave = 0): ftlog.debug('MMao.hasMao tiles:', tiles , ' maoDanSetting:', maoDanSetting , ' alreadyHave:', alreadyHave) maos = [] if (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB) and (not (alreadyHave & MTDefine.MAO_DAN_DNXBZFB)): pattern = [] values = [] for tile in tiles: if MTile.isFeng(tile) or MTile.isArrow(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: luanMao = {} luanMao['type'] = MTDefine.MAO_DAN_DNXBZFB luanMao['pattern'] = values luanMao['name'] = MTDefine.MAO_DAN_DNXBZFB_NAME maos.append(luanMao) if (maoDanSetting & MTDefine.MAO_DAN_DNXB) and \ (not (alreadyHave & MTDefine.MAO_DAN_DNXB) and \ (not (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB))): pattern = [] values = [] for tile in tiles: if MTile.isFeng(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: fengMao = {} fengMao['type'] = MTDefine.MAO_DAN_DNXB fengMao['pattern'] = values fengMao['name'] = MTDefine.MAO_DAN_DNXB_NAME maos.append(fengMao) if (maoDanSetting & MTDefine.MAO_DAN_ZFB) and \ (not (alreadyHave & MTDefine.MAO_DAN_ZFB)) and \ (not (maoDanSetting & MTDefine.MAO_DAN_DNXBZFB)): pattern = [] values = [] for tile in tiles: if MTile.isArrow(tile): pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: arrowMao = {} arrowMao['type'] = MTDefine.MAO_DAN_ZFB arrowMao['pattern'] = values arrowMao['name'] = MTDefine.MAO_DAN_ZFB_NAME maos.append(arrowMao) if (maoDanSetting & MTDefine.MAO_DAN_YAO) and (not (alreadyHave & MTDefine.MAO_DAN_YAO)): pattern = [] values = [] for tile in tiles: if MTile.getValue(tile) == 1: pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: yaoMao = {} yaoMao['type'] = MTDefine.MAO_DAN_YAO yaoMao['pattern'] = values yaoMao['name'] = MTDefine.MAO_DAN_YAO_NAME maos.append(yaoMao) if (maoDanSetting & MTDefine.MAO_DAN_JIU) and (not (alreadyHave & MTDefine.MAO_DAN_JIU)): pattern = [] values = [] for tile in tiles: if MTile.getValue(tile) == 9: pattern.append(tile) if tile not in values: values.append(tile) if len(values) >= 3: jiuMao = {} jiuMao['type'] = MTDefine.MAO_DAN_JIU jiuMao['pattern'] = values jiuMao['name'] = MTDefine.MAO_DAN_JIU_NAME maos.append(jiuMao) ftlog.debug('MMao.hasMao tiles:', tiles , ' maoDanSetting:', maoDanSetting , ' maos:', maos) return maos
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) isTing, tingResults = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('MTingJixiRule.canTing tiles:', tiles, 'tile:', tile) ftlog.debug('MTingJixiRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) # [{'dropTile': 11, 'winNodes': [{'winTile': 1, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [1, 2, 3]]}, {'winTile': 2, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [3, 4, 5], [2, 2]]}, {'winTile': 4, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [2, 3, 4]]}, {'winTile': 5, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [5, 5], [2, 3, 4]]}, {'winTile': 7, 'winTileCount': 1, 'pattern': [[6, 6], [5, 6, 7], [5, 6, 7], [2, 3, 4]]}, {'winTile': 8, 'winTileCount': 1, 'pattern': [[6, 7, 8], [6, 6, 6], [5, 5], [2, 3, 4]]}]}] #tingResults: [{'dropTile': 23, 'winNodes': [{'winTile': 12, 'winTileCount': 0, 'pattern': [[13, 14, 15], [12, 12, 12], [29, 29], [25, 25, 25]]}, {'winTile': 29, 'winTileCount': 1, 'pattern': [[13, 14, 15], [12, 12], [29, 29, 29], [25, 25, 25]]}]}] if not isTing: return False, [] # 检查刻,刻的来源,碰牌/明杠牌/手牌 pengCount = len(tiles[MHand.TYPE_PENG]) gangCount = len(tiles[MHand.TYPE_GANG]) keCount = pengCount + gangCount newTingResults = [] for tingResult in tingResults: newWinNodes = [] winNodes = tingResult['winNodes'] for winNode in winNodes: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tingResult['dropTile']) newTiles[MHand.TYPE_HAND].append(winNode['winTile']) tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToList(newTiles)) patterns = winNode['pattern'] isQiDui = self.isQiDui(patterns, newTiles) isPiaoHu = self.isPiaoHu(patterns, newTiles) #飘和七对可以手把一 if (isPiaoHu or isQiDui): if handCount < 2: continue else: if handCount < 5: continue # 飘和七小对不需要1,9,如果不是飘也不是七小对: # 检查牌中的幺/九 # 1软 听牌可以没有19,只要胡牌带19就可以 # 2硬 听牌时就要有19 if not (isPiaoHu or isQiDui): RuanYaoJiuConfig = self.getTableConfig( MTDefine.RUAN_YAO_JIU, 1) if RuanYaoJiuConfig == 0: #硬幺九 :听牌必须有19 #tileArr 减去 winNode['winTile'] 后判断 tileArr[winNode['winTile']] -= 1 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[ MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingJixiRule.canTing : YING yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) <= 0: continue else: #软幺九 :只要胡牌有19就行 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[ MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingJixiRule.canTing : RUAN yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) == 0: continue #夹起步(顺牌只能和夹和3,7) 不能和两头 可以单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) danDiaoJia = self.tableConfig.get(MTDefine.DAN_DIAO_JIA, 1) hasJia = False for pattern in patterns: if winNode['winTile'] in pattern: if len(pattern) == 3 and pattern[0] != pattern[1]: if pattern.index(winNode['winTile']) == 2: if bianMulti: if MTile.getValue( winNode['winTile']) == 3: hasJia = True break if pattern.index(winNode['winTile']) == 0: if bianMulti: if MTile.getValue( winNode['winTile']) == 7: hasJia = True break if pattern.index(winNode['winTile']) == 1: hasJia = True break #单吊 if len(pattern) == 2 and pattern[0] == pattern[ 1] and danDiaoJia: hasJia = True break if not hasJia: ftlog.debug( 'MTingHaerbinRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) ftlog.debug('MTingJixiRule.canTing keCount:', keCount) #胡牌必须有刻牌 七小对除外 if checkKeCount or isQiDui: newWinNodes.append(winNode) if len(newWinNodes) > 0: newTingResult = {} newTingResult['dropTile'] = tingResult['dropTile'] newTingResult['winNodes'] = newWinNodes newTingResults.append(newTingResult) ftlog.debug('MTingJixiRule.canTing :len(newTingResults) ', len(newTingResults), 'newTingResults', newTingResults) return len(newTingResults) > 0, newTingResults
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if handCount < 5: return False, [] isTing, tingResults = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('MTingHaerbinRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) # [{'dropTile': 11, 'winNodes': [{'winTile': 1, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [1, 2, 3]]}, {'winTile': 2, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [3, 4, 5], [2, 2]]}, {'winTile': 4, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [2, 3, 4]]}, {'winTile': 5, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [5, 5], [2, 3, 4]]}, {'winTile': 7, 'winTileCount': 1, 'pattern': [[6, 6], [5, 6, 7], [5, 6, 7], [2, 3, 4]]}, {'winTile': 8, 'winTileCount': 1, 'pattern': [[6, 7, 8], [6, 6, 6], [5, 5], [2, 3, 4]]}]}] if not isTing: return False, [] chiCount = len(tiles[MHand.TYPE_CHI]) pengCount = len(tiles[MHand.TYPE_PENG]) gangCount = len(tiles[MHand.TYPE_GANG]) mingGangCount = 0 anGangCount = 0 #计算明杠个数,因为暗杠不算开门 if gangCount != 0: mingGangCount, anGangCount = MTile.calcGangCount( tiles[MHand.TYPE_GANG]) ftlog.debug('MTingHaerbinRule.gang tiles:', tiles[MHand.TYPE_GANG], ' mingGangCount=', mingGangCount, ' anGangCount=', anGangCount) if (chiCount + pengCount + mingGangCount) == 0: return False, [] # 检查刻,刻的来源,碰牌/明杠牌/手牌 keCount = pengCount + mingGangCount + anGangCount # 必须有顺牌 shunCount = chiCount newTingResults = [] for tingResult in tingResults: newWinNodes = [] winNodes = tingResult['winNodes'] for winNode in winNodes: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tingResult['dropTile']) newTiles[MHand.TYPE_HAND].append(winNode['winTile']) tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToList(newTiles)) # ftlog.debug( 'MTingHaerbinRule.canTing tileArr:', tileArr ) # 清一色不可以听牌/和牌 if self.getTableConfig(MTDefine.YISE_CAN_TING, 0) != 1: newTileArr = copy.deepcopy(tileArr) newTileArr[MTile.TILE_HONG_ZHONG] = 0 colorCount = MTile.getColorCount(newTileArr) if colorCount == 1: # 清一色不能和牌 ftlog.debug('MTingHaerbinRule.canTing colorCount:', colorCount, ' can not win, continue....') continue # 检查牌中的幺/九 # 1软 听牌可以没有19,只要胡牌带19就可以 # 2硬 听牌时就要有19 RuanYaoJiuConfig = self.getTableConfig(MTDefine.RUAN_YAO_JIU, 1) if RuanYaoJiuConfig == 0: #硬幺九 :听牌必须有19 #tileArr 减去 winNode['winTile'] 后判断 tileArr[winNode['winTile']] -= 1 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingJixiRule.canTing : YING yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) <= 0: continue else: #软幺九 :只要胡牌有19就行 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingJixiRule.canTing : RUAN yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) == 0: continue patterns = winNode['pattern'] #夹起步(顺牌只能和夹和3,7) 除单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) danDiaoJia = self.tableConfig.get(MTDefine.DAN_DIAO_JIA, 1) hasJia = False for pattern in patterns: if winNode['winTile'] in pattern: if len(pattern) == 3 and pattern[0] != pattern[1]: if pattern.index(winNode['winTile']) == 2: if bianMulti: if MTile.getValue( winNode['winTile']) == 3: hasJia = True break if pattern.index(winNode['winTile']) == 0: if bianMulti: if MTile.getValue( winNode['winTile']) == 7: hasJia = True break if pattern.index(winNode['winTile']) == 1: hasJia = True break #单吊 if len(pattern) == 2 and pattern[0] == pattern[ 1] and danDiaoJia: hasJia = True break if not hasJia: ftlog.debug( 'MTingHaerbinRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) checkShunCount = shunCount + self.getShunCount(patterns) ftlog.debug('MTingHaerbinRule.canTing keCount:', keCount, ' shunCount:', shunCount) if checkKeCount and checkShunCount: newWinNodes.append(winNode) if len(newWinNodes) > 0: newTingResult = {} newTingResult['dropTile'] = tingResult['dropTile'] newTingResult['winNodes'] = newWinNodes newTingResults.append(newTingResult) return len(newTingResults) > 0, newTingResults
def hasExtendMao(cls, tiles, alreadyHave = 0): extendMaos = [] if alreadyHave & MTDefine.MAO_DAN_DNXBZFB: es = [] for tile in tiles: if MTile.isFeng(tile) or MTile.isArrow(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_DNXBZFB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_DNXBZFB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_DNXB: es = [] for tile in tiles: if MTile.isFeng(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_DNXB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_DNXB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_ZFB: es = [] for tile in tiles: if MTile.isArrow(tile): es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_ZFB faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_ZFB_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_YAO: es = [] for tile in tiles: if MTile.getValue(tile) == 1: es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_YAO faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_YAO_NAME extendMaos.append(faNode) if alreadyHave & MTDefine.MAO_DAN_JIU: es = [] for tile in tiles: if MTile.getValue(tile) == 9: es.append(tile) if len(es) > 0: faNode = {} faNode['type'] = MTDefine.MAO_DAN_JIU faNode['extends'] = es faNode['name'] = MTDefine.MAO_DAN_JIU_NAME extendMaos.append(faNode) return extendMaos
def hasChi(self, tiles, tile): """是否有吃牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待吃的牌 """ if tile >= MTile.TILE_DONG_FENG: return [] #是否允许会牌参与,如果不允许,删除会牌 tilesForChi = copy.deepcopy(tiles[MHand.TYPE_HAND]) if not self.tableTileMgr.allowMagicChiPengGang(): magicTile = self.tableTileMgr.getMagicTile() while magicTile in tilesForChi: tilesForChi.remove(magicTile) chiSolutions = MChi.hasChi(tilesForChi, tile) magicTiles = self.tableTileMgr.getMagicTiles(False) if len(magicTiles) == 0: return chiSolutions if not self.tableTileMgr.canUseMagicTile(MTableState.TABLE_STATE_CHI): return chiSolutions magicTile = magicTiles[0] tileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND]) magicCount = tileArr[magicTile] tileArr[magicTile] = 0 ftlog.debug('MChiRule.hasChi tile:', tile, ' magicCount:', magicCount) if magicCount == 0 or (tileArr[tile] == 0): return chiSolutions if MTile.getValue(tile) <= 7: # +1[-] +2[+] ==> [tile, magic, tile+2] if tileArr[tile + 1] == 0 and tileArr[tile + 2] > 0: chiSolutions.append([tile, magicTile, tile + 2]) # +1[+] +2[-] ==> [tile, tile + 1, magicTile] if tileArr[tile + 1] > 0 and tileArr[tile + 2] == 0: chiSolutions.append([tile, tile + 1, magicTile]) if (tileArr[tile + 1] + tileArr[tile + 2]) == 0 and magicCount >= 2: chiSolutions.append([tile, magicTile, magicTile]) if MTile.getValue(tile) >= 3: # -2[+] -1[-] ==> [tile - 2, magicTile, tile] if tileArr[tile - 2] > 0 and tileArr[tile - 1] == 0: chiSolutions.append([tile - 2, magicTile, tile]) # -2[0] -1[+] ==> [magicTile, tile - 1, tile] if tileArr[tile - 2] == 0 and tileArr[tile - 1] > 0: chiSolutions.append([magicTile, tile - 1, tile]) if (tileArr[tile - 2] + tileArr[tile - 1]) == 0 and magicCount >= 2: chiSolutions.append([magicTile, magicTile, tile]) if MTile.getValue(tile) >= 2 and MTile.getValue(tile) <= 8: # -1[-] 1[+] ==> magicTile, tile, tile + 1 if tileArr[tile - 1] == 0 and tileArr[tile + 1] > 0: chiSolutions.append([magicTile, tile, tile + 1]) # -1[+] 1[-] ==> [tile - 1, tile, magicTile] if tileArr[tile - 1] > 0 and tileArr[tile + 1] == 0: chiSolutions.append([tile - 1, tile, magicTile]) if (tileArr[tile + 1] + tileArr[tile - 1]) == 0 and magicCount >= 2: chiSolutions.append([magicTile, tile, magicTile]) return chiSolutions