def canTing(self, tiles, leftTiles, tile, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0): #if self.tableTileMgr.playMode == 'luosihu-suizhou' or self.tableTileMgr.playMode == 'luosihu-luosihu': #小于12张可以显示听牌 #if len(leftTiles) < 12: # 随州和孝感小于12张不能亮牌/听牌 # return False, [] isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, curSeatId, winSeatId, actionID) ftlog.debug( 'MTingLuosihuRule.canTing using MTing isTing:', isTing, ' tingResults:', tingResults ) #if not self.tableTileMgr: # # 用于单元测试,正常情况下都有tableTileMgr return isTing, tingResults finalTingResults = [] if isTing: # 听牌时,要丢弃的牌必须要过滤掉别人要胡的牌,如果都被滤掉了,就不能听牌 for tingResult in tingResults: resultOk = True for player in self.tableTileMgr.players: if player.curSeatId != winSeatId: if player.tingLiangWinTiles: if tingResult['dropTile'] and player.tingLiangWinTiles \ and tingResult['dropTile'] in player.tingLiangWinTiles: ftlog.debug( 'MTingLuosihuRule.canTing drop tile: ', tingResult['dropTile'], ' is forbidden by player: ', player.curSeatId) resultOk = False break if resultOk: for wn in tingResult['winNodes']: allWinTiles = [] for p in wn['pattern']: allWinTiles.extend(p) tileCountArr = MTile.changeTilesToValueArr(MTile.cloneTiles(allWinTiles)) #canKouTiles = [] #for p in wn['pattern']: # if len(p) == 2: # continue # if p[0] == p[1] and p[1] == p[2]: # if tileCountArr[p[0]] == 4 and p[0] != wn['winTile']: # # 手上已经有四张了(去掉winTile),不能扣牌 # continue # if (p[0] != wn['winTile'] or (p[0] == wn['winTile'] and tileCountArr[p[0]] == 4)) and p[0] not in canKouTiles: # # 手上只有3张一样的牌,或者手上有4张一样的牌(包含winTile) # canKouTiles.append(p[0]) # 此处为引用,原有tingResults在每个winNode增加canKouTiles #wn['canKouTiles'] = canKouTiles #ftlog.debug( 'MTingLuosihuRule.canTing winNode: ', wn, ' ,current allWinTiles: ', allWinTiles) finalTingResults.append(tingResult) ftlog.debug( 'MTingLuosihuRule.canTing using after liang filter tingResults:', finalTingResults ) if len(finalTingResults) > 0: return True, finalTingResults else: return False, []
def canTing(cls, tiles, leftTiles, winRule, tile, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0,tingForQiangjin = False,flowerRule = None): """ 判断是否可以听牌 参数: 1)tiles 手牌 2)leftTiles 剩余未发的牌 3) tingForQiangjin 是否是抢金,当是判断抢金时,有可听的结果就返回 modify by youjun 返回值: """ handTileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND]) leftTileArr = MTile.changeTilesToValueArr(leftTiles) leftTileCount = len(leftTileArr) ''' ftlog.debug('MTing.canTing leftTiles:', leftTiles , ' leftTileArr:', leftTileArr , ' leftTileCount:', leftTileCount) ''' result = [] for tile in range(MTile.TILE_MAX_VALUE): if handTileArr[tile] > 0: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tile) resultNode = cls.canWinAddOneTile(leftTileArr, leftTileCount, newTiles, winRule, magicTiles, curSeatId, winSeatId, actionID,tingForQiangjin,flowerRule) if len(resultNode) > 0: winNode = {} winNode['dropTile'] = tile winNode['winNodes'] = resultNode result.append(winNode) if tingForQiangjin: return len(result) > 0, result return len(result) > 0, result
def isPiao(self): playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI] if len(playerChiTiles) > 0: return False playerHandTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] newPlayerHandTiles = MTile.cloneTiles(playerHandTiles) if self.isMagicTile(): for wn in self.winNodes: realWinTile = wn['winTile'] ftlog.debug('MJixiOneResult.isPiao winTile:', realWinTile) newPlayerHandTiles.append(realWinTile) break else: newPlayerHandTiles.append(self.winTile) newPlayerHandTilesArr = MTile.changeTilesToValueArr(newPlayerHandTiles) twoCount = 0 for playerHandTileCount in newPlayerHandTilesArr: if playerHandTileCount == 1: return False elif playerHandTileCount == 2: twoCount += 1 elif playerHandTileCount == 4: twoCount += 2 if twoCount > 1: return False return True
def canWinAddOneTile(cls, leftTileArr, leftTileCount, tiles, winRule, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0,tingForQiangjin = False,flowerRule = None): """ tingForQiangjin 是否是抢金,当是判断抢金时,有可听的结果就返回 modify by youjun """ result = [] if len(magicTiles): testTile = MTile.cloneTiles(tiles) testTile[MHand.TYPE_HAND].append(magicTiles[0]) testResult,testPattern,_ = winRule.isHu(testTile, magicTiles[0], True, MWinRule.WIN_BY_MYSELF, magicTiles, [], curSeatId, winSeatId, actionID,False,False) if not testResult: return result for tile in range(leftTileCount): if flowerRule and flowerRule.isFlower(tile): break if tile % 10 == 0: continue newTile = MTile.cloneTiles(tiles) newTile[MHand.TYPE_HAND].append(tile) # 测试停牌时,默认听牌状态 modify youjun 06.23 默认未听牌状态 winResult, winPattern,indexFan = winRule.isHu(newTile, tile, True, MWinRule.WIN_BY_MYSELF, magicTiles, [], curSeatId, winSeatId, actionID,False,False) if winResult: winNode = {} winNode['winTile'] = tile winNode['winTileCount'] = leftTileArr[tile] ''' ftlog.debug('MTing.canWinAddOneTile winTile:', tile , ' winTileCount:', winNode['winTileCount'] , ' winPattern:', winPattern , ' result:',indexFan) ''' winNode['pattern'] = winPattern winNode['result'] = indexFan result.append(winNode) if tingForQiangjin: return result return result
def isPiao(self): # 如果有吃牌,且不是123条,返回false playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI] ftlog.debug('MJixiOneResult.isPiao playerChiTiles:', playerChiTiles) for chipattern in playerChiTiles: if (21 not in chipattern) or (22 not in chipattern) or ( 23 not in chipattern): return False playerHandTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] newPlayerHandTiles = MTile.cloneTiles(playerHandTiles) if self.isMagicTile(): for wn in self.winNodes: realWinTile = wn['winTile'] ftlog.debug('MJixiOneResult.isPiao winTile:', realWinTile) newPlayerHandTiles.append(realWinTile) break else: newPlayerHandTiles.append(self.winTile) # 排除21,22,23 while ((21 in newPlayerHandTiles) and (22 in newPlayerHandTiles) and (23 in newPlayerHandTiles)): newPlayerHandTiles.remove(21) newPlayerHandTiles.remove(22) newPlayerHandTiles.remove(23) # 排除中发白 while ((35 in newPlayerHandTiles) and (36 in newPlayerHandTiles) and (37 in newPlayerHandTiles)): newPlayerHandTiles.remove(35) newPlayerHandTiles.remove(36) newPlayerHandTiles.remove(37) newPlayerHandTilesArr = MTile.changeTilesToValueArr(newPlayerHandTiles) twoCount = 0 for playerHandTileCount in newPlayerHandTilesArr: if playerHandTileCount == 1: return False elif playerHandTileCount == 2: twoCount += 1 elif playerHandTileCount == 4: twoCount += 2 if twoCount > 1: return False return True
def canTingForQiangjin(self, tiles, leftTiles, tile, magicTiles=[], curSeatId=0, winSeatId=0, actionID=0, tingForQiangjin=True): isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, curSeatId, winSeatId, actionID, tingForQiangjin, self.flowerRule) ftlog.debug('MTingQueshouRule.canTingForQiangjin using MTing isTing:', isTing, ' tingResults:', tingResults) return isTing, tingResults
def canWinAddOneTile(cls, tilePatternChecker, tableTileMgr, leftTileArr, leftTileCount, tiles, winRule, magicTiles=[], winSeatId=0): result = [] #for tile in range(leftTileCount): ishuAll = True for tile in tableTileMgr.getAllTilesForTing(): newTile = MTile.cloneTiles(tiles) newTile[MHand.TYPE_HAND].append(tile) ''' # 添加tile牌,如果tile牌总数大于4,则不用判断 if newTile[MHand.TYPE_HAND].count(tile) > 4: continue ''' # 测试听牌时,默认听牌状态 winResult, winPattern = winRule.isHu(newTile, tile, True, MWinRule.WIN_BY_MYSELF, magicTiles, [], winSeatId) if winResult: winNode = {} winNode['winTile'] = tile winNode['winTileCount'] = leftTileArr[tile] # getVisibleTileCount 返回值是已经有几张了 最多为4张,一炮多响胡牌会算多 visibleTileCount = tableTileMgr.getVisibleTilesCount( tile, True, winSeatId) winNode['winTileCountUserCanSee'] = 4 - visibleTileCount tilePatternChecker.initChecker(newTile, tableTileMgr) winNode['winFan'] = tilePatternChecker.calcFanPatternTing() winNode['pattern'] = winPattern ftlog.debug('MTing.canWinAddOneTile winTile:', tile, ' winTileCount:', winNode['winTileCount'], ' winPattern:', winPattern, ' winNode:', winNode) result.append(winNode) else: ishuAll = False return result, ishuAll
def canTing(cls, tilePatternChecker, tableTileMgr, tiles, leftTiles, winRule, tile, magicTiles=[], winSeatId=0): """ 判断是否可以听牌 参数: 1)tiles 手牌 2)leftTiles 剩余未发的牌 返回值: """ ftlog.debug('MTile.changeTilesToValueArr', tiles[MHand.TYPE_HAND]) handTileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND]) leftTileArr = MTile.changeTilesToValueArr(leftTiles) leftTileCount = len(leftTileArr) ftlog.debug('MTing.canTing leftTiles:', leftTiles, ' leftTileArr:', leftTileArr, ' leftTileCount:', leftTileCount) result = [] for tile in tableTileMgr.getAllTilesForTing(): if handTileArr[tile] > 0: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tile) resultNode, istingAll = cls.canWinAddOneTile( tilePatternChecker, tableTileMgr, leftTileArr, leftTileCount, newTiles, winRule, magicTiles, winSeatId) if len(resultNode) > 0: winNode = {} winNode['dropTile'] = tile winNode['winNodes'] = resultNode winNode['isHuAll'] = istingAll result.append(winNode) return len(result) > 0, result
def isPiao(self): playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI] if len(playerChiTiles) > 0: return False playerHandTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] newPlayerHandTiles = MTile.cloneTiles(playerHandTiles) newPlayerHandTiles.append(self.winTile) newPlayerHandTilesArr = MTile.changeTilesToValueArr(newPlayerHandTiles) twoCount = 0 for playerHandTileCount in newPlayerHandTilesArr: if playerHandTileCount == 1: return False elif playerHandTileCount == 2: twoCount += 1 elif playerHandTileCount == 4: twoCount += 2 if twoCount > 1: return False return True
def isPiao(self): playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI] if len(playerChiTiles) > 0: return False playerHandTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] newPlayerHandTiles = MTile.cloneTiles(playerHandTiles) newPlayerHandTiles.append(self.winTile) ishu, pattern = MWin.isHu(newPlayerHandTiles, self.tableTileMgr.getMagicTiles(True), True) ftlog.debug('MPanjinOneResult.calcWin isPiao newPlayerHandTiles:', newPlayerHandTiles, 'ishu', ishu, 'pattern', pattern) if ishu: for p in pattern: if len(p) == 3: if (p[0] == p[2] or p[1] == p[2] or p[0] == p[1]): continue else: ftlog.debug('MPanjinOneResult.calcWin isPiao False') return False ftlog.debug('MPanjinOneResult.calcWin isPiao True') return True
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 canTingForQiangjin(self, tiles, leftTiles, tile, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0,tingForQiangjin = True): isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, curSeatId, winSeatId, actionID,tingForQiangjin,self.flowerRule) ftlog.debug( 'MTingQueshouRule.canTingForQiangjin using MTing isTing:', isTing, ' tingResults:', tingResults) return isTing, tingResults
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