785 lines
19 KiB
Go
785 lines
19 KiB
Go
package chesstitians
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"sort"
|
||
"strings"
|
||
"time"
|
||
|
||
"mongo.games.com/goserver/core/logger"
|
||
|
||
"mongo.games.com/game/common"
|
||
rule "mongo.games.com/game/gamerule/chess"
|
||
"mongo.games.com/game/gamesrv/base"
|
||
"mongo.games.com/game/model"
|
||
"mongo.games.com/game/proto"
|
||
"mongo.games.com/game/protocol/chesstitians"
|
||
"mongo.games.com/game/protocol/server"
|
||
"mongo.games.com/game/srvdata"
|
||
)
|
||
|
||
// SceneEx 房间上的额外数据
|
||
type SceneEx struct {
|
||
*base.Scene // 场景
|
||
players map[int32]*PlayerEx // 玩家信息
|
||
seats [rule.MaxNumOfPlayer]*PlayerEx // 玩家
|
||
opPos int // 当前等待出牌的玩家位置
|
||
winSnId int32 // 赢家id
|
||
masterSnId int32 // 房主
|
||
isAllRob bool // 是否是纯AI场
|
||
chess rule.Logic // 棋盘对象
|
||
lastMove []int32 // 上一步的行动
|
||
variant int // 棋类变种 对应fairy-stockfish
|
||
stepSnId int32 // 计步玩家SnId
|
||
stepNum int // 计步回合数
|
||
stepLimit int // 计步最大回合数
|
||
stepKing int // 孤王计步回合数
|
||
drawSnId int32 // 求和的玩家SnId
|
||
nextSnId int32 // 再来一局玩家SnId
|
||
}
|
||
|
||
func getChessVariant(gameId int) int {
|
||
var variant int
|
||
switch gameId {
|
||
case common.GameId_Chesstitians:
|
||
variant = rule.ChessVarChess
|
||
case common.GameId_ChesstitiansMakruk:
|
||
variant = rule.ChessVarMakruk
|
||
case common.GameId_ChesstitiansCambodian, common.GameId_ChesstitiansCambodianRobot:
|
||
variant = rule.ChessVarCambodian
|
||
}
|
||
return variant
|
||
}
|
||
|
||
func NewSceneEx(s *base.Scene) *SceneEx {
|
||
variant := getChessVariant(int(s.GameId))
|
||
chess := rule.NewChess(variant)
|
||
chess.Init()
|
||
sceneEx := &SceneEx{
|
||
Scene: s,
|
||
chess: chess,
|
||
players: make(map[int32]*PlayerEx),
|
||
variant: variant,
|
||
}
|
||
return sceneEx
|
||
}
|
||
|
||
func (e *SceneEx) init() bool {
|
||
// 初始配置
|
||
e.SetPlayerNum(rule.MaxNumOfPlayer)
|
||
return true
|
||
}
|
||
|
||
func (e *SceneEx) Clear() {
|
||
// 重置
|
||
e.chess.Init()
|
||
e.opPos = rule.InvalidPos
|
||
e.isAllRob = false
|
||
e.winSnId = 0
|
||
e.nextSnId = 0
|
||
for _, player := range e.players {
|
||
if player != nil {
|
||
player.UnmarkFlag(base.PlayerState_WaitNext)
|
||
}
|
||
}
|
||
e.lastMove = e.lastMove[:0]
|
||
e.stepSnId = 0
|
||
e.stepNum = 0
|
||
e.stepLimit = 0
|
||
e.drawSnId = 0
|
||
}
|
||
|
||
func (e *SceneEx) CanStart() bool {
|
||
if e.GetGaming() {
|
||
return false
|
||
}
|
||
|
||
if e.GetPlayerCnt() == rule.MaxNumOfPlayer {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (e *SceneEx) GetPlayerCnt() int {
|
||
var cnt int
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerEx := e.seats[i]
|
||
if playerEx == nil {
|
||
continue
|
||
}
|
||
cnt++
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (e *SceneEx) GetGamingPlayerCnt() int {
|
||
var cnt int
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerEx := e.seats[i]
|
||
if playerEx == nil {
|
||
continue
|
||
}
|
||
if playerEx.IsGameing() {
|
||
cnt++
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (e *SceneEx) GetRobotCnt() int {
|
||
var cnt int
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerEx := e.seats[i]
|
||
if playerEx == nil {
|
||
continue
|
||
}
|
||
if playerEx.IsRob {
|
||
cnt++
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (e *SceneEx) GetGamingRobotCnt() int {
|
||
var cnt int
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerEx := e.seats[i]
|
||
if playerEx == nil {
|
||
continue
|
||
}
|
||
if playerEx.IsRob && playerEx.IsGameing() {
|
||
cnt++
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (e *SceneEx) GetSeatPlayerCnt() int {
|
||
var cnt int
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerEx := e.seats[i]
|
||
if playerEx == nil {
|
||
continue
|
||
}
|
||
cnt++
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (e *SceneEx) delPlayer(p *base.Player) {
|
||
if p, exist := e.players[p.SnId]; exist {
|
||
e.seats[p.GetPos()] = nil
|
||
delete(e.players, p.SnId)
|
||
}
|
||
}
|
||
|
||
func (e *SceneEx) OnPlayerLeave(p *base.Player, reason int) {
|
||
e.delPlayer(p)
|
||
e.BroadcastPlayerLeave(p, reason)
|
||
}
|
||
|
||
func (e *SceneEx) SceneDestroy(force bool) {
|
||
//销毁房间
|
||
e.Scene.Destroy(force)
|
||
}
|
||
|
||
func (e *SceneEx) BroadcastPlayerLeave(p *base.Player, reason int) {
|
||
scLeavePack := &chesstitians.SCChesstitiansPlayerLeave{
|
||
Pos: proto.Int(p.GetPos()),
|
||
}
|
||
proto.SetDefaults(scLeavePack)
|
||
logger.Logger.Trace("SCChesstitiansPlayerLeave: ", p.SnId, " scLeavePack: ", scLeavePack)
|
||
e.Broadcast(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansPlayerLeave), scLeavePack, p.GetSid())
|
||
}
|
||
|
||
func (e *SceneEx) BroadcastAudienceNum(p *base.Player) {
|
||
pack := &chesstitians.SCChesstitiansUpdateAudienceNum{
|
||
AudienceNum: proto.Int(e.GetAudiencesNum()),
|
||
}
|
||
proto.SetDefaults(pack)
|
||
e.Broadcast(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansUpdateAudienceNum), pack, p.GetSid())
|
||
}
|
||
|
||
// BroadcastUpdateMasterSnId 广播房主更换
|
||
func (e *SceneEx) BroadcastUpdateMasterSnId(changeState bool) {
|
||
pack := &chesstitians.SCChesstitiansUpdateMasterSnid{
|
||
MasterSnid: proto.Int32(e.masterSnId),
|
||
}
|
||
proto.SetDefaults(pack)
|
||
e.Broadcast(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansUpdateMasterSnid), pack, 0)
|
||
//logger.Logger.Trace("BroadcastUpdateMasterSnId ", pack)
|
||
|
||
//重置开始倒计时
|
||
if changeState && e.CanStart() {
|
||
e.Scene.ChangeSceneState(rule.SceneStateWaitStart)
|
||
}
|
||
}
|
||
|
||
func (e *SceneEx) playerOpPack(snId int32, opcode int, opRetCode chesstitians.OpResultCode, params []int64) *chesstitians.SCChesstitiansPlayerOp {
|
||
pack := &chesstitians.SCChesstitiansPlayerOp{
|
||
OpCode: proto.Int(opcode),
|
||
OpParam: params,
|
||
SnId: proto.Int32(snId),
|
||
OpRetCode: opRetCode,
|
||
Check: e.chess.GetCheck(),
|
||
Checkmate: e.chess.GetCheckmate(),
|
||
StepSnId: e.stepSnId,
|
||
StepNum: int64(proto.Int(e.stepNum)),
|
||
StepLimit: int64(e.stepLimit),
|
||
}
|
||
p := e.GetPlayer(snId)
|
||
if p != nil {
|
||
if ex, ok := p.ExtraData.(*PlayerEx); ok {
|
||
pack.TotalTime = append(pack.TotalTime, ex.GetTotalTime())
|
||
for _, v := range e.seats {
|
||
if v != nil && v.Pos != ex.Pos {
|
||
pack.TotalTime = append(pack.TotalTime, v.GetTotalTime())
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
proto.SetDefaults(pack)
|
||
return pack
|
||
}
|
||
|
||
// OnPlayerSCOp 发送玩家操作情况
|
||
func (e *SceneEx) OnPlayerSCOp(p *base.Player, opcode int, opRetCode chesstitians.OpResultCode, params []int64) {
|
||
pack := e.playerOpPack(p.SnId, opcode, opRetCode, params)
|
||
p.SendToClient(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansPlayerOp), pack)
|
||
logger.Logger.Tracef("OnPlayerSCOp %s", pack)
|
||
}
|
||
|
||
// BroadcastPlayerSCOp 广播发送玩家操作情况
|
||
func (e *SceneEx) BroadcastPlayerSCOp(snid int32, opcode int, opRetCode chesstitians.OpResultCode, params []int64) {
|
||
pack := e.playerOpPack(snid, opcode, opRetCode, params)
|
||
e.Broadcast(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansPlayerOp), pack, 0)
|
||
logger.Logger.Tracef("BroadcastPlayerSCOp %s", pack)
|
||
}
|
||
|
||
// FindOnePos 逆时针找一个空位
|
||
func (e *SceneEx) FindOnePos() int {
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
if e.seats[i] == nil {
|
||
return i
|
||
}
|
||
}
|
||
return rule.InvalidPos
|
||
}
|
||
|
||
func (e *SceneEx) SystemCoinOut() int64 {
|
||
systemGain := int64(0)
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
playerData := e.seats[i]
|
||
|
||
if playerData != nil && playerData.IsGameing() && playerData.IsRob {
|
||
systemGain += playerData.winCoin
|
||
}
|
||
}
|
||
return systemGain
|
||
}
|
||
|
||
func (e *SceneEx) AllPlayerEnterGame() {
|
||
for i := 0; i < e.GetPlayerNum(); i++ {
|
||
if e.seats[i] == nil {
|
||
continue
|
||
}
|
||
|
||
if e.seats[i].IsMarkFlag(base.PlayerState_GameBreak) == false {
|
||
e.seats[i].UnmarkFlag(base.PlayerState_WaitNext)
|
||
e.seats[i].SyncFlag()
|
||
}
|
||
}
|
||
}
|
||
|
||
func (e *SceneEx) SetCurOpPos(pos int) {
|
||
e.opPos = pos
|
||
e.seats[pos].lastTime = time.Now()
|
||
}
|
||
|
||
func (e *SceneEx) GetCurOpPos() int {
|
||
return e.opPos
|
||
}
|
||
|
||
func (e *SceneEx) AddChessGrade(p *PlayerEx, num int64) {
|
||
if p == nil {
|
||
return
|
||
}
|
||
|
||
// 人机对战没有积分
|
||
if e.GetGameId() != common.GameId_ChesstitiansCambodianRobot {
|
||
p.AddChessGrade(num)
|
||
}
|
||
}
|
||
|
||
func (e *SceneEx) AddCoin(p *PlayerEx, num int64, gainWay int32, syncFlag int, oper, remark string) {
|
||
if p == nil {
|
||
return
|
||
}
|
||
|
||
// 人机对战没有金币结算
|
||
if e.GetGameId() != common.GameId_ChesstitiansCambodianRobot {
|
||
p.AddCoin(num, gainWay, syncFlag, oper, remark)
|
||
}
|
||
}
|
||
|
||
func (e *SceneEx) GetSeatByCKey(cKey string) *PlayerEx {
|
||
_cKey := strings.ToLower(cKey)
|
||
for _, seat := range e.seats {
|
||
if _cKey == "w" && !seat.isBlack || _cKey == "b" && seat.isBlack {
|
||
return seat
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ChessInit 棋盘初始化
|
||
func (e *SceneEx) ChessInit() {
|
||
e.chess.Init()
|
||
e.lastMove = []int32{}
|
||
// 空结构
|
||
// 随机
|
||
firstIdx := e.RandInt(2)
|
||
fmt.Println("@@firstIdx", firstIdx)
|
||
for idx, seat := range e.seats {
|
||
if seat != nil {
|
||
if idx == firstIdx {
|
||
// 默认seats中的第一个是白棋,先走
|
||
seat.isBlack = false
|
||
} else {
|
||
seat.isBlack = true
|
||
}
|
||
seat.oldGrade = seat.ChessGrade
|
||
pack := &chesstitians.SCChesstitiansCard{}
|
||
// 通过cards[0] 传递isBlack
|
||
if seat.isBlack {
|
||
pack.Cards = append(pack.Cards, int32(1))
|
||
} else {
|
||
pack.Cards = append(pack.Cards, int32(0))
|
||
}
|
||
// 生成棋数据
|
||
pack.Chess = e.chess.GetChess()
|
||
pack.Act = e.chess.GetAct()
|
||
pack.Castling = e.chess.GetCastling()
|
||
pack.CambodianMove = e.chess.GetCambodianMove()
|
||
pack.Enpassant = int32(e.chess.GetEnPassant())
|
||
pack.ChessRound = int32(e.chess.GetRound())
|
||
pack.Check = e.chess.GetCheck()
|
||
pack.Checkmate = e.chess.GetCheckmate()
|
||
proto.SetDefaults(pack)
|
||
seat.SendToClient(int(chesstitians.ChesstitiansPacketID_PACKET_SCChesstitiansCard), pack)
|
||
}
|
||
}
|
||
}
|
||
|
||
// PlayChess 判断客户端发来的行棋操作,返回是否合法
|
||
func (e *SceneEx) PlayChess(fromTo []int64) bool {
|
||
fromIdx, toIdx := int(fromTo[0]), int(fromTo[1])
|
||
// 判断该谁走
|
||
// 检查棋子本身能不能走
|
||
if !e.chess.CanMove(fromIdx, toIdx) {
|
||
logger.Logger.Errorf("非法行棋(棋子本身的路线错误) %v %v %v", fromIdx, toIdx, e.chess.GetPiece(fromIdx))
|
||
return false
|
||
}
|
||
// 王被吃
|
||
toPiece := e.chess.GetPiece(toIdx)
|
||
if toPiece == rule.WK { // 白王被吃,标记黑方获胜
|
||
for _, seat := range e.seats {
|
||
if seat != nil {
|
||
if seat.isBlack {
|
||
e.winSnId = seat.GetSnId()
|
||
}
|
||
}
|
||
}
|
||
} else if toPiece == rule.BK { // 黑王被吃,标记白方获胜
|
||
for _, seat := range e.seats {
|
||
if !seat.isBlack {
|
||
e.winSnId = seat.GetSnId()
|
||
}
|
||
}
|
||
}
|
||
|
||
c := e.chess.GetPiece(fromIdx)
|
||
e.chess.Move(fromIdx, toIdx)
|
||
e.lastMove = []int32{int32(fromIdx), int32(toIdx)}
|
||
|
||
// 将死
|
||
if rule.IsWhite(c) && e.chess.IsCheckmate(true) { // 白方胜
|
||
e.winSnId = e.GetSeatByCKey("w").GetSnId()
|
||
} else if !rule.IsWhite(c) && e.chess.IsCheckmate(false) { // 黑方胜
|
||
e.winSnId = e.GetSeatByCKey("b").GetSnId()
|
||
}
|
||
|
||
// 无子可动平局
|
||
if rule.IsWhite(c) && e.chess.IsStop(false) {
|
||
e.ChangeSceneState(rule.SceneStateBilled)
|
||
} else if rule.IsBlack(c) && e.chess.IsStop(true) {
|
||
e.ChangeSceneState(rule.SceneStateBilled)
|
||
}
|
||
return true
|
||
}
|
||
|
||
// NextOpPos 轮换到下一个操作的玩家
|
||
func (e *SceneEx) NextOpPos() {
|
||
lastPlayer := e.seats[e.opPos]
|
||
if !lastPlayer.lastTime.IsZero() {
|
||
lastPlayer.totalTime += int64(time.Now().Sub(lastPlayer.lastTime).Seconds())
|
||
}
|
||
|
||
e.opPos = (e.opPos + 1) % rule.MaxNumOfPlayer
|
||
e.chess.NextAct()
|
||
e.chess.PrintChess()
|
||
s := e.chess.GenFen()
|
||
println(s)
|
||
|
||
// 计步
|
||
if e.IsStep() {
|
||
curPlayer := e.seats[e.opPos]
|
||
if curPlayer.SnId == e.stepSnId {
|
||
e.stepNum++
|
||
}
|
||
if e.IsKingStep() {
|
||
e.stepKing++
|
||
if e.stepKing == 2 {
|
||
e.stepNum++
|
||
e.stepKing = 0
|
||
}
|
||
}
|
||
|
||
if e.stepNum > e.stepLimit {
|
||
// 计步结束,平局
|
||
e.ChangeSceneState(rule.SceneStateBilled)
|
||
return
|
||
}
|
||
}
|
||
|
||
// 检查孤王计步
|
||
// 任何一方只剩一个王时,开始计步;取消残局计步;确定回合限制
|
||
if !e.IsKingStep() {
|
||
if e.chess.Has(rule.WK) && e.chess.GetWhiteNum() == 1 ||
|
||
e.chess.Has(rule.BK) && e.chess.GetBlackNum() == 1 {
|
||
if e.IsStep() {
|
||
e.cancelStep()
|
||
}
|
||
e.StartKingStep()
|
||
}
|
||
}
|
||
// 记录操作开始时间
|
||
e.seats[e.opPos].lastTime = time.Now()
|
||
}
|
||
|
||
// IsStep 是否计步中
|
||
func (e *SceneEx) IsStep() bool {
|
||
if e.stepLimit > 0 {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (e *SceneEx) IsKingStep() bool {
|
||
if e.stepSnId == 0 && e.stepLimit > 0 {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// CanStep 是否可以计步
|
||
func (e *SceneEx) CanStep() bool {
|
||
if e.IsStep() {
|
||
return false
|
||
}
|
||
// 双方都没有兵
|
||
if e.chess.GetChessNum(rule.WP) == 0 && e.chess.GetChessNum(rule.BP) == 0 {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// StartStep 玩家开始计步
|
||
func (e *SceneEx) StartStep(p *PlayerEx) bool {
|
||
if !e.CanStep() {
|
||
return false
|
||
}
|
||
|
||
e.stepSnId = p.GetSnId()
|
||
e.stepNum = 1
|
||
e.stepLimit = rule.PlayerStepLimit
|
||
return true
|
||
}
|
||
|
||
// StartKingStep 开始孤王计步
|
||
func (e *SceneEx) StartKingStep() {
|
||
e.stepKing = 0
|
||
c := rule.White
|
||
if e.chess.Has(rule.WK) && e.chess.GetWhiteNum() == 1 {
|
||
c = rule.Black
|
||
}
|
||
|
||
//双车:8回合
|
||
//单车:16回合
|
||
//双象:22回合
|
||
//双马:32回合
|
||
//单象:44回合
|
||
//单马:64回合
|
||
//其他情况:64回合
|
||
r := e.chess.GetChessNum(rule.ToPiece(c, rule.R))
|
||
if r == 2 {
|
||
e.stepLimit = 8
|
||
} else if r == 1 {
|
||
e.stepLimit = 16
|
||
}
|
||
|
||
if e.stepLimit == 0 {
|
||
s := e.chess.GetChessNum(rule.ToPiece(c, rule.S))
|
||
if s == 2 {
|
||
e.stepLimit = 22
|
||
} else {
|
||
n := e.chess.GetChessNum(rule.ToPiece(c, rule.N))
|
||
if n == 2 {
|
||
e.stepLimit = 32
|
||
} else if s == 1 {
|
||
e.stepLimit = 44
|
||
} else if n == 1 {
|
||
e.stepLimit = 64
|
||
}
|
||
}
|
||
}
|
||
|
||
if e.stepLimit == 0 {
|
||
e.stepLimit = 64
|
||
}
|
||
|
||
// 起始回合数
|
||
//e.stepNum = e.chess.GetWhiteNum() + e.chess.GetBlackNum() + 1
|
||
e.stepNum = 1
|
||
}
|
||
|
||
// cancelStep 取消计步
|
||
func (e *SceneEx) cancelStep() {
|
||
e.stepSnId = 0
|
||
e.stepNum = 0
|
||
e.stepLimit = 0
|
||
}
|
||
|
||
// CancelStep 玩家取消计步
|
||
func (e *SceneEx) CancelStep(p *PlayerEx) bool {
|
||
if !e.IsStep() {
|
||
return false
|
||
}
|
||
if e.stepSnId != p.GetSnId() {
|
||
return false
|
||
}
|
||
e.cancelStep()
|
||
return true
|
||
}
|
||
|
||
// RequestDraw 玩家求和
|
||
func (e *SceneEx) RequestDraw(p *PlayerEx) bool {
|
||
if e.drawSnId > 0 {
|
||
return false
|
||
}
|
||
e.drawSnId = p.GetSnId()
|
||
return true
|
||
}
|
||
|
||
// RefuseDraw 玩家拒绝求和
|
||
func (e *SceneEx) RefuseDraw(p *PlayerEx) bool {
|
||
if e.drawSnId == 0 {
|
||
return false
|
||
}
|
||
if e.drawSnId == p.GetSnId() {
|
||
return false
|
||
}
|
||
e.drawSnId = 0
|
||
return true
|
||
}
|
||
|
||
// AgreeDraw 玩家同意求和
|
||
func (e *SceneEx) AgreeDraw(p *PlayerEx) bool {
|
||
if e.drawSnId == 0 {
|
||
return false
|
||
}
|
||
if e.drawSnId == p.GetSnId() {
|
||
return false
|
||
}
|
||
e.drawSnId = 0
|
||
e.ChangeSceneState(rule.SceneStateBilled)
|
||
return true
|
||
}
|
||
|
||
// CancelDraw 撤销求和
|
||
func (e *SceneEx) CancelDraw(p *PlayerEx) bool {
|
||
if e.drawSnId == 0 {
|
||
return false
|
||
}
|
||
if e.drawSnId != p.GetSnId() {
|
||
return false
|
||
}
|
||
e.drawSnId = 0
|
||
return true
|
||
}
|
||
|
||
func (e *SceneEx) GetChessRank(p *PlayerEx) int32 {
|
||
i := sort.Search(len(e.ChessRank), func(i int) bool {
|
||
return int64(e.ChessRank[i]) > p.ChessGrade
|
||
})
|
||
if i == len(e.ChessRank) {
|
||
return e.ChessRank[i-1]
|
||
}
|
||
i = i - 1
|
||
if i < 0 {
|
||
i = 0
|
||
}
|
||
if i < len(e.ChessRank) {
|
||
return e.ChessRank[i]
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (e *SceneEx) GetChessRankNext(p *PlayerEx) int32 {
|
||
i := sort.Search(len(e.ChessRank), func(i int) bool {
|
||
return int64(e.ChessRank[i]) > p.ChessGrade
|
||
})
|
||
if i == len(e.ChessRank) {
|
||
return e.ChessRank[i-1]
|
||
}
|
||
return e.ChessRank[i]
|
||
}
|
||
|
||
func (e *SceneEx) ToBilled(p1, p2 *PlayerEx, isWin int) (*chesstitians.ChesstitiansPlayerGameBilled, *model.ChesstitiansPerson) {
|
||
// 获取结算规则
|
||
var typeId int32
|
||
var billedRule, billedRuleDraw *server.DB_ChessBilledRules
|
||
|
||
// 人机对战不结算
|
||
if e.GetGameId() != common.GameId_ChesstitiansCambodianRobot {
|
||
winRank := e.GetChessRank(p1)
|
||
loseRank := e.GetChessRank(p2)
|
||
if winRank > loseRank {
|
||
typeId = rule.BilledTypeGT
|
||
} else if winRank < loseRank {
|
||
typeId = rule.BilledTypeLT
|
||
} else {
|
||
typeId = rule.BilledTypeEQ
|
||
}
|
||
|
||
for _, v := range srvdata.PBDB_ChessBilledRulesMgr.Datas.Arr {
|
||
if v.GetTypeId() == typeId {
|
||
billedRule = v
|
||
}
|
||
if v.GetTypeId() == rule.BilledTypeEQ {
|
||
billedRuleDraw = v
|
||
}
|
||
}
|
||
}
|
||
|
||
p1.isWin = int32(isWin)
|
||
p1.winCoin = 0
|
||
p1.taxCoin = 0
|
||
p1.winTimes = 0
|
||
p1.winScore = 0
|
||
p1.otherScore = 0
|
||
p1.nextRank = 0
|
||
|
||
switch isWin {
|
||
case rule.Win:
|
||
// 金币和税收
|
||
gainScore := int64(float64(e.GetBaseScore()) * float64(10000-e.GetDBGameFree().GetTaxRate()) / 10000.0)
|
||
p1.winCoin = gainScore
|
||
p1.taxCoin = int64(e.GetBaseScore()) - gainScore
|
||
|
||
// 连赢次数
|
||
winTimes := p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.WinGameTimesNum
|
||
e.AddCoin(p1, gainScore, common.GainWay_CoinSceneWin, 0, "system", e.GetSceneName())
|
||
p1.winTimes = int32(winTimes + 1)
|
||
|
||
var winScore int32
|
||
if billedRule != nil {
|
||
// 连赢积分
|
||
if p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.GetInt(rule.StaticsChessTime)+1 >= int(billedRule.GetWinTimes()) {
|
||
p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.SetInt(rule.StaticsChessTime, 0)
|
||
p1.AddChessGrade(int64(billedRule.OtherScore))
|
||
p1.otherScore = billedRule.OtherScore
|
||
winScore += billedRule.OtherScore
|
||
} else {
|
||
p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.Incr(rule.StaticsChessTime)
|
||
}
|
||
// 总积分
|
||
e.AddChessGrade(p1, int64(billedRule.GetWinScore()))
|
||
// 本局积分
|
||
winScore += billedRule.GetWinScore()
|
||
p1.winScore = winScore
|
||
}
|
||
|
||
case rule.Lose:
|
||
e.AddCoin(p1, int64(-e.GetDBGameFree().GetBaseScore()), common.GainWay_CoinSceneLost, 0, "system", e.GetSceneName())
|
||
p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.SetInt(rule.StaticsChessTime, 0)
|
||
p1.winCoin = int64(-e.GetDBGameFree().GetBaseScore())
|
||
|
||
if billedRule != nil {
|
||
// 总积分
|
||
e.AddChessGrade(p1, int64(billedRule.GetLoseScore()))
|
||
// 本局积分
|
||
p1.winScore = proto.Int32(billedRule.GetLoseScore())
|
||
}
|
||
|
||
case rule.Draw:
|
||
p1.GetGameFreeIdData(e.KeyGamefreeId).Statics.SetInt(rule.StaticsChessTime, 0)
|
||
if billedRule != nil {
|
||
// 总积分
|
||
e.AddChessGrade(p1, int64(billedRule.GetDrawScore()))
|
||
// 本局积分
|
||
p1.winScore = proto.Int32(billedRule.GetDrawScore())
|
||
}
|
||
}
|
||
|
||
if billedRuleDraw != nil {
|
||
// 还有几局晋级
|
||
n := math.Ceil(float64(int64(e.GetChessRankNext(p1))-p1.ChessGrade) / float64(billedRuleDraw.GetWinScore()))
|
||
p1.nextRank = int32(n)
|
||
}
|
||
|
||
// 人机对战,没有输赢分,没有积分变化
|
||
if e.GetGameId() == common.GameId_ChesstitiansCambodianRobot {
|
||
p1.winCoin = 0
|
||
p1.taxCoin = 0
|
||
p1.winScore = 0
|
||
p1.otherScore = 0
|
||
}
|
||
|
||
billData := &chesstitians.ChesstitiansPlayerGameBilled{
|
||
SnId: proto.Int32(p1.SnId),
|
||
WinCoin: proto.Int64(p1.winCoin),
|
||
GameCoin: proto.Int64(p1.GetCoin()),
|
||
IsWin: proto.Int32(p1.isWin),
|
||
WinTimes: proto.Int32(p1.winTimes),
|
||
OtherScore: proto.Int32(p1.otherScore),
|
||
NextRank: proto.Int32(p1.nextRank),
|
||
Score: proto.Int32(int32(p1.ChessGrade)),
|
||
WinScore: proto.Int32(p1.winScore),
|
||
OldChessGrade: proto.Int64(p1.oldGrade),
|
||
}
|
||
|
||
chessPerson := &model.ChesstitiansPerson{
|
||
UserId: p1.SnId,
|
||
UserIcon: p1.Head,
|
||
Platform: p1.Platform,
|
||
Channel: p1.Channel,
|
||
ChannelId: p1.ChannelId,
|
||
Promoter: p1.BeUnderAgentCode,
|
||
PackageTag: p1.PackageID,
|
||
InviterId: p1.InviterId,
|
||
WBLevel: p1.WBLevel,
|
||
IsRob: p1.IsRob,
|
||
IsFirst: e.IsPlayerFirst(e.GetPlayer(p1.SnId)),
|
||
IsLeave: false,
|
||
IsWin: p1.isWin,
|
||
Seat: p1.GetPos(),
|
||
GainCoin: p1.winCoin,
|
||
GainTaxCoin: p1.taxCoin,
|
||
}
|
||
return billData, chessPerson
|
||
}
|