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 isJiHu(self): # 只要牌里有幺鸡,就是鸡胡 # tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId])) if self.tableConfig.get(MTDefine.HUI_PAI, 0) and self.tableConfig.get( MTDefine.JI_HU, 0): magics = self.tableTileMgr.getMagicTiles(True) if magics[0] == MTile.TILE_ONE_TIAO == self.winTile: playerHandTiles = copy.deepcopy( self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) if MTile.TILE_ONE_TIAO in playerHandTiles: return False else: return True if self.tableConfig.get(MTDefine.JI_HU, 0): tempCount = MTile.getTileCount( MTile.TILE_ONE_TIAO, MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId])) ftlog.debug('MPanjinOneResult.calcWin isJiHu tempCount:', tempCount) # 胡牌 if tempCount >= 1: return True else: return False return False
def initChecker(self, playersAllTiles, winTile, tableTileMgr, isWinTileOnHand, curSeatId, winSeatId, actionID = 0): self.setLastSeatId(curSeatId) self.setWinSeatId(winSeatId) self.setActionID(actionID) self.setWinTile(winTile) self.setTableTileMgr(tableTileMgr) self.setTableConfig(self.tableTileMgr.tableConfig) self.__player_all_tiles = [[] for _ in range(self.tableTileMgr.playCount)] self.__player_all_tiles_arr = [[] for _ in range(self.tableTileMgr.playCount)] self.__player_hand_tiles_with_hu = [[] for _ in range(self.tableTileMgr.playCount)] # 不要用tableTileMgr.player里面的牌,因为可能这些牌还没抓到用户手里,以传入的playersAllTiles为准 for seatId in range(len(playersAllTiles)): # 按手牌格式的数组 self.__player_all_tiles[seatId] = copy.deepcopy(playersAllTiles[seatId]) # 合到一个数组中 self.__player_all_tiles_arr[seatId].extend(MHand.copyAllTilesToList(self.__player_all_tiles[seatId])) # 只获取手牌,此时手牌包含所胡的牌 self.__player_hand_tiles_with_hu[seatId] = copy.deepcopy(playersAllTiles[seatId][MHand.TYPE_HAND]) if not isWinTileOnHand and seatId == winSeatId: self.__player_hand_tiles_with_hu[seatId].append(winTile) ftlog.info('MTilePatternChecker.calcScore __player_all_tiles=', self.__player_all_tiles) ftlog.info('MTilePatternChecker.calcScore __player_all_tiles_arr=', self.__player_all_tiles_arr) ftlog.info('MTilePatternChecker.calcScore __player_hand_tiles_with_hu=', self.__player_hand_tiles_with_hu)
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 isJiHu(self): # 只要牌里有幺鸡,就是鸡胡 # tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId])) iszimo = self.lastSeatId == self.winSeatId tempCount = MTile.getTileCount( MTile.TILE_ONE_TIAO, MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId])) ftlog.debug('MBaichengOneResult.calcWin isJiHu tempCount:', tempCount) magics = self.tableTileMgr.getMagicTiles(True) if iszimo and (self.winTile == magics[0] == MTile.TILE_ONE_TIAO): isHuYaoji = False for wn in self.winNodes: if wn['winTile'] == MTile.TILE_ONE_TIAO: isHuYaoji = True if isHuYaoji: return True else: if tempCount <= 1: return False else: return True else: # 胡牌 if tempCount >= 1: return True else: return False
def isZhangYiSe(self, seatId): tiles = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) if len(tiles) % 2 > 0: tiles.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) for tile in tiles: if (tile >= MTile.TILE_DONG_FENG) or (MTile.getValue(tile) % 3 != 2): return False return True
def 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 isQingYiSe(self, allTiles, qingColor): ''' 判断当前是否是清一色 ''' allTilesArr = MHand.copyAllTilesToList(allTiles) for tile in allTilesArr: if MTile.getColor(tile) != qingColor: return False return True
def doQingYiSe(self, allTiles, leftTiles, seatId, abColors): ''' 是否做清一色 ''' isSanSha, bestColor = self.isSanShaQingYiSe(seatId, abColors) if isSanSha: ftlog.debug('SanSha, best situation!!! doSanShaQingYiSe') return True, bestColor length = 9 if len(leftTiles) >= 50: length = 8 elif len(leftTiles) >= 40: length = 9 elif len(leftTiles) >= 30: length = 10 elif len(leftTiles) >= 20: length = 11 allTilesArr = MHand.copyAllTilesToList(allTiles) cpgTiles = MHand.copyTiles( allTiles, [MHand.TYPE_CHI, MHand.TYPE_PENG, MHand.TYPE_GANG]) wans = MTile.filterTiles(allTilesArr, MTile.TILE_WAN) wanLength = len(wans) if wanLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_WAN: return False, MTile.TILE_FENG return True, MTile.TILE_WAN tongs = MTile.filterTiles(allTilesArr, MTile.TILE_TONG) tongLength = len(tongs) if tongLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_TONG: return False, MTile.TILE_FENG return True, MTile.TILE_TONG tiaos = MTile.filterTiles(allTilesArr, MTile.TILE_TIAO) tiaoLength = len(tiaos) if tiaoLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_TIAO: return False, MTile.TILE_FENG return True, MTile.TILE_TIAO if wanLength >= tongLength and wanLength >= tiaoLength: return False, MTile.TILE_WAN elif tongLength >= wanLength and tongLength >= tiaoLength: return False, MTile.TILE_TONG else: return False, MTile.TILE_TIAO
def isDuanYaoJiu(self): """ 断幺九:每副顺子,刻字,将牌都不包含1或9 """ if self.tableConfig.get(MTDefine.DUANYAOJIU, 0) != 1: return False allPlayerTiles = MHand.copyAllTilesToList(self.tableTileMgr.players[self.winSeatId].copyTiles()) yaoJiuCount = 0 for tile in allPlayerTiles: if MTile.getColor(tile) == MTile.TILE_FENG or tile%10 == 1 or tile%10 == 9: yaoJiuCount += 1 return yaoJiuCount == 0
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 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): #有幺九 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 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): #有幺九 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 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 doQingYiSe(self, allTiles, leftTiles): ''' 是否做清一色 ''' length = 9 if len(leftTiles) >= 50: length = 8 elif len(leftTiles) >= 40: length = 9 elif len(leftTiles) >= 30: length = 10 elif len(leftTiles) >= 20: length = 11 allTilesArr = MHand.copyAllTilesToList(allTiles) cpgTiles = MHand.copyTiles( allTiles, [MHand.TYPE_CHI, MHand.TYPE_PENG, MHand.TYPE_GANG]) wans = MTile.filterTiles(allTilesArr, MTile.TILE_WAN) wanLength = len(wans) if wanLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_WAN: return False, MTile.TILE_FENG return True, MTile.TILE_WAN tongs = MTile.filterTiles(allTilesArr, MTile.TILE_TONG) tongLength = len(tongs) if tongLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_TONG: return False, MTile.TILE_FENG return True, MTile.TILE_TONG tiaos = MTile.filterTiles(allTilesArr, MTile.TILE_TIAO) tiaoLength = len(tiaos) if tiaoLength >= length: for tile in cpgTiles: if MTile.getColor(tile) != MTile.TILE_TIAO: return False, MTile.TILE_FENG return True, MTile.TILE_TIAO if wanLength >= tongLength and wanLength >= tiaoLength: return False, MTile.TILE_WAN elif tongLength >= wanLength and tongLength >= tiaoLength: return False, MTile.TILE_TONG else: return False, MTile.TILE_TIAO
def SatisyYaoJiu(self, tiles): #有幺九 allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) if self.tableConfig.get(MTDefine.HUI_PAI, 0): magics = self.tableTileMgr.getMagicTiles(True) tilesArr[magics[0]] = 0 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 isDuanYaoJiu(self): """ 断幺九:每副顺子,刻字,将牌都不包含1或9 """ if self.tableConfig.get(MTDefine.DUANYAOJIU, 0) != 1: return False allPlayerTiles = MHand.copyAllTilesToList( self.tableTileMgr.players[self.winSeatId].copyTiles()) yaoJiuCount = 0 for tile in allPlayerTiles: if MTile.getColor( tile ) == MTile.TILE_FENG or tile % 10 == 1 or tile % 10 == 9: yaoJiuCount += 1 return yaoJiuCount == 0
def isQingyise(self): """ 清一色:只有一色牌(如全是万),有无金牌皆可,但金牌必须与其他牌同色 """ colorArr = [0, 0, 0, 0] handTile = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) # 手牌区+吃+碰+杠+锚+胡区 for tile in handTile: color = MTile.getColor(tile) colorArr[color] = 1 colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount == 1: return True return False
def initChecker(self, playersAllTiles, winTile, tableTileMgr, isWinTileOnHand, curSeatId, winSeatId, actionID=0): self.setLastSeatId(curSeatId) self.setWinSeatId(winSeatId) self.setActionID(actionID) self.setWinTile(winTile) self.setTableTileMgr(tableTileMgr) self.setTableConfig(self.tableTileMgr.tableConfig) self.__player_all_tiles = [[] for _ in range(self.tableTileMgr.playCount)] self.__player_all_tiles_arr = [ [] for _ in range(self.tableTileMgr.playCount) ] self.__player_hand_tiles_with_hu = [ [] for _ in range(self.tableTileMgr.playCount) ] # 不要用tableTileMgr.player里面的牌,因为可能这些牌还没抓到用户手里,以传入的playersAllTiles为准 for seatId in range(len(playersAllTiles)): # 按手牌格式的数组 self.__player_all_tiles[seatId] = copy.deepcopy( playersAllTiles[seatId]) # 合到一个数组中 self.__player_all_tiles_arr[seatId].extend( MHand.copyAllTilesToList(self.__player_all_tiles[seatId])) # 只获取手牌,此时手牌包含所胡的牌 self.__player_hand_tiles_with_hu[seatId] = copy.deepcopy( playersAllTiles[seatId][MHand.TYPE_HAND]) if not isWinTileOnHand and seatId == winSeatId: self.__player_hand_tiles_with_hu[seatId].append(winTile) ftlog.info('MTilePatternChecker.calcScore __player_all_tiles=', self.__player_all_tiles) ftlog.info('MTilePatternChecker.calcScore __player_all_tiles_arr=', self.__player_all_tiles_arr) ftlog.info( 'MTilePatternChecker.calcScore __player_hand_tiles_with_hu=', self.__player_hand_tiles_with_hu)
def SatisyKe2(self,tiles): #有刻 if len(tiles[MHand.TYPE_MAO])>0 or len(tiles[MHand.TYPE_PENG])>0: return True ming,an = MTile.calcGangCount(tiles[MHand.TYPE_GANG]) if (ming + an) >0: return True allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) #中发白做将 if tilesArr[MTile.TILE_HONG_ZHONG] >= 2 or tilesArr[MTile.TILE_FA_CAI] >= 2 or tilesArr[MTile.TILE_BAI_BAN] >= 2: return True #中发白 if (tilesArr[MTile.TILE_HONG_ZHONG]>0 and tilesArr[MTile.TILE_FA_CAI]>0 and tilesArr[MTile.TILE_BAI_BAN]>0): return True return False
def isHunyise(self): """ 混一色:由东南西北中发白 + 万、条、筒中的任意一种组成的胡牌 """ colorArr = [0, 0, 0, 0] handTile = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) # 手牌区+吃+碰+杠+锚+胡区 ftlog.debug('jinan_one_result.isHunyise handTile=', handTile) for tile in handTile: color = MTile.getColor(tile) colorArr[color] = 1 colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount == 2 and colorArr[3] == 1: ftlog.debug('jinan_one_result.isHunyise result: True') return True ftlog.debug('jinan_one_result.isHunyise result: False') return False
def isQingyise(self): """ 清一色:由同一门花色(筒子或条子)组成的和牌牌型 """ colorArr = [0, 0, 0, 0] handTile = MHand.copyAllTilesToList(self.playerAllTiles[self.winSeatId]) # 手牌区+吃+碰+杠+锚+胡区 ftlog.debug('jinan_one_result.isQingyise handTile=', handTile) for tile in handTile: color = MTile.getColor(tile) colorArr[color] = 1 colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount == 1 and colorArr[3] == 0: ftlog.debug('jinan_one_result.isQingyise result: True') return True ftlog.debug('jinan_one_result.isQingyise result: False') 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 # 三色全 allTiles = MHand.copyAllTilesToList(tiles) tilesArr = MTile.changeTilesToValueArr(allTiles) wanCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_WAN) tongCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TONG) tiaoCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TIAO) if wanCount==0 or tongCount==0 or tiaoCount==0: return False, [] #有幺九 if not self.SatisyYaoJiu(tiles): return False,[] if not self.SatisyKe(tiles): return False,[] result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND]) ftlog.debug('MWinRulePanjin.isHu tiles:', result, ' pattern:', pattern) return result, pattern
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): #tile已经加入到tiles ftlog.debug('MWinRulePanjin.isHu tiles:', tiles, ' magicTiles:', magicTiles, ' tile:', tile) if self.tableTileMgr.isPassHuTileBySeatId(winSeatId, tile): return False, [] #是否允许闭门胡 if not self.tableConfig.get(MTDefine.BI_MEN_FAN, 0): if len(tiles[MHand.TYPE_HAND]) == 14: return False, [] # 三色全 allTiles = MHand.copyAllTilesToList(tiles) #避免摸宝时候检查三色全问题,所以剔除最后一张 allTiles.remove(tile) #会牌剔除 if self.tableConfig.get(MTDefine.HUI_PAI, 0): magics = self.tableTileMgr.getMagicTiles(True) while magics[0] in allTiles: allTiles.remove(magics[0]) tilesArr = MTile.changeTilesToValueArr(allTiles) wanCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_WAN) tongCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TONG) tiaoCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TIAO) if wanCount == 0 or tongCount == 0 or tiaoCount == 0: return False, [] #有幺九 if not self.SatisyYaoJiu(tiles): return False, [] result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND], magicTiles, True) ftlog.debug('MWinRulePanjin.isHu tiles:', result, ' pattern:', pattern) if not result: return False, [] else: keAlreadyhas = self.SatisyKe2(tiles) if keAlreadyhas: return True, pattern else: #检查胡牌番型pattern,要有刻 for p in pattern: if len(p) == 3 and (p[0] == p[2] or p[1] == p[2] or p[0] == p[1]): return True, pattern elif len(p) == 2: if (p[0] in range(MTile.TILE_DONG_FENG,MTile.TILE_BAI_BAN+1)) \ or (p[1] in range(MTile.TILE_DONG_FENG,MTile.TILE_BAI_BAN+1)): return True, pattern if self.tableConfig.get(MTDefine.HUI_PAI, 0): if (p[0] == p[1] == magicTiles[0]): return True, pattern return False, []
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if handCount < 5: return False, [] isTing, tingResults = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('MTingMudanjiangRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults) # [{'dropTile': 11, 'winNodes': [{'winTile': 1, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [1, 2, 3]]}, {'winTile': 2, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [3, 4, 5], [2, 2]]}, {'winTile': 4, 'winTileCount': 3, 'pattern': [[6, 6], [5, 6, 7], [4, 5, 6], [2, 3, 4]]}, {'winTile': 5, 'winTileCount': 2, 'pattern': [[6, 6, 6], [5, 6, 7], [5, 5], [2, 3, 4]]}, {'winTile': 7, 'winTileCount': 1, 'pattern': [[6, 6], [5, 6, 7], [5, 6, 7], [2, 3, 4]]}, {'winTile': 8, 'winTileCount': 1, 'pattern': [[6, 7, 8], [6, 6, 6], [5, 5], [2, 3, 4]]}]}] if not isTing: return False, [] chiCount = len(tiles[MHand.TYPE_CHI]) pengCount = len(tiles[MHand.TYPE_PENG]) gangCount = len(tiles[MHand.TYPE_GANG]) mingGangCount = 0 anGangCount = 0 #计算明杠个数,因为暗杠不算开门 if gangCount != 0: mingGangCount, anGangCount = MTile.calcGangCount( tiles[MHand.TYPE_GANG]) ftlog.debug('MTingMudanjiangRule.gang tiles:', tiles[MHand.TYPE_GANG], ' mingGangCount=', mingGangCount, ' anGangCount=', anGangCount) #daKouConfig = self.getTableConfig(MTDefine.DA_KOU, 0) daKouConfig = 1 ftlog.debug('.canTing daKouConfig:', daKouConfig) if daKouConfig != 1: if (chiCount + pengCount + mingGangCount) == 0: return False, [] # 检查刻,刻的来源,碰牌/明杠牌/手牌 keCount = pengCount + mingGangCount + anGangCount # 必须有顺牌 shunCount = chiCount newTingResults = [] for tingResult in tingResults: newWinNodes = [] winNodes = tingResult['winNodes'] for winNode in winNodes: newTiles = MTile.cloneTiles(tiles) newTiles[MHand.TYPE_HAND].remove(tingResult['dropTile']) newTiles[MHand.TYPE_HAND].append(winNode['winTile']) tileArr = MTile.changeTilesToValueArr( MHand.copyAllTilesToList(newTiles)) # ftlog.debug( 'MTingMudanjiangRule.canTing tileArr:', tileArr ) # 清一色不可以听牌/和牌 if self.getTableConfig(MTDefine.YISE_CAN_TING, 0) != 1: newTileArr = copy.deepcopy(tileArr) newTileArr[MTile.TILE_HONG_ZHONG] = 0 colorCount = MTile.getColorCount(newTileArr) if colorCount == 1: # 清一色不能和牌 ftlog.debug('MTingMudanjiangRule.canTing colorCount:', colorCount, ' can not win, continue....') continue # 检查牌中的幺/九 # 1软 听牌可以没有19,只要胡牌带19就可以 # 2硬 听牌时就要有19 RuanYaoJiuConfig = self.getTableConfig(MTDefine.RUAN_YAO_JIU, 1) if RuanYaoJiuConfig == 0: #硬幺九 :听牌必须有19 #tileArr 减去 winNode['winTile'] 后判断 tileArr[winNode['winTile']] -= 1 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingMudanjiangRule.canTing : YING yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) <= 0: continue else: #软幺九 :只要胡牌有19就行 yaoCount = tileArr[MTile.TILE_ONE_WAN] + tileArr[ MTile.TILE_ONE_TONG] + tileArr[MTile.TILE_ONE_TIAO] jiuCount = tileArr[MTile.TILE_NINE_WAN] + tileArr[ MTile.TILE_NINE_TONG] + tileArr[MTile.TILE_NINE_TIAO] zhongCount = tileArr[MTile.TILE_HONG_ZHONG] ftlog.debug('MTingMudanjiangRule.canTing : RUAN yaoCount:', yaoCount, 'jiuCount', jiuCount, 'zhongCount', zhongCount) if (yaoCount + jiuCount + zhongCount) == 0: continue patterns = winNode['pattern'] winTile = winNode['winTile'] #夹起步(顺牌只能和夹和3,7) 除单吊 chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0) if chunJiaConfig: hasJia = False bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0) if bianMulti: if MTile.getValue( winTile ) == 3 and winTile < MTile.TILE_DONG_FENG: newTilesBian = copy.deepcopy(newTiles) # 1,2,3 if ((winTile - 2) in newTilesBian[MHand.TYPE_HAND]) and ( (winTile - 1) in newTilesBian[MHand.TYPE_HAND]): newTilesBian[MHand.TYPE_HAND].remove(winTile - 2) newTilesBian[MHand.TYPE_HAND].remove(winTile - 1) newTilesBian[MHand.TYPE_HAND].remove(winTile) newTilesBian[MHand.TYPE_CHI].append( [winTile - 2, winTile - 1, winTile]) rBian, rPattern = self.winRuleMgr.isHu( newTilesBian, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rBian: ftlog.debug( 'MTingMudanjiangRule isJia 3 Bian : ', newTilesBian, ' patterns:', rPattern) hasJia = True if not hasJia and MTile.getValue( winTile ) == 7 and winTile < MTile.TILE_DONG_FENG: newTiles37 = copy.deepcopy(newTiles) # 7,8,9 if ((winTile + 1) in newTiles37[MHand.TYPE_HAND]) and ( (winTile + 2) in newTiles37[MHand.TYPE_HAND]): newTiles37[MHand.TYPE_HAND].remove(winTile + 1) newTiles37[MHand.TYPE_HAND].remove(winTile + 2) newTiles37[MHand.TYPE_HAND].remove(winTile) newTiles37[MHand.TYPE_CHI].append( [winTile, winTile + 1, winTile + 2]) rQi, qiPattern = self.winRuleMgr.isHu( newTiles37, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rQi: ftlog.debug( 'MTingMudanjiangRule isJia 7 Bian : ', newTiles37, ' pattern:', qiPattern) hasJia = True danDiaoJia = self.tableConfig.get(MTDefine.DAN_DIAO_JIA, 1) if not hasJia and danDiaoJia: newTilesDan = copy.deepcopy(newTiles) ftlog.debug( 'MTingMudanjiangRule isJia in >> danDiao : ', newTilesDan) # 5,5 if winTile in newTilesDan[MHand.TYPE_HAND]: rDan, danPattern = MWin.isHuWishSpecialJiang( newTilesDan[MHand.TYPE_HAND], [winTile, winTile], magicTiles) if rDan: ftlog.debug( 'MTingMudanjiangRule isJia danDiao : ', newTilesDan, ' winTile:', winTile, ' pattern:', danPattern) hasJia = True if not hasJia: newTilesJia = copy.deepcopy(newTiles) # 2,3,4 if ((winTile - 1) in newTilesJia[MHand.TYPE_HAND]) and ( (winTile + 1) in newTilesJia[MHand.TYPE_HAND]): newTilesJia[MHand.TYPE_HAND].remove(winTile + 1) newTilesJia[MHand.TYPE_HAND].remove(winTile - 1) newTilesJia[MHand.TYPE_HAND].remove(winTile) newTilesJia[MHand.TYPE_CHI].append( [winTile - 1, winTile, winTile + 1]) rJia, jiaPattern = self.winRuleMgr.isHu( newTilesJia, winTile, True, MWinRule.WIN_BY_MYSELF, magicTiles) if rJia: ftlog.debug('MTingMudanjiangRule isJia : ', newTilesJia, ' pattern:', jiaPattern) hasJia = True # winNodes中的patterns只是胡牌的一种方式,不是全部的胡牌解,判断夹牌,只使用patterns的组合会有遗漏的情况 # 合理的做法是先把夹拿出来,在判断剩下的牌是否能胡。 if not hasJia: ftlog.debug( 'MTingMudanjiangRule.canTing :, can not win tile:', winNode['winTile'], ', not has jia continue....') continue patterns = winNode['pattern'] checkKeCount = keCount + self.getKeCount(patterns) checkShunCount = shunCount + self.getShunCount(patterns) ftlog.debug('MTingMudanjiangRule.canTing checkKeCount:', checkKeCount, ' checkShunCount:', checkShunCount) if checkKeCount and checkShunCount: newWinNodes.append(winNode) if len(newWinNodes) > 0: newTingResult = {} newTingResult['dropTile'] = tingResult['dropTile'] newTingResult['winNodes'] = newWinNodes newTingResults.append(newTingResult) return len(newTingResults) > 0, newTingResults
def 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 isHu(self, tiles, tile, isTing, getTileType, magicTiles = [], tingNodes = [], winSeatId = 0): ''' 三色全,玩家手中必须同时具有万饼条三种花色的牌 有幺九(喜杠、幺九杠、中发白作将或刻时可免幺九) 有刻(任意杠、中发白作将或刻时可免刻) ''' ftlog.debug('MWinRuleBaicheng.isHu TIAN_HU:', self.tableConfig.get(MTDefine.TIAN_HU, 0), ' len(self.tableTileMgr.addTiles[winSeatId]):', len(self.tableTileMgr.addTiles[winSeatId]), ' winSeatId:', winSeatId) if getTileType == MWinRule.WIN_BY_MYSELF: if 0==self.tableConfig.get(MTDefine.TIAN_HU, 0): if len(self.tableTileMgr.addTiles[winSeatId]) == 1: return False, [] #tile已经加入到tiles ftlog.debug('MWinRuleBaicheng.isHu tiles:', tiles , ' magicTiles:', magicTiles , ' tile:', tile) # 三色全 allTiles = MHand.copyAllTilesToList(tiles) #避免摸宝时候检查三色全问题,所以剔除最后一张 allTiles.remove(tile) tilesArr = MTile.changeTilesToValueArr(allTiles) wanCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_WAN) tongCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TONG) tiaoCount = MTile.getTileCountByColor(tilesArr, MTile.TILE_TIAO) if wanCount==0 or tongCount==0 or tiaoCount==0: return False, [] #摸到宝牌 if getTileType == MWinRule.WIN_BY_MYSELF: if (tile in magicTiles): canHuWithMagic = False for tileTry in range(MTile.TILE_MAX_VALUE): handTile = copy.deepcopy(tiles[MHand.TYPE_HAND]) handTile.remove(tile) handTile.append(tileTry) ishu, pattern = MWin.isHu(handTile,[],True) ftlog.debug('MWinRuleBaicheng.isHu handTile:', handTile,'tile',tile,'ishu',ishu,'pattern',pattern) if ishu: #摸宝的情况下,判断胡牌pattern里面是否有幺九,是否有刻 #把pattern胡牌加入到手牌,然后判断 allTilesMagicHu = copy.deepcopy(tiles) allTilesMagicHu[MHand.TYPE_HAND] = [] for p in pattern: allTilesMagicHu[MHand.TYPE_HAND].extend(p) ftlog.debug('MWinRuleBaicheng.isHu allTilesMagicHu:', allTilesMagicHu) #有幺九 if not self.SatisyYaoJiu(allTilesMagicHu): continue #有刻 if not self.SatisyKe(allTilesMagicHu): continue #可以胡,说明是摸宝胡牌 ftlog.debug('MWinRuleBaicheng.isHu canHuWithMagic:yes') canHuWithMagic = True return True,[] if not canHuWithMagic: return False, [] #有幺九 if not self.SatisyYaoJiu(tiles): return False,[] result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND],[],True) if not result: return False, [] else: keAlreadyhas = self.SatisyKe2(tiles) if keAlreadyhas: return True, pattern else: #检查胡牌番型pattern,要有刻 for p in pattern: if len(p)==3 and p[0]==p[1]==p[2]: return True,pattern return False,[]
def getBestDropTile(cls, tiles_player_hand, tiles_left, playMode, tile, isTing, magicTiles, absenceColor, tingRule=None, seatId=0): """ 手牌的价值,根据玩家自己的手牌和已经出的牌,计算手牌价值 参数: tiles_player_hand - 用户的手牌 tiles_droped - 牌桌上已经打出的牌和玩家手里已经成型的牌,这部分牌不再参与计算牌的可能性 计算方法: 1)没有的手牌,权值为0 2)有的手牌,初始权值为4 * count + 1 * left 3)左右相邻的手牌,增加权重 3 * count 4)左右隔一张的手牌,增加权重 2 * count """ ftlog.debug('MTileValue.getBestDropTile tiles_player_hand:', tiles_player_hand, ' tiles_left:', tiles_left, ' playMode:', playMode, ' tile:', tile, ' isTing:', isTing, ' magicTiles:', magicTiles, ' tingRule:', tingRule, ' seatId:', seatId) if isTing: # 听牌后,直接打出摸到的牌 return tile, 0 tiles_value_Arr, tiles_player_Arr = cls.getHandTilesValue( tiles_player_hand, tiles_left) # 放大癞子牌的作用 for mTile in magicTiles: tiles_value_Arr[mTile] = tiles_value_Arr[mTile] * 100 # 如果有一门花色大于9张牌,放大该门花色牌的价值,便于去做清一色番型 allTiles = MHand.copyAllTilesToList(tiles_player_hand) wans = MTile.filterTiles(allTiles, MTile.TILE_WAN) if len(wans) >= 9: for tile in MTile.traverseTile(MTile.TILE_WAN): tiles_value_Arr[tile] += 10 tongs = MTile.filterTiles(allTiles, MTile.TILE_TONG) if len(tongs) >= 9: for tile in MTile.traverseTile(MTile.TILE_TONG): tiles_value_Arr[tile] += 10 tiaos = MTile.filterTiles(allTiles, MTile.TILE_TIAO) if len(tiaos) >= 9: for tile in MTile.traverseTile(MTile.TILE_TIAO): tiles_value_Arr[tile] += 10 fengs = MTile.filterTiles(allTiles, MTile.TILE_FENG) if len(fengs) >= 9: for tile in MTile.traverseTile(MTile.TILE_FENG): tiles_value_Arr[tile] += 10 # 减小缺牌的作用 for tile in range(len(tiles_value_Arr)): if MTile.getColor(tile) == absenceColor: tiles_value_Arr[tile] -= 100 # [{'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 tingRule: canTing, tingResults = tingRule.canTing(tiles_player_hand, tiles_left, tile, magicTiles) ftlog.debug(canTing) ftlog.debug(tingResults) if canTing: for tingResult in tingResults: dropTile = tingResult['dropTile'] winNodes = tingResult['winNodes'] outs = 0 for winNode in winNodes: outs += winNode['winTileCount'] tiles_value_Arr[dropTile] = (0 - outs) minTile = 0 minValue = 0 for index in range(MTile.TILE_MAX_VALUE): if tiles_player_Arr[index] > 0: if minTile == 0: minTile = index minValue = tiles_value_Arr[index] continue if minValue > tiles_value_Arr[index]: minValue = tiles_value_Arr[index] minTile = index ftlog.debug('MTileValue.getBestDropTile minTile:', minTile, ' tileValue:', tiles_value_Arr[minTile]) return minTile, tiles_value_Arr[minTile]
def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[], winSeatId=0): ftlog.debug(self.TAG, '.isHu tiles:', tiles, ' tile:', tile, ' isTing:', isTing, ' getTileType:', getTileType, ' magicTiles:', magicTiles, ' tingNodes:', tingNodes, ' winSeatId:', winSeatId) # 平度麻将即可以听也可以不听,听牌后,校验tingNodes即可,无其他限制条件 if isTing: #[{'winTile': 16, 'winTileCount': 0, 'pattern': [[16, 17, 18], [12, 12]]}, {'winTile': 19, 'winTileCount': 0, 'pattern': [[17, 18, 19], [12, 12]]}] for tingNode in tingNodes: if tingNode['winTile'] == tile: pattern = tingNode['pattern'] return True, pattern # 烟台麻将允许胡七对 resultQiDui, patternQiDui = MWin.isQiDui(tiles[MHand.TYPE_HAND]) if resultQiDui: if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug('MWinRuleYantai.isHu checkQiDui with 258') for pattern in patternQiDui: tile = pattern[0] if tile > MTile.TILE_NINE_TIAO: continue if MTile.getValue(pattern[0]) % 3 == 2: return True, patternQiDui return False, [] return True, patternQiDui # 烟台麻将允许胡十三幺 self.tilePatternChecker.setPlayerAllTiles(tiles) if self.tilePatternChecker.isShisanyao(): if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug( 'MWinRuleYantai.isHu isShisanyao with 258, return False') return False, [] return True, tiles[MHand.TYPE_HAND] # 烟台麻将允许胡风一色 allTiles = MHand.copyAllTilesToList(tiles) allArr = MTile.changeTilesToValueArr(allTiles) colorCount = MTile.getColorCount(allArr) resultFeng, patternFeng = MWin.isLuanFengyise(tiles[MHand.TYPE_HAND], colorCount) if resultFeng: if self.tableConfig[MTDefine.ONLY_JIANG_258]: ftlog.debug( 'MWinRuleYantai.isHu isLuanFengyise with 258, return False' ) return False, [] return True, patternFeng # 挑出2,5,8将,看剩下的牌是否能胡牌 if self.tableConfig[MTDefine.ONLY_JIANG_258]: jiangPatterns = [[MTile.TILE_TWO_WAN, MTile.TILE_TWO_WAN], [MTile.TILE_FIVE_WAN, MTile.TILE_FIVE_WAN], [MTile.TILE_EIGHT_WAN, MTile.TILE_EIGHT_WAN], [MTile.TILE_TWO_TONG, MTile.TILE_TWO_TONG], [MTile.TILE_FIVE_TONG, MTile.TILE_FIVE_TONG], [MTile.TILE_EIGHT_TONG, MTile.TILE_EIGHT_TONG], [MTile.TILE_TWO_TIAO, MTile.TILE_TWO_TIAO], [MTile.TILE_FIVE_TIAO, MTile.TILE_FIVE_TIAO], [MTile.TILE_EIGHT_TIAO, MTile.TILE_EIGHT_TIAO]] ftlog.debug('MWinRuleYantai.isHu with 258') for jiangPat in jiangPatterns: result, pattern = MWin.isHuWishSpecialJiang( tiles[MHand.TYPE_HAND], jiangPat) if result: return result, pattern return False, [] else: result, pattern = MWin.isHu(tiles[MHand.TYPE_HAND]) return result, pattern
def canTing(self, tiles, leftTiles, tile, magicTiles=[], winSeatId=0): """子类必须实现 参数: 1)tiles 该玩家的手牌 2)leftTiles 剩余手牌 返回值: 是否可以听牌,听牌详情 """ handCount = len(tiles[MHand.TYPE_HAND]) if handCount < 5: return False, [] isTing, tingResults = MTing.canTing(self.tilePatternChecker, self.tableTileMgr, MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles, winSeatId) ftlog.debug('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