def isBu(cls, tileArr, resultArr, magicArr, tileType, hasJiang): """ 判断某个花色是否是三朴,缺的牌从癞子中获取,如果没有癞子牌了,也形不成三朴,和牌失败 """ 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) 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) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) if resultTmp: resultArr.append([tileIndex, tileIndex, mTile]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 2 magicArr.append(mTile) if (tileArr[tileIndex] == 1) and (len(magicArr) >= 2): # 单张,尝试加两张癞子组成刻 tileArr[tileIndex] -= 1 mTile1 = magicArr.pop(-1) mTile2 = magicArr.pop(-1) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) if resultTmp: resultArr.append([tileIndex, mTile1, mTile2]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 1 magicArr.append(mTile1) magicArr.append(mTile2) 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) oldJiang = hasJiang # 当前的对子当将测测是否成胡 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, True) if resultTmp: resultArr.append([tileIndex, jiangTile]) hasJiang = True return True, hasJiang else: # 还原将牌标记 hasJiang = oldJiang # 还原手牌 tileArr[tileIndex] += 1 if isMagicJiang: magicArr.append(jiangTile) else: tileArr[tileIndex] += 1 if tileIndex >= MTile.TILE_DONG_FENG: # 风箭牌不能组成顺 return False, hasJiang # 提取顺牌组合 if tileArr[tileIndex] > 0: # 测试顺子 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 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 测试顺子 -1 0 1 if 8 >= 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.append(magicArr.pop(-1)) else: pattern.append(tileIndex + 1) tileArr[tileIndex + 1] -= 1 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 测试顺子 -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 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 无和牌可能 return False, hasJiang
def canTing(self, tiles, leftTiles, tile, magicTiles=[]): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if len(tiles[MHand.TYPE_CHI]) == 0 and len(tiles[MHand.TYPE_PENG]) == 0 and len(tiles[MHand.TYPE_GANG]) == 0: isTing, tingResults = self.tingQiDui(tiles, tile, leftTiles) if isTing: ftlog.debug('MTingJixiRule.MTing.canTing tingQiDui tingResults:', tingResults) return isTing, tingResults # ftlog.debug( 'MTingJixiRule.canTing 0 tiles:', tiles ) isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles) # ftlog.debug( 'MTingJixiRule.canTing 1 tiles:', tiles ) ftlog.debug('MTingJixiRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) 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 = False isPiaoHu = self.isPiaoHu(patterns, newTiles) # 飘和七对可以手把一 if (isPiaoHu or isQiDui): if handCount < 1: continue else: if handCount < 5: continue # 夹起步(顺牌只能和夹和3,7) 不能和两头 可以单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) 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]: hasJia = True break if not hasJia: ftlog.debug('MTingHaerbinRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue zhongCount = tileArr[MTile.TILE_HONG_ZHONG] # 检查牌中的幺/九 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] # 飘和七小对不需要1,9 if (yaoCount + jiuCount + zhongCount) == 0 and (not isPiaoHu) and (not isQiDui): continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) ftlog.debug('MTingHaerbinRule.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) return len(newTingResults) > 0, newTingResults
def canTing(self, tiles, leftTiles, tile, magicTiles=[]): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if len(tiles[MHand.TYPE_CHI]) == 0 and len( tiles[MHand.TYPE_PENG]) == 0 and len( tiles[MHand.TYPE_GANG]) == 0: isTing, tingResults = self.tingQiDui(tiles, tile, leftTiles) if isTing: ftlog.debug( 'MTingJixiRule.MTing.canTing tingQiDui tingResults:', tingResults) return isTing, tingResults # ftlog.debug( 'MTingJixiRule.canTing 0 tiles:', tiles ) isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles) # ftlog.debug( 'MTingJixiRule.canTing 1 tiles:', tiles ) ftlog.debug('MTingJixiRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) 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 = False isPiaoHu = self.isPiaoHu(patterns, newTiles) # 飘和七对可以手把一 if (isPiaoHu or isQiDui): if handCount < 1: continue else: if handCount < 5: continue # 夹起步(顺牌只能和夹和3,7) 不能和两头 可以单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) 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]: hasJia = True break if not hasJia: ftlog.debug( 'MTingHaerbinRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue zhongCount = tileArr[MTile.TILE_HONG_ZHONG] # 检查牌中的幺/九 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] # 飘和七小对不需要1,9 if (yaoCount + jiuCount + zhongCount) == 0 and (not isPiaoHu) and (not isQiDui): continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) ftlog.debug('MTingHaerbinRule.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) return len(newTingResults) > 0, newTingResults
def hasChi(self, tiles, tile): """是否有吃牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待吃的牌 """ if tile >= MTile.TILE_DONG_FENG: return [] chiSolutions = MChi.hasChi(tiles[MHand.TYPE_HAND], 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 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 canTing(self, tiles, leftTiles, tile, magicTiles=[]): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if handCount < 5: return False, [] # ftlog.debug( 'MTingHaerbinRule.canTing 0 tiles:', tiles ) isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles) # ftlog.debug( 'MTingHaerbinRule.canTing 1 tiles:', tiles ) 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]) if (chiCount + pengCount + gangCount) == 0: return False, [] # 检查刻,刻的来源,碰牌/明杠牌/手牌 keCount = pengCount + gangCount # 必须有顺牌 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 ) # 夹起步(顺牌只能和夹和3,7) 除单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: chunJiaContinue = False patterns = winNode['pattern'] for pattern in patterns: if winNode['winTile'] in pattern: if len(pattern) == 3 and pattern[0] != pattern[1]: if (pattern.index(winNode['winTile'])) == 2 and MTile.getValue(winNode['winTile']) != 3: chunJiaContinue = True break if (pattern.index(winNode['winTile'])) == 0 and MTile.getValue(winNode['winTile']) != 7: chunJiaContinue = True break # 夹起步不能和对倒 if len(pattern) == 3 and pattern[0] == pattern[1]: chunJiaContinue = True break if chunJiaContinue: ftlog.debug('MTingHaerbinRule.canTing chunJiaConfig:', chunJiaConfig, ' can not win tile:', winNode['winTile'], ', continue....') continue if self.getTableConfig(MTDefine.YISE_CAN_TING, 0) != 1: # 清一色不可以听牌/和牌 colorCount = MTile.getColorCount(tileArr) if colorCount == 1: # 清一色不能和牌 ftlog.debug('MTingHaerbinRule.canTing colorCount:', colorCount, ' can not win, continue....') continue zhongCount = tileArr[MTile.TILE_HONG_ZHONG] # ftlog.debug( 'MTingHaerbinRule.canTing hongzhong count: ', zhongCount ) # 检查牌中的幺/九 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] # ftlog.debug( 'MTingHaerbinRule.canTing yaoCount:', yaoCount, ' jiuCount:', jiuCount ) if (yaoCount + jiuCount + zhongCount) == 0: 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 isBu(cls, tileArr, resultArr, magicArr, tileType, hasJiang): """ 判断某个花色是否是三朴,缺的牌从癞子中获取,如果没有癞子牌了,也形不成三朴,和牌失败 """ 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) 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) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) if resultTmp: resultArr.append([tileIndex, tileIndex, mTile]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 2 magicArr.append(mTile) if (tileArr[tileIndex] == 1) and (len(magicArr) >= 2): # 单张,尝试加两张癞子组成刻 tileArr[tileIndex] -= 1 mTile1 = magicArr.pop(-1) mTile2 = magicArr.pop(-1) resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) if resultTmp: resultArr.append([tileIndex, mTile1, mTile2]) return True, hasJiang # 还原手牌,继续判断 tileArr[tileIndex] += 1 magicArr.append(mTile1) magicArr.append(mTile2) 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) oldJiang = hasJiang # 当前的对子当将测测是否成胡 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, True) if resultTmp: resultArr.append([tileIndex, jiangTile]) hasJiang = True return True, hasJiang else: # 还原将牌标记 hasJiang = oldJiang # 还原手牌 tileArr[tileIndex] += 1 if isMagicJiang: magicArr.append(jiangTile) else: tileArr[tileIndex] += 1 if tileIndex >= MTile.TILE_DONG_FENG: # 风箭牌不能组成顺 return False, hasJiang # 提取顺牌组合 if tileArr[tileIndex] > 0: # 测试顺子 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 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 测试顺子 -1 0 1 if 8 >= 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.append(magicArr.pop(-1)) else: pattern.append(tileIndex + 1) tileArr[tileIndex + 1] -= 1 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 测试顺子 -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 resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang) 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 # 无和牌可能 return False, hasJiang
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 = '' 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)] # 正常和牌 if not (self.tianHu or 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() isQiDui = self.isQiDui() isPiao = self.isPiao() isQingYiSe = self.isQingYiSe() isTeDaJia = self.isTeDaJia() isMagic = self.isMagicTile() ftlog.debug('MJixiOneResult.calcWin isJia:', isJia , ' isBian:', isBian , ' isDanDiao', isDanDiao , ' isQiDui:', isQiDui , ' isPiao:', isPiao , ' isQingYiSe:', isQingYiSe ) self.clearWinFanPattern() # 计算基本番型(只有单吊 夹胡[3,7边] 七小对) name, index = self.calcBaseFan(isJia, isBian, isDanDiao, isQiDui) ftlog.debug('MHaerbinOneResult.calcWin BaseFan name:', name, ' index:', index) # 自摸番型处理(自摸 摸宝[2番] 杠开 ) if isZiMo: if isMagic: index += self.fanXing[self.MOBAO]['index'] else: index += self.fanXing[self.ZIMO]['index'] ftlog.debug('MHaerbinOneResult.calcWin ZiMoFan index:', index) # 高级番型处理(清一色 通宝 七对 飘胡 特大夹 宝中宝) isBaoZhongBao = False isTongBao = False if self.magicAfertTing: # 听牌之后是宝牌 直接和牌 # 宝中宝 宝夹 bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) if isDanDiao or isJia or (isBian and self.isSanQi() and bianMulti): isBaoZhongBao = True # 通宝 宝边 else: isTongBao = True if isTongBao: nameTongBao = self.fanXing[self.BAOBIAN]['name'] indexTongBao = self.fanXing[self.BAOBIAN]['index'] self.addWinFanPattern(nameTongBao, indexTongBao) index += self.fanXing[self.BAOBIAN]['index'] ftlog.debug('MHaerbinOneResult.calcWin MagicAfertTing name:', nameTongBao, ' index:', indexTongBao) 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('MHaerbinOneResult.calcWin MagicAfertTing name:', nameBaoZhongBao, ' index:', indexBaoZhongBao) if isPiao: namePiao = self.fanXing[self.PIAOHU]['name'] indexPiao = self.fanXing[self.PIAOHU]['index'] self.addWinFanPattern(namePiao, indexPiao) index += self.fanXing[self.PIAOHU]['index'] ftlog.debug('MHaerbinOneResult.calcWin PiaoFan name:', namePiao, ' index:', indexPiao) if isTeDaJia: nameTeDaJIa = self.fanXing[self.TEDAJIA]['name'] indexTeDaJia = self.fanXing[self.TEDAJIA]['index'] self.addWinFanPattern(nameTeDaJIa, indexTeDaJia) index += self.fanXing[self.TEDAJIA]['index'] ftlog.debug('MHaerbinOneResult.calcWin TeDaJiaFan name:', nameTeDaJIa, ' index:', indexTeDaJia) 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('MHaerbinOneResult.calcWin QingYiSeFan name:', nameQingYiSe, ' index:', indexQingYiSe) if self.bankerSeatId == self.winSeatId: index += 1 ftlog.info('MHaerbinOneResult.calcWin name:', name, ' index:', index, ' type:', type , ' bankerSeatId:', self.bankerSeatId , ' winSeatId:', self.winSeatId) # 最大番统计 resultStat[self.winSeatId].append({MOneResult.STAT_ZUIDAFAN: index}) scoreIndex = self.tableConfig.get(MTDefine.FAN_LIST, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) ftlog.info('MHaerbinOneResult.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: self.addWinFanPattern(self.fanXing[self.MOBAO]['name'], self.fanXing[self.MOBAO]['index']) 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']) 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) + "番"]) score = [index for _ in range(self.playerCount)] if self.lastSeatId != self.winSeatId: score[self.lastSeatId] += 1 ftlog.info('MHaerbinOneResult.calcWin dianpao score:', score) if self.bankerSeatId != self.winSeatId: score[self.bankerSeatId] += 1 ftlog.info('MHaerbinOneResult.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.info('MHaerbinOneResult.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.info('MHaerbinOneResult.calcWin score before baopei:', score) if self.lastSeatId != self.winSeatId: if self.tingState[self.lastSeatId] == 0: # 包赔 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('MHaerbinOneResult.calcWin dianpaobaozhuang score:', score , ' lastSeatId:', self.lastSeatId , ' winSeatId:', self.winSeatId , ' tingState:', self.tingState) else: if self.tianHu: name = self.fanXing[self.TIANHU]['name'] index = self.fanXing[self.TIANHU]['index'] self.addWinFanPattern(name, index) fanPattern[self.winSeatId] = self.winFanPattern() 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.info('MHaerbinOneResult.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}) elif self.wuDuiHu: 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('MHaerbinOneResult.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 = [] awardTiles = self.awardTiles if len(awardTiles) == 0: ftlog.debug('MHaerbinOneResult.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: score[seatId] -= awardScore score[self.winSeatId] += awardScore self.results[self.KEY_TYPE] = '和牌' self.results[self.KEY_NAME] = name ftlog.debug('MHaerbinOneResult.calcWin result score:', score) self.results[self.KEY_SCORE] = score ftlog.debug('MHaerbinOneResult.calcWin result winMode:', winMode) self.results[self.KEY_WIN_MODE] = winMode self.results[self.KEY_STAT] = resultStat ftlog.debug('MHaerbinOneResult.calcWin result fanPattern:', fanPattern) self.results[self.KEY_FAN_PATTERN] = fanPattern self.results[self.KEY_AWARD_INFO] = awardInfos