def getHandTilesValue(cls, tiles_player_hand, tiles_left): """计算手牌价值 返回值: 1)每张牌的价值 2)手牌花色个数的数组 """ tiles_player_Arr = MTile.changeTilesToValueArr( tiles_player_hand[MHand.TYPE_HAND]) tiles_left_Arr = MTile.changeTilesToValueArr(tiles_left) # 权值初始化 tiles_value_Arr = [0 for _ in range(40)] for index in range(MTile.TILE_MAX_VALUE): if tiles_player_Arr[index] == 0: continue tiles_value_Arr[ index] = tiles_player_Arr[index] * 4 + tiles_left_Arr[index] if index < 30: if index % 10 < 9: tiles_value_Arr[index] += tiles_player_Arr[index + 1] * 3 if index % 10 < 8: tiles_value_Arr[index] += tiles_player_Arr[index + 2] * 2 if index % 10 > 1: tiles_value_Arr[index] += tiles_player_Arr[index - 1] * 3 if index % 10 > 2: tiles_value_Arr[index] += tiles_player_Arr[index - 2] * 2 return tiles_value_Arr, tiles_player_Arr
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 getHandTilesValue(cls, tiles_player_hand, tiles_left): """计算手牌价值 返回值: 1)每张牌的价值 2)手牌花色个数的数组 """ tiles_player_Arr = MTile.changeTilesToValueArr(tiles_player_hand[MHand.TYPE_HAND]) tiles_left_Arr = MTile.changeTilesToValueArr(tiles_left) # 权值初始化 tiles_value_Arr = [0 for _ in range(40)] for index in range(MTile.TILE_MAX_VALUE): if tiles_player_Arr[index] == 0: continue tiles_value_Arr[index] = tiles_player_Arr[index] * 4 + tiles_left_Arr[index] if index < 30: if index % 10 < 9: tiles_value_Arr[index] += tiles_player_Arr[index + 1] * 3 if index % 10 < 8: tiles_value_Arr[index] += tiles_player_Arr[index + 2] * 2 if index % 10 > 1: tiles_value_Arr[index] += tiles_player_Arr[index - 1] * 3 if index % 10 > 2: tiles_value_Arr[index] += tiles_player_Arr[index - 2] * 2 return tiles_value_Arr, tiles_player_Arr
def isHunyise(self): """ 混一色:只有一色牌(如全是万),有金牌,但金牌不同色 """ ''' colorArr = [0, 0, 0, 0] handTile = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) # 手牌区+吃+碰+杠+锚+胡区 for tile in handTile: color = MTile.getColor(tile) colorArr[color] = 1 magicTile = self.tableTileMgr.getMagicTile() magicTileColor = MTile.getColor(magicTile) handTile = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) tilesArr = MTile.changeTilesToValueArr(handTile) count = MTile.getTileCountByColor(tilesArr, magicTileColor) magicCount = MTile.getTileCount(magicTile,handTile[MHand.TYPE_HAND]) if count!=magicCount: return False colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount == 2 and colorArr[magicTileColor] == 1: return True return False ''' magicTile = self.tableTileMgr.getMagicTile() magicCount = 0 allTiles = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) #allTiles = MHand.copyAllTilesToListButHu(handTile) allTileArr = MTile.changeTilesToValueArr(allTiles) allColors = MTile.getColorCount(allTileArr) for tile in allTiles: if magicTile and tile == magicTile: magicCount = magicCount + 1 for i in range(magicCount): allTiles.remove(magicTile) tileArr = MTile.changeTilesToValueArr(allTiles) colors = MTile.getColorCount(tileArr) if allColors == 2 and colors == 1: return True return False
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): # 检查是否过胡状态 自摸情况下不判断过胡 if getTileType != MWinRule.WIN_BY_MYSELF and self.tableTileMgr.isPassHuTileBySeatId( winSeatId, tile): ftlog.debug('MWinRuleXueZhan.isHu passHu...') return False, [] tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles)) # 获取当前座位号定缺的花色 colorAbsence = self.tableTileMgr.absenceColors[winSeatId] # 获取手牌中定缺花色牌的数量,大于0,不用判断胡 colorAbsenceNum = MTile.getTileCountByColor(tileArr, colorAbsence) # ftlog.debug('MWinRuleXueZhan colorAbsenceNum:', colorAbsenceNum, 'tiles:', tiles, 'tile:', tile, 'colorAbsence:', colorAbsence) if colorAbsenceNum > 0: return False, [] resultQidui, qiduiPattern = MWin.isQiDui(tiles[MHand.TYPE_HAND], []) if resultQidui: return True, qiduiPattern result, rePattern = MWin.isHu(tiles[MHand.TYPE_HAND]) if result: return True, rePattern return False, []
def isHuWishSpecialJiang(cls, tiles, jiangPattern, magics=[]): """ 指定将牌类型判断是否胡牌 暂时不考虑将牌 """ # 先移除将牌。无指定将牌,判和失败 tileArr = MTile.changeTilesToValueArr(tiles) jiangTile = jiangPattern[0] if tileArr[jiangTile] < 2: return False, [] # 移除将牌 tileArr[jiangTile] -= 2 # 计算剩下的结果 resultArr = [] resultArr.append(jiangPattern) tileTypes = [ MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG ] winResult = False for tileType in tileTypes: winResult, _, _tArr, _rArr, _mArr = cls.isHuWithMagic( tileArr, resultArr, magics, True, tileType, False) if not winResult: return False, [] else: tileArr = copy.deepcopy(_tArr) resultArr = copy.deepcopy(_rArr) return winResult, resultArr
def isQiDui(cls, tiles, baoTiles=[]): ''' 判断是否是七对 现在加入宝牌处理判断 特别注意,baoTiles不是癞子牌,是宝牌,穷和玩法特有的宝牌,上听后生效。 上听后摸到一张就和牌 baoTiles可以是癞子牌,但传进来的必须是手牌中的赖子数组,如手牌中有2个7是赖子 baoTiles=[7,7] ''' #ftlog.debug('MWin.isQiDui tiles:', tiles, ' baoTiles:', baoTiles) tileArr = MTile.changeTilesToValueArr(tiles) #ftlog.debug('MWin.isQiDui tileArr:', tileArr) for magicTile in baoTiles: tileArr[magicTile] -= 1 allMagicTiles = copy.deepcopy(baoTiles) resultArr = [] duiCount = 0 for tileIndex in range(0, len(tileArr)): if tileArr[tileIndex] == 0: continue #单张情况 elif tileArr[tileIndex] == 1: if len(allMagicTiles) >= 1: duiCount += 1 resultArr.append([tileIndex, allMagicTiles.pop(0)]) #三张情况 elif tileArr[tileIndex] == 3: if len(allMagicTiles) >= 1: duiCount += 2 resultArr.append([tileIndex, tileIndex]) resultArr.append([tileIndex, allMagicTiles.pop(0)]) #一对 elif tileArr[tileIndex] == 2: resultArr.append([tileIndex, tileIndex]) duiCount += 1 #两对 elif tileArr[tileIndex] == 4: resultArr.append([tileIndex, tileIndex]) resultArr.append([tileIndex, tileIndex]) duiCount += 2 for index in range(len(allMagicTiles)): if ((index + 1) % 2) == 0: resultArr.append( [allMagicTiles[index - 1], allMagicTiles[index]]) duiCount += 1 ftlog.info('MWin.isQiDui, tiles:', tiles, ' baoTiles:', baoTiles, ' duiCount:', duiCount, ' resultArr', resultArr) if (duiCount == 7) and (len(tiles) == 14): return True, resultArr elif (duiCount == 6) and (len(tiles) == 12): return True, resultArr else: return False, []
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 返回值: 是否可以听牌,听牌详情 """ # 血流 血战听牌 需要没有缺牌 tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles)) # 获取当前座位号定缺的花色 colorAbsence = self.tableTileMgr.absenceColors[winSeatId] # 获取手牌中定缺花色牌的数量,大于1,不用判断听 缺牌为1张的时候,打出去缺牌,有可能会听牌 colorAbsenceNum = MTile.getTileCountByColor(tileArr, colorAbsence) # ftlog.debug('MTingRuleSiChuan.canTing colorAbsenceNum:', colorAbsenceNum, 'tiles:', tiles, 'tile:', tile, 'colorAbsence:', colorAbsence) if colorAbsenceNum > 1: return False, [] resultFlag, result = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, tiles, leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) # 如果听牌中有定的缺色,需要把其余的听口去掉 ftlog.debug('MTingRuleSiChuan.canTing result:', result) if resultFlag and colorAbsenceNum == 1: filterResult = [] for tingNodes in result: if MTile.getColor(tingNodes['dropTile']) == colorAbsence: filterResult.append(tingNodes) ftlog.debug('MTingRuleSiChuan.canTing filterResult:', filterResult) return len(filterResult) > 0, filterResult else: return resultFlag, 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 getHandTilesValue(cls, tiles_player_hand, tiles_left): """计算手牌价值 返回值: 1)每张牌的价值 2)手牌花色个数的数组 """ tiles_player_Arr = MTile.changeTilesToValueArr( tiles_player_hand[MHand.TYPE_HAND]) # tiles_left_Arr = MTile.changeTilesToValueArr(tiles_left) # 权值初始化 tiles_value_Arr = [0 for _ in range(40)] for index in range(MTile.TILE_MAX_VALUE): if tiles_player_Arr[index] == 0: continue # 风牌只考虑自己的价值 tiles_value_Arr[index] = tiles_player_Arr[index] * 4 # + tiles_left_Arr[index] # 万筒条还考虑同周围牌的关系 if index < 30: if index % 10 < 9: tiles_value_Arr[index] += tiles_player_Arr[index + 1] * 3 if index % 10 < 8: tiles_value_Arr[index] += tiles_player_Arr[index + 2] * 2 if index % 10 > 1: tiles_value_Arr[index] += tiles_player_Arr[index - 1] * 3 if index % 10 > 2: tiles_value_Arr[index] += tiles_player_Arr[index - 2] * 2 ftlog.debug('getHandTilesValue valueArr:', tiles_value_Arr, 'playerArr:', tiles_player_Arr) return tiles_value_Arr, tiles_player_Arr
def isQiduiDa(self): """ 七大对:七对的牌面值是连续的 """ if not self.isQidui(): return False handTile = copy.deepcopy( self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) handTile.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) hTileArr = MTile.changeTilesToValueArr(handTile) shunCount = 0 shunIndex = 0 for tileIndex in range(len(hTileArr)): if hTileArr[tileIndex] > 0: if 0 == shunIndex: shunCount += 1 shunIndex = tileIndex else: if (tileIndex != (shunIndex + 1)): ftlog.debug( 'weihai_one_result.isQiduiDa result: False') return False else: shunCount += 1 shunIndex = tileIndex if shunCount == 7: ftlog.debug('weihai_one_result.isQiduiDa result: True') return True ftlog.debug('weihai_one_result.isQiduiDa result: False') return False
def canTingBeforeAddTile(cls, tilePatternChecker, tableTileMgr, tiles, leftTiles, winRule, magicTiles=[], curSeatId=0, winSeatId=0): """判断在摸牌之前是否可以听 """ ftlog.debug('MTing.canTingBeforeAddTile', tiles) leftTileArr = MTile.changeTilesToValueArr(leftTiles) leftTileCount = len(leftTileArr) ftlog.debug('MTing.canTing leftTiles:', leftTiles, ' leftTileArr:', leftTileArr, ' leftTileCount:', leftTileCount) result = [] resultNode, isHuAll = cls.canWinAddOneTile(tilePatternChecker, tableTileMgr, leftTileArr, leftTileCount, tiles, winRule, magicTiles, winSeatId) if len(resultNode) > 0: winNode = {} winNode['winNodes'] = resultNode result.append(winNode) return len(result) > 0, result
def isQingyise(self, tiles): """ 清一色:由同一门花色(筒子或条子)组成的和牌牌型 """ tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToListButHu(tiles)) colors = MTile.getColorCount(tileArr) #ftlog.debug('MWinRuleQueshou.isQingyise tileArr=',tileArr,colors) return colors == 1
def isHu(self, tiles, tile, isTing, getTileType, magicTiles = [], tingNodes = [], curSeatId = 0, winSeatId = 0, actionID = 0, isGangKai = False,isForHu = True): if self.tableTileMgr.playMode == "luosihu-luosihu" and isForHu: if not isTing: if not self.tableTileMgr.players[winSeatId].isWon(): return False,[],0 allTiles = MHand.copyAllTilesToListButHu(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) # 需要缺一门: 定缺的时候约定的那门 if self.absenceColor: if MTile.getTileCountByColor(tilesArr, self.absenceColor[winSeatId]) > 0: return False, [],0 result, pattern = self.isQidui(tiles) if result: if self.tableTileMgr.playMode == "luosihu-luosihu": self.fanXing[self.QIDUI]["index"] = 1 return True, pattern,self.fanXing[self.QIDUI]["index"] result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND], magicTiles) if result: ftlog.debug('MWinRuleLuosihu.isHu result=',result,' getTileType=',getTileType,' pattern=',pattern) player = self.tableTileMgr.players[winSeatId] self.winSeatId = winSeatId self.__tile_pattern_checker = MTilePatternCheckerFactory.getTilePatternChecker(MPlayMode.LUOSIHU) playersAllTiles = [[] for _ in range(self.tableTileMgr.playCount)] self.__win_patterns = [[] for _ in range(self.tableTileMgr.playCount)] self.__win_patterns[winSeatId] = [pattern] for seatId in range(self.tableTileMgr.playCount): if seatId == winSeatId: playersAllTiles[seatId] = copy.deepcopy(tiles) else: playersAllTiles[seatId] = self.tableTileMgr.players[seatId].copyTiles() self.setAllPlayerTiles(playersAllTiles) # 判断和牌的时候 self.__tile_pattern_checker.initChecker(playersAllTiles, tile, self.tableTileMgr, True, curSeatId, winSeatId, actionID) winnerResult = [] if self.tableTileMgr.playMode == "luosihu-ctxuezhan": winnerResult = self.getWinnerResultsForXueZhanDaoDi(winSeatId) elif self.tableTileMgr.playMode == "luosihu-xuezhan": winnerResult = self.getWinnerResultsForLuoSiHuXueZhan(winSeatId) elif self.tableTileMgr.playMode == "luosihu-luosihu": winnerResult = self.getWinnerResultsForLuoSiHu(winSeatId) finalResult = [] finalResult.extend(winnerResult) maxFan = self.tableConfig.get(MTDefine.MAX_FAN, 0) winScore,indexFan = self.getScoreByResults(finalResult, maxFan) ftlog.debug('MWinRuleLuosihu.isHu player.guoHuPoint :',winScore,' finalResult=',finalResult,' indexFan') # 过胡判断 if getTileType == MWinRule.WIN_BY_MYSELF: return True,pattern,indexFan if player.guoHuPoint >= winScore and self.tableTileMgr.playMode == "luosihu-ctxuezhan": return False, [],0 player.totalWinPoint = winScore return True,pattern,indexFan return False, [],0
def isQingyise(self, tiles): """ 清一色:由同一门花色(筒子或条子)组成的和牌牌型 """ tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToListButHu(tiles)) colors = MTile.getColorCount(tileArr) #ftlog.debug('MWinRuleQueshou.isQingyise tileArr=',tileArr,colors) return colors == 1
def hasPeng(cls, tiles, tile): """是否可以碰 判断之前tile已经加到tiles中 tiles - 手牌 tile - 待碰的牌 """ tileArr = MTile.changeTilesToValueArr(tiles) if tileArr[tile] >= 3: return True return False
def hasAnGang(cls, tiles, tile): """自摸是否可以暗杠 判断杠牌时,tile已经加入tiles中 tiles - 手牌 tile - 待杠的牌 """ tileArr = MTile.changeTilesToValueArr(tiles) if tileArr[tile] == 4: return True return False
def isFengyise(self): """ 风一色:由东南西北中发白组成的胡牌 """ handTile = MHand.copyAllTilesToList( self.playerAllTiles[self.winSeatId]) # 手牌区+吃+碰+杠+锚+胡区 handArr = MTile.changeTilesToValueArr(handTile) colorCount = MTile.getColorCount(handArr) result, _ = MWin.isLuanFengyise(handTile, colorCount) return result
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 getLongGenCount(self): ''' 获取玩家手牌根的个数 杠过的牌也算 ''' count = 0 tiles = MHand.copyAllTilesToListButHu(self.playerAllTiles) tileArr = MTile.changeTilesToValueArr(tiles) for tile in tileArr: if tile == 4: count += 1 return count
def isHunyise(self, tiles, magicTiles): if not len(magicTiles): return False magicTile = magicTiles[0] magicCount = 0 allTiles = MHand.copyAllTilesToListButHu(tiles) allTileArr = MTile.changeTilesToValueArr(allTiles) allColors = MTile.getColorCount(allTileArr) for tile in allTiles: if tile == magicTile: magicCount = magicCount + 1 for i in range(magicCount): allTiles.remove(magicTile) tileArr = MTile.changeTilesToValueArr(allTiles) colors = MTile.getColorCount(tileArr) #ftlog.debug('MWinRuleQueshou.isHunyise allColors colors=',allColors,colors,magicCount,allTiles) if allColors == 2 and colors == 1: return True return False
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 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 # 检查8张的规则 allTiles = MHand.copyAllTilesToListButHu(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) wanCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_WAN) tiaoCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TIAO) tongCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TONG) fengCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_FENG) ftlog.debug('win_rule_pingdu.isHu allTiles:', allTiles, ' tilesLength:', len(allTiles), ' tilesArr:', tilesArr, ' wanCount:', wanCount, ' tiaoCount:', tiaoCount, ' tongCount:', tongCount, ' fengCount:', fengCount) if (wanCount >= 8) or (tiaoCount >= 8) or (tongCount >= 8) or (fengCount >= 8): pass else: # ftlog.info('win_rule_pingdu.isHu ok but do not have >=8 tiles in one color, allTiles:', allTiles # , ' tilesLength:', len(allTiles) # , ' tilesArr:', tilesArr # , ' wanCount:', wanCount # , ' tiaoCount:', tiaoCount # , ' tongCount:', tongCount # , ' fengCount:', fengCount) return False, [] # 平度麻将允许胡七对 resultQiDui, patternQiDui = MWin.isQiDui(tiles[MHand.TYPE_HAND]) if resultQiDui: return True, patternQiDui result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND]) return result, pattern
def isLongGen(self): ''' 龙根 和牌时 判断手牌中是否有龙根 4张为龙根 ''' tiles = copy.deepcopy(self.playerAllTiles[MHand.TYPE_HAND]) tileArr = MTile.changeTilesToValueArr(tiles) ftlog.debug('MSiChuanTilePattern.isLongGen tiles: ', tiles, 'tileArr: ', tileArr) for tile in tileArr: if tile == 4: ftlog.debug('MSiChuanTilePattern.isLongGen: True tile: ', tile) return True ftlog.debug('MSiChuanTilePattern.isLongGen: False') return False
def isQingYiSe(self): if self.colorState[self.winSeatId] == 1: return True if self.isMagicTile(): tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToListButHu( self.playerAllTiles[self.winSeatId])) tempCountColor = MTile.getColorCount(tileArr) if tempCountColor == 1: return True return False
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 返回值: 是否可以听牌,听牌详情 """ tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles)) resultFlag, result = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, tiles, leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('MTingJiPingHuRule.canTing result:', resultFlag, result) return resultFlag, result
def SatisyYaoJiu(self,tiles): #有幺九 allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) yaojiucount = MTile.getYaoJiuCount(tilesArr) if yaojiucount>0: return True else: for feng in range(MTile.TILE_DONG_FENG,MTile.TILE_BAI_BAN+1): if tilesArr[feng]>=1: return True return False
def SatisyKe(self,tiles): #有刻 if len(tiles[MHand.TYPE_PENG])==0: ming,an = MTile.calcGangCount(tiles[MHand.TYPE_GANG]) if (ming + an) ==0: allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) #中发白做将 if tilesArr[MTile.TILE_HONG_ZHONG] < 2 and tilesArr[MTile.TILE_FA_CAI] < 2 and tilesArr[MTile.TILE_BAI_BAN] < 2: #中发白 if not self.hasKe(tiles[MHand.TYPE_HAND]): return False return True
def SatisyYaoJiu(self,tiles): #有幺九 if len(tiles[MHand.TYPE_MAO])==0: allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) #中发白做将 if tilesArr[MTile.TILE_HONG_ZHONG] < 2 and tilesArr[MTile.TILE_FA_CAI] < 2 and tilesArr[MTile.TILE_BAI_BAN] < 2: #中发白 if not (tilesArr[MTile.TILE_HONG_ZHONG]>0 and tilesArr[MTile.TILE_FA_CAI]>0 and tilesArr[MTile.TILE_BAI_BAN]>0): yaojiucount = MTile.getYaoJiuCount(tilesArr) if yaojiucount==0: return False return True
def hasChi(cls, tiles, tile): """是否可以吃 吃牌的判断中,tile已经在tiles中 参数: tiles - 手牌 tile - 待吃的牌 返回值:吃牌选择 最多三种解 例子: [[2, 3, 4], [3, 4, 5], [4, 5, 6 """ tileArr = MTile.changeTilesToValueArr(tiles) result = [] # 第一种情况 001 if (tile % 10) >= 3: if tileArr[tile - 2] > 0 and tileArr[tile - 1] > 0 and tileArr[tile] > 0: solution = [tile - 2, tile - 1, tile] result.append(solution) ''' # 第三种情况 100 if (tile % 10) < 8: if tileArr[tile] > 0 and tileArr[tile + 1] > 0 and tileArr[tile + 2] > 0: solution = [tile, tile + 1, tile + 2] result.append(solution) ''' # 第二种情况 010 if (tile % 10) >= 2 and (tile % 10) < 9: if tileArr[tile - 1] > 0 and tileArr[tile] > 0 and tileArr[tile + 1] > 0: solution = [tile - 1, tile, tile + 1] result.append(solution) # 第三种情况 100 if (tile % 10) < 8: if tileArr[tile] > 0 and tileArr[tile + 1] > 0 and tileArr[tile + 2] > 0: solution = [tile, tile + 1, tile + 2] result.append(solution) ''' # 第一种情况 001 if (tile % 10) >= 3: if tileArr[tile - 2] > 0 and tileArr[tile - 1] > 0 and tileArr[tile] > 0: solution = [tile - 2, tile - 1, tile] result.append(solution) ''' return result
def getWinnerGen(self): #只要你手上有4个一样的,哪怕是碰了之后自己摸的加杠,或者手上有4张一样的牌,没有杠等等都算一番,你有2根就是2番,*4 #杠牌个数+手中可暗杠个数 winnerGen = 0 handTiles = self.tableTileMgr.players[self.winSeatId].copyHandTiles() tileArr = MTile.changeTilesToValueArr(handTiles) for tile in range(MTile.TILE_MAX_VALUE): if tileArr[tile] == 4: winnerGen += 1 gangTiles = self.tableTileMgr.players[self.winSeatId].copyGangArray() winnerGen += len(gangTiles) if winnerGen > 0: return True,winnerGen else: return False,winnerGen
def getWinnerGen(self): #只要你手上有4个一样的,哪怕是碰了之后自己摸的加杠,或者手上有4张一样的牌,没有杠等等都算一番,你有2根就是2番,*4 #杠牌个数+手中可暗杠个数 winnerGen = 0 handTiles = self.tableTileMgr.players[self.winSeatId].copyHandTiles() tileArr = MTile.changeTilesToValueArr(handTiles) for tile in range(MTile.TILE_MAX_VALUE): if tileArr[tile] == 4: winnerGen += 1 gangTiles = self.tableTileMgr.players[self.winSeatId].copyGangArray() winnerGen += len(gangTiles) if winnerGen > 0: return True, winnerGen else: return False, winnerGen
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): ftlog.debug('MWinRuleJiPingHu.isHu tiles:', tiles , ' tile:', tile , ' isTing:', isTing , ' getTileType:', getTileType , ' magicTiles:', magicTiles , ' tingNodes:', tingNodes , ' winSeatId:', winSeatId ) # 检查是否过胡状态 if self.tableTileMgr.isPassHuTileBySeatId(winSeatId, tile): if self.msgProcessor: ftlog.debug('songsong MWinRuleJiPingHu.isHu isPassHuTileBySeatId:',winSeatId, 'tile:',tile) self.msgProcessor.table_call_show_tips(MTDefine.TIPS_NUM_10, self.tableTileMgr.players[winSeatId]) return False, [] huqidui = self.tableConfig.get(MTDefine.HUQIDUI, MTDefine.HUQIDUI_YES) if huqidui: resultQidui, qiduiPattern = MWin.isQiDui(tiles[MHand.TYPE_HAND], magicTiles) if resultQidui: ftlog.debug('MWinRuleJiPingHu.isQiDui True,', qiduiPattern) return True, qiduiPattern resultshisan = MWin.isShisanyao(tiles, magicTiles) if resultshisan: ftlog.debug('MWinRuleJiPingHu.isShisanyao True,') return True, [] tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles)) result, rePattern = MWin.isHu(tiles[MHand.TYPE_HAND], magicTiles) if result: ftlog.debug('MWinRuleJiPingHu.isHu True, ', rePattern) if getTileType == MWinRule.WIN_BY_OTHERS: jipinghu = False # 【鸡胡】:X1,顺牌+刻牌+1对将. 鸡胡只能自摸/抢杠胡 jipinghu = self.isJipinghu(rePattern, tiles, tileArr, magicTiles) if jipinghu: if self.msgProcessor: ftlog.debug('MWinRuleJiPingHu.isHu jipinghu buneng hu:') self.msgProcessor.table_call_show_tips(MTDefine.TIPS_NUM_12,self.tableTileMgr.players[winSeatId]) return False, [] else: return True, rePattern else: return True, rePattern ftlog.debug('MWinRuleJiPingHu.isHu False, []') return False, []
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 hasPeng(self, tiles, tile, seatId=-1): """是否有碰牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待碰的牌 """ #是否允许会牌参与,如果不允许,删除会牌 tilesForPeng = copy.deepcopy(tiles[MHand.TYPE_HAND]) if not self.tableTileMgr.allowMagicChiPengGang(): magicTile = self.tableTileMgr.getMagicTile() while magicTile in tilesForPeng: tilesForPeng.remove(magicTile) pengSolutions = [] normalPeng = MPeng.hasPeng(tilesForPeng, tile) if normalPeng: pengSolutions.append([tile, tile, tile]) magics = self.tableTileMgr.getMagicTiles(False) tileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND]) tileArr, magicTiles = self.tableTileMgr.exculeMagicTiles(tileArr, magics) magicCount = len(magicTiles) if magicCount == 0: return pengSolutions if not self.tableTileMgr.canUseMagicTile(MTableState.TABLE_STATE_PENG): return pengSolutions ftlog.debug('MPengRule.hasPeng tile:', tile , ' tileCount:', tileArr[tile] , ' magicCount:', magicCount) if (magicCount == 0) or (tileArr[tile] == 0): return pengSolutions if magicCount >= 1 and tileArr[tile] >= 2: # 使用一个癞子 pengSolutions.append([tile, tile, magicTiles[0]]) if magicCount >= 2 and tileArr[tile] >= 1: # 使用两个癞子 pengSolutions.append([tile, magicTiles[0], magicTiles[1]]) return pengSolutions
def isQidui(self, tiles): handTiles = copy.deepcopy(tiles[MHand.TYPE_HAND]) handTilesArr = MTile.changeTilesToValueArr(handTiles) if len(handTiles) != 14: return False, [] pattern = [] for tile in range(MTile.TILE_MAX_VALUE): if handTilesArr[tile] == 1 or handTilesArr[tile] == 3: # 只要出现单数,必然不是七对 return False, [] if handTilesArr[tile] == 2: pattern.append([tile, tile]) if handTilesArr[tile] == 4: # 和LuosihuOneResult配合 pattern.extend([[tile, tile],[tile, tile]]) return True, pattern
def canTingBeforeAddTile(cls, tiles, leftTiles, winRule, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0,tingForQiangjin = False,flowerRule = None): """判断在摸牌之前是否可以听 """ #ftlog.debug('MTile.changeTilesToValueArr', tiles[MHand.TYPE_HAND]) leftTileArr = MTile.changeTilesToValueArr(leftTiles) leftTileCount = len(leftTileArr) ''' ftlog.debug('MTing.canTingBeforeAddTile leftTiles:', leftTiles , ' leftTileArr:', leftTileArr , ' leftTileCount:', leftTileCount) ''' result = [] resultNode = cls.canWinAddOneTile(leftTileArr, leftTileCount, tiles, winRule, magicTiles, curSeatId, winSeatId, actionID,tingForQiangjin,flowerRule) if len(resultNode) > 0: winNode = {} winNode['winNodes'] = resultNode result.append(winNode) if tingForQiangjin: return len(result) > 0, result return len(result) > 0, result
def getTileLeftCount(self, tile): """获取某个tile剩余数量""" tileArr = MTile.changeTilesToValueArr(self.__tiles) return tileArr[tile]
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
from majiang2.table_tile.table_tile_luosihu import MTableTileLuosihu from majiang2.table_tile.table_tile_queshou import MTableTileQueshou class MTableTileFactory(object): def __init__(self): super(MTableTileFactory, self).__init__() @classmethod def getTableTileMgr(cls, playerCount, playMode, runMode): """牌桌手牌管理器获取工厂 输入参数: playMode - 玩法 返回值: 对应玩法手牌管理器 """ if MPlayMode().isSubPlayMode(playMode, MPlayMode.LUOSIHU): return MTableTileLuosihu(playerCount, playMode, runMode) elif MPlayMode().isSubPlayMode(playMode, MPlayMode.QUESHOU): return MTableTileQueshou(playerCount, playMode, runMode) return MTableTile(playerCount, playMode, runMode) if __name__ == "__main__": tableTileMgr = MTableTileFactory.getTableTileMgr(4, MPlayMode.LUOSIHU, MRunMode.CONSOLE) tableTileMgr.tileTestMgr.setHandTiles([[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]]) tableTileMgr.tileTestMgr.setTiles([9, 9, 9, 9]) tableTileMgr.shuffle(0, 13) tiles = tableTileMgr.tiles print tiles tileArr = MTile.changeTilesToValueArr(tiles) print tileArr