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 hasChi(self, tiles, tile, extendInfo={}): """是否有吃牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待吃的牌 """ newTiles = copy.deepcopy(tiles) absenseColor = extendInfo.get('absenseColor', -1) if MTile.getColor(tile) == absenseColor: return [] newTiles[MHand.TYPE_HAND] = filter( lambda x: MTile.getColor(x) != absenseColor, newTiles[MHand.TYPE_HAND]) return super(MChiRuleXuezhan, self).hasChi(newTiles, tile)
def isWin(self, allTiles, winTile, winStyle, leftTiles, seatResponse, extend={}): ''' 默认能胡就胡 allTiles - 当前玩家的所有手牌 winTile - 胡牌 winStyle - 是吃炮胡,抢杠胡,还是自摸胡。 被人点炮则胡 自摸胡时,考虑下是否更换听口,以博取更好的机会 seatResponse - 玩家是否选择,已选择,则返回True extend - 扩展信息,本接口不要再添加更多参数,更多参数通过extend传递 ''' ftlog.debug('isWin allTiles:', allTiles, ' winTile:', winTile, ' winStyle:', winStyle, ' leftTiles:', leftTiles, ' seatResponse:', seatResponse) if seatResponse: return True seatId = extend.get('seatId', None) abColors = extend.get('absenceColor', None) doQing, qingColor = self.doQingYiSe(allTiles, leftTiles, seatId, abColors) if doQing: return self.isQingYiSe( allTiles, qingColor) and (MTile.getColor(winTile) == qingColor) return True
def isChi(self, allTiles, chiTile, chiPatterns, leftTiles, tingResults, seatResponse, extend={}): ''' 默认能吃就吃 allTiles - 当前玩家的所有手牌 chiTile - 吃牌 chiPatterns - 吃牌方案 seatResponse - 玩家是否做出选择 extend - 扩展信息,本接口不要再添加更多参数,更多参数通过extend传递 ''' if seatResponse: return True seatId = extend.get('seatId', None) abColors = extend.get('absenceColor', None) doQing, qingColor = self.doQingYiSe(allTiles, leftTiles, seatId, abColors) if doQing: return (MTile.getColor(chiTile) == qingColor) return True
def isPeng(self, allTiles, pengTile, pengPatterns, leftTiles, tingResults, seatResponse, extend={}): ''' 默认能碰就碰 allTiles - 当前玩家的所有手牌 pengTile - 碰牌 pengPatterns - 碰牌方案 seatResponse - 玩家是否选择 extend - 扩展信息,本接口不要再添加更多参数,更多参数通过extend传递 ''' if seatResponse: return True seatId = extend.get('seatId', None) abColors = extend.get('absenceColor', None) doQing, qingColor = self.doQingYiSe(allTiles, leftTiles, seatId, abColors) if doQing: return (MTile.getColor(pengTile) == qingColor) return True
def shuffle(self, goodPointCount, handTileCount): """ 洗牌器 子类里可添加特殊逻辑,比如确定宝牌 """ if self.tileTestMgr.initTiles(): # 检查手牌 handTiles = self.tileTestMgr.handTiles poolTiles = self.tileTestMgr.tiles ftlog.debug("self.tiles len1 = ", len(self.__tiles), "poolTiles = ", poolTiles, "handTiles = ", handTiles) if self.__dealer.initTiles(handTiles, poolTiles): ftlog.debug("self.tiles len2 = ", len(self.__tiles), "poolTiles = ", poolTiles, "handTiles = ", handTiles) self.__tiles = copy.deepcopy(self.__dealer.tiles) ftlog.debug("self.tiles len3 = ", len(self.__tiles), "poolTiles = ", poolTiles, "handTiles = ", handTiles) else: ftlog.debug("self.tiles len4 = ", len(self.__tiles)) self.__tiles = self.__dealer.shuffle(goodPointCount, handTileCount) ftlog.debug("self.tiles len5 = ", len(self.__tiles)) ftlog.info('MTableTile.shuffle tiles:', self.__tiles) if self.removeFeng: self.__tiles = filter(lambda x: not MTile.isFeng(x), self.__tiles) if self.removeArrow: self.__tiles = filter(lambda x: not MTile.isArrow(x), self.__tiles) if self.isRemoveWanTile: self.__tiles = filter( lambda x: MTile.getColor(x) == MTile.TILE_WAN, self.__tiles) return self.__tiles
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 isTing(self, allTiles, dropTile, leftTiles, seatResponse=False, extend={}): ''' 是否听牌 ''' ftlog.debug('isTing allTiles:', allTiles, ' dropTile:', dropTile, ' leftTiles:', leftTiles, ' seatResponse:', seatResponse) if seatResponse: return True seatId = extend.get('seatId', None) abColors = extend.get('absenceColor', None) doQing, qingColor = self.doQingYiSe(allTiles, leftTiles, seatId, abColors) if doQing: handTiles = copy.deepcopy(allTiles[MHand.TYPE_HAND]) handColors = MTile.filterTiles(handTiles, qingColor) if (MTile.getColor(dropTile) == qingColor) and (len(handTiles) != len(handColors)): ftlog.debug('handTiles:', handTiles, ' handColors:', handColors, ' dropTile:', dropTile, ' doQingYiSe, do not drop...') return False return True
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 isQingYiSe(self, allTiles, qingColor): ''' 判断当前是否是清一色 ''' allTilesArr = MHand.copyAllTilesToList(allTiles) for tile in allTilesArr: if MTile.getColor(tile) != qingColor: return False return True
def hasGang(self, tiles, curTile, state, extendInfo={}): """判断杠牌""" # 缺门的牌不能杠 absenceColor = extendInfo.get('absenceColor', -1) if MTile.getColor(curTile) == absenceColor: return [] return super(MGangRuleHeXian, self).hasGang(tiles, curTile, state, extendInfo)
def getFengKe(self): """ 获得风刻的分数:手牌区和碰牌区 """ score = 0 pengTile = self.playerAllTiles[self.winSeatId][MHand.TYPE_PENG] # 碰牌区 handTile = copy.deepcopy(self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) for pengPatten in pengTile: if MTile.getColor(pengPatten[0]) == 3: score = score + 1 tileCountArr = MTile.changeTilesToValueArr(handTile) # 手牌区 for tileIndex in range(0, len(tileCountArr)): # 刻子 if tileCountArr[tileIndex] == 3 and MTile.getColor(tileIndex) == 3: score = score + 1 ftlog.debug('jinan_one_result.getFengKe ', score) return score
def isWin(self, allTiles, winTile, winStyle, leftTiles): ''' 默认能胡就胡 allTiles - 当前玩家的所有手牌 winTile - 胡牌 winStyle - 是吃炮胡,抢杠胡,还是自摸胡。 被人点炮则胡 自摸胡时,考虑下是否更换听口,以博取更好的机会 ''' doQing, qingColor = self.doQingYiSe(allTiles, leftTiles) if doQing: return (MTile.getColor(winTile) == qingColor) return True
def chooseBestDropTile(self, tiles, leftTiles, mostColor): ''' 从若干最小分值的牌中选择一个最合适的 附加权重: 1)自身权重 1、9的本身附加权重为0 2,8的附件权重为1 3,4,5,6,7的附件权重为2 2)剩余牌数权重 剩余牌数的附件权重每张为1 3)花色权重 花色之间的比较,花色较多的一方去加权重为1,花色较少的一方附件权重为0 ''' if len(tiles) == 1: return tiles[0] tiles.sort() values = [0 for _ in tiles] minTile = 0 minValue = 0 for index in range(len(tiles)): tile = tiles[index] if (MTile.getValue(tile) == 1) or (MTile.getValue(tile) == 9): values[index] += 0 elif (MTile.getValue(tile) == 2) or (MTile.getValue(tile) == 8): values[index] += 1 else: values[index] += 2 tileCount = 0 for _t in leftTiles: if _t == tile: tileCount += 1 values[index] += tileCount if MTile.getColor(tile) == mostColor: values[index] += 1 if (minTile == 0) or (minValue > values[index]): minTile = tile minValue = values[index] ftlog.debug('chooseBestDropTile tiles:', tiles, ' leftTiles:', leftTiles, ' mostColor:', mostColor, ' values:', values, ' minTile:', minTile, ' minValue:', minValue) return minTile
def 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 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 isQingyise(self): """ 清一色:由同一门花色(筒子或条子)组成的和牌牌型 """ colorArr = [0, 0, 0, 0] for tile in self.playerAllTilesArr[self.winSeatId]: color = MTile.getColor(tile) colorArr[color] = 1 colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount > 1: ftlog.debug('MTilePatternChecker.isQingyise result: False') return False ftlog.debug('MTilePatternChecker.isQingyise result: True') return True
def isQingyise(self): """ 清一色:由同一门花色(筒子或条子)组成的和牌牌型 """ colorArr = [0,0,0,0] for tile in self.playerAllTilesArr[self.winSeatId]: color = MTile.getColor(tile) colorArr[color] = 1 colorCount = 0 for eachColor in colorArr: if eachColor: colorCount += 1 if colorCount > 1: ftlog.debug('MTilePatternChecker.isQingyise result: False') return False ftlog.debug('MTilePatternChecker.isQingyise result: True') return True
def hasPeng(self, tiles, tile, extendInfo={}): """是否有碰牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待碰的牌 """ absenceColor = extendInfo.get('absenceColor', -1) if MTile.getColor(tile) == absenceColor: return [] tilesForPeng = copy.deepcopy(tiles[MHand.TYPE_HAND]) tilesForPeng = MTile.filterTilesWithOutColor(tilesForPeng, absenceColor) pengSolutions = [] if MPeng.hasPeng(tilesForPeng, tile): pengSolutions.append([tile, tile, tile]) return pengSolutions
def isWin(self, allTiles, winTile, winStyle, leftTiles, seatResponse): ''' 默认能胡就胡 allTiles - 当前玩家的所有手牌 winTile - 胡牌 winStyle - 是吃炮胡,抢杠胡,还是自摸胡。 被人点炮则胡 自摸胡时,考虑下是否更换听口,以博取更好的机会 seatResponse - 玩家是否选择,已选择,则返回True ''' ftlog.debug('isWin allTiles:', allTiles, ' winTile:', winTile, ' winStyle:', winStyle, ' leftTiles:', leftTiles, ' seatResponse:', seatResponse) if seatResponse: return True doQing, qingColor = self.doQingYiSe(allTiles, leftTiles) if doQing: return (MTile.getColor(winTile) == qingColor) return True
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 hasPeng(self, tiles, tile, extendInfo={}): """是否有碰牌解 参数说明; tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌 tile - 待碰的牌 """ pengSolutions = [] seatId = extendInfo.get('seatId', -1) if seatId == -1: return pengSolutions # 缺门不能碰 absenceColor = self.tableTileMgr.absenceColors[seatId] if MTile.getColor(tile) == absenceColor: return pengSolutions # 手牌里加上这张牌>=3张,可以碰 normalPeng = MPeng.hasPeng(tiles[MHand.TYPE_HAND], tile) if normalPeng: pengSolutions.append([tile, tile, tile]) return pengSolutions
def isChi(self, allTiles, chiTile, chiPatterns, leftTiles, tingResults, seatResponse, tingRule=None): ''' 默认能吃就吃 allTiles - 当前玩家的所有手牌 chiTile - 吃牌 chiPatterns - 吃牌方案 seatResponse - 玩家是否做出选择 ''' if seatResponse: return True doQing, qingColor = self.doQingYiSe(allTiles, leftTiles) if doQing: return (MTile.getColor(chiTile) == qingColor) return True
def isPeng(self, allTiles, pengTile, pengPatterns, leftTiles, tingResults, seatResponse, tingRule=None): ''' 默认能碰就碰 allTiles - 当前玩家的所有手牌 pengTile - 碰牌 pengPatterns - 碰牌方案 seatResponse - 玩家是否选择 ''' if seatResponse: return True doQing, qingColor = self.doQingYiSe(allTiles, leftTiles) if doQing: return (MTile.getColor(pengTile) == qingColor) return True
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 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 calcWin(self): """ 济南赢牌算分 """ # ## 清理 self.clearWinFanPattern() # 在和牌时统计自摸,点炮状态 resultStat = [[] for _ in range(self.playerCount)] winMode = [MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount)] fanPattern = [[] for _ in range(self.playerCount)] fanXing = self.fanXing[self.PINGHU] resultStat[self.winSeatId].append({MOneResult.STAT_WIN:1}) isZiMo = (self.lastSeatId == self.winSeatId) if isZiMo: resultStat[self.lastSeatId].append({MOneResult.STAT_ZIMO:1}) winMode[self.lastSeatId] = MOneResult.WIN_MODE_ZIMO else: resultStat[self.lastSeatId].append({MOneResult.STAT_DIANPAO: 1}) winMode[self.lastSeatId] = MOneResult.WIN_MODE_DIANPAO winMode[self.winSeatId] = MOneResult.WIN_MODE_PINGHU if self.qiangGang: winMode[self.winSeatId] = MOneResult.WIN_MODE_QIANGGANGHU score = [0 for _ in range(self.playerCount)] # 底分 配置项的底分 baseScore = self.tableTileMgr.tableConfig.get(MTDefine.WIN_BASE, 1) ftlog.debug('jinan_one_result.calcWin baseScore=====', baseScore) # ## 算杠分 gangscore = 0 # 杠牌得分 gangList = self.playerGangTiles[self.winSeatId] for ga in gangList: if MTile.getColor(ga['pattern'][0]) == 3: gangscore += 1 if ga['style'] == 0: # 暗杠 gangscore += 2 else: gangscore += 1 baseScore = baseScore + gangscore ftlog.debug('jinan_one_result.calcWin baseScore=====', baseScore, ' gangscore:', gangscore) # ## 算风刻分 baseScore = baseScore + self.getFengKe() ftlog.debug('jinan_one_result.calcWin baseScore=====', baseScore, ' getFengKe:', self.getFengKe()) # #算花分 huaScore = len(self.tableTileMgr.flowerTiles(self.winSeatId)) baseScore = baseScore + huaScore ftlog.debug('jinan_one_result.calcWin baseScore=====', baseScore, ' huaScore:', huaScore) # 胡型判断 if self.isDadiaoche(): # 大吊车 ftlog.debug('jinan_one_result.calcWin isDadiaoche=====', self.isDadiaoche()) fx = self.fanXing[self.DADIAOCHE] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 if self.tableTileMgr.isHaidilao(): # 海底捞月 ftlog.debug('jinan_one_result.calcWin isHaidilao=====', self.tableTileMgr.isHaidilao()) fx = self.fanXing[self.HAIDILAO] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 if self.gangKai: # 杠呲 ftlog.debug('jinan_one_result.calcWin isGangKai=====', self.gangKai) fx = self.fanXing[self.GANGCI] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 if self.huaCi: # 花呲 ftlog.debug('jinan_one_result.calcWin isHuaCi=====', self.huaCi) fx = self.fanXing[self.HUACI] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 if self.tingState[self.winSeatId]: # 明搂 ftlog.debug('jinan_one_result.calcWin isMingLou=====', self.tingState[self.winSeatId]) fx = self.fanXing[self.MINGLOU] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 ####牌型判断 if self.isFlowerHu(): # 花胡 fx = self.fanXing[self.FLOWERHU] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 1 if self.isQingyise(): # 清一色 ftlog.debug('jinan_one_result.calcWin isQingyise=====', self.isQingyise()) fx = self.fanXing[self.QINGYISE] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 4 elif self.isHunyise(): # 混一色 fx = self.fanXing[self.HUNYISE] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 if self.isQidui(): if self.isQiduiHao(): # 豪华七小对 ftlog.debug('jinan_one_result.calcWin isQiduiHao=====', self.isQiduiHao()) fx = self.fanXing[self.HHQIXIAODUI] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 4 else: # 七小对 ftlog.debug('jinan_one_result.calcWin isQidui=====', self.isQidui()) fx = self.fanXing[self.QIXIAODUI] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 elif self.isPengpenghu(): # 碰碰胡 ftlog.debug('jinan_one_result.calcWin isPengpenghu=====', self.isPengpenghu()) fx = self.fanXing[self.PENGPENGHU] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 elif self.isQuanjiang(): # 全将 ftlog.debug('jinan_one_result.calcWin isQuanjiang=====', self.isQuanjiang()) fx = self.fanXing[self.QUANJIANG] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 elif self.is13BuKao(): # 十三不靠 ftlog.debug('jinan_one_result.calcWin is13BuKao=====', self.is13BuKao()) fx = self.fanXing[self.BUKAO13] self.addWinFanPattern(fx['name'], fx['index']) baseScore = baseScore * 2 ftlog.debug('jinan_one_result.calcWin baseScore=====', baseScore) #### 胡法判断 if isZiMo: # 自摸 score = [-baseScore for _ in range(self.playerCount)] score[self.winSeatId] = (self.playerCount - 1) * baseScore else: # 点炮 if self.qiangGang: # 抢杠包三家 score = [0 for _ in range(self.playerCount)] score[self.winSeatId] = (self.playerCount - 1) * baseScore score[self.lastSeatId] = -(self.playerCount - 1) * baseScore else: score[self.lastSeatId] = -baseScore score[self.winSeatId] = baseScore #### 跑分计算 if isZiMo: # 自摸 自己的飘 + 别人的飘 + 必票*n for loose in range(self.playerCount): if loose != self.winSeatId: piao = self.piaoProcessor.getPiaoPointsBySeats(self.winSeatId, loose) # 算飘的分 ftlog.debug('jinan_one_result.calcWin isZiMo.piao=====', piao) score[loose] -= piao score[self.winSeatId] += piao else: # 点炮 if self.qiangGang: # 抢杠包三家 for loose in range(self.playerCount): if loose != self.winSeatId: piao = self.piaoProcessor.getPiaoPointsBySeats(self.winSeatId, loose) # 算飘的分 score[self.lastSeatId] -= piao score[self.winSeatId] += piao else: piao = self.piaoProcessor.getPiaoPointsBySeats(self.winSeatId, self.lastSeatId) # 算飘的分 ftlog.debug('jinan_one_result.calcWin dianpao.piao=====', piao) score[self.lastSeatId] -= piao score[self.winSeatId] += piao piaoPoints = {} piaoPoints['points'] = [self.piaoProcessor.piaoPoints[seat] for seat in range(self.playerCount)] # 给前端显示票分 flowerScores = {} flowerScores['scores'] = [self.tableTileMgr.flowerScores(seat) for seat in range(self.playerCount)] # 给前端显示花分 # 最大番统计(改成单局最佳) resultStat[self.winSeatId].append({MOneResult.STAT_ZUIDAFAN: score[self.winSeatId]}) self.results[self.KEY_TYPE] = '和牌' self.results[self.KEY_NAME] = fanXing['name'] self.results[self.KEY_SCORE] = score self.results[self.KEY_WIN_MODE] = winMode self.results[self.KEY_STAT] = resultStat fanPattern[self.winSeatId] = self.winFanPattern ftlog.debug('jinan_one_result.calcWin result fanPattern:', fanPattern) self.results[self.KEY_FAN_PATTERN] = fanPattern self.results[self.KEY_PIAO_POINTS] = piaoPoints self.results[self.KEY_FLOWER_SCORES] = flowerScores
def getBestDropTile(self, tiles_player_hand, tiles_left, tile, isTing, magicTiles, absenceColor, tingRule=None): """ 手牌的价值,根据玩家自己的手牌和已经出的牌,计算手牌价值 参数: tiles_player_hand - 用户的手牌 tiles_droped - 牌桌上已经打出的牌和玩家手里已经成型的牌,这部分牌不再参与计算牌的可能性 计算方法: 1)没有的手牌,权值为0 2)有的手牌,初始权值为4 * count + 1 * left 3)左右相邻的手牌,增加权重 3 * count 4)左右隔一张的手牌,增加权重 2 * count """ ftlog.debug( 'MDropCardStrategyJipinghu.getBestDropTile tiles_player_hand:', tiles_player_hand, ' tiles_left:', tiles_left, ' tile:', tile, ' isTing:', isTing, ' magicTiles:', magicTiles, ' absenceColor:', absenceColor, ' tingRule:', tingRule) if isTing: # 听牌后,直接打出摸到的牌 return tile, 0 doQing, qingColor = self.doQingYiSe(tiles_player_hand, tiles_left) tiles_value_Arr, tiles_player_Arr = MTileValue.getHandTilesValue( tiles_player_hand, tiles_left) # 放大癞子牌的作用 for mTile in magicTiles: tiles_value_Arr[mTile] = tiles_value_Arr[mTile] * 100 # 如果有一门花色大于9张牌,放大该门花色牌的价值,便于去做清一色番型 if doQing: for tile in MTile.traverseTile(qingColor): tiles_value_Arr[tile] += 10 # 减小缺牌的作用 for tile in range(len(tiles_value_Arr)): if MTile.getColor(tile) == absenceColor: tiles_value_Arr[tile] -= 100 continue if doQing and MTile.getColor(tile) != qingColor: tiles_value_Arr[tile] -= 10 continue # [{'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: totalValue = 0 for tingResult in tingResults: dropTile = tingResult['dropTile'] winNodes = tingResult['winNodes'] for winNode in winNodes: totalValue += winNode['winTileCount'] * winNode[ 'winFan'] for tingResult in tingResults: dropTile = tingResult['dropTile'] winNodes = tingResult['winNodes'] dropValue = 0 for winNode in winNodes: dropValue += winNode['winTileCount'] * winNode['winFan'] tiles_value_Arr[dropTile] = (totalValue - dropValue) if doQing and (MTile.getColor(dropTile) == qingColor) and ( tiles_value_Arr[dropTile] != -4): # 优先打出非清一色颜色的上听牌 tiles_value_Arr[dropTile] += (totalValue / len(tingResults)) ftlog.debug( 'MDropCardStrategyJipinghu.getBestDropTile adjust tileValue by ting:', tiles_value_Arr, ' tingResults:', tingResults, ' totalValue:', totalValue) 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('MDropCardStrategyJipinghu.getBestDropTile minTile:', minTile, ' tileValue:', tiles_value_Arr[minTile]) return minTile, tiles_value_Arr[minTile]
def gangsFilter(gang): for tile in gang['pattern']: if tile != 0 and tile not in magics: if MTile.getColor(tile) == quemen: return False return True
def getBestDropTile(self, tiles_player_hand, tiles_left, tile, isTing, magicTiles, extend={}): """ 手牌的价值,根据玩家自己的手牌和已经出的牌,计算手牌价值 参数: tiles_player_hand - 用户的手牌 tiles_droped - 牌桌上已经打出的牌和玩家手里已经成型的牌,这部分牌不再参与计算牌的可能性 计算方法: 1)没有的手牌,权值为0 2)有的手牌,初始权值为4 * count + 1 * left 3)左右相邻的手牌,增加权重 3 * count 4)左右隔一张的手牌,增加权重 2 * count """ ftlog.debug( 'MDropCardStrategyXuezhan.getBestDropTile tiles_player_hand:', tiles_player_hand, ' tiles_left:', tiles_left, ' tile:', tile, ' isTing:', isTing, ' magicTiles:', magicTiles, ' extend:', extend) if isTing: # 听牌后,直接打出摸到的牌 return tile, 0 tiles_value_Arr, tiles_player_Arr = MTileValue.getHandTilesValue( tiles_player_hand, tiles_left) # 如果有缺牌,打出缺牌 seatId = extend.get('seatId', 0) abColors = extend.get('absenceColor', []) absenceColor = MTile.TILE_FENG if len(abColors) > 0: absenceColor = abColors[seatId] abMinTile = 0 abMinValue = 0 for tile in MTile.traverseTile(absenceColor): if tiles_player_Arr[tile] > 0: if abMinTile == 0: abMinTile = tile abMinValue = tiles_value_Arr[tile] continue if abMinValue > tiles_value_Arr[tile]: abMinValue = tiles_value_Arr[tile] abMinTile = tile if abMinTile: ftlog.debug('has Absence, drop the min absence tile:', abMinTile, ' abMinValue:', abMinValue) return abMinTile, abMinValue seatId = extend.get('seatId', None) abColors = extend.get('absenceColor', None) doQing, qingColor = self.doQingYiSe(tiles_player_hand, tiles_left, seatId, abColors) # 放大癞子牌的作用 for mTile in magicTiles: tiles_value_Arr[mTile] = tiles_value_Arr[mTile] * 100 # 如果有一门花色大于9张牌,放大该门花色牌的价值,便于去做清一色番型 if doQing: colors = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO] colors.remove(absenceColor) colors.remove(qingColor) dMinTiles = [] dMinValue = 0 for tile in MTile.traverseTile(colors[0]): if tiles_player_Arr[tile] > 0: if len(dMinTiles) == 0: dMinValue = tiles_value_Arr[tile] dMinTiles.append(tile) continue if dMinValue > tiles_value_Arr[tile]: dMinValue = tiles_value_Arr[tile] dMinTiles = [tile] elif dMinValue == tiles_value_Arr[tile]: dMinTiles.append(tile) if len(dMinTiles) > 0: ftlog.debug('doQingYiSe, qingColor:', qingColor, ' dMinTiles:', dMinTiles, ' dMinValue:', dMinValue) return self.chooseBestDropTile(dMinTiles, tiles_left, qingColor), dMinValue tingRule = extend.get('tingRule', None) # [{'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: totalValue = 0 for tingResult in tingResults: # 对dropTile的价值重新考虑 dropTile = tingResult['dropTile'] tiles_value_Arr[dropTile] = 0 winNodes = tingResult['winNodes'] for winNode in winNodes: totalValue += winNode['winTileCount'] * winNode[ 'winFan'] for tingResult in tingResults: dropTile = tingResult['dropTile'] winNodes = tingResult['winNodes'] dropValue = 0 for winNode in winNodes: dropValue += winNode['winTileCount'] * winNode['winFan'] tiles_value_Arr[dropTile] += (-dropValue) if doQing and (MTile.getColor(dropTile) == qingColor): # 优先打出非清一色颜色的上听牌 tiles_value_Arr[dropTile] += (totalValue / len(tingResults)) ftlog.debug( 'MDropCardStrategyXuezhan.getBestDropTile dropTile:', dropTile, ' dropTileValue:', tiles_value_Arr[dropTile]) ftlog.debug( 'MDropCardStrategyXuezhan.getBestDropTile adjust tileValue by ting:', tiles_value_Arr, ' tingResults:', tingResults, ' totalValue:', totalValue) minTiles = [] minValue = 0 for index in range(MTile.TILE_MAX_VALUE): if tiles_player_Arr[index] > 0: if (len(minTiles) == 0) or (minValue > tiles_value_Arr[index]): minValue = tiles_value_Arr[index] minTiles = [index] elif minValue == tiles_value_Arr[index]: minTiles.append(index) ftlog.debug('MDropCardStrategyJipinghu.getBestDropTile minTiles:', minTiles, ' tileValue:', minValue) return self.chooseBestDropTile(minTiles, tiles_left, qingColor), minValue