Beispiel #1
0
    def isPiao(self):
        playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI]
        if len(playerChiTiles) > 0:
            return False

        isHasKe = False
        playerPengTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_PENG]
        if len(playerPengTiles) > 0:
            isHasKe = True

        playerGangTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_GANG]
        if len(playerGangTiles) > 0:
            isHasKe = True

        playerHandTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]
        newPlayerHandTiles = MTile.cloneTiles(playerHandTiles)
        newPlayerHandTilesArr = MTile.changeTilesToValueArr(newPlayerHandTiles)
        for playerHandTileCount in newPlayerHandTilesArr:
            if playerHandTileCount == 3:
                isHasKe = True
                break

        if not isHasKe:
            return False

        for wn in self.winNodes:
            # if wn['winTile'] == self.winTile:
            patterns = wn['pattern']
            ftlog.debug('MJixiOneResult.isPiao winTile:', self.winTile, ' winPatterns:', patterns)
            for p in patterns:
                if len(p) == 3 and p[0] != p[1]:
                    return False

        return True
Beispiel #2
0
    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
Beispiel #3
0
    def canTing(cls, tiles, leftTiles, winRule, cur_tile, magicTiles=list()):
        """
        判断所有的听牌情况
        :param tiles 手牌
        :param leftTiles 剩余未发的牌
        :param winRule:
        :param cur_tile:
        :param magicTiles:
        :type tiles HandTiles
        :return
        """
        ftlog.debug('MTile.changeTilesToValueArr', tiles[MHand.TYPE_HAND])
        handTileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND])

        leftTileArr = MTile.changeTilesToValueArr(leftTiles)
        leftTileCount = len(leftTileArr)
        ftlog.debug('MTing.canTing leftTileArr:', leftTileArr,
                    ' leftTileCount:', leftTileCount)

        result = []
        for tile, _ in handTileArr.tile_items():
            # 打出一张牌后可以听牌
            newTiles = HandTiles.clone(tiles)
            newTiles.dropHand(tile)
            resultNode = cls.canWinAddOneTile(leftTileArr, leftTileCount,
                                              newTiles, winRule, 0, magicTiles)
            if len(resultNode) > 0:
                winNode = {'dropTile': tile, 'winNodes': resultNode}
                result.append(winNode)

        return len(result) > 0, result
Beispiel #4
0
    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
Beispiel #5
0
    def isHu(self, tiles, tile, isTing, getTileType, magicTiles=list(), tingNodes=list()):
        result, rePattern = MWin.isHu(tiles[MHand.TYPE_HAND])
        if not result:
            return False, []

        # 分析花色
        tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles))
        colors = MTile.getColorCount(tileArr)
        ftlog.debug('MWinRuleSichuan.isHu colors:', colors)

        if colors <= 2:
            # 花色缺门,可以和
            return True, rePattern
        return False, []
Beispiel #6
0
    def isHu(cls, hand_tiles, magicTiles=list()):
        """
        胡牌判断,只判断手牌,杠牌,吃牌,碰牌不在内
           杠牌、吃牌、碰牌已成型,不用另外计算
        * 肯定包含将牌
        * 剩下的牌里不会有暗杠牌
        * 杠牌/吃牌/碰牌是已经成型的牌,按成型的样式计算积分,不再重新计算
        :param magicTiles 赖子牌
        :return 是否胡了
        """
        tileArr = MTile.changeTilesToValueArr(hand_tiles)
        magicArr = []
        for magicTile in magicTiles:
            magicArr.extend([magicTile for _ in range(tileArr[magicTile])])
            tileArr[magicTile] = 0

        resultArr = []
        tileTypes = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG]
        hasJiang = False
        winResult = False

        for tileType in tileTypes:
            winResult, hasJiang, _tArr, _rArr, _mArr = cls.isHuWithMagic(tileArr, resultArr, magicArr, hasJiang,
                                                                         tileType)
            if not winResult:
                return False, []
            else:
                tileArr = copy.deepcopy(_tArr)
                resultArr = copy.deepcopy(_rArr)
                magicArr = copy.deepcopy(_mArr)

        if winResult and not hasJiang and len(magicArr) >= 2:
            hasJiang = True
        return hasJiang and winResult, resultArr
Beispiel #7
0
    def isHu(self,
             tiles,
             last_tile,
             isTing,
             getTileType,
             magicTiles=list(),
             tingNodes=list()):
        hu_tiles = HuTiles()
        handTileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND])
        if not M14.find_first(
                handTileArr,
                hu_tiles,
                M14.is7Dui if self.dui7 else M14.justPass,
                M14.isPHu,
        ):
            # 基本的胡牌类型都挂了
            return False, None
        dui_list = handTileArr.tiles_dui()
        if len(dui_list) == 0:
            # 没有将牌
            return False, []
        if len(hu_tiles) != 7 and not set(
                zip(*dui_list)[0]) & MWinRuleJiNan.JIANG:
            # 没有2,5,8将牌
            return False, []

        return True, hu_tiles
Beispiel #8
0
    def isPairs(cls, tiles, magicTiles):
        if len(tiles[MHand.TYPE_CHI]) != 0:
            return False
        if len(tiles[MHand.TYPE_PENG]) != 0:
            return False
        if len(tiles[MHand.TYPE_GANG]) != 0:
            return False
        pairTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])

        haveMagicCount = 0
        for magicTile in magicTiles:
            while magicTile in pairTiles:
                pairTiles.remove(magicTile)
                haveMagicCount += 1
        ftlog.debug("win_rule_zhaotong::isPairs pairTiles = ", pairTiles, "haveMagicCount =", haveMagicCount)
        tileArr = MTile.changeTilesToValueArr(pairTiles)
        for count in tileArr:
            if count % 2 == 0:
                continue
            else:
                if haveMagicCount <= 0:
                    return False
                else:
                    haveMagicCount -= 1
                    continue
        return True
Beispiel #9
0
    def isPairs(cls, tiles, magicTiles):
        if len(tiles[MHand.TYPE_CHI]) != 0:
            return False
        if len(tiles[MHand.TYPE_PENG]) != 0:
            return False
        if len(tiles[MHand.TYPE_GANG]) != 0:
            return False
        pairTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])

        haveMagicCount = 0
        for magicTile in magicTiles:
            while magicTile in pairTiles:
                pairTiles.remove(magicTile)
                haveMagicCount += 1
        ftlog.debug("win_rule_zhaotong::isPairs pairTiles = ", pairTiles,
                    "haveMagicCount =", haveMagicCount)
        tileArr = MTile.changeTilesToValueArr(pairTiles)
        for count in tileArr:
            if count % 2 == 0:
                continue
            else:
                if haveMagicCount <= 0:
                    return False
                else:
                    haveMagicCount -= 1
                    continue
        return True
Beispiel #10
0
    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)

        # 第二种情况 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)

        return result
Beispiel #11
0
 def canTing(self, tiles, leftTiles, tile, magicTiles=[]):
     if len(leftTiles) < 12:
         # 小于12张不能亮牌/听牌
         return False, []
     isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles)
     ftlog.debug('MTingKawuxingRule.canTing using MTing isTing:', isTing, ' tingResults:', tingResults)
     return isTing, tingResults
Beispiel #12
0
    def isQiDui(self):
        playerChiTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_CHI]
        if len(playerChiTiles) > 0:
            return False

        playerPengTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_PENG]
        if len(playerPengTiles) > 0:
            return False

        playerGangTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_GANG]
        if len(playerGangTiles) > 0:
            return False

        for wn in self.winNodes:
            if wn['winTile'] == self.winTile:
                patterns = wn['pattern']
                ftlog.debug('MJixiOneResult.isQiDui winTile:', self.winTile, ' winPatterns:', patterns)
                for p in patterns:
                    if len(p) == 3:
                        return False

        # 宝牌情况
        if self.isMagicTile():
            for wn in self.winNodes:
                winTile = wn['winTile']
                patterns = wn['pattern']
                for p in patterns:
                    if (winTile in p) and len(p) == 3:
                        return False

        handTiles = self.playerAllTiles[self.winSeatId][MHand.TYPE_HAND]
        newHandTiles = MTile.cloneTiles(handTiles)
        ftlog.debug('MTingJixiRule.MTing.canTing isQiDui handTiles:', handTiles, 'isMagic:', self.isMagicTile(),
                    'winTile:', self.winTile)
        newHandTiles.append(self.winTile)
        handTilesArr = MTile.changeTilesToValueArr(newHandTiles)
        duiCount = 0
        for index in range(len(handTilesArr)):
            if handTilesArr[index] == 2:
                duiCount += 1
            elif handTilesArr[index] == 4:
                duiCount += 2

        if duiCount == 7 or (duiCount == 6 and self.isMagicTile()):  # 宝牌情况
            return True

        return False
Beispiel #13
0
    def isLanPaiHu(cls, tiles, magicTiles):
        """先做简单的牌型检查,如果符合再进行细节判断"""
        if len(tiles[MHand.TYPE_CHI]) != 0:
            return False
        if len(tiles[MHand.TYPE_PENG]) != 0:
            return False
        if len(tiles[MHand.TYPE_GANG]) != 0:
            return False
        # 去除手牌赖子,并计数
        haveMagicCount = 0
        lanpaiTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])
        for magicTile in magicTiles:
            while magicTile in lanpaiTiles:
                lanpaiTiles.remove(magicTile)
                haveMagicCount += 1
        tileArr = MTile.changeTilesToValueArr(lanpaiTiles)
        # 去除赖子后手牌数不能有超过2张的
        for count in tileArr:
            if count <= 1:
                continue
            else:
                return False

        # 去除赖子后不重复字牌加赖子数要大于等于5,并且可用赖子数=字牌+赖子-5
        # canUseMagicCount = haveMagicCount
        tempFengTiles = MTile.traverseTile(MTile.TILE_FENG)
        fengArr = tileArr[tempFengTiles[0]:tempFengTiles[len(tempFengTiles) -
                                                         1] + 1]

        # 检查字牌种类和每种的数量,之前因为已经判断过数量小于等于1,这里不再重复
        fengCount = 0
        for count in fengArr:
            if count == 1:
                fengCount += 1

        # 如果字牌每种不超过1张且有五种,开始判断其它花色
        if fengCount + haveMagicCount >= 5:
            # 分别判断三种花色
            if cls.checkBukao(tileArr, MTile.TILE_WAN) and cls.checkBukao(
                    tileArr, MTile.TILE_TONG) and cls.checkBukao(
                        tileArr, MTile.TILE_TIAO):
                return True
        else:
            return False

        return False
Beispiel #14
0
 def canTing(self, tiles, leftTiles, tile, magicTiles=[]):
     if len(leftTiles) < 12:
         # 小于12张不能亮牌/听牌
         return False, []
     isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles,
                                         self.winRuleMgr, tile, magicTiles)
     ftlog.debug('MTingKawuxingRule.canTing using MTing isTing:', isTing,
                 ' tingResults:', tingResults)
     return isTing, tingResults
Beispiel #15
0
    def isLanPaiHu(cls, tiles, magicTiles):
        """先做简单的牌型检查,如果符合再进行细节判断"""
        if len(tiles[MHand.TYPE_CHI]) != 0:
            return False
        if len(tiles[MHand.TYPE_PENG]) != 0:
            return False
        if len(tiles[MHand.TYPE_GANG]) != 0:
            return False
        # 去除手牌赖子,并计数
        haveMagicCount = 0
        lanpaiTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])
        for magicTile in magicTiles:
            while magicTile in lanpaiTiles:
                lanpaiTiles.remove(magicTile)
                haveMagicCount += 1
        tileArr = MTile.changeTilesToValueArr(lanpaiTiles)
        # 去除赖子后手牌数不能有超过2张的
        for count in tileArr:
            if count <= 1:
                continue
            else:
                return False

        # 去除赖子后不重复字牌加赖子数要大于等于5,并且可用赖子数=字牌+赖子-5
        # canUseMagicCount = haveMagicCount
        tempFengTiles = MTile.traverseTile(MTile.TILE_FENG)
        fengArr = tileArr[tempFengTiles[0]:tempFengTiles[len(tempFengTiles) - 1] + 1]

        # 检查字牌种类和每种的数量,之前因为已经判断过数量小于等于1,这里不再重复
        fengCount = 0
        for count in fengArr:
            if count == 1:
                fengCount += 1

        # 如果字牌每种不超过1张且有五种,开始判断其它花色
        if fengCount + haveMagicCount >= 5:
            # 分别判断三种花色
            if cls.checkBukao(tileArr, MTile.TILE_WAN) and cls.checkBukao(tileArr, MTile.TILE_TONG) and cls.checkBukao(
                    tileArr, MTile.TILE_TIAO):
                return True
        else:
            return False

        return False
Beispiel #16
0
    def isLanPaiCheck(self, tiles, magicTiles):
        """先做简单的牌型检查,如果符合再进行细节判断"""
        if len(tiles[MHand.TYPE_HAND]) != 14:
            return False, 0, 0
        ftlog.debug("isLanPaiCheck handcard is ok")
        # 去除手牌赖子,并计数
        haveMagicCount = 0
        lanpaiTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])
        for magicTile in magicTiles:
            while magicTile in lanpaiTiles:
                lanpaiTiles.remove(magicTile)
                haveMagicCount += 1
        ftlog.debug("isLanPaiCheck haveMagicCount =", haveMagicCount, "lanpaiTiles =", lanpaiTiles)
        tileArr = MTile.changeTilesToValueArr(lanpaiTiles)
        # 去除赖子后手牌数不能有超过2张的
        for count in tileArr:
            if count <= 1:
                continue
            else:
                return False, 0, 0

        # 去除赖子后不重复字牌加赖子数要大于等于5,并且可用赖子数=字牌+赖子-5
        # canUseMagicCount = haveMagicCount
        tempFengTiles = MTile.traverseTile(MTile.TILE_FENG)
        fengArr = tileArr[tempFengTiles[0]:tempFengTiles[len(tempFengTiles) - 1] + 1]
        ftlog.debug("isLanPaiCheck fengArr =", fengArr)
        # 检查字牌种类和每种的数量,之前因为已经判断过数量小于等于1,这里不再重复
        fengCount = 0
        for count in fengArr:
            if count == 1:
                fengCount += 1

        # 如果字牌每种不超过1张且有五种,开始判断其它花色
        if fengCount + haveMagicCount >= 5:
            # 分别判断三种花色
            ftlog.debug("isLanPaiCheck checkBukao begin tileArr = ", tileArr)
            if self.checkBukao(tileArr, MTile.TILE_WAN) and self.checkBukao(tileArr,
                                                                            MTile.TILE_TONG) and self.checkBukao(
                    tileArr, MTile.TILE_TIAO):
                return True, fengCount, haveMagicCount
        else:
            return False, 0, 0

        return False, 0, 0
Beispiel #17
0
 def hasAnGang(cls, tiles, tile):
     """自摸是否可以暗杠
     判断杠牌时,tile已经加入tiles中
     tiles - 手牌
     tile - 待杠的牌
     """
     tileArr = MTile.changeTilesToValueArr(tiles)
     if tileArr[tile] == 4:
         return True
     return False
Beispiel #18
0
    def isHu(self,
             tiles,
             tile,
             isTing,
             getTileType,
             magicTiles=list(),
             tingNodes=list()):
        result, rePattern = MWin.isHu(tiles[MHand.TYPE_HAND])
        if not result:
            return False, []

        # 分析花色
        tileArr = MTile.changeTilesToValueArr(MHand.copyAllTilesToList(tiles))
        colors = MTile.getColorCount(tileArr)
        ftlog.debug('MWinRuleSichuan.isHu colors:', colors)

        if colors <= 2:
            # 花色缺门,可以和
            return True, rePattern
        return False, []
Beispiel #19
0
 def hasPeng(cls, tiles, tile):
     """
     是否可以碰
     判断之前tile已经加到tiles中
     tiles - 手牌
     tile - 待碰的牌
     """
     tileArr = MTile.changeTilesToValueArr(tiles)
     if tileArr[tile] >= 3:
         return True
     return False
Beispiel #20
0
 def __init__(self):
     """初始化
         子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌
         包含所有的牌
     """
     super(AllColorDealer, self).__init__()
     # 本玩法包含的花色
     self.__card_colors = [MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG]
     # 花色数量
     self.__card_count = len(self.__card_colors)
     # 初始化本玩法包含的牌
     self.setCardTiles(MTile.getTiles(self.__card_colors))
     ftlog.debug(self.cardTiles)
Beispiel #21
0
 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)
Beispiel #22
0
 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)
Beispiel #23
0
    def hasPeng(self, tiles, tile):
        """
        是否有碰牌解
        
        参数说明;
        tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌
        tile - 待碰的牌
        """
        pengSolutions = []
        normalPeng = MPeng.hasPeng(tiles[MHand.TYPE_HAND], 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

        magicPengMaxCount = self.tableTileMgr.magicPengMaxCount
        if magicPengMaxCount > 3 or magicPengMaxCount < 0:
            magicPengMaxCount = 3

        ftlog.debug('MPengRule.hasPeng tile:', tile, ' tileCount:',
                    tileArr[tile], ' magicCount:', magicCount,
                    'magicPengMaxCount', magicPengMaxCount)

        if (magicCount == 0) or (tileArr[tile]
                                 == 0) or (magicPengMaxCount <= 0):
            return pengSolutions

        if magicCount >= 1 and tileArr[tile] >= 2 and magicPengMaxCount >= 1:
            # 使用一个癞子
            pattern1 = [tile, tile, magicTiles[0]]
            pattern1.sort()
            pengSolutions.append(pattern1)

        if magicCount >= 2 and tileArr[tile] >= 1 and magicPengMaxCount >= 2:
            # 使用两个癞子
            pattern2 = [tile, magicTiles[0], magicTiles[1]]
            pattern2.sort()
            pengSolutions.append(pattern2)

        return pengSolutions
Beispiel #24
0
 def __init__(self):
     """初始化
         子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌
         包含所有的牌
     """
     super(AllColorDealer, self).__init__()
     # 本玩法包含的花色
     self.__card_colors = [
         MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG
     ]
     # 花色数量
     self.__card_count = len(self.__card_colors)
     # 初始化本玩法包含的牌
     self.setCardTiles(MTile.getTiles(self.__card_colors))
     ftlog.debug(self.cardTiles)
Beispiel #25
0
 def __init__(self):
     """初始化
         子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌
         多余红中麻将/哈尔滨麻将
         包括万/筒/条三门+红中
     """
     super(SanMenWithZhonggDealer, self).__init__()
     # 本玩法包含的花色
     self.__card_colors = [MTile.TILE_WAN, 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))
Beispiel #26
0
    def isWuDuiHu(self, allTiles, winTile):
        huSeatId = -1
        for seatId, playerTiles in enumerate(allTiles):
            handTiles = playerTiles[MHand.TYPE_HAND]
            handTilesArr = MTile.changeTilesToValueArr(handTiles)
            huSeatId = seatId
            for handTile in handTiles:
                if handTilesArr[handTile] >= 2:
                    huSeatId = -1
                    break

        if huSeatId >= 0:
            return True, huSeatId

        return False, -1
Beispiel #27
0
    def isWuDuiHu(self, allTiles, winTile):
        huSeatId = -1
        for seatId, playerTiles in enumerate(allTiles):
            handTiles = playerTiles[MHand.TYPE_HAND]
            handTilesArr = MTile.changeTilesToValueArr(handTiles)
            huSeatId = seatId
            for handTile in handTiles:
                if handTilesArr[handTile] >= 2:
                    huSeatId = -1
                    break

        if huSeatId >= 0:
            return True, huSeatId

        return False, -1
Beispiel #28
0
 def __init__(self):
     """初始化
         子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌
         卡五星
         包括筒/条两门+中发白
     """
     super(TongTiaoWithZFBDealer, self).__init__()
     # 本玩法包含的花色
     self.__card_colors = [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))
Beispiel #29
0
 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))
Beispiel #30
0
    def hasPeng(self, tiles, tile):
        """
        是否有碰牌解
        
        参数说明;
        tiles - 玩家的所有牌,包括手牌,吃牌,碰牌,杠牌,胡牌
        tile - 待碰的牌
        """
        pengSolutions = []
        normalPeng = MPeng.hasPeng(tiles[MHand.TYPE_HAND], 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

        magicPengMaxCount = self.tableTileMgr.magicPengMaxCount
        if magicPengMaxCount > 3 or magicPengMaxCount < 0:
            magicPengMaxCount = 3

        ftlog.debug('MPengRule.hasPeng tile:', tile
                    , ' tileCount:', tileArr[tile]
                    , ' magicCount:', magicCount
                    , 'magicPengMaxCount', magicPengMaxCount)

        if (magicCount == 0) or (tileArr[tile] == 0) or (magicPengMaxCount <= 0):
            return pengSolutions

        if magicCount >= 1 and tileArr[tile] >= 2 and magicPengMaxCount >= 1:
            # 使用一个癞子
            pattern1 = [tile, tile, magicTiles[0]]
            pattern1.sort()
            pengSolutions.append(pattern1)

        if magicCount >= 2 and tileArr[tile] >= 1 and magicPengMaxCount >= 2:
            # 使用两个癞子
            pattern2 = [tile, magicTiles[0], magicTiles[1]]
            pattern2.sort()
            pengSolutions.append(pattern2)

        return pengSolutions
Beispiel #31
0
 def isPairsCheck(self, tiles, magicTiles):
     """判断七对型胡牌"""
     # 不能吃碰杠
     if len(tiles[MHand.TYPE_CHI]) != 0:
         return False, 0, 0, 0, 0
     if len(tiles[MHand.TYPE_PENG]) != 0:
         return False, 0, 0, 0, 0
     if len(tiles[MHand.TYPE_GANG]) != 0:
         return False, 0, 0, 0, 0
     # 用赖子给其他牌配对
     pairTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])
     fourCount = 0
     specialFourCount = 0
     twoCount = 0
     haveMagicCount = 0
     for magicTile in magicTiles:
         while magicTile in pairTiles:
             pairTiles.remove(magicTile)
             haveMagicCount += 1
     tileArr = MTile.changeTilesToValueArr(pairTiles)
     for count in tileArr:
         if count % 2 == 0:
             if count == 4:
                 fourCount += 1
             elif count == 2:
                 twoCount += 1
             continue
         else:
             if haveMagicCount <= 0:
                 return False, 0, 0, 0, 0
             else:
                 haveMagicCount -= 1
                 if count == 3:
                     specialFourCount += 1
                     fourCount += 1
                 elif count == 1:
                     twoCount += 1
                 continue
     # 配对结束,赖子必须剩偶数个
     if haveMagicCount % 2 == 0:
         # 尽量凑4个的
         while haveMagicCount >= 2 and twoCount >= 1:
             twoCount -= 1
             specialFourCount += 1
             fourCount += 1
             haveMagicCount -= 2
         return True, haveMagicCount, fourCount, twoCount, specialFourCount
     return False, 0, 0, 0, 0
Beispiel #32
0
    def getPaoqiaomobaBaCount(self):
        """
        跑恰摸八中的八:筒、条、风这三门牌里面,和牌时,有几门达到8张
        每种花色,8张加1分,9张加2分,以此类推
        """
        baCount = 0
        if self.tableConfig.get(MTDefine.PAOQIAMOBA, 0):
            colorCountArr = [0, 0, 0, 0]
            for tile in self.__player_all_tiles_arr[self.winSeatId]:
                color = MTile.getColor(tile)
                colorCountArr[color] += 1

            for colorCount in colorCountArr:
                if colorCount >= 8:
                    baCount += colorCount - 7
        ftlog.debug('MKawuxingOneResult.getPaoqiaomobaBaCount baCount: ', baCount)
        return baCount
Beispiel #33
0
 def isPairsCheck(self, tiles, magicTiles):
     """判断七对型胡牌"""
     # 不能吃碰杠
     if len(tiles[MHand.TYPE_CHI]) != 0:
         return False, 0, 0, 0
     if len(tiles[MHand.TYPE_PENG]) != 0:
         return False, 0, 0, 0
     if len(tiles[MHand.TYPE_GANG]) != 0:
         return False, 0, 0, 0
     # 用赖子给其他牌配对
     pairTiles = copy.deepcopy(tiles[MHand.TYPE_HAND])
     fourCount = 0
     twoCount = 0
     haveMagicCount = 0
     for magicTile in magicTiles:
         while magicTile in pairTiles:
             pairTiles.remove(magicTile)
             haveMagicCount += 1
     tileArr = MTile.changeTilesToValueArr(pairTiles)
     for count in tileArr:
         if count % 2 == 0:
             if count == 4:
                 fourCount += 1
             elif count == 2:
                 twoCount += 1
             continue
         else:
             if haveMagicCount <= 0:
                 return False, 0, 0, 0
             else:
                 haveMagicCount -= 1
                 if count == 3:
                     fourCount += 1
                 elif count == 1:
                     twoCount += 1
                 continue
     # 配对结束,赖子必须剩偶数个
     if haveMagicCount % 2 == 0:
         # 尽量凑4个的
         while haveMagicCount >= 2 and twoCount >= 1:
             twoCount -= 1
             fourCount += 1
             haveMagicCount -= 2
         return True, haveMagicCount, fourCount, twoCount
     return False, 0, 0, 0
Beispiel #34
0
    def isQingyise(self):
        """
        清一色:由同一门花色(筒子或条子)组成的和牌牌型
        """
        colorArr = [0, 0, 0, 0]
        for tile in self.__player_all_tiles_arr[self.winSeatId]:
            color = MTile.getColor(tile)
            colorArr[color] = 1

        colorCount = 0
        for eachColor in colorArr:
            if eachColor:
                colorCount += 1
        if colorCount > 1:
            ftlog.debug('MKawuxingOneResult.isQingyise result: False')
            return False
        ftlog.debug('MKawuxingOneResult.isQingyise result: True')
        return True
Beispiel #35
0
    def getPaoqiaomobaBaCount(self):
        """
        跑恰摸八中的八:筒、条、风这三门牌里面,和牌时,有几门达到8张
        每种花色,8张加1分,9张加2分,以此类推
        """
        baCount = 0
        if self.tableConfig.get(MTDefine.PAOQIAMOBA, 0):
            colorCountArr = [0, 0, 0, 0]
            for tile in self.__player_all_tiles_arr[self.winSeatId]:
                color = MTile.getColor(tile)
                colorCountArr[color] += 1

            for colorCount in colorCountArr:
                if colorCount >= 8:
                    baCount += colorCount - 7
        ftlog.debug('MKawuxingOneResult.getPaoqiaomobaBaCount baCount: ',
                    baCount)
        return baCount
Beispiel #36
0
    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:
                # 和KawuxingOneResult配合
                pattern.extend([[tile, tile], [tile, tile]])
        return True, pattern
Beispiel #37
0
    def isHu(self, tiles, last_tile, isTing, getTileType, magicTiles=list(), tingNodes=list()):
        hu_tiles = HuTiles()
        handTileArr = MTile.changeTilesToValueArr(tiles[MHand.TYPE_HAND])
        if not M14.find_first(handTileArr, hu_tiles,
                              M14.is7Dui if self.dui7 else M14.justPass,
                              M14.isPHu,
                              ):
            # 基本的胡牌类型都挂了
            return False, None
        dui_list = handTileArr.tiles_dui()
        if len(dui_list) == 0:
            # 没有将牌
            return False, []
        if len(hu_tiles) != 7 and not set(zip(*dui_list)[0]) & MWinRuleJiNan.JIANG:
            # 没有2,5,8将牌
            return False, []

        return True, hu_tiles
Beispiel #38
0
 def __init__(self):
     """初始化
         子类在自己的初始化方法里,初始化麻将牌池范围,准备发牌
         卡五星
         包括筒/条两门+中发白
     """
     super(TongTiaoWithZFBDealer, self).__init__()
     # 本玩法包含的花色
     self.__card_colors = [
         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))
Beispiel #39
0
    def isQingyise(self):
        """
        清一色:由同一门花色(筒子或条子)组成的和牌牌型
        """
        colorArr = [0, 0, 0, 0]
        for tile in self.__player_all_tiles_arr[self.winSeatId]:
            color = MTile.getColor(tile)
            colorArr[color] = 1

        colorCount = 0
        for eachColor in colorArr:
            if eachColor:
                colorCount += 1
        if colorCount > 1:
            ftlog.debug('MKawuxingOneResult.isQingyise result: False')
            return False
        ftlog.debug('MKawuxingOneResult.isQingyise result: True')
        return True
Beispiel #40
0
 def checkBukao(cls, tileArr, tileType):
     """烂牌检查三种花色的不靠"""
     tempTiles = MTile.traverseTile(tileType)
     colorArr = tileArr[tempTiles[0]:tempTiles[len(tempTiles) - 1] + 1]
     colorTiles = []
     for i in range(len(colorArr)):
         if colorArr[i] > 0:
             colorTiles.append(i)
         if len(colorTiles) > 3:
             return False
         # 然后只需要判断不靠即可
         elif len(colorTiles) == 2:
             if (colorTiles[0] - colorTiles[1]) % 3 != 0:
                 return False
         elif len(colorTiles) == 3:
             if (colorTiles[0] - colorTiles[1]) % 3 != 0 or (colorTiles[0] - colorTiles[2]) % 3 != 0 or (
                 colorTiles[1] - colorTiles[2]) % 3 != 0:
                 return False
     return True
Beispiel #41
0
 def checkBukao(cls, tileArr, tileType):
     """烂牌检查三种花色的不靠"""
     tempTiles = MTile.traverseTile(tileType)
     colorArr = tileArr[tempTiles[0]:tempTiles[len(tempTiles) - 1] + 1]
     colorTiles = []
     for i in range(len(colorArr)):
         if colorArr[i] > 0:
             colorTiles.append(i)
         if len(colorTiles) > 3:
             return False
         # 然后只需要判断不靠即可
         elif len(colorTiles) == 2:
             if (colorTiles[0] - colorTiles[1]) % 3 != 0:
                 return False
         elif len(colorTiles) == 3:
             if (colorTiles[0] - colorTiles[1]) % 3 != 0 or (
                     colorTiles[0] - colorTiles[2]) % 3 != 0 or (
                         colorTiles[1] - colorTiles[2]) % 3 != 0:
                 return False
     return True
Beispiel #42
0
 def calcFanDaduizi(self, fanData, nowTiles, magicTiles, magicTileCount,
                    winTile, seatId, lastSeatId):
     """计算大对子番型"""
     fan = fanData.get('fan', 0)
     patterns = fanData.get('patterns', [])
     isUnique = fanData.get('isUnique', False)
     isSpecial = fanData.get('isSpecial', False)
     isDaduizi = False
     # 大对子,门前不能有吃,手牌多加一个赖子,能保证都是3张
     if len(nowTiles[MHand.TYPE_CHI]) == 0:
         duiziTiles = copy.deepcopy(nowTiles[MHand.TYPE_HAND])
         for magicTile in magicTiles:
             while magicTile in duiziTiles:
                 duiziTiles.remove(magicTile)
         # 如果点炮胡,需要给牌堆里加回去一张赖子,并当普通牌处理
         if seatId != lastSeatId and winTile in magicTiles:
             duiziTiles.append(winTile)
         duiziArr = MTile.changeTilesToValueArr(duiziTiles)
         ftlog.debug("MYunnanOneResult duiziArr = ", duiziArr)
         cardTypeCount = 0
         # 假设多一张赖子
         duiziMagicCount = magicTileCount + 1
         for index in range(len(duiziArr)):
             if duiziArr[index] != 0:
                 cardTypeCount += 1
                 if duiziArr[index] < 3:
                     duiziMagicCount = duiziMagicCount - (3 -
                                                          duiziArr[index])
         if cardTypeCount <= 5 and duiziMagicCount >= 0:
             if not isUnique:
                 patterns.append(self.fanXing[self.DUIDUIHU]['name'])
                 fan += self.fanXing[self.DUIDUIHU]['index']
                 ftlog.debug("MYunnanOneResult fanxing = ", patterns,
                             "fan = ", fan)
                 isDaduizi = True
                 isSpecial = True
     fanData['isUnique'] = isUnique
     fanData['fan'] = fan
     fanData['isSpecial'] = isSpecial
     return fan, patterns, isUnique, isDaduizi
Beispiel #43
0
    def shuffle(self, goodPointCount, cardCountPerHand):
        """参数说明
            goodPointCount : 好牌点的人数
            cardCountPerHand : 每手牌的麻将牌张数
        """
        # 初始化一下cardTiles,因为每设置一次好牌点都会从里面弹出13张牌
        self.setCardTiles(MTile.getTiles(self.__card_colors))

        for color in self.__card_colors:
            random.shuffle(self.cardTiles[color])

        for _ in range(goodPointCount):
            self.addTiles(self.getGoodCard(cardCountPerHand))

        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
Beispiel #44
0
    def shuffle(self, goodPointCount, cardCountPerHand):
        """参数说明
            goodPointCount : 好牌点的人数
            cardCountPerHand : 每手牌的麻将牌张数
        """
        # 初始化一下cardTiles,因为每设置一次好牌点都会从里面弹出13张牌
        self.setCardTiles(MTile.getTiles(self.__card_colors))

        for color in self.__card_colors:
            random.shuffle(self.cardTiles[color])

        for _ in range(goodPointCount):
            self.addTiles(self.getGoodCard(cardCountPerHand))

        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
Beispiel #45
0
    def isHu(cls, hand_tiles, magicTiles=list()):
        """
        胡牌判断,只判断手牌,杠牌,吃牌,碰牌不在内
           杠牌、吃牌、碰牌已成型,不用另外计算
        * 肯定包含将牌
        * 剩下的牌里不会有暗杠牌
        * 杠牌/吃牌/碰牌是已经成型的牌,按成型的样式计算积分,不再重新计算
        :param magicTiles 赖子牌
        :return 是否胡了
        """
        tileArr = MTile.changeTilesToValueArr(hand_tiles)
        magicArr = []
        for magicTile in magicTiles:
            magicArr.extend([magicTile for _ in range(tileArr[magicTile])])
            tileArr[magicTile] = 0

        resultArr = []
        tileTypes = [
            MTile.TILE_WAN, MTile.TILE_TONG, MTile.TILE_TIAO, MTile.TILE_FENG
        ]
        hasJiang = False
        winResult = False

        for tileType in tileTypes:
            winResult, hasJiang, _tArr, _rArr, _mArr = cls.isHuWithMagic(
                tileArr, resultArr, magicArr, hasJiang, tileType)
            if not winResult:
                return False, []
            else:
                tileArr = copy.deepcopy(_tArr)
                resultArr = copy.deepcopy(_rArr)
                magicArr = copy.deepcopy(_mArr)

        if winResult and not hasJiang and len(magicArr) >= 2:
            hasJiang = True
        return hasJiang and winResult, resultArr
Beispiel #46
0
    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)

        # 第二种情况 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)

        return result
Beispiel #47
0
    def isBu(cls, tileArr, resultArr, magicArr, tileType, hasJiang):
        """
        判断某个花色是否是三朴,缺的牌从癞子中获取,如果没有癞子牌了,也形不成三朴,和牌失败
        """
        if 0 == cls.getCardNumByType(tileArr, tileType):
            # 这个花色没有牌
            return True, hasJiang

        # ftlog.debug('check card:', MTile.traverseTile(tileType))
        for tileIndex in MTile.traverseTile(tileType):
            if tileArr[tileIndex] == 0:
                continue

            if tileArr[tileIndex] >= 3:
                # 刻,没有占用癞子
                tileArr[tileIndex] -= 3
                resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                if resultTmp:
                    resultArr.append([tileIndex, tileIndex, tileIndex])
                    return True, hasJiang
                # 还原手牌,继续判断
                tileArr[tileIndex] += 3

            if (tileArr[tileIndex] == 2) and (len(magicArr) >= 1):
                # 对子,尝试加一张癞子组成刻
                tileArr[tileIndex] -= 2
                mTile = magicArr.pop(-1)
                resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                if resultTmp:
                    resultArr.append([tileIndex, tileIndex, mTile])
                    return True, hasJiang

                # 还原手牌,继续判断
                tileArr[tileIndex] += 2
                magicArr.append(mTile)

            if (tileArr[tileIndex] == 1) and (len(magicArr) >= 2):
                # 单张,尝试加两张癞子组成刻
                tileArr[tileIndex] -= 1
                mTile1 = magicArr.pop(-1)
                mTile2 = magicArr.pop(-1)
                resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                if resultTmp:
                    resultArr.append([tileIndex, mTile1, mTile2])
                    return True, hasJiang
                # 还原手牌,继续判断
                tileArr[tileIndex] += 1
                magicArr.append(mTile1)
                magicArr.append(mTile2)

            if not hasJiang and tileArr[tileIndex] > 0 and (tileArr[tileIndex] + len(magicArr) >= 2):
                # 凑对了
                tileArr[tileIndex] -= 1
                isMagicJiang = False
                jiangTile = tileIndex
                if tileArr[tileIndex] > 0:
                    tileArr[tileIndex] -= 1
                else:
                    isMagicJiang = True
                    jiangTile = magicArr.pop(-1)
                oldJiang = hasJiang
                # 当前的对子当将测测是否成胡
                resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, True)
                if resultTmp:
                    resultArr.append([tileIndex, jiangTile])
                    hasJiang = True
                    return True, hasJiang
                else:
                    # 还原将牌标记
                    hasJiang = oldJiang

                # 还原手牌
                tileArr[tileIndex] += 1
                if isMagicJiang:
                    magicArr.append(jiangTile)
                else:
                    tileArr[tileIndex] += 1

            if tileIndex >= MTile.TILE_DONG_FENG:
                # 风箭牌不能组成顺
                return False, hasJiang

            # 提取顺牌组合
            if tileArr[tileIndex] > 0:
                # 测试顺子 0 1 2
                if MTile.getValue(tileIndex) <= 7:
                    tile0 = tileIndex
                    needMagic = 0
                    is1Magic = False
                    is2Magic = False
                    if tileArr[tileIndex + 1] == 0:
                        needMagic += 1
                        is1Magic = True
                    if tileArr[tileIndex + 2] == 0:
                        needMagic += 1
                        is2Magic = True

                    if needMagic <= len(magicArr):
                        pattern = [tile0, None, None]
                        tileArr[tileIndex] -= 1

                        if is1Magic:
                            pattern[1] = (magicArr.pop(-1))
                        else:
                            pattern[1] = (tileIndex + 1)
                            tileArr[tileIndex + 1] -= 1

                        if is2Magic:
                            pattern[2] = (magicArr.pop(-1))
                        else:
                            pattern[2] = (tileIndex + 2)
                            tileArr[tileIndex + 2] -= 1

                        resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                        if resultTmp:
                            resultArr.append(pattern)
                            return True, hasJiang

                        # 还原手牌
                        tileArr[tileIndex] += 1
                        if is1Magic:
                            magicArr.append(pattern[1])
                        else:
                            tileArr[tileIndex + 1] += 1

                        if is2Magic:
                            magicArr.append(pattern[2])
                        else:
                            tileArr[tileIndex + 2] += 1

                # 测试顺子 -1 0 1
                if 8 >= MTile.getValue(tileIndex) >= 2:
                    tile1 = tileIndex
                    needMagic = 0
                    is0Magic = False
                    is2Magic = False
                    if tileArr[tileIndex - 1] == 0:
                        needMagic += 1
                        is0Magic = True
                    if tileArr[tileIndex + 1] == 0:
                        needMagic += 1
                        is2Magic = True

                    if needMagic <= len(magicArr):
                        pattern = [None, tile1, None]
                        tileArr[tileIndex] -= 1

                        if is0Magic:
                            pattern[0] = (magicArr.pop(-1))
                        else:
                            pattern[0] = (tileIndex - 1)
                            tileArr[tileIndex - 1] -= 1

                        if is2Magic:
                            pattern.append(magicArr.pop(-1))
                        else:
                            pattern.append(tileIndex + 1)
                            tileArr[tileIndex + 1] -= 1

                        resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                        if resultTmp:
                            resultArr.append(pattern)
                            return True, hasJiang

                        # 还原手牌
                        tileArr[tileIndex] += 1
                        if is0Magic:
                            magicArr.append(pattern[0])
                        else:
                            tileArr[tileIndex - 1] += 1

                        if is2Magic:
                            magicArr.append(pattern[2])
                        else:
                            tileArr[tileIndex + 1] += 1

                            # 测试顺子 -2 -1 0
                if MTile.getValue(tileIndex) >= 3:
                    tile2 = tileIndex
                    needMagic = 0
                    is0Magic = False
                    is1Magic = False
                    if tileArr[tileIndex - 2] == 0:
                        needMagic += 1
                        is0Magic = True
                    if tileArr[tileIndex - 1] == 0:
                        needMagic += 1
                        is1Magic = True

                    if needMagic <= len(magicArr):
                        pattern = [None, None, tile2]
                        tileArr[tileIndex] -= 1

                        if is0Magic:
                            pattern[0] = (magicArr.pop(-1))
                        else:
                            pattern[0] = (tileIndex - 2)
                            tileArr[tileIndex - 2] -= 1

                        if is1Magic:
                            pattern[1] = (magicArr.pop(-1))
                        else:
                            pattern[1] = (tileIndex - 1)
                            tileArr[tileIndex - 1] -= 1

                        resultTmp, hasJiang = cls.isBu(tileArr, resultArr, magicArr, tileType, hasJiang)
                        if resultTmp:
                            resultArr.append(pattern)
                            return True, hasJiang

                        # 还原手牌
                        tileArr[tileIndex] += 1
                        if is0Magic:
                            magicArr.append(pattern[0])
                        else:
                            tileArr[tileIndex - 2] += 1

                        if is1Magic:
                            magicArr.append(pattern[1])
                        else:
                            tileArr[tileIndex - 1] += 1
                            # 无和牌可能
        return False, hasJiang
Beispiel #48
0
 def getCardNumByType(cls, tileArr, tileType):
     num = 0
     for tile in MTile.traverseTile(tileType):
         num += tileArr[tile]
     return num
Beispiel #49
0
    def canTing(self, tiles, leftTiles, tile, magicTiles=[]):
        """子类必须实现
        参数:
        1)tiles 该玩家的手牌
        2)leftTiles 剩余手牌
        返回值:
        是否可以听牌,听牌详情
        """
        handCount = len(tiles[MHand.TYPE_HAND])

        if len(tiles[MHand.TYPE_CHI]) == 0 and len(
                tiles[MHand.TYPE_PENG]) == 0 and len(
                    tiles[MHand.TYPE_GANG]) == 0:
            isTing, tingResults = self.tingQiDui(tiles, tile, leftTiles)
            if isTing:
                ftlog.debug(
                    'MTingJixiRule.MTing.canTing tingQiDui tingResults:',
                    tingResults)
                return isTing, tingResults

                #         ftlog.debug( 'MTingJixiRule.canTing 0 tiles:', tiles )
        isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles,
                                            self.winRuleMgr, tile, magicTiles)
        #         ftlog.debug( 'MTingJixiRule.canTing 1 tiles:', tiles )
        ftlog.debug('MTingJixiRule.MTing.canTing isTing:', isTing,
                    ' tingResults:', tingResults)

        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 = False
                isPiaoHu = self.isPiaoHu(patterns, newTiles)

                # 飘和七对可以手把一
                if (isPiaoHu or isQiDui):
                    if handCount < 1:
                        continue
                else:
                    if handCount < 5:
                        continue

                # 夹起步(顺牌只能和夹和3,7) 不能和两头 可以单吊
                chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0)
                if chunJiaConfig:
                    bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0)
                    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]:
                                hasJia = True
                                break

                    if not hasJia:
                        ftlog.debug(
                            'MTingHaerbinRule.canTing :, can not win tile:',
                            winNode['winTile'], ', not has jia continue....')
                        continue

                zhongCount = tileArr[MTile.TILE_HONG_ZHONG]

                # 检查牌中的幺/九
                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]

                # 飘和七小对不需要1,9
                if (yaoCount + jiuCount +
                        zhongCount) == 0 and (not isPiaoHu) and (not isQiDui):
                    continue

                patterns = winNode['pattern']
                checkKeCount = keCount + self.getKeCount(patterns)
                ftlog.debug('MTingHaerbinRule.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)

        return len(newTingResults) > 0, newTingResults
Beispiel #50
0
    def tingQiDui(self, tiles, cur_tile, leftTiles):
        """
        检查是否可以听七小对
        二种牌型可听
        * 别人打牌 五对(包括杠) 一刻 粘一张
        * 自己上牌 六对(包括杠) 两个单张
        :param tiles 手牌
        :param cur_tile 刚刚摸的牌
        :param leftTiles: 全局剩余的牌
        :return
          [
            {
              'isQiDui' : 1
              'dropTile' : 11, # 出牌`一筒`
              'winNodes' : [{ # 听牌细节
                  'winTile' : 1, # 听`一万`
                  'winTileCount' : 3, # 剩`三张一万`
                  'pattern' : [
                    [6, 6], # 听牌的条件
                    ...
                  ]
                }]
            }
          ]
        """
        ftlog.debug('MTingHaerbinJixi.MTing.tingQiDui handTiles:',
                    tiles[MHand.TYPE_HAND], ' tile:', cur_tile)
        handTiles = tiles[MHand.TYPE_HAND]
        newHandTiles = MTile.cloneTiles(handTiles)
        # 不考虑摸牌
        newHandTiles.remove(cur_tile)
        if len(newHandTiles) < 13:
            # 手牌不够
            return False, []

        newHandTilesArr = MTile.changeTilesToValueArr(newHandTiles)
        duiCount = 0
        singleTiles = []
        duiPattern = []
        for tile, number in newHandTilesArr.tile_items():
            if number == 2:
                # 对
                duiCount += 1
                duiPattern.append([tile, tile])
            elif number == 4:
                # 杠算两对
                duiCount += 2
                duiPattern.append([tile, tile])
                duiPattern.append([tile, tile])
            elif number == 3:
                # 碰
                if tile != cur_tile:
                    # 摸牌不能凑杠 有单张了
                    singleTiles.append(tile)
                duiPattern.append([tile, tile])
            elif tile != cur_tile:
                # 摸牌不能凑对 有单张了
                singleTiles.append(tile)
            else:
                duiPattern.append([cur_tile, cur_tile])

        if len(singleTiles) != 2:
            # 单张过多不能听七对
            # 单张过少则已经可以胡牌(不能听了)
            # ftlog.debug('MTingJixiRule.MTing.canTing tingQiDui the singleTiles count error: ', len(singleTiles))
            return False, []

        # 站牌处理 手里有五对 并且有一张或三张上的牌 那么可以听 方案就是剩下的两张
        newLeftTilesArr = MTile.changeTilesToValueArr(leftTiles)
        tingResult = [
            {  # 听第2张单牌
                'isQiDui':
                1,
                'dropTile':
                singleTiles[0],
                'winNodes': [{
                    'winTile':
                    singleTiles[1],
                    'winTileCount':
                    newLeftTilesArr[singleTiles[1]],
                    'pattern':
                    duiPattern + [[singleTiles[1], singleTiles[1]]]
                }]
            },
            {  # 听第1张单牌
                'isQiDui':
                1,
                'dropTile':
                singleTiles[1],
                'winNodes': [{
                    'winTile':
                    singleTiles[0],
                    'winTileCount':
                    newLeftTilesArr[singleTiles[0]],
                    'pattern':
                    duiPattern + [[singleTiles[0], singleTiles[0]]]
                }]
            }
        ]

        return True, tingResult
Beispiel #51
0
    def calcScore(self):
        """算分"""

        # 序列化
        self.serialize()

        # 牌型数据都在tabletilemgr里面可以取到
        playerAllTiles = [[] for _ in range(self.playerCount)]
        playerAllTilesArr = [[] for _ in range(self.playerCount)]
        playerHandTiles = [[] for _ in range(self.playerCount)]
        for player in self.tableTileMgr.players:
            # 按手牌格式的数组
            playerAllTiles[player.curSeatId] = player.copyTiles()
            # 合到一个数组中
            playerAllTilesArr[player.curSeatId].extend(MHand.copyAllTilesToList(playerAllTiles[player.curSeatId]))
            # 只获取手牌                
            playerHandTiles[player.curSeatId] = player.copyHandTiles()
        ftlog.debug("playerHandTiles", playerHandTiles)
        ftlog.debug("playerAllTiles", playerAllTiles)
        ftlog.debug("playerAllTilesArr", playerAllTilesArr)
        ftlog.debug("self.winTile", self.winTile)
        self.results[self.KEY_TYPE] = ''
        self.results[self.KEY_NAME] = ''
        self.results[self.KEY_SCORE] = [0 for _ in range(self.playerCount)]
        self.results[self.KEY_WIN_TILE] = [0 for _ in range(self.playerCount)]
        self.results[self.KEY_WIN_MODE] = [MOneResult.WIN_MODE_LOSS for _ in range(self.playerCount)]
        # 在和牌时统计自摸,点炮,最大番数
        self.results[self.KEY_STAT] = [[] for _ in range(self.playerCount)]
        self.results[self.KEY_FAN_PATTERN] = [[] for _ in range(self.playerCount)]
        fanArr = [0 for _ in range(self.playerCount)]
        baseScore = 1

        # 流局不走后面的结算,确保没有设置的值不会被使用
        if self.resultType == self.RESULT_FLOW:
            self.results[self.KEY_TYPE] = MOneResult.KEY_TYPE_NAME_FLOW
            ftlog.debug("MYunnanOneResult calcScore Type = RESULT_FLOW return")
            return

        self.results[self.KEY_TYPE] = MOneResult.KEY_TYPE_NAME_HU

        if len(self.winSeats) <= 0:
            ftlog.debug("MYunnanOneResult self.winSeats error no winner")
            return
        ftlog.debug("MYunnanOneResultCalcScore self.winSeats = ", self.winSeats)

        if self.lastSeatId not in self.winSeats:
            self.results[self.KEY_WIN_MODE][self.lastSeatId] = MOneResult.WIN_MODE_DIANPAO

        # 计算胡牌者的番型和分数
        for seatId in self.winSeats:
            # 番型
            patterns = []
            fan = 0
            ftlog.debug('MajiangTableLogic.gameWin.yipaoduoxiang dealwith seatId:'
                        , seatId
                        , 'lastSeatId:', self.lastSeatId
                        , 'winSeatId:', self.winSeatId
                        , 'self.winSeats:', self.winSeats
                        , 'self.actionID:', self.actionID
                        )
            ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan, "seatId = ", seatId)
            if seatId == self.lastSeatId:
                self.results[self.KEY_WIN_MODE][seatId] = MOneResult.WIN_MODE_ZIMO
            else:
                self.results[self.KEY_WIN_MODE][seatId] = MOneResult.WIN_MODE_PINGHU
            magicTiles = self.tableTileMgr.getMagicTiles()
            tempArrColor = copy.deepcopy(playerAllTilesArr[seatId])
            # colorState里面要去掉赖子包含的花色
            magicTileCount = 0
            for magicTile in magicTiles:
                while magicTile in tempArrColor:
                    tempArrColor.remove(magicTile)
                    magicTileCount += 1
            # 重新处理一次花色,不算赖子
            oldColorState = copy.deepcopy(self.colorState)
            ftlog.debug("MYunnanOneResultCalcScore tempArrColor = ", tempArrColor)
            ftlog.debug("MYunnanOneResultCalcScore self.colorState1 = ", self.colorState)
            self.colorState[seatId] = MTile.getColorCount(MTile.changeTilesToValueArr(tempArrColor))
            ftlog.debug("MYunnanOneResultCalcScore self.colorState2 = ", self.colorState)
            isUnique = False

            # 七对和五六七星烂,十风,十三幺,四幺鸡
            # 取出dropTiles来判断是否十风和十三幺
            dropTiles = self.tableTileMgr.dropTiles[seatId]
            nowTiles = playerAllTiles[seatId]
            nowTiles[MHand.TYPE_HAND].append(self.winTile)

            # 杠上花和杠上炮
            ftlog.debug("MYunnanOneResultCalcScorelatestGangState = ", self.latestGangState)
            ftlog.debug("MYunnanOneResultCalcScorelatestGangState self.winSeatId:= ", self.winSeatId)
            ftlog.debug("MYunnanOneResultCalcScorelatestGangState seatId:= ", seatId)
            ftlog.debug("MYunnanOneResultCalcScorelatestGangState self.lastSeatId:= ", self.lastSeatId)

            if self.latestGangState != -1:
                if self.latestGangState == seatId:
                    # 杠牌的是自己
                    wumeihuaTiles = copy.deepcopy(nowTiles)
                    if self.winTile in wumeihuaTiles[MHand.TYPE_HAND]:
                        wumeihuaTiles[MHand.TYPE_HAND].remove(self.winTile)
                    wumeihuaTiles[MHand.TYPE_HAND].append(MTile.TILE_FIVE_TONG)
                    result, _ = MWinRuleYunnan.checkHuByMagicTiles(wumeihuaTiles, magicTiles)
                    if result and (self.winTile == MTile.TILE_FIVE_TONG or self.winTile in magicTiles):
                        # 五梅花,包括幺鸡当五筒
                        if not isUnique:
                            patterns.append(self.fanXing[self.GANGSHANGHUAWUMEIHUA]['name'])
                            fan += self.fanXing[self.GANGSHANGHUAWUMEIHUA]['index']
                            ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                    else:
                        if not isUnique:
                            patterns.append(self.fanXing[self.GANGSHANGHUA]['name'])
                            fan += self.fanXing[self.GANGSHANGHUA]['index']
                            ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                elif self.latestGangState == self.lastSeatId:
                    # 杠牌的是别人
                    if not isUnique:
                        patterns.append(self.fanXing[self.GANGSHANGPAO]['name'])
                        fan += self.fanXing[self.GANGSHANGPAO]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            # 四幺鸡,必须是自摸,必须是手牌
            if nowTiles[MHand.TYPE_HAND].count(MTile.TILE_ONE_TIAO) == 4 and (seatId == self.lastSeatId):
                if not isUnique:
                    self.results[self.KEY_WIN_MODE][seatId] = MYunnanOneResult.WIN_MODE_SIYAOJI
                    patterns = []
                    patterns.append(self.fanXing[self.SIYAOJI]['name'])
                    isUnique = True
                    fan = 0
                    fan += self.fanXing[self.SIYAOJI]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            ftlog.debug("MYunnanOneResult dropTiles = ", dropTiles, "nowTiles = ", nowTiles)
            if self.isShifeng(dropTiles, nowTiles):
                if not isUnique:
                    self.results[self.KEY_WIN_MODE][seatId] = MYunnanOneResult.WIN_MODE_SHIFENG
                    patterns.append(self.fanXing[self.SHIFENG]['name'])
                    fan = 0
                    fan += self.fanXing[self.SHIFENG]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                    isUnique = True
                    self.setDropHuFlag(1)
            if self.isShisanyao(dropTiles, nowTiles):
                if not isUnique:
                    self.results[self.KEY_WIN_MODE][seatId] = MYunnanOneResult.WIN_MODE_SHISANYAO
                    patterns.append(self.fanXing[self.SHISANYAO]['name'])
                    fan = 0
                    fan += self.fanXing[self.SHISANYAO]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                    isUnique = True
                    self.setDropHuFlag(1)
            ftlog.debug("MYunnanOneResult check lanpai nowTiles =", nowTiles, "magicTiles =", magicTiles)
            result, fengCount, lanPanMagicCount = self.isLanPaiCheck(nowTiles, magicTiles)
            lanPaiPatternForWuji = False
            if result:
                lanPaiPatternForWuji = True
                if fengCount + lanPanMagicCount >= 7:
                    # 七星烂
                    if not isUnique:
                        patterns.append(self.fanXing[self.QIXINGLAN]['name'])
                        fan += self.fanXing[self.QIXINGLAN]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                elif fengCount + lanPanMagicCount >= 6:
                    # 六星烂
                    if not isUnique:
                        patterns.append(self.fanXing[self.LIUXINGLAN]['name'])
                        fan += self.fanXing[self.LIUXINGLAN]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                elif fengCount + lanPanMagicCount >= 5:
                    # 五星烂
                    if not isUnique:
                        patterns.append(self.fanXing[self.WUXINGLAN]['name'])
                        fan += self.fanXing[self.WUXINGLAN]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
            # 七对必须门清
            isPairs = False
            if self.menState[seatId] == 1:
                if seatId == self.lastSeatId:
                    # 自摸
                    pairResult, leftMagicCount, fourCount, _ = self.isPairsCheck(nowTiles, magicTiles)
                    if pairResult:
                        isPairs = True
                        if fourCount >= 1:
                            if not isUnique:
                                patterns.append(self.fanXing[self.LONGZHUABEI]['name'])
                                fan += self.fanXing[self.LONGZHUABEI]['index']
                                ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                        else:
                            # 小七对
                            if not isUnique:
                                patterns.append(self.fanXing[self.XIAOQIDUI]['name'])
                                fan += self.fanXing[self.XIAOQIDUI]['index']
                                ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                else:
                    # 点炮
                    if self.winTile in magicTiles:
                        transferTiles = copy.deepcopy(nowTiles)
                        magicCount = 0
                        for magicTile in magicTiles:
                            while magicTile in transferTiles[MHand.TYPE_HAND]:
                                transferTiles[MHand.TYPE_HAND].remove(magicTile)
                                transferTiles[MHand.TYPE_HAND].append(0)
                                magicCount += 1
                            if magicCount >= 1:
                                transferTiles[MHand.TYPE_HAND].remove(0)
                                transferTiles[MHand.TYPE_HAND].append(magicTile)
                        pairResult, leftMagicCount, fourCount, _ = self.isPairsCheck(transferTiles, [0])
                        if pairResult:
                            isPairs = True
                            if leftMagicCount >= 2:
                                if not isUnique:
                                    patterns.append(self.fanXing[self.LONGZHUABEI]['name'])
                                    fan += self.fanXing[self.LONGZHUABEI]['index']
                                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                            else:
                                # 小七对
                                if not isUnique:
                                    patterns.append(self.fanXing[self.XIAOQIDUI]['name'])
                                    fan += self.fanXing[self.XIAOQIDUI]['index']
                                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                    else:
                        pairResult, leftMagicCount, fourCount, _ = self.isPairsCheck(nowTiles, magicTiles)
                        if pairResult:
                            isPairs = True
                            if nowTiles[MHand.TYPE_HAND].count(self.winTile) + leftMagicCount >= 3:
                                # 一定是龙爪背
                                if not isUnique:
                                    patterns.append(self.fanXing[self.LONGZHUABEI]['name'])
                                    fan += self.fanXing[self.LONGZHUABEI]['index']
                                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                            else:
                                # 小七对
                                if not isUnique:
                                    patterns.append(self.fanXing[self.XIAOQIDUI]['name'])
                                    fan += self.fanXing[self.XIAOQIDUI]['index']
                                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

                                    # 杠数
                                    #         if len(self.playerGangTiles[seatId]) == 1:
                                    #             if not isUnique:
                                    #                 self.results[self.KEY_NAME] = self.fanXing[self.YIGANG]['name']
                                    #                 patterns.append(self.fanXing[self.YIGANG]['name'])
                                    #                 fan += self.fanXing[self.YIGANG]['index']
                                    #                 ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                                    #         el
            if len(self.playerGangTiles[seatId]) == 2:
                if not isUnique:
                    self.results[self.KEY_NAME] = self.fanXing[self.LIANGGANG]['name']
                    patterns.append(self.fanXing[self.LIANGGANG]['name'])
                    fan += self.fanXing[self.LIANGGANG]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
            elif len(self.playerGangTiles[seatId]) == 3:
                if not isUnique:
                    self.results[self.KEY_NAME] = self.fanXing[self.SANGANG]['name']
                    patterns.append(self.fanXing[self.SANGANG]['name'])
                    fan += self.fanXing[self.SANGANG]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
            elif len(self.playerGangTiles[seatId]) == 4:
                if not isUnique:
                    self.results[self.KEY_NAME] = self.fanXing[self.SIGANG]['name']
                    patterns.append(self.fanXing[self.SIGANG]['name'])
                    fan += self.fanXing[self.SIGANG]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            # 字一色
            ziyiseWuji = False
            if self.colorState[seatId] == 0:
                if self.getZiTypeCountBySeatId(seatId) > 0:
                    ziyiseWuji = True
                    if not isUnique:
                        self.results[self.KEY_NAME] = self.fanXing[self.ZIYISE]['name']
                        patterns.append(self.fanXing[self.ZIYISE]['name'])
                        fan += self.fanXing[self.ZIYISE]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            # 大对子,门前不能有吃,手牌多加一个赖子,能保证都是3张
            if len(nowTiles[MHand.TYPE_CHI]) == 0:
                duiziTiles = copy.deepcopy(nowTiles[MHand.TYPE_HAND])
                for magicTile in magicTiles:
                    while magicTile in duiziTiles:
                        duiziTiles.remove(magicTile)
                # 如果点炮胡,需要给牌堆里加回去一张赖子,并当普通牌处理
                if seatId != self.lastSeatId and self.winTile in magicTiles:
                    duiziTiles.append(self.winTile)
                duiziArr = MTile.changeTilesToValueArr(duiziTiles)
                ftlog.debug("MYunnanOneResult duiziArr = ", duiziArr)
                cardTypeCount = 0
                # 假设多一张赖子
                duiziMagicCount = magicTileCount + 1
                for index in range(len(duiziArr)):
                    if duiziArr[index] != 0:
                        cardTypeCount += 1
                        if duiziArr[index] < 3:
                            duiziMagicCount = duiziMagicCount - (3 - duiziArr[index])
                if cardTypeCount <= 5 and duiziMagicCount >= 0:
                    patterns.append(self.fanXing[self.DADUIZI]['name'])
                    fan += self.fanXing[self.DADUIZI]['index']
                    ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                    # 清一色和混一色
            qingyiseForWuji = False
            if self.colorState[seatId] == 1:
                qingyiseForWuji = True
                if self.getZiTypeCountBySeatId(seatId) > 0:
                    if not isUnique:
                        self.results[self.KEY_NAME] = self.fanXing[self.HUNYISE]['name']
                        patterns.append(self.fanXing[self.HUNYISE]['name'])
                        fan += self.fanXing[self.HUNYISE]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                else:
                    if not isUnique:
                        self.results[self.KEY_NAME] = self.fanXing[self.QINGYISE]['name']
                        patterns.append(self.fanXing[self.QINGYISE]['name'])
                        fan += self.fanXing[self.QINGYISE]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)


                        # 不求人 门清并自摸
            # 暗杠也算门清,重新计算
            # 烂牌和七对牌型时不计算不求人
            if not lanPaiPatternForWuji and not isPairs:
                isMenQing = False
                gangInfo = playerAllTiles[seatId][MHand.TYPE_GANG]
                chiInfo = playerAllTiles[seatId][MHand.TYPE_CHI]
                pengInfo = playerAllTiles[seatId][MHand.TYPE_PENG]
                if len(chiInfo) == 0 and len(pengInfo) == 0:
                    isMenQing = True
                    for gang in gangInfo:
                        if gang['style'] == 1:
                            isMenQing = False
                if isMenQing and seatId == self.lastSeatId:
                    if not isUnique:
                        self.results[self.KEY_WIN_MODE][seatId] = MYunnanOneResult.WIN_MODE_BUQIUREN
                        patterns.append(self.fanXing[self.BUQIUREN]['name'])
                        fan += self.fanXing[self.BUQIUREN]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            # 全求人 最后手里只有一张牌 单钓 不能有暗杠
            if len(playerHandTiles[seatId]) == 1 and seatId != self.lastSeatId:
                noAnGang = True
                for gangInfo in nowTiles[MHand.TYPE_GANG]:
                    if gangInfo.has_key('style'):
                        gangStyle = gangInfo.get('style', 1)
                        if gangStyle == 0:
                            noAnGang = False
                            break;
                if noAnGang:
                    if not isUnique:
                        patterns.append(self.fanXing[self.QUANQIUREN]['name'])
                        fan += self.fanXing[self.QUANQIUREN]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

                        # 三元和混三元
            sanyuanForWuji = False
            baibanCount = self.getZiCountByTypeBySeatId(seatId, MTile.TILE_BAI_BAN)
            hongzhongCount = self.getZiCountByTypeBySeatId(seatId, MTile.TILE_HONG_ZHONG)
            facaiCount = self.getZiCountByTypeBySeatId(seatId, MTile.TILE_FA_CAI)
            sanyuanMagicCount = nowTiles[MHand.TYPE_HAND].count(MTile.TILE_ONE_TIAO)
            if baibanCount + sanyuanMagicCount >= 2 \
                    and hongzhongCount + sanyuanMagicCount >= 2 \
                    and facaiCount + sanyuanMagicCount >= 2:
                if baibanCount + hongzhongCount + sanyuanMagicCount >= 5 \
                        and baibanCount + facaiCount + sanyuanMagicCount >= 5 \
                        and hongzhongCount + facaiCount + sanyuanMagicCount >= 5:
                    if baibanCount + hongzhongCount + facaiCount + sanyuanMagicCount >= 8:
                        if self.colorState[seatId] == 1 and self.noFengPai(seatId):
                            # 混三元
                            if not isUnique:
                                sanyuanForWuji = True
                                patterns.append(self.fanXing[self.HUNSANYUAN]['name'])
                                fan += self.fanXing[self.HUNSANYUAN]['index']
                                ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                        else:
                            # 三元
                            if not isUnique:
                                patterns.append(self.fanXing[self.SANYUAN]['name'])
                                fan += self.fanXing[self.SANYUAN]['index']
                                ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)

            # 无鸡
            isWuji = False
            wujiTiles = copy.deepcopy(nowTiles)
            # 手牌不要赖子能胡
            result0, _ = MWinRuleYunnan.checkHuByMagicTiles(wujiTiles, [])
            for temp in nowTiles[MHand.TYPE_CHI]:
                wujiTiles[MHand.TYPE_HAND].extend(temp)
            for temp in nowTiles[MHand.TYPE_PENG]:
                wujiTiles[MHand.TYPE_HAND].extend(temp)
            ftlog.debug("MYunnanOneResult wujiTiles = ", wujiTiles)
            # 加上碰吃,不要赖子也能胡
            result1, _ = MWinRuleYunnan.checkHuByMagicTiles(wujiTiles, [])
            wujiMagicCount = playerAllTilesArr[seatId].count(MTile.TILE_ONE_TIAO)
            ftlog.debug("MYunnanOneResult wujiTiles = ", wujiTiles, "result1=", result1)
            result2 = True
            # 算杠,不是4个幺鸡都是有赖子
            for magicTile in magicTiles:
                for gangInfo in wujiTiles[MHand.TYPE_GANG]:
                    wujiGangMagicCount = 0
                    if gangInfo.has_key('pattern'):
                        tempGangInfo = copy.deepcopy(gangInfo['pattern'])
                        while magicTile in tempGangInfo:
                            tempGangInfo.remove(magicTile)
                            wujiGangMagicCount += 1
                        if wujiGangMagicCount != 4 and wujiGangMagicCount != 0:
                            result2 = False
                            break
            ftlog.debug("MYunnanOneResult wujiTiles = ", wujiTiles
                        , "result1=", result1
                        , "result2=", result2
                        , "result0=", result0)
            if result1 and result2 and result0:
                isWuji = True
            if isWuji:
                if wujiMagicCount > 0:
                    canXiaojiguiwei = True
                    # 小鸡归位,要排除赖子应用在其它番型导致小鸡归位和其它番型不同存的情况
                    ftlog.debug("MYunnanOneResult canXiaojiguiwei oldColorState", oldColorState
                                , "lanPaiPatternForWuji", lanPaiPatternForWuji
                                , "qingyiseForWuji", qingyiseForWuji
                                , "ziyiseWuji", ziyiseWuji
                                , "sanyuanForWuji", sanyuanForWuji)

                    if lanPaiPatternForWuji:
                        # 如果是烂牌的小鸡归位,重新检查在没有赖子的情况能不能胡
                        resultNoMagic, fengCountNoMagic, lanPanMagicCountNoMagic = self.isLanPaiCheck(nowTiles, [])
                        if lanPanMagicCount > 0:
                            # 带赖子的六星烂,如果无赖子判定能胡,那就可以胡五星烂+小鸡归位
                            if self.fanXing[self.LIUXINGLAN]['name'] in patterns and resultNoMagic:
                                patterns.remove(self.fanXing[self.LIUXINGLAN]['name'])
                                fan -= self.fanXing[self.LIUXINGLAN]['index']
                                patterns.append(self.fanXing[self.WUXINGLAN]['name'])
                                fan += self.fanXing[self.WUXINGLAN]['index']
                                canXiaojiguiwei = True
                            elif self.fanXing[self.QIXINGLAN][
                                'name'] in patterns and resultNoMagic and fengCountNoMagic >= 7:
                                canXiaojiguiwei = True
                            else:
                                canXiaojiguiwei = False
                        else:
                            canXiaojiguiwei = True
                    if qingyiseForWuji:
                        if oldColorState[seatId] > 1:
                            canXiaojiguiwei = False
                    if ziyiseWuji:
                        if oldColorState[seatId] > 0:
                            canXiaojiguiwei = False
                    if sanyuanForWuji:
                        if oldColorState[seatId] > 1:
                            canXiaojiguiwei = False
                    if canXiaojiguiwei:
                        if not isUnique:
                            patterns.append(self.fanXing[self.XIAOJIGUIWEI]['name'])
                            fan += self.fanXing[self.XIAOJIGUIWEI]['index']
                            ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
                else:
                    if not isUnique:
                        patterns.append(self.fanXing[self.WUJI]['name'])
                        fan += self.fanXing[self.WUJI]['index']
                        ftlog.debug("MYunnanOneResult fanxing = ", patterns, "fan = ", fan)
            self.results[self.KEY_FAN_PATTERN][seatId] = patterns
            self.results[self.KEY_WIN_TILE][seatId] = self.winTile
            fanArr[seatId] = fan

        if self.lastSeatId in self.winSeats:
            self.results[self.KEY_STAT][self.lastSeatId].append({MOneResult.STAT_ZIMO: 1})
        else:
            # 点炮,点炮者点炮+1
            self.results[self.KEY_STAT][self.lastSeatId].append({MOneResult.STAT_DIANPAO: 1})
        # 最大番,当前的赢家番数
        self.results[self.KEY_STAT][seatId].append({MOneResult.STAT_ZUIDAFAN: fan})

        # 计算积分
        winScore = baseScore * (self.multiple)
        if self.qiangGang:
            if self.winRuleMgr.itemParams.get('QGHSanbei', 1) == 2:
                winScore = winScore
            else:
                winScore = winScore * 3
            for player in self.tableTileMgr.players:
                if player.curSeatId == self.lastSeatId and self.lastSeatId not in self.winSeats:
                    ftlog.debug("MYunnanOneResultQGH lose seatId:", player.curSeatId, "lastSeatId:", self.lastSeatId)
                    if self.winTile in player.handTiles:
                        ftlog.debug("MYunnanOneResultQGH lose seatId:", player.curSeatId, "lastSeatId:",
                                    self.lastSeatId, "remove tile:", self.winTile)
                        player.handTiles.remove(self.winTile)
                    else:
                        if self.showTile in player.handTiles and self.showTile != 0:
                            ftlog.debug("MYunnanOneResultQGH lose seatId:", player.curSeatId, "lastSeatId:",
                                        self.lastSeatId, "remove tile:", self.showTile)
                            player.handTiles.remove(self.showTile)
            for seatId in self.winSeats:
                if self.winRuleMgr.itemParams.get('QGHJiafan', 1) == 2:
                    fanArr[seatId] += 1
                self.results[self.KEY_WIN_MODE][seatId] = MOneResult.WIN_MODE_QIANGGANGHU

        # 番数上限3
        for win in self.winSeats:
            if fanArr[win] > 3:
                fanArr[win] = 3

        # 计算分数增减
        if self.lastSeatId in self.winSeats:
            for i in range(self.playerCount):
                if self.lastSeatId == i:
                    self.results[self.KEY_SCORE][i] = winScore * (2 ** fanArr[i]) * (self.playerCount - 1)
                else:
                    self.results[self.KEY_SCORE][i] = -winScore * (2 ** fanArr[self.lastSeatId])
        else:
            dianPaoScore = 0
            for i in range(self.playerCount):
                if i in self.winSeats:
                    self.results[self.KEY_SCORE][i] = winScore * (2 ** fanArr[i])
                    dianPaoScore += winScore * (2 ** fanArr[i])
            self.results[self.KEY_SCORE][self.lastSeatId] = -dianPaoScore

        ftlog.debug('MYunnanOneResult calcScore:KEY_SCORE:', self.results[self.KEY_SCORE])
        ftlog.debug('MYunnanOneResult calcScore:KEY_NAME:', self.results[self.KEY_NAME])
        ftlog.debug('MYunnanOneResult calcScore:KEY_TYPE:', self.results[self.KEY_TYPE])
        ftlog.debug('MYunnanOneResult calcScore:KEY_WIN_MODE:', self.results[self.KEY_WIN_MODE])
        ftlog.debug('MYunnanOneResult calcScore:KEY_FAN_PATTERN:', self.results[self.KEY_FAN_PATTERN])
        ftlog.debug('MYunnanOneResult calcScore:KEY_STAT:', self.results[self.KEY_STAT])
Beispiel #52
0
    def isHu(self, tiles, tile, isTing, getTileType, magicTiles=[], tingNodes=[]):
        """
        tiles:玩家所有的牌,但是手牌是加入了要胡的那张牌的
        """
        # 昭通无听牌
        ftlog.debug('MWinRuleZhaotong.isHu tiles:', tiles
                    , ' tile:', tile
                    , ' magicTils:', magicTiles
                    , ' getTileType:', getTileType)

        if getTileType != MWinRule.WIN_BY_MYSELF and MTableTile.isMagicTile(tile, magicTiles):
            # 如果是听用,不能胡
            return False, []

            # 先查花色
        playerAllTiles = []
        playerAllTiles.extend(tiles[MHand.TYPE_HAND])
        for chi in tiles[MHand.TYPE_CHI]:
            playerAllTiles.extend(chi)
        for peng in tiles[MHand.TYPE_PENG]:
            playerAllTiles.extend(peng)
        for gang in tiles[MHand.TYPE_GANG]:
            playerAllTiles.extend(gang['pattern'])
        colorStateWithMagic = MTile.getColorCount(MTile.changeTilesToValueArr(playerAllTiles))
        magicCount, tempTiles = MTableTile.getMagicTileCountInTiles(playerAllTiles, magicTiles)
        colorState = MTile.getColorCount(MTile.changeTilesToValueArr(tempTiles))
        ftlog.debug("MWinRuleZhaotong.isHu colorState = ", colorState
                    , "playerAllTiles = ", playerAllTiles
                    , "tempTiles = ", tempTiles
                    , "colorStateWithMagic = ", colorStateWithMagic
                    , "magicCount = ", magicCount)
        # 必须缺一门才能胡牌
        if colorState >= 3:
            ftlog.debug("MWinRuleZhaotong.isHu men >= 3 can not hu")
            return False, []

        result1, pattern1 = MWinRuleZhaotong.checkHuByMagicTiles(tiles, magicTiles)
        #         result2, pattern2 = MWinRuleZhaotong.checkHuByMagicTiles(tiles, [])
        #         if colorStateWithMagic >= 3:
        #             if result1 and not result2:
        #                 return result1, pattern1
        #             else:
        #                 return False, []
        #         else:
        #             if result1:
        #                 return result1, pattern1
        #             else:
        #                 return False, []
        if result1:
            return result1, pattern1
        #             if getTileType != MWinRule.WIN_BY_MYSELF:
        #                 hasMagic = False
        #                 for magicTile in magicTiles:
        #                     if magicTile in tiles[MHand.TYPE_HAND]:
        #                         hasMagic = True
        #                 if hasMagic:
        #                     # 点炮和抢杠胡要检查是不是叫听用,如果叫听用,可以胡任意牌,采用抽3张牌测试的方式,如果通过就认为是叫听用
        #                     testTiles = []
        #                     if tile/10 == 0:
        #                         testTiles.append(2)
        #                         testTiles.append(6)
        #                         testTiles.append(9)
        #                     elif tile/10 == 1:
        #                         testTiles.append(12)
        #                         testTiles.append(14)
        #                         testTiles.append(17)
        #                     elif tile/10 == 2:
        #                         testTiles.append(22)
        #                         testTiles.append(24)
        #                         testTiles.append(28)
        #                     else:
        #                         return False, []
        #                     dandiao = True
        #                     for testTile in testTiles:
        #                         tempDandiao = copy.deepcopy(tiles)
        #                         if tile in tempDandiao[MHand.TYPE_HAND]:
        #                             tempDandiao[MHand.TYPE_HAND].remove(tile)
        #                         tempDandiao[MHand.TYPE_HAND].append(testTile)
        #                         resultDandiao, _ = MWinRuleZhaotong.checkHuByMagicTiles(tempDandiao, magicTiles)
        #                         if not resultDandiao:
        #                             dandiao = False
        #                     if not dandiao:
        #                         return result1, pattern1
        #                 else:
        #                     return result1, pattern1
        #             else:
        #                 return result1, pattern1
        return False, []
Beispiel #53
0
    def isHu(self,
             tiles,
             tile,
             isTing,
             getTileType,
             magicTiles=[],
             tingNodes=[]):
        """
        tiles:玩家所有的牌,但是手牌是加入了要胡的那张牌的
        """
        # 昭通无听牌
        ftlog.debug('MWinRuleZhaotong.isHu tiles:', tiles, ' tile:', tile,
                    ' magicTils:', magicTiles, ' getTileType:', getTileType)

        if getTileType != MWinRule.WIN_BY_MYSELF and MTableTile.isMagicTile(
                tile, magicTiles):
            # 如果是听用,不能胡
            return False, []

            # 先查花色
        playerAllTiles = []
        playerAllTiles.extend(tiles[MHand.TYPE_HAND])
        for chi in tiles[MHand.TYPE_CHI]:
            playerAllTiles.extend(chi)
        for peng in tiles[MHand.TYPE_PENG]:
            playerAllTiles.extend(peng)
        for gang in tiles[MHand.TYPE_GANG]:
            playerAllTiles.extend(gang['pattern'])
        colorStateWithMagic = MTile.getColorCount(
            MTile.changeTilesToValueArr(playerAllTiles))
        magicCount, tempTiles = MTableTile.getMagicTileCountInTiles(
            playerAllTiles, magicTiles)
        colorState = MTile.getColorCount(
            MTile.changeTilesToValueArr(tempTiles))
        ftlog.debug("MWinRuleZhaotong.isHu colorState = ", colorState,
                    "playerAllTiles = ", playerAllTiles, "tempTiles = ",
                    tempTiles, "colorStateWithMagic = ", colorStateWithMagic,
                    "magicCount = ", magicCount)
        # 必须缺一门才能胡牌
        if colorState >= 3:
            ftlog.debug("MWinRuleZhaotong.isHu men >= 3 can not hu")
            return False, []

        result1, pattern1 = MWinRuleZhaotong.checkHuByMagicTiles(
            tiles, magicTiles)
        #         result2, pattern2 = MWinRuleZhaotong.checkHuByMagicTiles(tiles, [])
        #         if colorStateWithMagic >= 3:
        #             if result1 and not result2:
        #                 return result1, pattern1
        #             else:
        #                 return False, []
        #         else:
        #             if result1:
        #                 return result1, pattern1
        #             else:
        #                 return False, []
        if result1:
            return result1, pattern1
        #             if getTileType != MWinRule.WIN_BY_MYSELF:
        #                 hasMagic = False
        #                 for magicTile in magicTiles:
        #                     if magicTile in tiles[MHand.TYPE_HAND]:
        #                         hasMagic = True
        #                 if hasMagic:
        #                     # 点炮和抢杠胡要检查是不是叫听用,如果叫听用,可以胡任意牌,采用抽3张牌测试的方式,如果通过就认为是叫听用
        #                     testTiles = []
        #                     if tile/10 == 0:
        #                         testTiles.append(2)
        #                         testTiles.append(6)
        #                         testTiles.append(9)
        #                     elif tile/10 == 1:
        #                         testTiles.append(12)
        #                         testTiles.append(14)
        #                         testTiles.append(17)
        #                     elif tile/10 == 2:
        #                         testTiles.append(22)
        #                         testTiles.append(24)
        #                         testTiles.append(28)
        #                     else:
        #                         return False, []
        #                     dandiao = True
        #                     for testTile in testTiles:
        #                         tempDandiao = copy.deepcopy(tiles)
        #                         if tile in tempDandiao[MHand.TYPE_HAND]:
        #                             tempDandiao[MHand.TYPE_HAND].remove(tile)
        #                         tempDandiao[MHand.TYPE_HAND].append(testTile)
        #                         resultDandiao, _ = MWinRuleZhaotong.checkHuByMagicTiles(tempDandiao, magicTiles)
        #                         if not resultDandiao:
        #                             dandiao = False
        #                     if not dandiao:
        #                         return result1, pattern1
        #                 else:
        #                     return result1, pattern1
        #             else:
        #                 return result1, pattern1
        return False, []
Beispiel #54
0
    def canTing(self, tiles, leftTiles, tile, magicTiles=[]):
        """子类必须实现
        参数:
        1)tiles 该玩家的手牌
        2)leftTiles 剩余手牌
        返回值:
        是否可以听牌,听牌详情
        """
        handCount = len(tiles[MHand.TYPE_HAND])

        if len(tiles[MHand.TYPE_CHI]) == 0 and len(tiles[MHand.TYPE_PENG]) == 0 and len(tiles[MHand.TYPE_GANG]) == 0:
            isTing, tingResults = self.tingQiDui(tiles, tile, leftTiles)
            if isTing:
                ftlog.debug('MTingJixiRule.MTing.canTing tingQiDui tingResults:', tingResults)
                return isTing, tingResults

                #         ftlog.debug( 'MTingJixiRule.canTing 0 tiles:', tiles )
        isTing, tingResults = MTing.canTing(MTile.cloneTiles(tiles), leftTiles, self.winRuleMgr, tile, magicTiles)
        #         ftlog.debug( 'MTingJixiRule.canTing 1 tiles:', tiles )
        ftlog.debug('MTingJixiRule.MTing.canTing isTing:', isTing, ' tingResults:', tingResults)

        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 = False
                isPiaoHu = self.isPiaoHu(patterns, newTiles)

                # 飘和七对可以手把一
                if (isPiaoHu or isQiDui):
                    if handCount < 1:
                        continue
                else:
                    if handCount < 5:
                        continue

                # 夹起步(顺牌只能和夹和3,7) 不能和两头 可以单吊
                chunJiaConfig = self.getTableConfig(MTDefine.MIN_MULTI, 0)
                if chunJiaConfig:
                    bianMulti = self.tableConfig.get(MTDefine.BIAN_MULTI, 0)
                    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]:
                                hasJia = True
                                break

                    if not hasJia:
                        ftlog.debug('MTingHaerbinRule.canTing :, can not win tile:', winNode['winTile'],
                                    ', not has jia continue....')
                        continue

                zhongCount = tileArr[MTile.TILE_HONG_ZHONG]

                # 检查牌中的幺/九
                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]

                # 飘和七小对不需要1,9
                if (yaoCount + jiuCount + zhongCount) == 0 and (not isPiaoHu) and (not isQiDui):
                    continue

                patterns = winNode['pattern']
                checkKeCount = keCount + self.getKeCount(patterns)
                ftlog.debug('MTingHaerbinRule.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)

        return len(newTingResults) > 0, newTingResults
Beispiel #55
0
    def tingQiDui(self, tiles, cur_tile, leftTiles):
        """
        检查是否可以听七小对
        二种牌型可听
        * 别人打牌 五对(包括杠) 一刻 粘一张
        * 自己上牌 六对(包括杠) 两个单张
        :param tiles 手牌
        :param cur_tile 刚刚摸的牌
        :param leftTiles: 全局剩余的牌
        :return
          [
            {
              'isQiDui' : 1
              'dropTile' : 11, # 出牌`一筒`
              'winNodes' : [{ # 听牌细节
                  'winTile' : 1, # 听`一万`
                  'winTileCount' : 3, # 剩`三张一万`
                  'pattern' : [
                    [6, 6], # 听牌的条件
                    ...
                  ]
                }]
            }
          ]
        """
        ftlog.debug('MTingHaerbinJixi.MTing.tingQiDui handTiles:', tiles[MHand.TYPE_HAND], ' tile:', cur_tile)
        handTiles = tiles[MHand.TYPE_HAND]
        newHandTiles = MTile.cloneTiles(handTiles)
        # 不考虑摸牌
        newHandTiles.remove(cur_tile)
        if len(newHandTiles) < 13:
            # 手牌不够
            return False, []

        newHandTilesArr = MTile.changeTilesToValueArr(newHandTiles)
        duiCount = 0
        singleTiles = []
        duiPattern = []
        for tile, number in newHandTilesArr.tile_items():
            if number == 2:
                # 对
                duiCount += 1
                duiPattern.append([tile, tile])
            elif number == 4:
                # 杠算两对
                duiCount += 2
                duiPattern.append([tile, tile])
                duiPattern.append([tile, tile])
            elif number == 3:
                # 碰
                if tile != cur_tile:
                    # 摸牌不能凑杠 有单张了
                    singleTiles.append(tile)
                duiPattern.append([tile, tile])
            elif tile != cur_tile:
                # 摸牌不能凑对 有单张了
                singleTiles.append(tile)
            else:
                duiPattern.append([cur_tile, cur_tile])

        if len(singleTiles) != 2:
            # 单张过多不能听七对
            # 单张过少则已经可以胡牌(不能听了)
            # ftlog.debug('MTingJixiRule.MTing.canTing tingQiDui the singleTiles count error: ', len(singleTiles))
            return False, []

        # 站牌处理 手里有五对 并且有一张或三张上的牌 那么可以听 方案就是剩下的两张
        newLeftTilesArr = MTile.changeTilesToValueArr(leftTiles)
        tingResult = [{  # 听第2张单牌
            'isQiDui': 1,
            'dropTile': singleTiles[0],
            'winNodes': [{
                'winTile': singleTiles[1],
                'winTileCount': newLeftTilesArr[singleTiles[1]],
                'pattern': duiPattern + [[singleTiles[1], singleTiles[1]]]
            }]
        }, {  # 听第1张单牌
            'isQiDui': 1,
            'dropTile': singleTiles[1],
            'winNodes': [{
                'winTile': singleTiles[0],
                'winTileCount': newLeftTilesArr[singleTiles[0]],
                'pattern': duiPattern + [[singleTiles[0], singleTiles[0]]]
            }]
        }]

        return True, tingResult