github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/game/poker/landlordanalyzer.go (about)

     1  package poker
     2  
     3  import (
     4  	"common"
     5  	"sort"
     6  
     7  	"github.com/name5566/leaf/log"
     8  )
     9  
    10  type LandlordAnalyzer struct {
    11  	cardValueMarker map[int]int // 记牌器(Key 牌值、Value 牌的数量)
    12  	cards           []int
    13  
    14  	hasKingBomb      bool
    15  	hasBomb          bool
    16  	hasTrio          bool
    17  	hasPair          bool
    18  	hasAirplaneChain bool
    19  	hasPairSisters   bool
    20  	hasSoloChain     bool
    21  
    22  	kingBomb       []int
    23  	bombs          [][]int
    24  	trios          [][]int
    25  	pairs          [][]int
    26  	airplaneChains [][]int
    27  	pairSisterss   [][]int
    28  	soloChains     [][]int
    29  
    30  	unrelated []int
    31  }
    32  
    33  func (analyzer *LandlordAnalyzer) init() {
    34  	analyzer.cardValueMarker = make(map[int]int)
    35  	analyzer.cards = []int{}
    36  
    37  	analyzer.hasKingBomb = false
    38  	analyzer.hasBomb = false
    39  	analyzer.hasTrio = false
    40  	analyzer.hasPair = false
    41  	analyzer.hasAirplaneChain = false
    42  	analyzer.hasPairSisters = false
    43  	analyzer.hasSoloChain = false
    44  
    45  	analyzer.kingBomb = []int{}
    46  	analyzer.bombs = [][]int{}
    47  	analyzer.trios = [][]int{}
    48  	analyzer.pairs = [][]int{}
    49  	analyzer.airplaneChains = [][]int{}
    50  	analyzer.pairSisterss = [][]int{}
    51  	analyzer.soloChains = [][]int{}
    52  
    53  	analyzer.unrelated = []int{}
    54  }
    55  
    56  func (analyzer *LandlordAnalyzer) setCardValueMarker() {
    57  	for i := 3; i < 18; i++ { // 3、4、5、6、7、8、9、10、J、Q、K、A、2、小王、大王
    58  		analyzer.cardValueMarker[i] = 0
    59  	}
    60  	for _, card := range analyzer.cards {
    61  		analyzer.cardValueMarker[CardValue(card)]++
    62  	}
    63  }
    64  
    65  // 传入的牌必须降序排列
    66  func (analyzer *LandlordAnalyzer) Analyze(cards []int) {
    67  	analyzer.init()
    68  	analyzer.cards = append([]int{}, cards...)
    69  	analyzer.setCardValueMarker()
    70  	analyzer.analyzeKingBomb()
    71  	analyzer.analyzeBomb()
    72  	analyzer.analyzeTrio()
    73  	if analyzer.hasTrio {
    74  		analyzer.analyzeAirplaneChains(unite(analyzer.trios))
    75  	}
    76  	analyzer.analyzePair()
    77  	if analyzer.hasPair {
    78  		analyzer.analyzePairSisters(unite(analyzer.pairs))
    79  	}
    80  	analyzer.analyzeSoloChain(exclude(analyzer.cards))
    81  	analyzer.analyzeUnrelated()
    82  }
    83  
    84  func (analyzer *LandlordAnalyzer) analyzeKingBomb() {
    85  	if len(analyzer.cards) > 1 && analyzer.cards[0] == 53 && analyzer.cards[1] == 52 {
    86  		analyzer.hasKingBomb = true
    87  		analyzer.kingBomb = []int{53, 52}
    88  	} else {
    89  		analyzer.hasKingBomb = false
    90  	}
    91  }
    92  
    93  func (analyzer *LandlordAnalyzer) analyzeBomb() {
    94  	for cardValue := 15; cardValue > 2; cardValue-- {
    95  		if analyzer.cardValueMarker[cardValue] == 4 {
    96  			bomb := []int{4*cardValue - 12, 4*cardValue - 11, 4*cardValue - 10, 4*cardValue - 9}
    97  			analyzer.bombs = append(analyzer.bombs, bomb)
    98  		}
    99  	}
   100  	if len(analyzer.bombs) == 0 {
   101  		analyzer.hasBomb = false
   102  	} else {
   103  		analyzer.hasBomb = true
   104  	}
   105  }
   106  
   107  func (analyzer *LandlordAnalyzer) analyzeTrio() {
   108  	for value := 15; value > 2; value-- {
   109  		if analyzer.cardValueMarker[value] > 2 {
   110  			temp := GetCardsByValue(analyzer.cards, value)
   111  			analyzer.trios = append(analyzer.trios, temp[:3])
   112  		}
   113  	}
   114  	if len(analyzer.trios) == 0 {
   115  		analyzer.hasTrio = false
   116  	} else {
   117  		analyzer.hasTrio = true
   118  	}
   119  }
   120  
   121  func (analyzer *LandlordAnalyzer) analyzePair() {
   122  	for value := 15; value > 2; value-- {
   123  		countCardValue := analyzer.cardValueMarker[value]
   124  		switch countCardValue {
   125  		case 2, 3:
   126  			temp := GetCardsByValue(analyzer.cards, value)
   127  			analyzer.pairs = append(analyzer.pairs, temp[:2])
   128  		case 4:
   129  			temp := GetCardsByValue(analyzer.cards, value)
   130  			analyzer.pairs = append(analyzer.pairs, temp[:2])
   131  			analyzer.pairs = append(analyzer.pairs, temp[2:])
   132  		}
   133  	}
   134  	if len(analyzer.pairs) == 0 {
   135  		analyzer.hasPair = false
   136  	} else {
   137  		analyzer.hasPair = true
   138  	}
   139  }
   140  
   141  func (analyzer *LandlordAnalyzer) analyzeAirplaneChains(cards []int) {
   142  	airplaneChains := GetLandlordAirplaneChains(cards)
   143  	if len(airplaneChains) == 0 {
   144  		analyzer.hasAirplaneChain = false
   145  	} else {
   146  		analyzer.hasAirplaneChain = true
   147  		for _, airplaneChain := range airplaneChains {
   148  			analyzer.airplaneChains = append(analyzer.airplaneChains, airplaneChain)
   149  		}
   150  	}
   151  }
   152  
   153  func (analyzer *LandlordAnalyzer) analyzePairSisters(cards []int) {
   154  	remain := append([]int{}, cards...)
   155  	pairSisterss := GetLandlordPairSisters(remain)
   156  	if len(pairSisterss) == 0 {
   157  		if len(analyzer.pairSisterss) == 0 {
   158  			analyzer.hasPairSisters = false
   159  		}
   160  	} else {
   161  		analyzer.hasPairSisters = true
   162  		for _, pairSisters := range pairSisterss {
   163  			analyzer.pairSisterss = append(analyzer.pairSisterss, pairSisters)
   164  			remain = common.Remove(remain, pairSisters)
   165  		}
   166  		analyzer.analyzePairSisters(remain)
   167  	}
   168  }
   169  
   170  func (analyzer *LandlordAnalyzer) analyzeSoloChain(cards []int) {
   171  	remain := append([]int{}, cards...)
   172  	soloChains := GetLandlordSoloChains(remain)
   173  	if len(soloChains) == 0 {
   174  		if len(analyzer.soloChains) == 0 {
   175  			analyzer.hasSoloChain = false
   176  		}
   177  	} else {
   178  		analyzer.hasSoloChain = true
   179  		for _, soloChain := range soloChains {
   180  			analyzer.soloChains = append(analyzer.soloChains, soloChain)
   181  			remain = common.Remove(remain, soloChain)
   182  		}
   183  		analyzer.analyzeSoloChain(remain)
   184  	}
   185  }
   186  
   187  func (analyzer *LandlordAnalyzer) analyzeUnrelated() {
   188  	cardMarker := make(map[int]bool)
   189  	cardMarker = GetCardsMap(analyzer.kingBomb, cardMarker)
   190  	cardMarker = GetMeldsCardsMap(analyzer.bombs, cardMarker)
   191  	cardMarker = GetMeldsCardsMap(analyzer.trios, cardMarker)
   192  	cardMarker = GetMeldsCardsMap(analyzer.pairs, cardMarker)
   193  	cardMarker = GetMeldsCardsMap(analyzer.airplaneChains, cardMarker)
   194  	cardMarker = GetMeldsCardsMap(analyzer.pairSisterss, cardMarker)
   195  	cardMarker = GetMeldsCardsMap(analyzer.soloChains, cardMarker)
   196  	for _, card := range analyzer.cards {
   197  		if !cardMarker[card] {
   198  			analyzer.unrelated = append(analyzer.unrelated, card)
   199  			cardMarker[card] = true
   200  		}
   201  	}
   202  	sort.Ints(analyzer.unrelated)
   203  }
   204  
   205  func (analyzer *LandlordAnalyzer) Print() {
   206  	melds := [][]int{}
   207  	if analyzer.hasKingBomb {
   208  		melds = append(melds, analyzer.kingBomb)
   209  	}
   210  	melds = append(melds, analyzer.bombs...)
   211  	melds = append(melds, analyzer.airplaneChains...)
   212  	melds = append(melds, analyzer.trios...)
   213  	melds = append(melds, analyzer.pairSisterss...)
   214  	melds = append(melds, analyzer.pairs...)
   215  	melds = append(melds, analyzer.soloChains...)
   216  	if len(analyzer.unrelated) > 0 {
   217  		melds = append(melds, analyzer.unrelated)
   218  	}
   219  	log.Debug("%v", ToMeldsString(melds))
   220  }
   221  
   222  func unite(melds [][]int) []int {
   223  	temp := []int{}
   224  	for _, meld := range melds {
   225  		if CardValue(meld[0]) < 15 {
   226  			temp = append(temp, meld...)
   227  		}
   228  	}
   229  	return temp
   230  }
   231  
   232  // 把大于A的牌排除
   233  func exclude(cards []int) []int {
   234  	temp := []int{}
   235  	for _, card := range cards {
   236  		if CardValue(card) < 15 {
   237  			temp = append(temp, card)
   238  		}
   239  	}
   240  	return temp
   241  }
   242  
   243  // 排除顺子、对子
   244  func (analyzer *LandlordAnalyzer) analyze2(cards []int) {
   245  	analyzer.init()
   246  	analyzer.cards = append([]int{}, cards...)
   247  	analyzer.setCardValueMarker()
   248  	//analyzer.analyzeKingBomb()
   249  	//if analyzer.hasKingBomb {
   250  	//	analyzer.cards = common.Remove(analyzer.cards, []int{53, 52})
   251  	//	analyzer.setCardValueMarker()
   252  	//}
   253  	//analyzer.analyzeBomb()
   254  	//if analyzer.hasBomb {
   255  	//	for _, bomb := range analyzer.bombs {
   256  	//		analyzer.cards = common.Remove(analyzer.cards, bomb)
   257  	//	}
   258  	//	analyzer.setCardValueMarker()
   259  	//}
   260  	analyzer.analyzeSoloChain(exclude(analyzer.cards))
   261  	if analyzer.hasSoloChain {
   262  		for _, soloChain := range analyzer.soloChains {
   263  			analyzer.cards = common.Remove(analyzer.cards, soloChain)
   264  		}
   265  		analyzer.setCardValueMarker()
   266  	}
   267  	analyzer.analyzeTrio()
   268  	if analyzer.hasTrio {
   269  		for _, trio := range analyzer.trios {
   270  			analyzer.cards = common.Remove(analyzer.cards, trio)
   271  		}
   272  		analyzer.setCardValueMarker()
   273  		// analyzer.analyzeAirplaneChains(unite(analyzer.trios))
   274  	}
   275  	analyzer.analyzePair()
   276  	if analyzer.hasPair {
   277  		for _, pair := range analyzer.pairs {
   278  			analyzer.cards = common.Remove(analyzer.cards, pair)
   279  		}
   280  		analyzer.setCardValueMarker()
   281  		// analyzer.analyzePairSisters(unite(analyzer.pairs))
   282  	}
   283  	analyzer.unrelated = append([]int{}, analyzer.cards...)
   284  	sort.Ints(analyzer.unrelated)
   285  }
   286  
   287  func (analyzer *LandlordAnalyzer) GetMinDiscards(cards []int) []int {
   288  	analyzer.init()
   289  	analyzer.cards = append([]int{}, cards...)
   290  	analyzer.setCardValueMarker()
   291  
   292  	analyzer.analyzeKingBomb()
   293  	if analyzer.hasKingBomb {
   294  		analyzer.cards = common.Remove(analyzer.cards, analyzer.kingBomb)
   295  		analyzer.setCardValueMarker()
   296  		if len(analyzer.cards) == 0 {
   297  			return []int{analyzer.kingBomb[1]}
   298  		}
   299  	}
   300  	analyzer.analyzeBomb()
   301  	if analyzer.hasBomb {
   302  		for _, bomb := range analyzer.bombs {
   303  			analyzer.cards = common.Remove(analyzer.cards, bomb)
   304  		}
   305  		analyzer.setCardValueMarker()
   306  		if len(analyzer.cards) == 0 {
   307  			return analyzer.bombs[len(analyzer.bombs)-1]
   308  		}
   309  	}
   310  	analyzer.analyzeTrio()
   311  	if analyzer.hasTrio {
   312  		analyzer.analyzeAirplaneChains(unite(analyzer.trios))
   313  	}
   314  	analyzer.analyzePair()
   315  	if analyzer.hasPair {
   316  		analyzer.analyzePairSisters(unite(analyzer.pairs))
   317  	}
   318  	analyzer.analyzeSoloChain(exclude(analyzer.cards))
   319  	analyzer.analyzeUnrelated()
   320  	analyzer.Print()
   321  
   322  	minCard := analyzer.cards[len(analyzer.cards)-1]
   323  	if analyzer.hasAirplaneChain {
   324  		meld := analyzer.airplaneChains[len(analyzer.airplaneChains)-1]
   325  		if common.InArray(meld, minCard) {
   326  			remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld))
   327  			return mixAirplane(meld, exclude(remain))
   328  		}
   329  	}
   330  	if analyzer.hasTrio {
   331  		meld := analyzer.trios[len(analyzer.trios)-1]
   332  		if common.InArray(meld, minCard) {
   333  			remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld))
   334  			return mixTrio(meld, exclude(remain))
   335  		}
   336  	}
   337  	if analyzer.hasPairSisters {
   338  		meld := analyzer.pairSisterss[len(analyzer.pairSisterss)-1]
   339  		if common.InArray(meld, minCard) {
   340  			return meld
   341  		}
   342  	}
   343  	if analyzer.hasSoloChain {
   344  		meld := analyzer.soloChains[len(analyzer.soloChains)-1]
   345  		if common.InArray(meld, minCard) {
   346  			return meld
   347  		}
   348  	}
   349  	if analyzer.hasPair {
   350  		meld := analyzer.pairs[len(analyzer.pairs)-1]
   351  		if common.InArray(meld, minCard) {
   352  			remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld))
   353  			return mixPair(meld, exclude(remain))
   354  		}
   355  	}
   356  	meld := []int{minCard}
   357  	remain := RemoveCardByValue(analyzer.cards, GetCardValueMap(meld))
   358  	return mixSolo(meld, exclude(remain))
   359  }
   360  
   361  func mixAirplane(meld []int, cards []int) []int {
   362  	kickerLen := len(meld) / 3
   363  	if kickerLen > len(cards) {
   364  		return meld
   365  	}
   366  	analyzer := new(LandlordAnalyzer)
   367  	analyzer.analyze2(cards)
   368  	if len(analyzer.unrelated) >= kickerLen {
   369  		newMeld := append([]int{}, meld...)
   370  		newMeld = append(newMeld, analyzer.unrelated[:kickerLen]...)
   371  		return newMeld
   372  	}
   373  	if len(analyzer.pairs) >= kickerLen {
   374  		newMeld := append([]int{}, meld...)
   375  		newMeld = append(newMeld, unite(analyzer.pairs[len(analyzer.pairs)-kickerLen:])...)
   376  		return newMeld
   377  	}
   378  	return meld
   379  }
   380  
   381  func mixTrio(meld []int, cards []int) []int {
   382  	if len(cards) == 0 {
   383  		return meld
   384  	}
   385  	analyzer := new(LandlordAnalyzer)
   386  	analyzer.analyze2(cards)
   387  	if len(analyzer.unrelated) > 0 {
   388  		newMeld := append([]int{}, meld...)
   389  		newMeld = append(newMeld, analyzer.unrelated[0])
   390  		return newMeld
   391  	}
   392  	if len(analyzer.pairs) > 0 {
   393  		newMeld := append([]int{}, meld...)
   394  		newMeld = append(newMeld, analyzer.pairs[len(analyzer.pairs)-1]...)
   395  		return newMeld
   396  	}
   397  	return meld
   398  }
   399  
   400  func mixPair(meld []int, cards []int) []int {
   401  	if len(cards) == 0 {
   402  		return meld
   403  	}
   404  	analyzer := new(LandlordAnalyzer)
   405  	analyzer.Analyze(cards)
   406  	if len(analyzer.airplaneChains) > 0 {
   407  		airplaneChain := analyzer.airplaneChains[len(analyzer.airplaneChains)-1]
   408  		newCards := append([]int{}, cards...)
   409  		newCards = append(newCards, meld...)
   410  		sort.Sort(sort.Reverse(sort.IntSlice(newCards)))
   411  		remain := common.Remove(newCards, airplaneChain)
   412  		return mixAirplane(airplaneChain, remain)
   413  	}
   414  	if len(analyzer.trios) > 0 {
   415  		newMeld := append([]int{}, analyzer.trios[len(analyzer.trios)-1]...)
   416  		newMeld = append(newMeld, meld...)
   417  		return newMeld
   418  	}
   419  	return meld
   420  }
   421  
   422  func mixSolo(meld []int, cards []int) []int {
   423  	return mixPair(meld, cards)
   424  }