package gamelogic import ( "encoding/json" "math/rand" "sort" "bet24.com/log" "bet24.com/servers/games/baloot/config" ladder "bet24.com/servers/micros/ladderservice/proto" ) type GameScene struct { Banker int // 庄家 FirstActionChair int // 第一个操作的玩家,用作标识 Phase int // 场景阶段 PhaseIndex int // 场景阶段索引 BuyChair int // 当前买牌玩家 BuyAction int // 当前买公共牌动作 FinalClub int // 最终模式 WhoseTurn int // 当前轮到谁操作 LastTurn int // 上个操作的玩家 Players []PlayerInfo // 玩家信息 userActions []userAction // 玩家动作用作回放数据 tableId int // 桌子ID Index int // 场景索引 GameIndex int // 第几局 ScoreToWin int // 达到多少分就赢,负数表示打多少局 PublicCard int // 本局公共牌 RoundType int // 当前圈牌色 RoundWinner int // 本圈赢家 RoundIndex int // 第几轮出牌 LeftSec int // 剩余时间 BaseTimes int // 本轮倍数 TrumpType int // 主牌花色,Sun或Ashkal模式下为CardType_Invalid IsBO1 bool // 本轮是否一局定胜负 IsClose bool // 为true表示本局在每一轮第一个出牌时不能出主牌(除了手上全是主牌的情况) ShowAllCards bool // 是否要展示所有人的牌,用于玩家选择全部打出剩余牌的时候 LastWinChair int // 最后一轮赢牌玩家 DoublingDetails []DoublingData // 加倍详情 GameOutCardHistory []int // 已出的牌 CorrectMode int // 纠错模式 SawaChair int // 做了Sawa的玩家 CorrectResult int // 胜利结果 CorrectCards []int // 纠错牌 CorrectType int // 纠错类型 CanCorrect bool // 能否质疑 LeftSurrenderCount int // 剩余投降次数 isCorrectEnd bool // 是否是纠错结束 isEnterAshkal bool // 是否有人选过Ashkal reshuffleResult int // 进入重洗前的买牌结果 reshufflePhase int // 进入重新前的场景阶段 buyPhase int // 确定买牌阶段 scoreHistory []perRoundScores currentRoundDoubling int maxDoublingTime int robotSendChatCount int robotSendChatMaxCount int robotChatList []robotChatAction statics []robotChatActionList isSendChat bool } func (gs *GameScene) addAction(chairId int, action int, data int) { gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: data}) gs.Index++ } func (gs *GameScene) addOutCardAction(chairId int, action int, data int, projects []int) { gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: data, ExtData: projects}) gs.Index++ gs.PhaseIndex++ } func (gs *GameScene) addCorrectAction(chairId int, action int, correctType int, correctCards []int) { gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: correctType, ExtData: correctCards}) gs.Index++ } func newGameScene(tableId int, winpoint int, leftSurrenderCount int) *GameScene { gs := new(GameScene) gs.ctor() gs.Banker = rand.Intn(CHAIR_COUNT) gs.initData(tableId, winpoint, leftSurrenderCount) gs.GameIndex = 0 gs.robotSendChatMaxCount = 12 if winpoint == -1 { gs.robotSendChatMaxCount = 6 } return gs } func (gs *GameScene) ctor() { gs.Players = make([]PlayerInfo, CHAIR_COUNT) for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].isEndToStart = false } } func (gs *GameScene) initData(tableId int, winpoint int, leftSurrenderCount int) { gs.userActions = []userAction{} gs.scoreHistory = []perRoundScores{} gs.LeftSurrenderCount = leftSurrenderCount gs.robotSendChatCount = 0 gs.robotChatList = []robotChatAction{} gs.statics = []robotChatActionList{} // 比赛场海选赛打的一场,ScoreToWin为1,淘汰赛打三场,ScoreToWin为-3, // 做统一处理:当ScoreToWin<0时表示打多少场 initScore := 0 if winpoint <= 2 { if winpoint > 0 { winpoint = -winpoint } gs.ScoreToWin = winpoint } else { // gs.ScoreToWin = SCORE_TO_WIN // initScore = SCORE_TO_WIN - winpoint gs.ScoreToWin = winpoint } gs.Index = 0 for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].initData(0, 0, initScore) } gs.tableId = tableId gs.maxDoublingTime = -1 gs.gameInit(-1) } func (gs *GameScene) gameInit(whoseTurn int) { gs.BuyChair = -1 gs.BuyAction = -1 gs.Phase = Phase_Free gs.PhaseIndex = 0 gs.WhoseTurn = whoseTurn gs.FirstActionChair = whoseTurn gs.LastTurn = -1 gs.PublicCard = CARD_COUNT gs.RoundType = CardType_Invalid gs.RoundWinner = CHAIR_COUNT gs.GameOutCardHistory = []int{} gs.RoundIndex = 0 gs.BaseTimes = 1 gs.TrumpType = CardType_Invalid gs.IsBO1 = false gs.FinalClub = Suit_Invalid gs.IsClose = false gs.ShowAllCards = false gs.LastWinChair = -1 gs.reshuffleResult = -1 gs.reshufflePhase = Phase_Free gs.isCorrectEnd = false gs.isEnterAshkal = false gs.DoublingDetails = []DoublingData{} gs.CorrectMode = Correct_Invaild gs.SawaChair = CHAIR_COUNT gs.CorrectResult = -1 gs.CorrectCards = []int{} gs.CanCorrect = false gs.buyPhase = Phase_FirstBuy gs.currentRoundDoubling = 0 gs.isSendChat = false for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].gameInit() } } func (gs *GameScene) initAllPlayerLastAction() { for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].intLastAction() } } func (gs *GameScene) canDouble(chairId int) bool { return gs.Players[chairId].TotalScore > 100 && gs.Players[getNextChair(chairId)].TotalScore < 100 } func (gs *GameScene) canDoubleInSun() bool { if gs.FinalClub == Suit_Hokum { return false } return gs.Players[gs.BuyChair].TotalScore > 100 && gs.Players[getNextChair(gs.BuyChair)].TotalScore < 100 } func (gs *GameScene) checkProject(chairId int, projects []int) { gs.Players[chairId].analysisProject(projects, gs.FinalClub) } func (gs *GameScene) initAllPlayerTime() { for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].ininTime() } } func (gs *GameScene) isBuySunEnterDouble(buyAction, buyChairId int) bool { if buyAction != Action_Buy_Sun { return false } if gs.BuyAction == Action_Buy_Hokum { return false } if gs.isEnterAshkal && buyChairId != gs.FirstActionChair { return false } return gs.canDouble(buyChairId) } // 0 表示继续买牌或者直接进入double阶段,1表示结束买牌阶段,进入发剩余牌阶段 func (gs *GameScene) resetBuyActionOfChangeBuyChair(buyAction, buyChairId int) int { // 先把做完买牌玩家可做动作清空 gs.Players[buyChairId].setPlayerOperators([]int{}) // 如果玩家选择pass且当前都没有人买牌 if buyAction == Action_Buy_Pass { // 如果当前买牌的人为庄家,则进入第二次买牌阶段 if buyChairId == gs.Banker && gs.Phase == Phase_FirstBuy { gs.Phase = Phase_SecondBuy gs.PhaseIndex = 0 } gs.WhoseTurn = getPreviousChair(gs.WhoseTurn) for i := 0; i < CHAIR_COUNT; i++ { buyList := []int{} if i == gs.WhoseTurn { buyList = append(buyList, Action_Buy_Pass, Action_Buy_Hokum, Action_Buy_Sun) if i == gs.Banker || isPreviousChair(i, gs.Banker) { buyList = append(buyList, Action_Buy_Ashkal) } gs.Players[i].setPlayerOperators(buyList) } else { gs.Players[i].setPlayerOperators(buyList) } } return 0 } // 如果玩家选择hokum if buyAction == Action_Buy_Hokum { gs.BuyAction = buyAction gs.BuyChair = buyChairId for i := 0; i < CHAIR_COUNT; i++ { buyList := []int{} if i == gs.BuyChair { continue } buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun) if i == gs.Banker || isPreviousChair(i, gs.Banker) { buyList = append(buyList, Action_Buy_Ashkal) } gs.Players[i].setPlayerOperators(buyList) gs.Players[i].intLastAction() } gs.WhoseTurn = -1 return 0 } // 如果玩家选择Action_Buy_Sun或者Action_Buy_Ashkal result := 1 if buyAction == Action_Buy_Sun || buyAction == Action_Buy_Ashkal { if buyAction == Action_Buy_Ashkal { gs.isEnterAshkal = true } bOnlyOnePlayer := false isBeforeBuyHokum := (gs.BuyAction == Action_Buy_Hokum) if !isBeforeBuyHokum { bOnlyOnePlayer = true gs.BuyAction = buyAction gs.BuyChair = buyChairId for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].setPlayerOperators([]int{}) } } else { result = 0 if isFriendChair(gs.BuyChair, buyChairId) && buyAction == Action_Buy_Ashkal { result = 1 gs.BuyAction = buyAction gs.BuyChair = buyChairId for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].setPlayerOperators([]int{}) } bOnlyOnePlayer = true } else { for i := 0; i < CHAIR_COUNT; i++ { buyList := []int{} if i == gs.BuyChair { buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun) if (i == gs.Banker || isPreviousChair(i, gs.Banker)) && !gs.isEnterAshkal { buyList = append(buyList, Action_Buy_Ashkal) } if gs.BuyChair == getNextChair(buyChairId) { bOnlyOnePlayer = true } } gs.Players[i].setPlayerOperators(buyList) } gs.WhoseTurn = gs.BuyChair gs.BuyAction = buyAction gs.BuyChair = buyChairId } } buyList := []int{} buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun) if buyAction == Action_Buy_Ashkal { result = 0 if bOnlyOnePlayer { gs.WhoseTurn = getNextChair(buyChairId) } else { gs.WhoseTurn = -1 } gs.Players[getNextChair(buyChairId)].setPlayerOperators(buyList) } if gs.isEnterAshkal && buyAction == Action_Buy_Sun && buyChairId != gs.FirstActionChair { result = 0 if bOnlyOnePlayer { gs.WhoseTurn = getNextChair(buyChairId) } else { gs.WhoseTurn = -1 } gs.Players[getNextChair(buyChairId)].setPlayerOperators(buyList) } } if result == 1 { gs.setFinalSuit() gs.TrumpType = CardType_Invalid // sun模式下,判断玩家能不能买double if gs.canDoubleInSun() { for i := 0; i < CHAIR_COUNT; i++ { buyList := []int{} if isSameTeam(i, gs.BuyChair) { gs.Players[i].setPlayerOperators(buyList) continue } buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double) gs.Players[i].setPlayerOperators(buyList) } gs.WhoseTurn = -1 gs.Phase = Phase_Double gs.PhaseIndex = 0 result = 0 } } return result } func (gs *GameScene) isBuyChairWin() bool { if !isValidChair(gs.BuyChair) { return false } return gs.Players[gs.BuyChair].FinalCalcScore >= gs.Players[getNextChair(gs.BuyChair)].FinalCalcScore } func (gs *GameScene) isAllPlayerPass() bool { for i := 0; i < CHAIR_COUNT; i++ { if i == gs.BuyChair { continue } if !gs.Players[i].isBuyPass() { return false } } return true } func (gs *GameScene) isAllCanDoReshufflePlayerPass() bool { for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].CanDoReshuffle { continue } if gs.Players[i].ReshuffleAction != Reshuffle_Pass { return false } } return true } func (gs *GameScene) setFinalSuit() { switch gs.BuyAction { case Action_Buy_Hokum: gs.FinalClub = Suit_Hokum case Action_Buy_Sun: gs.FinalClub = Suit_Sun case Action_Buy_Ashkal: gs.FinalClub = Suit_Ashkal } } func (gs *GameScene) setBaseTimes(buyAction int) { if buyAction < Action_Buy_Double || buyAction > Action_Buy_Four { return } time := buyAction - Action_Buy_Double + 2 if time < 2 { time = 2 } gs.BaseTimes = time if gs.BaseTimes > 4 { gs.BaseTimes = 4 } } func (gs *GameScene) havePlayerConfirmReshuffle(chairId int) bool { for i := 0; i < CHAIR_COUNT; i++ { if chairId == i { continue } if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction == Reshuffle_Confirm { return true } } return false } func (gs *GameScene) canReshuffle(buyAction, chairId int) bool { if buyAction <= Action_Buy_Pass { return false } for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction > Reshuffle_None { return false } } canReshuffle := false for i := 0; i < CHAIR_COUNT; i++ { if i == chairId { continue } if gs.Players[i].needReshuffle() { canReshuffle = true } } return canReshuffle } func (gs *GameScene) isEnterReshuffle(buyAction int) bool { if buyAction <= Action_Buy_Pass { return false } for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction > Reshuffle_None { return false } } canReshuffle := false for i := 0; i < CHAIR_COUNT; i++ { if i == gs.BuyChair { continue } if gs.Players[i].isAllZeroScoreCard() { canReshuffle = true } } if canReshuffle { gs.reshufflePhase = gs.Phase gs.Phase = Phase_Reshuffle gs.PhaseIndex = 0 } return canReshuffle } func (gs *GameScene) isPlayerCanAction() bool { for i := 0; i < CHAIR_COUNT; i++ { if len(gs.Players[i].CanAction) > 0 { return true } } return false } // 0表示继续等待其他人操作,1表示进入选花色或者加倍阶段或者继续买牌二次确认阶段,2表示进入发剩余牌阶段 func (gs *GameScene) resetBuyActionOfNotChangeBuyChair(buyChair, buyAction int) int { result := 0 // 先把做完买牌玩家可做动作清空 gs.Players[buyChair].setPlayerOperators([]int{}) // 已经有人买牌,当前玩家没有抢牌 if buyAction == Action_Buy_Pass { if !gs.isEnterAshkal { if gs.isAllPlayerPass() { for i := 0; i < CHAIR_COUNT; i++ { if i == buyChair { continue } gs.Players[i].setPlayerOperators([]int{}) } if gs.BuyAction == Action_Buy_Hokum { buyList := []int{} buyList = append(buyList, Action_Buy_ConfirmHokum, Action_Buy_SwitchSun) gs.Players[gs.BuyChair].setPlayerOperators(buyList) gs.WhoseTurn = gs.BuyChair result = 1 } else { gs.setFinalSuit() gs.TrumpType = CardType_Invalid result = 2 } } } else { if !gs.isPlayerCanAction() { gs.setFinalSuit() gs.TrumpType = CardType_Invalid result = 2 } } } if buyAction == Action_Buy_ConfirmHokum { result = 1 gs.WhoseTurn = -1 gs.setFinalSuit() if gs.Phase == Phase_SecondBuy { gs.Phase = Phase_ChooseTrump gs.PhaseIndex = 0 gs.WhoseTurn = gs.BuyChair gs.Players[gs.BuyChair].setPlayerOperators([]int{}) return result } gs.TrumpType = getCardType(gs.PublicCard) for i := 0; i < CHAIR_COUNT; i++ { sort.Slice(gs.Players[i].HandCards, func(m, n int) bool { return getCardSortValue(gs.Players[i].HandCards[m], gs.TrumpType) < getCardSortValue(gs.Players[i].HandCards[n], gs.TrumpType) }) buyList := []int{} if isSameTeam(i, gs.BuyChair) { gs.Players[i].setPlayerOperators(buyList) continue } buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double) gs.Players[i].setPlayerOperators(buyList) } gs.initAllPlayerLastAction() gs.Phase = Phase_Double gs.PhaseIndex = 0 } if buyAction == Action_Buy_SwitchSun { for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].setPlayerOperators([]int{}) } gs.BuyAction = Action_Buy_Sun gs.TrumpType = CardType_Invalid gs.setFinalSuit() result = 2 } if result == 2 && gs.FinalClub != Suit_Hokum { if gs.canDoubleInSun() { for i := 0; i < CHAIR_COUNT; i++ { buyList := []int{} if isSameTeam(i, gs.BuyChair) { gs.Players[i].setPlayerOperators(buyList) continue } buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double) gs.Players[i].setPlayerOperators(buyList) } gs.WhoseTurn = -1 gs.Phase = Phase_Double gs.PhaseIndex = 0 result = 1 } } return result } func (gs *GameScene) setNextBanker() { for i := 1; i < CHAIR_COUNT; i++ { next := (gs.Banker + CHAIR_COUNT - i) % CHAIR_COUNT if gs.Players[next].IsValid { gs.Banker = next break } } } // 本圈已出牌人数 func (gs *GameScene) getRoundOutedPlayerCount() int { outedCount := 0 for _, v := range gs.Players { if v.CurrentCard != CARD_COUNT { outedCount++ } } return outedCount } func (gs *GameScene) isRoundEnd() bool { return gs.getRoundOutedPlayerCount() == CHAIR_COUNT } func (gs *GameScene) nextChair() { gs.LastTurn = gs.WhoseTurn gs.WhoseTurn = getPreviousChair(gs.LastTurn) } // 获取本圈玩家出牌 func (gs *GameScene) getRoundCards() []int { ret := make([]int, CHAIR_COUNT) for i := 0; i < CHAIR_COUNT; i++ { ret[i] = gs.Players[i].CurrentCard } return ret } func (gs *GameScene) endAOutCardRound(winner int) int { winScore := 0 for i := 0; i < CHAIR_COUNT; i++ { score := getCardPoint(gs.Players[i].CurrentCard, gs.TrumpType) winScore += score gs.Players[i].CurrentCard = CARD_COUNT gs.Players[i].BigCards = []int{} } gs.Players[winner].winCardScore += winScore for i := 0; i < CHAIR_COUNT; i++ { if isSameTeam(i, winner) { gs.Players[i].addScore(winScore) } else { gs.Players[i].addScore(0) } } gs.Players[winner].WinCardNumber += 4 gs.RoundWinner = winner gs.WhoseTurn = -1 gs.addAction(-1, Action_RoundEnd, gs.RoundType) return winScore } // 本局是否已结束 func (gs *GameScene) isGameEnd() bool { for _, v := range gs.Players { if len(v.HandCards) > 0 { return false } } return true } func (gs *GameScene) newOutCardRound() { gs.RoundIndex++ gs.RoundType = CardType_Invalid if !isValidChair(gs.RoundWinner) { log.Debug("Wrong RoundWinner:%d", gs.RoundWinner) return } if !gs.ShowAllCards { for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].CurrentCard = CARD_COUNT } } else { gs.ShowAllCards = false } if gs.isGameEnd() { gs.LastWinChair = gs.RoundWinner } if gs.RoundIndex == 2 { gs.compareProject() } for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].CallProject = PROJECT_INVALID gs.Players[i].IsCallBiggest = false } gs.LastTurn = -1 gs.WhoseTurn = gs.RoundWinner gs.RoundWinner = CHAIR_COUNT } func (gs *GameScene) checkCanGawah() { handLen := len(gs.Players[gs.WhoseTurn].HandCards) if handLen <= 1 || handLen == 8 { gs.Players[gs.WhoseTurn].CanGawah = false return } gs.Players[gs.WhoseTurn].CanGawah = checkCanGawah(gs.getAllPlayerCards(), gs.WhoseTurn, gs.TrumpType) } func (gs *GameScene) compareProject() { buyProject := []SingleProject{} playerProject := []SingleProject{} for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].CallProject == PROJECT_INVALID || len(gs.Players[i].Projects) == 0 { continue } if isSameTeam(i, gs.BuyChair) { buyProject = append(buyProject, gs.Players[i].Projects[0]) } else { playerProject = append(playerProject, gs.Players[i].Projects[0]) } } if len(buyProject) == 0 || len(playerProject) == 0 { return } // 从大到小排序 sort.Slice(buyProject, func(i, j int) bool { return buyProject[i].isBiggerThan(buyProject[j]) }) sort.Slice(playerProject, func(i, j int) bool { return playerProject[i].isBiggerThan(playerProject[j]) }) isBuyBig := buyProject[0].isBiggerThan(playerProject[0]) for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].CallProject == PROJECT_INVALID { continue } if isSameTeam(i, gs.BuyChair) { if !isBuyBig { gs.Players[i].Projects = []SingleProject{} } } else { if isBuyBig { gs.Players[i].Projects = []SingleProject{} } } } } func (gs *GameScene) gameEnd() { gs.Phase = Phase_GameEnd gs.PhaseIndex = 0 scores := make([]int, CHAIR_COUNT) // 这里计算Buy方和player方得分 buyPoint := 0 playerPoint := 0 for i := 0; i < CHAIR_COUNT; i++ { if isSameTeam(i, gs.BuyChair) { buyPoint += gs.Players[i].getProjectScore() } else { playerPoint += gs.Players[i].getProjectScore() } } if !isValidCard(gs.BuyChair) { log.Debug("Serious Error Buy Chair:%d", gs.BuyChair) return } buyWinCardScore := gs.Players[gs.BuyChair].WinCardScore playerWinCardScore := gs.Players[getNextChair(gs.BuyChair)].WinCardScore buyPoint += gs.Players[gs.BuyChair].WinCardScore playerPoint += gs.Players[getNextChair(gs.BuyChair)].WinCardScore gs.Players[gs.LastWinChair].winCardScore += LAST_WIN_SCORE if isSameTeam(gs.BuyChair, gs.LastWinChair) { buyPoint += LAST_WIN_SCORE buyWinCardScore += LAST_WIN_SCORE } else { playerPoint += LAST_WIN_SCORE playerWinCardScore += LAST_WIN_SCORE } buyAbnat := buyPoint playerAbnat := playerPoint // 如果买的一方输的情况 if (buyPoint == playerPoint && (gs.BaseTimes > 1 || gs.IsBO1)) || buyPoint < playerPoint { playerPoint += buyPoint if gs.Players[gs.BuyChair].WinCardScore == 0 && !gs.isCorrectEnd { playerPoint += ALL_WIN_EXTRA_SCORE } buyPoint = 0 } else { if gs.Players[getNextChair(gs.BuyChair)].WinCardScore == 0 && !gs.isCorrectEnd { buyPoint += ALL_WIN_EXTRA_SCORE playerPoint = 0 } if gs.IsBO1 || gs.BaseTimes > 1 { buyPoint += playerAbnat playerPoint = 0 } } finalBuyPoint := calcFinalPonit(buyPoint) finalPlayerPoint := calcFinalPonit(playerPoint) if gs.FinalClub != Suit_Hokum { finalBuyPoint *= 2 finalPlayerPoint *= 2 if buyWinCardScore%10 == 5 && playerWinCardScore%10 == 5 && buyPoint > 0 && playerPoint > 0 { finalBuyPoint++ finalPlayerPoint++ } } else { if buyWinCardScore%10 == 6 && playerWinCardScore%10 == 6 && buyPoint > 0 && playerPoint > 0 { finalPlayerPoint-- } } finalBuyPoint *= gs.BaseTimes finalPlayerPoint *= gs.BaseTimes for i := 0; i < CHAIR_COUNT; i++ { if isSameTeam(i, gs.BuyChair) { scores[i] = finalBuyPoint } else { scores[i] = finalPlayerPoint } } var scoreData = 0 for i := 0; i < CHAIR_COUNT; i++ { scoreData += int(scores[i]) if i != CHAIR_COUNT-1 { scoreData *= 1000 } } isBuyChairBO1Win := false isPlayerBO1Win := false if gs.IsBO1 { isBuyChairBO1Win = (finalBuyPoint > finalPlayerPoint) if isBuyChairBO1Win { finalPlayerPoint = 0 } else { finalBuyPoint = 0 isPlayerBO1Win = true } } totalTimes := gs.getDoublingTotalTimes() if totalTimes > 1 { gs.currentRoundDoubling = totalTimes } gs.userActions = append(gs.userActions, userAction{ChairId: -1, Action: Action_GameEnd, Data: scoreData}) for i := 0; i < CHAIR_COUNT; i++ { if isSameTeam(i, gs.BuyChair) { gs.Players[i].addEndScore(finalBuyPoint, buyAbnat, isBuyChairBO1Win, SCORE_TO_WIN) if finalBuyPoint >= finalPlayerPoint && totalTimes > 1 { gs.Players[i].addDoublingData(gs.GameIndex, totalTimes) } } else { gs.Players[i].addEndScore(finalPlayerPoint, playerAbnat, isPlayerBO1Win, SCORE_TO_WIN) if finalBuyPoint < finalPlayerPoint && totalTimes > 1 { gs.Players[i].addDoublingData(gs.GameIndex, totalTimes) } } } gs.WhoseTurn = -1 } func (gs *GameScene) getDoublingTotalTimes() int { totalTimes := 1 for n := 0; n < len(gs.DoublingDetails); n++ { totalTimes *= gs.DoublingDetails[n].DoublingTimes } return totalTimes } func (gs *GameScene) isPlayerWinInQuickGame(chairId int) bool { if gs.Players[chairId].FinalCalcScore < gs.Players[getNextChair(chairId)].FinalCalcScore { return false } if gs.Players[chairId].FinalCalcScore == gs.Players[getNextChair(chairId)].FinalCalcScore && !isSameTeam(chairId, gs.BuyChair) { return false } return true } func (gs *GameScene) isFirstOutCardInCloseMode() bool { return gs.FinalClub == Suit_Hokum && gs.RoundType == CardType_Invalid && gs.IsClose } func (gs *GameScene) isGameFinish() bool { if gs.IsBO1 && gs.ScoreToWin > 0 { return true } // ScoreToWin小于0表示大多少局结束 if gs.ScoreToWin < 0 { if (gs.ScoreToWin + gs.GameIndex) >= -1 { return true } } else { for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].getTotalScore() >= gs.ScoreToWin && gs.Players[i].getTotalScore() != gs.Players[getNextChair(i)].getTotalScore() { return true } } } return false } // 如果已经要结算了,在返回FALSE func (gs *GameScene) nextGame(isSurrenderFinish bool) bool { if isSurrenderFinish { return false } gs.GameIndex++ if gs.IsBO1 && gs.ScoreToWin > 0 { return false } // ScoreToWin小于0表示大多少局结束 if gs.ScoreToWin < 0 { if (gs.ScoreToWin + gs.GameIndex) >= 0 { return false } } else { for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].getTotalScore() >= gs.ScoreToWin && gs.Players[i].getTotalScore() != gs.Players[getNextChair(i)].getTotalScore() { return false } } } gs.setNextBanker() gs.gameInit(getPreviousChair(gs.Banker)) return true } func (gs *GameScene) getWinner() []int { var ret []int var biggestScore int = -10000 biggestChair := CHAIR_COUNT for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].IsValid { continue } chairScore := gs.Players[i].getTotalScore() if biggestChair == CHAIR_COUNT || chairScore > biggestScore { biggestChair = i biggestScore = chairScore } } for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].IsValid { continue } if gs.Players[i].getTotalScore() == biggestScore { ret = append(ret, i) } } if len(ret) == CHAIR_COUNT { ret = []int{} for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].IsValid { continue } if isSameTeam(i, gs.BuyChair) { ret = append(ret, i) } } } return ret } func (gs *GameScene) pointsToEndScore() { for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].IsValid { continue } gs.Players[i].pointsToEndScore() } } func (gs *GameScene) initMaxDoubling(isDoublingMode bool) { if !isDoublingMode || gs.Players[0].enterGold == 0 || gs.Players[0].bet == 0 { return } maxTimes := gs.Players[0].enterGold / gs.Players[0].bet for i := 1; i < CHAIR_COUNT; i++ { times := gs.Players[i].enterGold / gs.Players[i].bet if maxTimes > times { maxTimes = times } } gs.maxDoublingTime = maxTimes } func (gs *GameScene) getTotalBet(winner int) int { ret := 0 baseTimes := 0 for n := 0; n < len(gs.Players[winner].Doublings); n++ { baseTimes += gs.Players[winner].Doublings[n].DoublingTotalTimes } if baseTimes > gs.maxDoublingTime && gs.maxDoublingTime != -1 { baseTimes = gs.maxDoublingTime } for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].IsValid { continue } playerBet := gs.Players[i].bet if baseTimes > 0 && !isSameTeam(winner, i) { playerBet *= baseTimes gs.Players[i].EndScore = gs.Players[i].bet - playerBet } ret += playerBet } return ret } func (gs *GameScene) getValidUserCount() int { ret := 0 for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].IsValid { ret++ } } return ret } func (gs *GameScene) getUserCount() int { ret := 0 for i := 0; i < CHAIR_COUNT; i++ { if !gs.Players[i].isRobot { ret++ } } return ret } func (gs *GameScene) getControlRobot() int { team1RobotCount := 0 team2RobotCount := 0 for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].isRobot && isSameTeam(i, 0) { team1RobotCount++ } if gs.Players[i].isRobot && isSameTeam(i, 1) { team2RobotCount++ } } if team1RobotCount == team2RobotCount { return -1 } controlRobot := -1 if team1RobotCount > team2RobotCount { for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].isRobot && isSameTeam(i, 0) { controlRobot = i break } } } else { for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].isRobot && isSameTeam(i, 1) { controlRobot = i break } } } return controlRobot } func (gs *GameScene) dump(includeAction bool) { log.Debug("====GameScene Table[%d] Index[%d] GameIndex[%d] ScoreToWin[%d]====", gs.tableId, gs.Index, gs.GameIndex, gs.ScoreToWin) log.Debug(" Phase[%s],PhaseIndex[%d],BuyChair[%d], WhoseTurn[%d],LastTurn[%d],Banker[%d],FirstActionChair[%d]", getPhaseDesc(gs.Phase), gs.PhaseIndex, gs.BuyChair, gs.WhoseTurn, gs.LastTurn, gs.Banker, gs.FirstActionChair) log.Debug(" BuyAction[%d],FinalClub[%s],RoundType[%d],RoundIndex[%d], RoundWinner[%d]", gs.BuyAction, getSuitDesc(gs.FinalClub), gs.RoundType, gs.RoundIndex, gs.RoundWinner) log.Debug(" PublicCard[%s],BaseTimes[%d],TrumpType[%d],IsBO1[%v],IsClose[%v], ShowAllCards[%v], LastWinChair[%d]", getCardHex(gs.PublicCard), gs.BaseTimes, gs.TrumpType, gs.IsBO1, gs.IsClose, gs.ShowAllCards, gs.LastWinChair) log.Debug(" reshuffleResult[%d], reshufflePhase[%d]", gs.reshuffleResult, gs.reshufflePhase) log.Debug(" isCorrectEnd[%v], isEnterAshkal[%v]", gs.isCorrectEnd, gs.isEnterAshkal) log.Debug(" GameOutCardHistory%s", getCardsHex(gs.GameOutCardHistory)) log.Debug(" CorrectMode[%s], SawaChair[%d], CorrectResult[%d], CorrectCards%s, CorrectType[%s], CanCorrect[%v]", getCorrectModeDesc(gs.CorrectMode), gs.SawaChair, gs.CorrectResult, getCardsHex(gs.CorrectCards), getCorrectTypeDesc(gs.CorrectType), gs.CanCorrect) log.Debug(" doublingDetails:") for n := 0; n < len(gs.DoublingDetails); n++ { gs.DoublingDetails[n].dump() } log.Debug(" Users:%d", gs.getValidUserCount()) for i := 0; i < CHAIR_COUNT; i++ { gs.Players[i].dump(i) } if includeAction && len(gs.userActions) > 0 { log.Debug(" Actions:%d", len(gs.userActions)) for _, v := range gs.userActions { v.dump() } } log.Debug("---------------------------") } func (gs *GameScene) getPlayerLadderInfo() string { type GameUserLadderInfo struct { UserID int LadderInfo ladder.UserLadderInfo } var ret []GameUserLadderInfo for i := 0; i < CHAIR_COUNT; i++ { if gs.Players[i].userID == 0 { continue } ret = append(ret, GameUserLadderInfo{ UserID: gs.Players[i].userID, LadderInfo: gs.Players[i].LadderInfo, }) } d, _ := json.Marshal(ret) return string(d) } func (gs *GameScene) getCopy() GameScene { var ret GameScene d, _ := json.Marshal(gs) json.Unmarshal(d, &ret) return ret } func (gs *GameScene) getScene(chairId int, isPlayer bool, isOwnerWatCh bool) string { tmp := gs.getCopy() if gs.Phase == Phase_GameEnd && gs.ScoreToWin < -1 && (gs.ScoreToWin+gs.GameIndex) < -1 && config.Server.IsLadderRoom == 1 { tmp.Phase = Phase_End } if isOwnerWatCh { /*for i := 0; i < CHAIR_COUNT; i++ { tmp.Players[i].hideSecretData() }*/ d, _ := json.Marshal(tmp) return string(d) } for i := 0; i < CHAIR_COUNT; i++ { if gs.Phase == Phase_End || gs.Phase == Phase_GameEnd { continue } if gs.ShowAllCards { continue } if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction == Reshuffle_Confirm && gs.Phase == Phase_Reshuffle { continue } if chairId == i { continue } tmp.Players[i].hideSecretData() tmp.Players[i].ProjectTips = []int{0, 0, 0, 0} } d, _ := json.Marshal(tmp) return string(d) } func (gs *GameScene) getAllPlayerCards() [][]int { var ret [][]int for i := 0; i < CHAIR_COUNT; i++ { ret = append(ret, gs.Players[i].HandCards) } return ret } func (gs *GameScene) onAllCardsSent() { // 插入所有玩家的牌 for i := 0; i < CHAIR_COUNT; i++ { cardList := make([]int, len(gs.Players[i].HandCards)) copy(cardList, gs.Players[i].HandCards) gs.userActions = append(gs.userActions, userAction{ ChairId: i, Action: Action_RoundStart, Data: 0, ExtData: cardList, }) } } func (gs *GameScene) getLeftScore() int { leftScore := 0 if gs.FinalClub == Suit_Hokum { leftScore = HOKUM_TOTAL_SCORE - gs.Players[0].WinCardScore - gs.Players[1].WinCardScore } else { leftScore = SUN_TOTAL_SCORE - gs.Players[0].WinCardScore - gs.Players[1].WinCardScore } return leftScore } func (gs *GameScene) getLeftCardNumber() int { leftCard := CARD_COUNT for i := 0; i < CHAIR_COUNT; i++ { leftCard -= gs.Players[i].WinCardNumber } return leftCard }