| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- package gamelogic
- import (
- "math/rand"
- "os"
- "path/filepath"
- "sort"
- "strconv"
- "bet24.com/log"
- cardlibrary "bet24.com/servers/micros/cardlibrary/proto"
- "bet24.com/utils"
- "github.com/360EntSecGroup-Skylar/excelize"
- )
- type cardlogic struct {
- cards []int
- trumpType int
- suit int
- currentCardIndex int
- isFirstOutCardClose bool
- }
- func newCardLogic() *cardlogic {
- ret := new(cardlogic)
- ret.initData()
- return ret
- }
- func (cl *cardlogic) initData() {
- cl.trumpType = CardType_Invalid
- cl.suit = Suit_Invalid
- cl.shuffle(false, -1, -1, -1, false)
- }
- func (cl *cardlogic) readBalootCards() bool {
- fileName := "balootcards.xlsx"
- sheetName := "Sheet1"
- readFile, err := excelize.OpenFile(filepath.Join("./baloot_excel/", fileName))
- if err != nil {
- return false
- }
- cards := []int{}
- for rowIndex, readRow := range readFile.GetRows(sheetName) {
- if rowIndex > 0 {
- break
- }
- for _, colCell := range readRow {
- value, _ := strconv.Atoi(colCell)
- if isValidCard(value) {
- cards = append(cards, value)
- }
- }
- }
- if len(cards) == 0 || len(cards) > CARD_COUNT {
- return false
- }
- for d := 0; d < CARD_COUNT; d++ {
- cl.cards[d] = d
- }
- for i := CARD_COUNT - 1; i > 1; i-- {
- place := rand.Intn(i)
- tmp := cl.cards[place]
- cl.cards[place] = cl.cards[i]
- cl.cards[i] = tmp
- }
- for n := 0; n < len(cards); n++ {
- pos := -1
- for j := 0; j < CARD_COUNT; j++ {
- if cards[n] == cl.cards[j] {
- pos = j
- break
- }
- }
- if pos == -1 {
- continue
- }
- tmp := cl.cards[pos]
- cl.cards[n] = cards[n]
- cl.cards[pos] = tmp
- }
- return true
- }
- func (cl *cardlogic) shuffle(test bool, controlChair, firstOutCard, doubling int, isNewUser bool) {
- cl.trumpType = CardType_Invalid
- cl.currentCardIndex = 0
- cl.isFirstOutCardClose = false
- cl.cards = make([]int, CARD_COUNT)
- if test {
- ret := cl.readBalootCards()
- if ret {
- return
- }
- }
- if isValidChair(controlChair) {
- libraryType := cardlibrary.Baloot_LibraryType_Scenario
- r := rand.Intn(100)
- if r >= 80 && r < 90 {
- libraryType = cardlibrary.Baloot_LibraryType_Invincible
- } else if r >= 90 {
- libraryType = cardlibrary.Baloot_LibraryType_HighScore
- }
- if doubling >= 0 {
- libraryType = cardlibrary.Baloot_LibraryType_Doubling
- if r >= 50 {
- libraryType = cardlibrary.Baloot_LibraryType_Doubling_Scenario
- }
- }
- if isNewUser {
- libraryType = cardlibrary.Baloot_LibraryType_NewUser
- }
- success, cardList := cardlibrary.GetControlCards(libraryType, controlChair, firstOutCard, doubling)
- if success {
- cl.cards = cardList
- return
- }
- }
- for d := 0; d < CARD_COUNT; d++ {
- cl.cards[d] = d
- }
- for i := CARD_COUNT - 1; i > 1; i-- {
- place := rand.Intn(i)
- tmp := cl.cards[place]
- cl.cards[place] = cl.cards[i]
- cl.cards[i] = tmp
- }
- }
- func (cl *cardlogic) getCardsByProjectDesc(project cardlibrary.ProjectConf, startIndex int) []int {
- cards := []int{}
- cardList := []int{}
- for n := cl.currentCardIndex + startIndex; n < CARD_COUNT; n++ {
- cardList = append(cardList, cl.cards[n])
- }
- switch project.ProjectDesc {
- case "三联顺":
- value, bHaveSerial := haveSerial(3, cardList)
- if bHaveSerial {
- for n := value - 2; n <= value; n++ {
- cards = append(cards, n)
- }
- }
- case "四联顺":
- value, bHaveSerial := haveSerial(4, cardList)
- if bHaveSerial {
- for n := value - 3; n <= value; n++ {
- cards = append(cards, n)
- }
- }
- case "五联顺":
- value, bHaveSerial := haveSerial(5, cardList)
- if bHaveSerial {
- for n := value - 4; n <= value; n++ {
- cards = append(cards, n)
- }
- }
- case "四张相同":
- value, bHaveFour := 0, false
- for i := CardValue10; i <= CardValueA; i++ {
- count := 0
- for n := 0; n < len(cardList); n++ {
- if cardList[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
- }
- func (cl *cardlogic) getNormalCardsInControl(userId int) []int {
- maxCount := BUY_PHRSE_HOLD_CARD
- ret := make([]int, maxCount)
- success, librarys := cardlibrary.GetUserControlCards(userId)
- if success {
- getCount := 0
- for l := 0; l < len(librarys); l++ {
- library := librarys[l]
- for n := 0; n < len(library.Cards); n++ {
- if getCount >= 6 {
- break
- }
- for m := 0; m < library.Cards[n].Count; m++ {
- if getCount >= 6 {
- break
- }
- pos := -1
- for j := cl.currentCardIndex + getCount; j < CARD_COUNT; j++ {
- if getCardValueByDesc(library.Cards[n].ValueDesc) == getCardValue(cl.cards[j]) {
- pos = j
- break
- }
- }
- if pos == -1 {
- continue
- }
- if getCount >= 6 {
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[PUBLIC_CARD_POS]
- cl.cards[PUBLIC_CARD_POS] = tmp
- break
- }
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[cl.currentCardIndex+getCount]
- cl.cards[cl.currentCardIndex+getCount] = tmp
- getCount++
- }
- }
- if getCount < 6 {
- for i := 0; i < len(library.Projects); i++ {
- if getCount >= 6 {
- break
- }
- if library.Projects[i].Count == 0 {
- continue
- }
- for m := 0; m < library.Projects[i].Count; m++ {
- if getCount >= 6 {
- break
- }
- startIndex := getCount
- cardList := cl.getCardsByProjectDesc(library.Projects[i], startIndex)
- for n := 0; n < len(cardList); n++ {
- if getCount >= 6 {
- break
- }
- pos := -1
- for j := cl.currentCardIndex + startIndex; j < CARD_COUNT; j++ {
- if cardList[n] == cl.cards[j] {
- pos = j
- break
- }
- }
- if pos == -1 {
- continue
- }
- if getCount >= 6 {
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[PUBLIC_CARD_POS]
- cl.cards[PUBLIC_CARD_POS] = tmp
- break
- }
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[cl.currentCardIndex+getCount]
- cl.cards[cl.currentCardIndex+getCount] = tmp
- getCount++
- }
- }
- }
- }
- if getCount < 6 {
- startIndex := getCount
- rType := rand.Intn(4)
- for n := 0; n < library.SameTypeCount; n++ {
- if getCount >= 6 {
- break
- }
- pos := -1
- for j := cl.currentCardIndex + startIndex; j < CARD_COUNT; j++ {
- if rType == getCardType(cl.cards[j]) {
- pos = j
- break
- }
- }
- if pos == -1 {
- continue
- }
- if getCount >= 6 {
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[PUBLIC_CARD_POS]
- cl.cards[PUBLIC_CARD_POS] = tmp
- break
- }
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[cl.currentCardIndex+getCount]
- cl.cards[cl.currentCardIndex+getCount] = tmp
- getCount++
- }
- }
- pos := -1
- for j := cl.currentCardIndex + getCount; j < CARD_COUNT; j++ {
- if getCardValueByDesc(library.PublicCard) == getCardValue(cl.cards[j]) {
- pos = j
- break
- }
- }
- if pos != -1 {
- tmp := cl.cards[pos]
- cl.cards[pos] = cl.cards[PUBLIC_CARD_POS]
- cl.cards[PUBLIC_CARD_POS] = tmp
- }
- if getCount > 0 {
- break
- }
- }
- }
- for i := 0; i < maxCount; i++ {
- ret[i] = cl.getOneCard()
- }
- sort.Slice(ret, func(i, j int) bool {
- return getCardSortValue(ret[i], CardType_Invalid) < getCardSortValue(ret[j], CardType_Invalid)
- })
- return ret
- }
- func (cl *cardlogic) getNormalCards() []int {
- maxCount := BUY_PHRSE_HOLD_CARD
- ret := make([]int, maxCount)
- for i := 0; i < maxCount; i++ {
- ret[i] = cl.getOneCard()
- }
- sort.Slice(ret, func(i, j int) bool {
- return getCardSortValue(ret[i], CardType_Invalid) < getCardSortValue(ret[j], CardType_Invalid)
- })
- return ret
- }
- func (cl *cardlogic) getOneCard() int {
- ret := cl.cards[cl.currentCardIndex]
- cl.currentCardIndex++
- return ret
- }
- func (cl *cardlogic) getLeftCards(bBuyChiar bool) []int {
- maxCount := SURPLUS_SEND_CARD
- if bBuyChiar {
- maxCount--
- }
- ret := make([]int, maxCount)
- for i := 0; i < maxCount; i++ {
- ret[i] = cl.getOneCard()
- }
- return ret
- }
- func (cl *cardlogic) setTrumpAndSuit(t, s int) {
- cl.trumpType = t
- cl.suit = s
- }
- func (cl *cardlogic) setIsFirstOutCardClose(isClose bool) {
- cl.isFirstOutCardClose = isClose
- }
- // 能否出这张牌
- func (cl *cardlogic) canOut(card int, cardType int, handCards []int) bool {
- found := false
- for _, v := range handCards {
- if v == card {
- found = true
- }
- }
- if !found {
- log.Release("cardlogic.canOut %d not exist in [%v]", card, handCards)
- return false
- }
- if cardType == CardType_Invalid {
- return true
- }
- t := getCardType(card)
- if t == cardType {
- return true
- }
- foundSameType := false
- for _, v := range handCards {
- if cardType == getCardType(v) {
- foundSameType = true
- }
- }
- return !foundSameType
- }
- func (cl *cardlogic) getCardRank(card int, referType int) int {
- if !isValidCard(card) {
- return -2
- }
- cardType := getCardType(card)
- cardScore := 0
- if cardType == cl.trumpType {
- cardScore += 100
- } else if cardType != referType {
- return -1
- }
- value := getCardCompareValue(card, cl.trumpType)
- return cardScore + value
- }
- // outCards 按椅子顺序的出牌
- func (cl *cardlogic) getWinner(outCards []int, referType int) int {
- ranks := make([]int, CHAIR_COUNT)
- winner := -1
- bestRank := -2
- for i := 0; i < CHAIR_COUNT; i++ {
- ranks[i] = cl.getCardRank(outCards[i], referType)
- if ranks[i] > bestRank {
- bestRank = ranks[i]
- winner = i
- }
- }
- return winner
- }
- func (cl *cardlogic) worstCard(cards []int, cardType int) int {
- if len(cards) == 0 {
- return CARD_COUNT
- }
- if len(cards) == 1 {
- return cards[0]
- }
- // 先按花色存储
- sortedCards := sortCards(cards)
- if cardType != CardType_Invalid && len(sortedCards[cardType]) > 0 {
- return sortedCards[cardType][0]
- }
- typeCounts := make([]int, 4)
- minIndex := -1
- minCount := 8
- maxIndex := -1
- maxCount := 0
- for i := 0; i < len(typeCounts); i++ {
- typeCounts[i] = len(sortedCards[i])
- if i == cl.trumpType || typeCounts[i] == 0 {
- continue
- }
- if typeCounts[i] < minCount {
- minCount = typeCounts[i]
- minIndex = i
- }
- if typeCounts[i] > maxCount {
- maxCount = typeCounts[i]
- maxIndex = i
- }
- }
- // 如果我有主,则丢一张最少花色的牌 否则丢最多花色的牌
- if cl.trumpType == CardType_Invalid {
- if maxIndex > 0 {
- return sortedCards[maxIndex][0]
- }
- return cards[0]
- }
- if typeCounts[cl.trumpType] == 0 {
- if maxIndex > 0 {
- return sortedCards[maxIndex][0]
- }
- } else {
- if minIndex >= 0 {
- if cl.isFirstOutCardClose &&
- minIndex == cl.trumpType &&
- cardType == CardType_Invalid {
- for i := 0; i < len(cards); i++ {
- if getCardType(cards[i]) != cl.trumpType {
- return cards[i]
- }
- }
- } else {
- return sortedCards[minIndex][0]
- }
- }
- }
- return cards[0]
- }
- func (cl *cardlogic) getBestProject(cardList []int) []int {
- ret := make([]int, 4)
- for i := PROJECT_FOURHUNDRED; i >= PROJECT_SIRA; i-- {
- if cl.suit == Suit_Hokum && i == PROJECT_FOURHUNDRED {
- continue
- }
- for n := 0; n < 2; n++ {
- cards, bInclude := isIncludeTheProject(cardList, i, cl.suit)
- if bInclude {
- cardList = removeCards(cardList, cards)
- ret[i]++
- }
- }
- }
- return ret
- }
- func (cl *cardlogic) test() bool {
- if len(os.Args) < 2 {
- return false
- }
- defer utils.TimeCost("cardlogic.test")()
- return true
- }
|