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 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 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 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 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) return self.__tiles
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 isSanQi(self): """是否三七边""" # 1,2,3 拿出来,剩下的能不能胡 # 7,8,9 拿出来 剩下的能不能胡 handTile = copy.deepcopy( self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]) handTile.extend(self.playerAllTiles[self.winSeatId][MHand.TYPE_HU]) if MTile.getValue(self.winTile) == 7 and self.winTile < 30 and ( self.winTile + 1) in handTile and (self.winTile + 2) in handTile: handTile.remove(self.winTile) handTile.remove(self.winTile + 1) handTile.remove(self.winTile + 2) res, _ = MWin.isHu(handTile) ftlog.debug('weihai_one_result.isSanQi result: ', res) return res elif MTile.getValue(self.winTile) == 3 and self.winTile < 30 and ( self.winTile - 1) in handTile and self.winTile - 2 in handTile: handTile.remove(self.winTile) handTile.remove(self.winTile - 1) handTile.remove(self.winTile - 2) res, _ = MWin.isHu(handTile) ftlog.debug('weihai_one_result.isSanQi result: ', res) return res else: ftlog.debug('weihai_one_result.isSanQi result: False') return False
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 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 isJipinghu(self, pattern, tiles, tileArr, magicTiles): useforColor = tileArr if len(magicTiles) > 0: useforColor[magicTiles[0]] = 0 hasfeng = 0 for tile in MTile.traverseTile(MTile.TILE_FENG): if tileArr[tile]: hasfeng += 1 break if MTile.getColorCount(useforColor) - hasfeng <= 1: return False kecount = 0 shuncount = 0 bothok = 0 for p in pattern: if len(p) == 3: magiccount = 0 for x in p: if len(magicTiles) > 0 and x == magicTiles[0]: magiccount += 1 if magiccount >= 2: bothok += 1 else: if p[0] == p[1] or p[0] == p[2] or p[1] == p[2]: kecount += 1 else: shuncount += 1 kecount += len(tiles[MHand.TYPE_PENG]) kecount += len(tiles[MHand.TYPE_GANG]) ftlog.debug('MWinRuleJiPingHu.isJipinghu kecount:', kecount, 'shuncount:', shuncount, 'bothok:', bothok) # 排除掉碰碰胡 if shuncount == 0: return False # 排除掉三元 haszhong = 0 for tile in [35, 36, 37]: if tileArr[tile] > 0: haszhong += 1 if haszhong == 3: return False # 排除掉四喜 hasfeng = 0 for tile in [31, 32, 33, 34]: if tileArr[tile] > 0: hasfeng += 1 if hasfeng == 4: return False if shuncount > 0 and kecount > 0: ftlog.debug('MWinRuleJiPingHu.isJipinghu True') return True return False
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 is13BuKaoWithOutLimit(cls, handTiles, hanMagics=[]): ''' 判断是否十三不靠 只要手牌没有靠着的就行 没有其他限制 hanMagics是手牌中的赖子数组,如手牌中有2个7是赖子 baoTiles=[7,7] ''' newHandTiles = copy.deepcopy(handTiles) # 有五张不同的风牌或箭牌 fengTiles = [] for index in range(0, len(newHandTiles)): if (MTile.isFeng(newHandTiles[index]) or MTile.isArrow(newHandTiles[index])): if (newHandTiles[index] not in fengTiles): fengTiles.append(newHandTiles[index]) else: return False, [] if len(fengTiles) > 0: for tile in fengTiles: newHandTiles.remove(tile) # 排序 newHandTiles.sort() for magic in hanMagics: if magic in newHandTiles: newHandTiles.remove(magic) # 根据花色分组 groups = [[] for _ in xrange(3)] for tile in newHandTiles: if ((tile % 10) == 0) or (tile >= 30): continue index = tile / 10 groups[index].append(tile) # 每组3张牌 buKaoCount = 0 for grp in groups: if len(grp) == 0: continue v = grp[0] % 10 if len(grp) == 2 and ((grp[1] % 10 == (v + 3) or grp[1] % 10 == (v + 6))): buKaoCount += len(grp) elif len(grp) == 3 and ((grp[1] % 10 == (v + 3) and grp[2] % 10 == (v + 6))): buKaoCount += len(grp) elif len(grp) == 1: buKaoCount += len(grp) ftlog.debug("buKaoCount ===", buKaoCount) ftlog.debug("handMagics ===", len(hanMagics)) ftlog.debug("fengTiles ===", len(fengTiles)) if buKaoCount + len(hanMagics) + len(fengTiles) != 14: return False, [] return True, [handTiles]
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 is13BuKao(cls, handTiles): ''' 判断是否十三不靠 ''' #有五张不同的风牌或箭牌 fengTiles = [] for index in range(0, len(handTiles)): if (MTile.isFeng(handTiles[index]) or MTile.isArrow(handTiles[index])): if (handTiles[index] not in fengTiles): fengTiles.append(handTiles[index]) else: return False, [] if len(fengTiles) > 0: for tile in fengTiles: handTiles.remove(tile) #剩余9张牌 if not (len(fengTiles) == 5 and len(handTiles) == 9): return False, [] #排序 handTiles.sort() ftlog.debug("handTiles ===", handTiles) #根据花色分组 groups = [[] for _ in xrange(3)] for tile in handTiles: if ((tile % 10) == 0) or (tile >= 30): continue index = tile / 10 groups[index].append(tile) ftlog.debug("groups ===", groups) # 每组3张牌 types = [1, 2, 3] for grp in groups: if len(grp) != 3: return False, [] v = grp[0] % 10 if not (grp[1] % 10 == (v + 3) and grp[2] % 10 == (v + 6)): return False, [] if v in types: types.remove(v) else: return False, [] ftlog.debug("handTile ===", handTiles) handTiles.extend(fengTiles) return True, [handTiles]
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(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 isDadiaoche(self, tiles): """ 大吊车:胡牌时自己手上只有一张牌,且胡的是二五八 """ handTile = tiles[MHand.TYPE_HAND] huTile = tiles[MHand.TYPE_HU][0] handTile.extend(tiles[MHand.TYPE_HU]) if len(handTile) == 2 and huTile < MTile.TILE_DONG_FENG and ( MTile.getValue(huTile) == 2 or MTile.getValue(huTile) == 5 or MTile.getValue(huTile) == 8): return True, [handTile] 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 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 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 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 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 isLuanFengyise(cls, tiles, colorCount): """ 风一色 """ ftlog.debug('MWin.isLuanFengyise tiles:', tiles, ' colorCount:', colorCount) if colorCount > 1: return False, [] for tile in tiles: if (not MTile.isFeng(tile)) and (not MTile.isArrow(tile)): return False, [] ftlog.debug('MWin.isLuanFengyise ok, pattern:', tiles) return True, [tiles]
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 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 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 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 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 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 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 checkPengMao(cls,tile,maoDanSetting,maoTiles): ftlog.debug('MMao.checkChiMao tile:', tile, 'maoDanSetting: ', maoDanSetting,'maoTiles: ',maoTiles) if maoDanSetting & MTDefine.MAO_DAN_DNXBZFB: #乱锚情况下 if len(maoTiles) > 0:#已经放过锚 if MTile.isArrow(tile) or MTile.isFeng(tile):# return False else: if len(maoTiles) > 0:#已经放过锚 for mao in maoTiles: ftlog.debug('MMao.checkChiMao type:', mao['type']) if MTile.isArrow(tile) and mao['type'] == 1:#已放箭牌 return False if MTile.isFeng(tile) and mao['type'] == 2:#已放风牌 return False return True
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 __init__(self): """初始化 子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌 包含所有的牌 """ super(AllFlowerDealer, self).__init__() # 本玩法包含的花色 self.__card_colors = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG,MTile.TILE_FLOWER] # 花色数量 self.__card_count = len(self.__card_colors) # 初始化本玩法包含的牌 self.setCardTiles(MTile.getTiles(self.__card_colors))
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 __init__(self): """初始化 子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌 四川玩法,只有三门,没有风 """ super(SanMenNoFengDealer, self).__init__() # 本玩法包含的花色 self.__card_colors = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO] # 花色数量 self.__card_count = len(self.__card_colors) # 初始化本玩法包含的牌 self.setCardTiles(MTile.getTiles(self.__card_colors)) ftlog.debug( self.cardTiles )
def __init__(self): """初始化 子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌 包括万/筒/条三门+中发白 """ super(SanMenWithZFBDealer, self).__init__() # 本玩法包含的花色 self.__card_colors = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG] # 风牌的描述 self.__feng_details = MTile.FENG_ZHONG | MTile.FENG_FA | MTile.FENG_BAI # 花色数量 self.__card_count = len(self.__card_colors) # 初始化本玩法包含的牌 self.setCardTiles(MTile.getTiles(self.__card_colors, self.__feng_details))
def isJinQue(self,magicTile,pattern,handTiles): """ 金雀:金做将对 """ magicCount = MTile.getTileCount(magicTile,handTiles) if magicCount != 2: return False for p in pattern: for oneTile in p: if oneTile in handTiles: handTiles.remove(oneTile) if len(handTiles) == 2 and handTiles[0] == handTiles[1] and handTiles[0] == magicTile: 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 canWinAddOneTile(cls, leftTileArr, leftTileCount, tiles, winRule, magicTiles = [], curSeatId = 0, winSeatId = 0, actionID = 0,tingForQiangjin = False,flowerRule = None): """ tingForQiangjin 是否是抢金,当是判断抢金时,有可听的结果就返回 modify by youjun """ result = [] if len(magicTiles): testTile = MTile.cloneTiles(tiles) testTile[MHand.TYPE_HAND].append(magicTiles[0]) testResult,testPattern,_ = winRule.isHu(testTile, magicTiles[0], True, MWinRule.WIN_BY_MYSELF, magicTiles, [], curSeatId, winSeatId, actionID,False,False) if not testResult: return result for tile in range(leftTileCount): if flowerRule and flowerRule.isFlower(tile): break if tile % 10 == 0: continue newTile = MTile.cloneTiles(tiles) newTile[MHand.TYPE_HAND].append(tile) # 测试停牌时,默认听牌状态 modify youjun 06.23 默认未听牌状态 winResult, winPattern,indexFan = winRule.isHu(newTile, tile, True, MWinRule.WIN_BY_MYSELF, magicTiles, [], curSeatId, winSeatId, actionID,False,False) if winResult: winNode = {} winNode['winTile'] = tile winNode['winTileCount'] = leftTileArr[tile] ''' ftlog.debug('MTing.canWinAddOneTile winTile:', tile , ' winTileCount:', winNode['winTileCount'] , ' winPattern:', winPattern , ' result:',indexFan) ''' winNode['pattern'] = winPattern winNode['result'] = indexFan result.append(winNode) if tingForQiangjin: return result return result
def __init__(self): """初始化 子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌 鸡西麻将三人玩法 包括筒/条三门+红中 """ super(TongTiaoWithZhonggDealer, self).__init__() # 本玩法包含的花色 self.__card_colors = [MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG] # 风牌的描述 self.__feng_details = MTile.FENG_ZHONG # 花色数量 self.__card_count = len(self.__card_colors) # 初始化本玩法包含的牌 self.setCardTiles(MTile.getTiles(self.__card_colors, self.__feng_details))
def isSanJinDao(self): """ 三金倒 """ magicTile = self.tableTileMgr.getMagicTile() handTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] magicCount = MTile.getTileCount(magicTile,handTiles) huTiles = self.tableTileMgr.players[self.winSeatId].huTiles ftlog.debug('isSanJinDao. self.winSeatId,huTiles=',self.winSeatId,huTiles) if len(huTiles) and huTiles[0] == magicTile: magicCount = magicCount + 1 ftlog.debug('isSanJinDao.magicCount=',magicCount,handTiles,magicTile) if magicCount == 3: return True return False
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 shuffle(self, goodPointCount, cardCountPerHand): """参数说明 goodPointCount : 好牌点的人数 cardCountPerHand : 每手牌的麻将牌张数 """ # 初始化一下cardTiles,因为每设置一次好牌点都会从里面弹出13张牌 self.setCardTiles(MTile.getTiles(self.__card_colors)) left_tiles = [] for color in self.__card_colors: left_tiles.extend(self.cardTiles[color]) # 对剩余的牌洗牌 random.shuffle(left_tiles) self.addTiles(left_tiles) return self.tiles
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 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 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 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 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 isJinQue(self,isZiMo = False): """ 金雀:金做将对 if not isZiMo: return False """ magicTile = self.tableTileMgr.getMagicTile() handTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] magicCount = MTile.getTileCount(magicTile,handTiles) huTiles = self.tableTileMgr.players[self.winSeatId].huTiles if len(huTiles) and huTiles[0] == magicTile: magicCount = magicCount + 1 if magicCount != 2: return False for p in self.__win_pattern: if len(p) == 2: if p[0] == p[1] and p[0] == magicTile: return True return False
def canJinQue(self,magicTile,pattern,handTiles,tile): ''' magicCount = MTile.getTileCount(magicTile,handTiles) if magicCount == 2: result, pattern= MWin.isHu(handTiles, []) ftlog.debug('MWinRuleQueshou.canJinQue result, pattern=',result, pattern) if result: return True return False ''' magicCount = MTile.getTileCount(magicTile,handTiles) if magicCount == 2: if tile in handTiles: handTiles.remove(tile) handTiles.append(31) result, pattern= MWin.isHu(handTiles, [31]) ftlog.debug('MWinRuleQueshou.canJinQue result, pattern=',result, pattern,handTiles) if result: return True return False
def isYouJin(self,magicTile,pattern,handTiles,tile): ''' 游金:金做将对 游金不胡点炮 ftlog.debug('MWinRuleQueshou.isYouJin pattern,handTiles,tile',pattern,handTiles,tile) for p in pattern: if len(p) == 2: if magicTile in p: p.remove(magicTile) if p[0] == tile: return True ''' magicCount = MTile.getTileCount(magicTile,handTiles) if magicCount == 1: if tile in handTiles: handTiles.remove(tile) handTiles.append(31) result, pattern= MWin.isHu(handTiles, [magicTile]) #ftlog.debug('MWinRuleQueshou.canJinQue result, pattern=',result, pattern,handTiles) if result: return True return False
def calcWin(self,winState = 0): 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: if not winState: 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 = 1 winScore = 0 # 连庄 bankerRemainCount = 0 if self.winSeatId == self.bankerSeatId: bankerRemainCount = self.tableTileMgr.tableConfig.get(MTDefine.WIN_BASE,1) - 1 winScore = winScore + bankerRemainCount ### 算杠分 minggangScore = 0 angangScore = 0 gangscore = 0 # 杠牌得分 gangList = self.playerGangTiles[self.winSeatId] for gang in gangList: #if MTile.getColor(gang['pattern'][0]) == 3: # gangscore += 1 # minggangScore += 1 if gang['style'] == 0: # 暗杠 gangscore += 2 angangScore += 2 else: gangscore += 1 minggangScore += 1 #winScore = winScore + angangScore + minggangScore ##算花分 huaScore = len(self.tableTileMgr.flowerTiles(self.winSeatId)) #winScore = winScore + huaScore ###算金分 magicTile = self.tableTileMgr.getMagicTile() handTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND] magicScore = MTile.getTileCount(magicTile,handTiles) huTiles = self.tableTileMgr.players[self.winSeatId].huTiles if len(huTiles) > 0 and huTiles[0] == magicTile and not winState == MTableState.TABLE_STATE_SANJINDAO: magicScore = magicScore + 1 ftlog.debug('calcWin handTiles=',handTiles,huTiles,magicScore) winScore = winScore + magicScore winnerResults = [] if winState: if winState == MTableState.TABLE_STATE_TIANHU: winnerResults.append(self.processFanXingResult(self.TIANHU)) elif winState == MTableState.TABLE_STATE_QIANGJIN: winnerResults.append(self.processFanXingResult(self.QIANGJIN)) elif winState == MTableState.TABLE_STATE_QIANGJIN_B: winnerResults.append(self.processFanXingResult(self.QIANGJIN)) elif winState == MTableState.TABLE_STATE_SANJINDAO: winnerResults.append(self.processFanXingResult(self.SANJINDAO)) #if not isZiMo: if not huaScore and not len(gangList): winnerResults.append(self.processFanXingResult(self.PINGHU)) if huaScore + gangscore == 1: winnerResults.append(self.processFanXingResult(self.PINGHUYIHUA)) if winState and winState == MTableState.TABLE_STATE_TIANHU: if self.isSanJinDao(): winnerResults.append(self.processFanXingResult(self.SANJINDAO)) if self.tableConfig.get(MTDefine.QINGHUNYISE, 0): if self.isQingyise(): #清一色 winnerResults.append(self.processFanXingResult(self.QINGYISE)) elif self.isHunyise(): # 混一色 winnerResults.append(self.processFanXingResult(self.HUNYISE)) if self.tableTileMgr.players[self.winSeatId].jinkanState: winnerResults.append(self.processFanXingResult(self.JINKAN)) if self.isJinQue(isZiMo): winnerResults.append(self.processFanXingResult(self.JINQUE)) if not winState: if self.isSanJinDao(): winnerResults.append(self.processFanXingResult(self.SANJINDAO)) if self.tableConfig.get(MTDefine.QINGHUNYISE, 0): if self.isQingyise(): #清一色 winnerResults.append(self.processFanXingResult(self.QINGYISE)) elif self.isHunyise(): # 混一色 winnerResults.append(self.processFanXingResult(self.HUNYISE)) if self.tableTileMgr.players[self.winSeatId].jinkanState: winnerResults.append(self.processFanXingResult(self.JINKAN)) if self.isJinQue(isZiMo): winnerResults.append(self.processFanXingResult(self.JINQUE)) if not len(winnerResults): winScore = winScore + baseScore ###自摸 或者特殊番型*2 #if isZiMo or len(winnerResults) > 0: # winScore = winScore * 2 bestWinnerResult = None maxScore = 0 for result in winnerResults: tempScore = self.getScoreByResults(result) if tempScore > maxScore: maxScore = tempScore bestWinnerResult = result if bestWinnerResult and bestWinnerResult['index'] == 19: huaScore = 0 else: winScore = winScore + angangScore + minggangScore winScore = winScore + huaScore ###自摸 或者特殊番型*2 if isZiMo or len(winnerResults) > 0: winScore = winScore * 2 winScore = winScore + maxScore #### 胡法判断 if isZiMo: #自摸 score = [-winScore for _ in range(self.playerCount)] score[self.winSeatId] = (self.playerCount-1) * winScore else: #点炮 # if self.qiangGang: #抢杠包三家 # score = [0 for _ in range(self.playerCount)] # score[self.winSeatId] = (self.playerCount - 1) * winScore # score[self.lastSeatId] = -(self.playerCount - 1) * winScore # else: if winState: #抢金 score = [-winScore for _ in range(self.playerCount)] score[self.winSeatId] = (self.playerCount-1) * winScore else: if self.getFangHuConfig() == 1: score = [-winScore for _ in range(self.playerCount)] score[self.winSeatId] = (self.playerCount-1) * winScore elif self.getFangHuConfig() == 2: score[self.lastSeatId] = -winScore score[self.winSeatId] = winScore if bestWinnerResult: winMode[self.winSeatId] = bestWinnerResult['index'] 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] = bestWinnerResult #self.results[self.KEY_FAN_PATTERN] = fanPattern ''' winInfo = [] jinResult = [] huaResult = [] baseResult = [] winPatt = [] if len(winnerResults) > 0 or isZiMo: #self.results['double'] = 2 jinResult.append("金牌:" + str(magicScore) + "花" + "*2") huaResult.append("花牌:" + str(huaScore) + "花" + "*2") baseResult.append("底分:" + str(baseScore) + "花" + "*2") if bestWinnerResult: winPatt.append(bestWinnerResult['name'] + ":" + str(bestWinnerResult['value'])+ "花") else: jinResult.append("金牌:" + str(magicScore) + "花") huaResult.append("花牌:" + str(huaScore) + "花") baseResult.append("底分:" + str(baseScore) + "花") winInfo.append(baseResult) if magicScore: winInfo.append(jinResult) if huaScore: winInfo.append(huaResult) if len(winPatt) > 0: winInfo.append(winPatt) ''' winInfo = [] jinResult = "金牌" + str(magicScore) huaResult = "花牌" + str(huaScore) baseResult = "底分" + str(baseScore) remainResult = "连庄" + str(bankerRemainCount) winPatt = None if bestWinnerResult: winPatt = bestWinnerResult['name'] + str(bestWinnerResult['value']) minggangResult = "明杠" + str(minggangScore) angangResult = "暗杠" + str(angangScore) winResult = "(" if not len(winnerResults): winResult = winResult + " " + baseResult if huaScore: winResult = winResult + " " + huaResult if magicScore: winResult = winResult + " " + jinResult if minggangScore: winResult = winResult + " " + minggangResult if angangScore: winResult = winResult + " " + angangResult if bankerRemainCount: winResult = winResult + " " + remainResult if len(winnerResults) > 0 or isZiMo: if bestWinnerResult: winPatt = bestWinnerResult['name'] + str(bestWinnerResult['value']) if huaScore or magicScore or minggangScore or angangScore or bankerRemainCount: winResult = winResult + " )" + " *2 + " + winPatt + " = " + str(winScore) else: winResult = winPatt + " = " + str(winScore) else: winResult = winResult + " )" + " *2" + " = " + str(winScore) else: winResult = winResult + " )" + " *1" + " = " + str(winScore) winInfo.append([winResult]) fanPattern[self.winSeatId] = winInfo self.results[self.KEY_FAN_PATTERN] = fanPattern self.results[self.KEY_FLOWER_SCORES] = flowerScores self.results[self.KEY_LIANZHUANG] = bankerRemainCount