| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- 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
- }
|