package gamelogic import ( "fmt" "math/rand" "runtime/debug" "sort" "bet24.com/log" ) /* 牌的排列顺序为 方块 梅花 红心 黑桃 */ const ( CardType_Diamond = iota CardType_Club CardType_Heart CardType_Spade CardType_Invalid ) const ( CardValue7 = iota CardValue8 CardValue9 CardValue10 CardValueJ CardValueQ CardValueK CardValueA ) const ( CARD_COUNT = 32 // 牌数量 BUY_PHRSE_HOLD_CARD = 5 // 买牌阶段手持牌 SURPLUS_SEND_CARD = 3 // 剩余发牌数量 NORMAL_HOLD_CARD = 8 // 正常手持牌 PUBLIC_CARD_POS = 20 // 公共牌位置 ) var type_desc = []string{"♦", "♣", "♥", "♠", ""} var value_desc = []string{"7", "8", "9", "10", "J", "Q", "K", "A"} var value_regular = []int{0, 0, 0, 10, 2, 3, 4, 11} var value_trump = []int{0, 0, 14, 10, 20, 3, 4, 11} func isValidCard(card int) bool { return card >= 0 && card < CARD_COUNT } func getCardHex(card int) string { if !isValidCard(card) { return "n/a" } return fmt.Sprintf("%s%s", type_desc[getCardType(card)], value_desc[getCardValue(card)]) } func getCardsHex(cards []int) string { ret := "[" for _, v := range cards { ret += getCardHex(v) ret += " " } ret += "]" return ret } func getCardType(card int) int { if !isValidCard(card) { log.Debug("%s", debug.Stack()) return CardType_Invalid } return card / 8 } func getCardValue(card int) int { if !isValidCard(card) { log.Debug("%s", debug.Stack()) return -1 } return card % 8 } func getCardValueByDesc(desc string) int { for i := 0; i < len(value_desc); i++ { if desc == value_desc[i] { return i } } return -1 } func getCardCompareValue(card, trumpType int) int { value := getCardValue(card) t := getCardType(card) if trumpType != CardType_Invalid && t == trumpType { // 因为主牌9比A大,比J小,但是9的value + value_trump[value]值为16,J为24 // 但是A为18,所以这里为了提高9的比值,做个+4的特殊处理 if value == CardValue9 { return (value + value_trump[value] + 4) } return (value + value_trump[value]) } return (value + value_regular[value]) } func getCardPoint(card, trumpType int) int { value := getCardValue(card) t := getCardType(card) if trumpType != CardType_Invalid && t == trumpType { return value_trump[value] } return value_regular[value] } func getCardSortValue(card, trumpType int) int { return getCardType(card)*100 + getCardCompareValue(card, trumpType) } func getTypeDesc(t int) string { if t >= CardType_Invalid { return "n/a" } return type_desc[t] } func getCardCount(cards []int, card int) int { if !isValidCard(card) { return 0 } ret := 0 for _, v := range cards { if v == card { ret++ } } return ret } func getChooseTrumpDesc(data int) string { if data >= CardType_Invalid { return "SwitchSun" } return type_desc[data] } func isIncludeTheProject(handCards []int, projectType int, suit int) ([]int, bool) { cards := []int{} bInclude := false switch projectType { case PROJECT_FOURHUNDRED: if haveFourA(handCards) { bInclude = true for i := CardType_Diamond; i <= CardType_Spade; i++ { card := CardValueA + i*8 cards = append(cards, card) } } case PROJECT_HUNDRED: return haveHundred(handCards, suit) case PROJECT_FIFTY: return haveFifty(handCards) case PROJECT_SIRA: return haveSira(handCards) } return cards, bInclude } func haveSira(handCards []int) ([]int, bool) { value := -1 cards := []int{} bHaveSerial := false value, bHaveSerial = haveSerial(3, handCards) if bHaveSerial { for n := value - 2; n <= value; n++ { cards = append(cards, n) } } return cards, bHaveSerial } func haveFifty(handCards []int) ([]int, bool) { value := -1 cards := []int{} bHaveSerial := false value, bHaveSerial = haveSerial(4, handCards) if bHaveSerial { for n := value - 3; n <= value; n++ { cards = append(cards, n) } } return cards, bHaveSerial } func haveHundred(handCards []int, suit int) ([]int, bool) { value := -1 bHaveFour := false cards := []int{} bHaveSerial := false value, bHaveSerial = haveSerial(5, handCards) if bHaveSerial { for n := value - 4; n <= value; n++ { cards = append(cards, n) } return cards, true } for i := CardValue10; i <= CardValueA; i++ { if suit != Suit_Hokum && i == CardValueA { continue } count := 0 for n := 0; n < len(handCards); n++ { if handCards[n]%8 == i { count++ } } if count == 4 { value = i bHaveFour = true break } } if bHaveFour { for i := 0; i < 4; i++ { card := value + i*8 cards = append(cards, card) } } return cards, bHaveFour } func haveSerial(length int, handCards []int) (int, bool) { bHave := false start := -1 for i := CardType_Spade; i >= CardType_Diamond; i-- { bHave, start = haveSerialInAType(i, length, handCards) if bHave { break } } return start, bHave } func haveSerialInAType(cardType int, length int, handCards []int) (bool, int) { cards := []int{} for i := 0; i < len(handCards); i++ { if handCards[i]/8 == cardType { cards = append(cards, handCards[i]) } } if len(cards) < length { return false, -1 } sort.Slice(cards, func(i, j int) bool { return cards[i] > cards[j] }) start := 0 bExist := false for n := 0; n < len(cards); n++ { start = cards[n] if (n + length) > len(cards) { break } end := cards[n+length-1] if (start - end) == (length - 1) { bExist = true break } } return bExist, start } func haveFourA(handCards []int) bool { count := 0 for i := 0; i < len(handCards); i++ { if handCards[i]%8 == CardValueA { count++ } } return count == 4 } func removeCards(handCards []int, delCards []int) []int { for j := 0; j < len(delCards); j++ { for i := 0; i < len(handCards); { if handCards[i] == delCards[j] { handCards = append(handCards[:i], handCards[i+1:]...) break } else { i++ } } } return handCards } func sortCards(cards []int) [][]int { sortedCards := make([][]int, 4) for i := 0; i < len(cards); i++ { t := getCardType(cards[i]) sortedCards[t] = append(sortedCards[t], cards[i]) } return sortedCards } func haveCard(cards []int, card int) bool { return getCardCount(cards, card) > 0 } func isScoreCard(card int, handCards []int, outedCards []int, trumpType int) bool { v := getCardValue(card) t := getCardType(card) rv := getCardCompareValue(card, trumpType) if (v == CardValueA && t != trumpType) || (v == CardValueJ && t == trumpType) { return true } for i := CardValue7; i <= CardValueA; i++ { if i == v { continue } checkCard := i + t*8 if getCardCompareValue(checkCard, trumpType) < rv { continue } if !haveCard(handCards, checkCard) && !haveCard(outedCards, checkCard) { return false } } return true } func getScoreCards(handCards []int, outedCards []int, trumpType int, isFirstOutCardClose bool) []int { var scoreCards []int for i := 0; i < len(handCards); i++ { v := handCards[i] if isFirstOutCardClose && getCardType(v) == trumpType { continue } if isScoreCard(v, handCards, outedCards, trumpType) { scoreCards = append(scoreCards, v) } } return scoreCards } func getBestTrumpType(cards []int, publicCard int) int { bestType := CardType_Invalid most := -1 counts := make([]int, 4) for _, v := range cards { if getCardType(v) == getCardType(publicCard) { continue } counts[getCardType(v)]++ } scoreCounts := make([]int, 4) for i := 0; i < CardType_Invalid; i++ { if i == getCardType(publicCard) { continue } scoreCards := getScoreCards(cards, []int{}, i, false) for _, v := range scoreCards { scoreCounts[getCardType(v)]++ } } for i := 0; i < len(counts); i++ { if i == getCardType(publicCard) { continue } if counts[i] > most { most = counts[i] bestType = i } if counts[i] > most && scoreCounts[i] > scoreCounts[bestType] { // 比较得分牌,多的优先 most = counts[i] bestType = i } } if bestType != getCardType(publicCard) && (most > 4 || (most > 3 && haveCard(cards, CardValueJ+bestType*8))) { return bestType } if bestType == CardType_Invalid { for i := 0; i < CardType_Invalid; i++ { if i != getCardType(publicCard) { continue } if most == counts[i] { bestType = i break } } } return bestType } func getLAGsBestTrumpType(cards []int, publicCard int) int { bestType := CardType_Invalid most := -1 counts := make([]int, 4) for _, v := range cards { if getCardType(v) == getCardType(publicCard) { continue } counts[getCardType(v)]++ } scoreCounts := make([]int, 4) for i := 0; i < CardType_Invalid; i++ { if i == getCardType(publicCard) { continue } scoreCards := getScoreCards(cards, []int{}, i, false) for _, v := range scoreCards { scoreCounts[getCardType(v)]++ } } startType := rand.Intn(4) for i := 0; i < len(counts); i++ { t := (startType + i) % 4 if t == getCardType(publicCard) { continue } if counts[t] > most { most = counts[t] bestType = t } if counts[t] > most && scoreCounts[t] > scoreCounts[bestType] { // 比较得分牌,多的优先 most = counts[t] bestType = t } } if bestType == getCardType(publicCard) { return CardType_Invalid } if most < 3 { return CardType_Invalid } return bestType } func calcFinalPonit(point int) int { var ret int if point%10 > 5 { point = point/10 + 1 ret = point } else { point /= 10 ret = point } return ret } // 判断是否最大的牌,非Hokom为A,Hokom为J func isBiggestCard(card int, trumpType int) bool { v := getCardValue(card) t := getCardType(card) if trumpType != CardType_Invalid && t == trumpType { return v == CardValueJ } return v == CardValueA } func checkCanGawah(allplayerHandCards [][]int, chairId int, trumpType int) bool { if chairId >= CHAIR_COUNT { return false } handCards := allplayerHandCards[chairId] var otherHandCards []int for i := 0; i < CHAIR_COUNT; i++ { if i == chairId { continue } otherHandCards = append(otherHandCards, allplayerHandCards[i]...) } for _, v := range handCards { if !isBiggerThanAll(v, otherHandCards, trumpType) { return false } } return true } func isBiggerThanAll(card int, cards []int, trumpType int) bool { t := getCardType(card) for _, v := range cards { t1 := getCardType(v) // 如果对面有主牌,我的不是主牌 if t != trumpType && t1 == trumpType { return false } // 不同花色不比较 if t1 != t { continue } if getCardCompareValue(card, trumpType) < getCardCompareValue(v, trumpType) { return false } } return true } func genACard(cardType, cardValue int) int { return cardType*8 + cardValue } func isExistCardInHand(card int, cards []int) bool { for i := 0; i < len(cards); i++ { if cards[i] == card { return true } } return false } func getScoreCardNum(cards []int, cardType int, isTrumpType bool) int { scoreCardNum := 0 cardList2 := []int{CardValueA, CardValue10, CardValueK, CardValueQ, CardValueJ, CardValue9, CardValue8, CardValue7} cardList1 := []int{CardValueJ, CardValue9, CardValueA, CardValue10, CardValueK, CardValueQ, CardValue8, CardValue7} if isTrumpType { for i := 0; i < len(cardList1); i++ { card := cardList1[i] + cardType*8 if !isExistCardInHand(card, cards) { break } scoreCardNum++ } } else { for i := 0; i < len(cardList2); i++ { card := cardList2[i] + cardType*8 if !isExistCardInHand(card, cards) { break } scoreCardNum++ } } return scoreCardNum } func isBothInclude9J(cards []int) bool { bInclude9 := false bIncludeJ := false for i := 0; i < len(cards); i++ { if cards[i]%8 == CardValue9 { bInclude9 = true } if cards[i]%8 == CardValueJ { bIncludeJ = true } } return bInclude9 && bIncludeJ } func isMostOverKInHandCard(cards []int, trumpType int) bool { bigCount := 0 for i := 0; i < len(cards); i++ { if getCardCompareValue(cards[i], trumpType) > 4 { bigCount++ } } return bigCount > 4 } func isAllBelow10InHandCard(cards []int) bool { smallCount := 0 for i := 0; i < len(cards); i++ { if getCardCompareValue(cards[i], CardType_Invalid) < 10 { smallCount++ } } return smallCount <= 2 }