package gamelogic import ( "encoding/json" "fmt" "math" "math/rand" "time" coreservice "bet24.com/servers/coreservice/client" "bet24.com/servers/games/quickludo/config" robotmanager "bet24.com/servers/insecureframe/robot" waterpool "bet24.com/servers/micros/waterpool/proto" "bet24.com/servers/user" ) func (ts *tablesink) checkAndStartGame() { if ts.gameScene.Phase != Phase_Free && ts.gameScene.Phase != Phase_End { return } // 查看是否所有人都ready readyCount := 0 for i := 0; i < CHAIR_COUNT; i++ { usr := ts.table.GetUserByChair(i) if usr == nil { continue } userStatus := usr.GetUserStatus() // 旁观不判断 if userStatus <= user.UserStatus_Free || userStatus == user.UserStatus_Watch { continue } // 如果是开始 if userStatus == user.UserStatus_Play { ts.table.LogWithTableId("-----checkAndStartGame: chair[%d]: %d, playing kicked", i, usr.GetUserId()) //ts.table.KickUserByChair(i, true) continue } if userStatus != user.UserStatus_Ready { ts.table.LogWithTableId("-----checkAndStartGame: chair[%d]: %d, status: %d", i, usr.GetUserId(), usr.GetUserStatus()) return } readyCount++ } ts.table.LogWithTableId("-----checkAndStartGame IsDual:%v readyCount:%d ", ts.IsDual(), readyCount) if (ts.IsDual() && readyCount == 2) || (!ts.IsDual() && readyCount == 4) { ts.startGame() } } func (ts *tablesink) checkIsNeedRobot() { if !robotmanager.IsRunning() { return } //私人场不补机器人 if ts.table.IsPrivate() { return } if ts.gameScene.Phase != Phase_Free && ts.gameScene.Phase != Phase_End { return } count := 0 for i := 0; i < CHAIR_COUNT; i++ { usr := ts.table.GetUserByChair(i) if usr == nil { continue } /*if usr.IsRobot() { continue }*/ if usr.GetUserStatus() <= user.UserStatus_Free { continue } count++ } chairCount := CHAIR_COUNT if ts.IsDual() { chairCount = 2 } if count >= chairCount { return } robotCount := 1 if !ts.IsDual() { robotCount = rand.Intn(chairCount-count) + 1 } ts.table.LogWithTableId("-------checkIsNeedRobot. need: %d ------", robotCount) for i := 0; i < robotCount; i++ { sec := rand.Intn(robotCount*3*1000) + 1000 time.AfterFunc(time.Duration(sec)*time.Millisecond, func() { if ts.gameScene.Phase != Phase_Free && ts.gameScene.Phase != Phase_End { return } tableID := ts.table.GetTableID() robotmanager.GetOneRobotEnterTable(tableID, ts.roomInfo.MinGold, ts.roomInfo.MaxGold) }) } } func (ts *tablesink) removeOneRobot() { if ts.gameScene.Phase != Phase_End { return } for i := 0; i < CHAIR_COUNT; i++ { usr := ts.table.GetUserByChair(i) if usr == nil { continue } if !usr.IsRobot() { continue } ts.table.KickUserByChair(i, false) return } } func (ts *tablesink) checkUserReadyStatus(chair int) { if ts.gameScene.Phase != Phase_Free && ts.gameScene.Phase != Phase_End { return } usr := ts.table.GetUserByChair(chair) if usr == nil { return } if !usr.IsRobot() { ts.table.LogWithTableId("1111111------checkUserReadyStatus: %d %d", chair, usr.GetUserId()) //超时没有准备则踢出 ts.table.KickUserByChair(chair, true) return } //桌上还有没有真人,有就准备,没有就踢走 count := 0 for i := 0; i < CHAIR_COUNT; i++ { u := ts.table.GetUserByChair(i) if u == nil { continue } if u.IsRobot() { continue } if u.GetUserStatus() <= user.UserStatus_Free { continue } count++ } //只要有一个真人在就准备 if count >= 1 { ts.table.LogWithTableId("tablesink.checkUserReadyStatus: %d robot to ready ", usr.GetUserId()) ts.table.SetUserReadyStatus(usr.GetUserIndex(), true) } else { ts.table.LogWithTableId("------checkUserReadyStatus: %d ", usr.GetUserId()) //超时没有准备则踢出 ts.table.KickUser(usr.GetUserIndex(), !usr.IsRobot()) // if usr.IsRobot() { // //ts.table.UserWatch(usr.GetUserIndex()) // ts.table.KickUser(usr.GetUserIndex(), false) // } else { // ts.table.UserWatch(usr.GetUserIndex()) // } } } func (ts *tablesink) checkUserQuitStatus(chair int) { if ts.gameScene.Phase != Phase_End { return } usr := ts.table.GetUserByChair(chair) if usr == nil { return } if usr.IsRobot() { ts.table.KillTimer(TIMER_QUIT_0 + chair) ts.table.KillTimer(TIMER_READY_0 + chair) ts.table.KickUser(usr.GetUserIndex(), !usr.IsRobot()) return } } // 匹配阶段超时 func (ts *tablesink) dealMatchTimeOut() { ts.gameScene.Phase = Phase_Move ts.LastOpraTime = time.Now() ts.gameScene.Index++ ts.table.NotifySceneChanged(-1) ts.resetGameTimer(false, false, 0) } // 移动棋子或掷骰子 阶段超时 func (ts *tablesink) dealPlayTimeOut() { if ts.gameScene.Phase != Phase_Dice && ts.gameScene.Phase != Phase_Move { return } if isValidChair(ts.gameScene.WhoseTurn) { ts.gameScene.Players[ts.gameScene.WhoseTurn].AutoOut = true } ts.dealGamePlay() } // 处理游戏阶段逻辑 包含掷骰子和移动飞机 func (ts *tablesink) dealGamePlay() { ts.LastOpraTime = time.Now() chairId := ts.gameScene.WhoseTurn if !isValidChair(chairId) { ts.table.LogWithTableId("tablesink.dealGamePlay whoseturn invalid %d", chairId) return } player := ts.gameScene.Players[chairId] // 掷骰子 if player.LastAction == Action_Move { ts.doAction(chairId, Action_Dice, 0, nil) } else { ts.doAction(chairId, Action_Move, -1, nil) } } func (ts *tablesink) onRobotChatTimer() { start := rand.Intn(4) for i := 0; i < CHAIR_COUNT; i++ { chair := (start + i) % CHAIR_COUNT usr := ts.table.GetUserByChair(chair) if usr == nil || !usr.IsRobot() { continue } whoseturn := ts.table.GetUserByChair(ts.gameScene.WhoseTurn) if whoseturn == nil { return } ts.sendBatChat(usr.GetUserIndex(), usr.GetUserId(), whoseturn.GetUserId()) return } } func (ts *tablesink) sendBatChat(userIndex int32, sender, receiver int) { if sender == receiver { return } if rand.Intn(100) >= 35 { return } chatIds := []int{0, 4, 10, 11} chatId := chatIds[rand.Intn(4)] data := fmt.Sprintf("3/%d/%d/%d", chatId, sender, receiver) ts.table.LogWithTableId("tablesink.sendBatChat ,%s", data) ts.recvChatMsg(userIndex, data) } // 检查机器人操作 func (ts *tablesink) checkRobotAction(isCanMove, isNextChair bool, moveDuration int) { chairId := ts.gameScene.WhoseTurn usr := ts.table.GetUserByChair(chairId) if usr == nil { return } if !usr.IsRobot() { return } //机器人也要考虑延迟问题 否则会导致前端收消息过快 delay := SEC_DELAY //掷骰子时间 机器人用等待时间 switch ts.gameScene.Phase { case Phase_Dice: //如果没有可以移动的则直接进入掷骰子阶段的定时间 if isNextChair && !isCanMove { //没有移动直接换人 加延迟 delay += SEC_NEXT_CHAIR } else if isCanMove { //移动棋子时间 delay -= SEC_NEXT_CHAIR //机器人要判断是否只有一个棋子可以移动 count := ts.gameScene.Players[chairId].canMovePlaneCountByPosition() if count != 1 { //有多个棋子时增加选择时间 delay += rand.Intn(2500) } } case Phase_Move: //前一个有移动的话 要算上移动的等待时间 if isCanMove { delay += moveDuration } } time.AfterFunc(time.Duration(delay)*time.Millisecond, func() { ts.dealGamePlay() }) } func (ts *tablesink) startGame() { // 创建场景 tableId := ts.table.GetTableID() ts.gameScene.initData(tableId) ts.gameScene.base = ts.roomInfo.BaseScore validChairs := []int{} for i := 0; i < CHAIR_COUNT; i++ { usr := ts.table.GetUserByChair(i) if usr == nil { continue } userStatus := usr.GetUserStatus() if userStatus != user.UserStatus_Ready { ts.table.LogWithTableId("ts.startGame chair[%d] userStatue = %d", i, userStatus) if usr.IsRobot() { go ts.table.KickUser(usr.GetUserIndex(), false) } return } userGold := ts.table.GetUserChipOrGoldByUser(usr) if userGold < ts.roomInfo.MinGold || (ts.roomInfo.MaxGold > 0 && userGold > ts.roomInfo.MaxGold) { ts.table.LogWithTableId("tablesink.startGame %d 金币不足, 站起", usr.GetUserId()) if usr.IsRobot() { go ts.table.KickUser(usr.GetUserIndex(), false) } else { go ts.table.UserWatch(usr.GetUserIndex()) } break } // 先投注 ok := ts.writeScore(usr.GetUserId(), -ts.roomInfo.BaseScore, 0, 0, ScoreType_Bet, ts.roomInfo.RoomName, usr.IsRobot()) if !ok { break } ts.gameScene.Players[i].initData(i, usr.GetUserId(), userGold) ts.gameScene.Players[i].IsValid = true ts.gameScene.Players[i].userId = usr.GetUserId() ts.gameScene.Players[i].bet = ts.roomInfo.BaseScore ts.gameScene.Players[i].isRobot = usr.IsRobot() ts.gameScene.pool += ts.roomInfo.BaseScore validChairs = append(validChairs, i) } readyCount := len(validChairs) if (ts.IsDual() && readyCount != 2) || (!ts.IsDual() && readyCount < CHAIR_COUNT) { ts.table.LogWithTableId("游戏开始,用户不足") ts.gameScene.Phase = Phase_End // 分数还原 for i := 0; i < CHAIR_COUNT; i++ { if !ts.gameScene.Players[i].IsValid { continue } if ts.gameScene.Players[i].bet > 0 { ts.writeScore(ts.gameScene.Players[i].userId, ts.gameScene.Players[i].bet, 0, 0, ScoreType_Return, ts.roomInfo.RoomName, ts.gameScene.Players[i].isRobot) } } ts.endGame() ts.gameScene.initData(tableId) return } ts.gameScene.gameInit(validChairs[rand.Intn(len(validChairs))]) ts.sendMatchEnd() ts.gameScene.dump(false) ts.table.StartGame() } // 发送匹配结束 func (ts *tablesink) sendMatchEnd() { //发送匹配结束 ts.gameScene.Phase = Phase_Match ts.table.SetTimer(TIMER_MATCH, SEC_MATCH) ts.table.KillTimer(TIMER_ROBOT) } func (ts *tablesink) endGame() { ts.table.LogWithTableId("--------endGame-----------") ts.gameScene.dump(true) ts.gameScene.Index = 0 ts.table.KillAllTimer() if ts.table.IsPrivate() { // ts.table.SetTimer(TIMER_DELAY_END, 1000) // 私人场,不继续下一把 //if ts.roomInfo.BaseScore == 0 { //ts.gameScene.pointsToEndScore() //} return } // 先调用框架的EngGame,保证旁观用户状态改变 ts.table.EndGame() realUserCount := 0 robotCount := 0 for i := 0; i < CHAIR_COUNT; i++ { usr := ts.table.GetUserByChair(i) if usr == nil { continue } // 机器人,随机3-5秒准备 if !usr.IsRobot() { ts.table.SetTimer(TIMER_READY_0+i, SEC_READY) realUserCount++ } else { ts.table.SetTimer(TIMER_READY_0+i, 100) robotCount++ } } if (ts.IsDual() && realUserCount >= 1 && robotCount > 0) || !ts.IsDual() && realUserCount >= 3 && robotCount > 0 { ts.table.SetTimer(TIMER_REMOVE_ROBOT, 6000+rand.Intn(3000)) } } // 聊天 func (ts *tablesink) recvChatMsg(userIndex int32, data string) { usr := ts.table.GetPlayer(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.recvChatMsg,usr[%d] not exist", userIndex) return } ts.table.SendGameData(-1, CMD_TABLECHAT, data) } // 取消托管消息 func (ts *tablesink) recvCancleAutoMsg(userIndex int32, data string) { usr := ts.table.GetPlayer(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.recvCancleAutoMsg,usr[%d] not exist", userIndex) return } chairId := usr.GetUserChairId() if chairId == -1 { return } ts.gameScene.Players[chairId].AutoOut = false // 重启倒计时 if ts.gameScene.WhoseTurn != chairId { return } ts.table.KillTimer(TIMER_GAME) switch ts.gameScene.Phase { case Phase_Dice: ts.table.SetTimer(TIMER_GAME, ts.GetMoveSec()) return case Phase_Move: ts.table.SetTimer(TIMER_GAME, ts.GetDiceSec()) return } } // 操作掷骰子或者移动飞机 func (ts *tablesink) recvAction(userIndex int32, data string) { if ts.gameScene.Phase != Phase_Dice && ts.gameScene.Phase != Phase_Move { ts.table.LogWithTableId("tablesink.recvAction,phase is wrong! %d ", ts.gameScene.Phase) return } usr := ts.table.GetPlayer(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.recvAction,usr[%d] not exist", userIndex) return } chairId := usr.GetUserChairId() if !isValidChair(chairId) { ts.table.LogWithTableId("tablesink.recvAction invalid chair %d", chairId) return } var action CmdAction err := json.Unmarshal([]byte(data), &action) if err != nil { ts.table.LogWithTableId("tablesink.recvAction,Unmarshal failed[%d] %s", userIndex, data) return } if action.Action == Action_Drop { ts.table.LogWithTableId("tablesink.recvAction,dealDrop[%d] %s", userIndex, data) ts.dealDrop(chairId) return } ts.doAction(chairId, action.Action, action.PlaneId, usr) } // 获得骰子点数 func (ts *tablesink) getDicePoint(chairId int, isRobot bool) int { number := 0 round := ts.gameScene.Players[chairId].round hopeRound := ts.gameScene.Players[chairId].hopeRound hope := ts.gameScene.Players[chairId].hope if isRobot { //如果是机器人出点的时候 检查是否有可以攻击的对手 rnd := rand.Intn(100) points := []int{1, 2, 3, 4, 5, 6} if rnd <= config.Rooms.GetParam1(ts.roomInfo.RoomID) { //检查前方是否有非机器人棋子 for _, v := range ts.gameScene.Players[chairId].Planes { //没有出机场或者已经到终点和快到终点的过滤 if v.Position == 0 || v.Position == MAX_STEP || v.Position >= SAFE_START { continue } for _, p := range points { //可以攻击优先 total, _, _ := ts.gameScene.checkPositionIsCrashed(chairId, v.Position+p, v.Id) if total == 1 { number = 6 if p < 6 { number = p } if number == hope { ts.gameScene.Players[chairId].isShakeOutHope = true } return number } } } } } //每过4轮检查一次期待点数 if hopeRound%4 == 0 { if !ts.gameScene.Players[chairId].isShakeOutHope { //如果3轮内没有出过 则必出期待点 number = hope ts.gameScene.Players[chairId].isShakeOutHope = true return number } ts.gameScene.Players[chairId].isShakeOutHope = false } //随机取 number = ts.getRandomNumber(round) if ts.IsDual() && !isRobot { //如果是两人场 减少机器人被攻击的可能性 rnd := rand.Intn(100) if rnd <= config.Rooms.GetParam1(ts.roomInfo.RoomID) { //可以攻击 则替换点数 unAttackPoint := ts.gameScene.getUnAttackPoint(chairId) if len(unAttackPoint) > 0 { number = unAttackPoint[rand.Intn(len(unAttackPoint))] } } } else if ts.IsDual() && isRobot && number < 3 && ts.gameScene.checkIsBehind(chairId) { //从3,4,5,6中随机取一个 number = rand.Intn(4) + 3 } if number == hope { ts.gameScene.Players[chairId].isShakeOutHope = true } return number } func (ts *tablesink) doAction(chairId, action, planeId int, usr *user.UserInfo) { isRobot := ts.isRobot(chairId) number := 0 if action == Action_Dice { ts.gameScene.Players[chairId].round++ ts.gameScene.Players[chairId].hopeRound++ number = ts.getDicePoint(chairId, isRobot) //ts.sendWinChat(usr.GetUserIndex(), usr.GetUserId(), 2000+rand.Intn(2000)) } ok, errMsg, isNextChair, stepCount := ts.gameScene.addAction(chairId, action, number, planeId, isRobot) if !ok { if usr != nil { ts.table.SendGameData(usr.GetUserIndex(), CMD_ACTION, errMsg) } return } ts.table.KillTimer(TIMER_GAME) if ts.gameScene.Players[chairId].isWin() { ts.checkAndEndGame(chairId, stepCount) return } isCanMove := true moveDuration := 0 if isNextChair { ts.gameScene.nextChair() //如果切换玩家并且前一个玩家是移动棋子则需要增加延迟 if action == Action_Dice { isCanMove = false } } if action == Action_Move { ts.gameScene.Phase = Phase_Move moveDuration = stepCount * SEC_MOVE_TIME if ts.gameScene.ActionResult.CrashedChairId >= 0 && ts.gameScene.ActionResult.CrashedPlaneId >= 0 { //有攻击则增加时间 moveDuration += SEC_DELAY } } else { ts.gameScene.Phase = Phase_Dice } ts.gameScene.Index++ ts.table.NotifySceneChanged(-1) ts.resetGameTimer(isCanMove, isNextChair, moveDuration) } // 重置游戏计时器 func (ts *tablesink) resetGameTimer(isCanMove, isNextChair bool, moveDuration int) { ts.table.KillTimer(TIMER_GAME) ts.table.KillTimer(TIMER_ROBOT) if !isValidChair(ts.gameScene.WhoseTurn) { return } switch ts.gameScene.Phase { case Phase_Dice: if ts.gameScene.Players[ts.gameScene.WhoseTurn].AutoOut { times := SEC_AUTO if isNextChair && !isCanMove { //没有移动直接换人 加延迟 times += SEC_NEXT_CHAIR } else if isCanMove { times = SEC_AUTO + SEC_DELAY } ts.table.SetTimer(TIMER_GAME, times) } else { //如果没有可以移动的则直接进入掷骰子阶段的定时间 times := ts.GetDiceSec() if isNextChair && !isCanMove { //没有移动直接换人 加延迟 times += SEC_NEXT_CHAIR } else if isCanMove { times = ts.GetMoveSec() + SEC_DELAY } ts.table.SetTimer(TIMER_GAME, times) } case Phase_Move: if ts.gameScene.WhoseTurn != -1 && ts.gameScene.Players[ts.gameScene.WhoseTurn].AutoOut { //移动棋子时间要长一些 times := SEC_AUTO if isCanMove { times += moveDuration } ts.table.SetTimer(TIMER_GAME, times) } else { //前一个有移动的话 要算上移动的等待时间 times := ts.GetDiceSec() if isCanMove { times += moveDuration } ts.table.SetTimer(TIMER_GAME, times) } } ts.table.SetTimer(TIMER_ROBOT, SEC_ROBOT_CHAT) ts.LastOpraTime = time.Now() ts.checkRobotAction(isCanMove, isNextChair, moveDuration) } func (ts *tablesink) checkAndEndGame(winner, stepCount int) { _, ended := ts.gameScene.addWinner(winner) if ended { // 结束了,把没写分的都写分 for i := 0; i < CHAIR_COUNT; i++ { ts.writeChairScore(i) } //私人房上报获胜玩家,这个游戏只会有一个玩家获胜 if ts.table.IsPrivate() { winnerUsers := make([]int, 1) for i := 0; i < 1; i++ { winnerUsers[i] = ts.gameScene.Players[winner].userId } ts.table.PrivateRoomSetWinners(winnerUsers) } ts.enterEndPhase() } else { // 没有结束,先写分 ts.writeChairScore(winner) ts.table.SetUserEndGame(winner) ts.gameScene.Players[winner].IsValid = false ts.gameScene.Index++ ts.gameScene.nextChair() ts.table.NotifySceneChanged(-1) //额外增加播放旗子动画 moveDuration := stepCount*SEC_MOVE_TIME + SEC_DELAY*2 ts.resetGameTimer(true, true, moveDuration) } } func (ts *tablesink) writeChairScore(chairId int) { if !ts.gameScene.Players[chairId].IsValid { return } if ts.gameScene.Players[chairId].writtenScore { return } player := &ts.gameScene.Players[chairId] if player.Dropped { return } score := ts.gameScene.Players[chairId].Score if score <= 0 { ts.gameScene.Players[chairId].Score = -ts.roomInfo.BaseScore ts.writeScore(player.userId, 0, 0, 1, ScoreType_End, ts.roomInfo.RoomName, ts.isRobot(chairId)) ts.writeExpScore(chairId) go ts.table.WriteBetRecord(player.userId, ts.roomInfo.BaseScore, 0, 1.0, "lose", "lose", GAME_NAME) player.writtenScore = true usr := ts.table.GetUserByChair(chairId) if usr != nil { go ts.table.RequestADAward(usr.GetUserIndex(), -ts.roomInfo.BaseScore) } return } tax := (score - ts.roomInfo.BaseScore) * ts.roomInfo.RoomInfoBase.TaxRate / 100 ts.writeScore(player.userId, score-tax, tax, 1, ScoreType_End, ts.roomInfo.RoomName, ts.isRobot(chairId)) ts.writeExpScore(chairId) go ts.table.WriteBetRecord(player.userId, ts.roomInfo.BaseScore, score-tax, 1.0, "win", fmt.Sprintf("win[%d]", player.Place), GAME_NAME) player.writtenScore = true } // 写经验分数 func (ts *tablesink) writeExpScore(chairId int) { if !ts.table.IsPrivate() && ts.roomInfo.LevelParam >= 100 { exp := 400 if ts.gameScene.Players[chairId].Score <= 0 { exp = 200 } value := (ts.roomInfo.LevelParam * exp) / 100 value = ts.table.AddExperience(ts.gameScene.Players[chairId].userId, value) ts.gameScene.Players[chairId].LevelValue = value } } func (ts *tablesink) enterEndPhase() { ts.gameScene.Phase = Phase_End ts.gameScene.WhoseTurn = -1 ts.gameScene.Index++ ts.table.NotifySceneChanged(-1) ts.endGame() ts.gameScene.initData(ts.table.GetTableID()) } func (ts *tablesink) writeScore(userId int, amount, tax int, status, scoreType int, sourceName string, isRobot bool) bool { if !isRobot { config.Rooms.AddWinAmount(ts.roomInfo.RoomID, -amount) } if config.Server.LoseTax > 0 && scoreType == ScoreType_End { if amount > 0 && tax > 0 { go coreservice.ModifyJackpot(tax/10, GAMEID, userId, GAME_NAME, config.Server.IsChipRoom > 0) tax = 0 } else { // 如果是退出、放弃,则加税 score := ts.gameScene.getScore(userId) if score < 0 { tax = int(math.Abs(float64(score))) * ts.roomInfo.RoomInfoBase.TaxRate / 100 } } } ok, _ := ts.table.WriteUserMoney(userId, amount, tax, status, scoreType, sourceName) if ok && !isRobot { waterpool.ReduceInventoryValue(GAMEID, ts.roomInfo.RoomName, amount, waterpool.RoomType_Normal) } return ok } func (ts *tablesink) isRobot(chairId int) bool { usr := ts.table.GetUserByChair(chairId) if usr == nil { return false } return usr.IsRobot() } func (ts *tablesink) dealDrop(chairId int) bool { ts.table.LogWithTableId("tablesink.dealDrop 用户弃权 chairId:%d Players:%v", chairId, ts.gameScene.Players[chairId]) if !isValidChair(chairId) { ts.table.LogWithTableId("tablesink.dealDrop invalid ChairId %d", chairId) return false } if !ts.gameScene.Players[chairId].IsValid { ts.table.LogWithTableId("tablesink.dealDrop invalid ChairId2 %d", chairId) return false } if ts.gameScene.Players[chairId].Place > 0 { ts.table.LogWithTableId("tablesink.dealDrop Winning users cannot dropped %d", chairId) return false } if ts.gameScene.Players[chairId].Dropped { ts.table.LogWithTableId("tablesink.dealDrop already dropped %d", chairId) return false } ts.gameScene.Index++ ts.gameScene.Players[chairId].drop() ts.gameScene.Players[chairId].LastAction = Action_Drop // 如果没人了,结算并写分 validPlayerCount := 0 winner := -1 //获胜者 for i := 0; i < CHAIR_COUNT; i++ { if !ts.gameScene.Players[i].IsValid { continue } if ts.gameScene.Players[i].Dropped { continue } validPlayerCount++ winner = i } usr := ts.table.GetUserByChair(chairId) ts.gameScene.Players[chairId].Score = -ts.roomInfo.BaseScore if ts.gameScene.Players[chairId].Score+ts.gameScene.Players[chairId].enterGold < 0 { ts.table.LogWithTableId("tablesink.dealDrop 分数不够扣 %d %d", ts.gameScene.Players[chairId].Score, ts.gameScene.Players[chairId].enterGold) ts.gameScene.Players[chairId].Score = -ts.gameScene.Players[chairId].enterGold } //逃跑也写分 ts.writeScore(usr.GetUserId(), 0, 0, 1, ScoreType_End, ts.roomInfo.RoomName, ts.isRobot(chairId)) go ts.table.WriteBetRecord(ts.gameScene.Players[chairId].userId, ts.roomInfo.BaseScore, 0, 1.0, "drop", "drop", GAME_NAME) if usr != nil { go ts.table.RequestADAward(usr.GetUserIndex(), -ts.roomInfo.BaseScore) } ts.table.SetUserEndGame(chairId) ts.gameScene.Players[chairId].gameInit() ts.broadcastDrop(chairId) //广播弃权消息滞后避免广播弃权消息时,用户已经退出 if validPlayerCount <= 1 { ts.gameScene.LastTurn = chairId ts.checkAndEndGame(winner, 0) return true } // 其他人还能继续 if ts.gameScene.WhoseTurn == chairId { ts.gameScene.nextChair() ts.resetGameTimer(true, true, 0) ts.table.NotifySceneChanged(-1) } return true } func (ts *tablesink) broadcastDrop(chairId int) { var cmd CmdDrop cmd.ChairId = chairId d, _ := json.Marshal(cmd) ts.table.SendGameData(-1, CMD_DROP, string(d)) }