1459 lines
41 KiB
Go
1459 lines
41 KiB
Go
package thirteen
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"math/rand"
|
||
"sort"
|
||
"strings"
|
||
"time"
|
||
|
||
"mongo.games.com/goserver/core/logger"
|
||
|
||
"mongo.games.com/game/common"
|
||
rule "mongo.games.com/game/gamerule/thirteen"
|
||
"mongo.games.com/game/gamesrv/base"
|
||
"mongo.games.com/game/proto"
|
||
"mongo.games.com/game/protocol/thirteen"
|
||
)
|
||
|
||
type PlayerData struct {
|
||
SnId int32
|
||
cards [13]int //手牌信息
|
||
cardsO *rule.Group //确定的牌型信息
|
||
isDP bool // 是否倒排
|
||
gainCoin int64 //本局赢的金币
|
||
taxCoin int64 //本局税收
|
||
clubPump int64 //俱乐部抽水
|
||
deterMine bool //玩家是否确定牌
|
||
score [7]int64 //玩家每墩的得分 0:头 1中 2尾 3:特殊牌型分数 4打枪 5全垒打 6离场补偿分
|
||
tableScore [6]int64 // 客户端展示
|
||
winThreePos map[int]int64 //只包含打枪玩家位置和总赢分
|
||
winAllPlayers map[int]int64 //玩家位置和输赢分
|
||
isStand bool //玩家站起 true打开 本局结束后自动离开房间 false未打开
|
||
isBilled bool // 是否结算
|
||
IsRob bool
|
||
Pos int
|
||
Coin int64
|
||
StartCoin int64
|
||
Head int32 //头像
|
||
flag int
|
||
Platform string //平台
|
||
Channel string //渠道信息
|
||
PackageID string //推广包标识 对应客户端的packagetag
|
||
PromoterTree int32
|
||
InviterId int32 //邀请人Id
|
||
WBLevel int32 //黑白名单 白:[1,10] 黑:[-1,-10]
|
||
CurIsWin int64 //当局输赢 负数:输 0:平局 正数:赢
|
||
BeUnderAgentCode string //隶属经销商(推广人)
|
||
Name string //名字
|
||
Sex int32 //性别
|
||
City string //城市
|
||
Longitude int32 //经纬度
|
||
Latitude int32 //经纬度
|
||
AgentCode string //代理商编号
|
||
HeadOutLine int32 //头像框
|
||
VIP int32 //VIP帐号 等级
|
||
allGroup map[int]*rule.Group
|
||
TestLog []string
|
||
RoleId int32
|
||
PlayerPool int // 个人水池分
|
||
SkinId int32
|
||
}
|
||
|
||
type SceneEx struct {
|
||
*base.Scene //场景
|
||
poker *rule.Pokers // 扑克牌对象
|
||
logic *rule.Logic // 十三张算法
|
||
players map[int32]*PlayerEx // 玩家信息
|
||
seats []*PlayerEx // 本局游戏中的玩家状态数据
|
||
isCanAllHitPos int // 全垒打玩家坐标 =4人 并且没有特殊牌型
|
||
currOpPos int // 当前操作的玩家
|
||
hitTime time.Duration // 打枪阶段按打枪人数加时间
|
||
specialTime time.Duration // 亮牌阶段有特殊牌型增加时间
|
||
specialTypeNum int // 玩家有特殊牌的个数
|
||
entryHitState bool // 是否可以进入打枪阶段
|
||
robotNum int // 参与游戏的机器人数量
|
||
gamePlayerNum int // 参与游戏的人数量
|
||
|
||
r int // 体验场测试数据
|
||
cardsSlice [][13]int // 从大到小排列四副牌
|
||
nowMaxCardsIsIn bool // 现在最大牌是否还在
|
||
PlayerBackup map[int32]*PlayerData // 本局离场玩家数据备份
|
||
LeaveNum int // 离场扣分人数
|
||
testPokers []int64 // 测试牌堆
|
||
logid string
|
||
ctrlType int // 1控赢 2控输 0不控
|
||
cardsArr [][13]int
|
||
cardsGroup []map[int]*rule.Group
|
||
}
|
||
|
||
func NewThirteenWaterSceneData(s *base.Scene) *SceneEx {
|
||
sceneEx := &SceneEx{
|
||
Scene: s,
|
||
logic: new(rule.Logic),
|
||
players: make(map[int32]*PlayerEx),
|
||
seats: make([]*PlayerEx, s.GetPlayerNum()),
|
||
PlayerBackup: make(map[int32]*PlayerData),
|
||
}
|
||
if s.GetPlayerNum() > 4 { // 两幅牌
|
||
sceneEx.poker = rule.NewPokers(2, sceneEx.HasLaiZi())
|
||
} else {
|
||
sceneEx.poker = rule.NewPokers(1, sceneEx.HasLaiZi())
|
||
}
|
||
if sceneEx.HasLaiZi() {
|
||
sceneEx.logic.LaiZi = []int{52, 53} // 目前只有大小王为癞子
|
||
}
|
||
return sceneEx
|
||
}
|
||
|
||
func (this *SceneEx) init() bool {
|
||
this.Clear()
|
||
return true
|
||
}
|
||
|
||
func (this *SceneEx) Clear() {
|
||
this.poker.Init()
|
||
this.isCanAllHitPos = -1
|
||
this.currOpPos = -1
|
||
this.hitTime = rule.ThirteenWaterHitTimeout
|
||
this.specialTypeNum = 0
|
||
this.entryHitState = false
|
||
this.robotNum = 0
|
||
this.gamePlayerNum = 0
|
||
this.r = 1
|
||
this.cardsSlice = nil
|
||
this.nowMaxCardsIsIn = true
|
||
this.PlayerBackup = make(map[int32]*PlayerData)
|
||
this.LeaveNum = 0
|
||
this.ctrlType = 0
|
||
this.cardsArr = nil
|
||
this.cardsGroup = nil
|
||
|
||
for i := 0; i < this.GetPlayerNum(); i++ {
|
||
if this.seats[i] != nil {
|
||
this.seats[i].Clear()
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) delPlayer(p *base.Player) {
|
||
if p, exist := this.players[p.SnId]; exist {
|
||
this.seats[p.GetPos()] = nil
|
||
delete(this.players, p.SnId)
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) BroadcastPlayerLeave(p *base.Player, reason int) {
|
||
scLeavePack := &thirteen.SCThirteenPlayerLeave{
|
||
Pos: proto.Int(p.GetPos()),
|
||
}
|
||
proto.SetDefaults(scLeavePack)
|
||
|
||
this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerLeave), scLeavePack, p.GetSid())
|
||
}
|
||
|
||
func (this *SceneEx) OnPlayerLeave(p *base.Player, reason int) {
|
||
this.delPlayer(p)
|
||
this.BroadcastPlayerLeave(p, reason)
|
||
}
|
||
|
||
func (this *SceneEx) SceneDestroy(force bool) {
|
||
//销毁房间
|
||
this.Scene.Destroy(force)
|
||
}
|
||
|
||
func (this *SceneEx) CanStart() bool {
|
||
//房间人数>=2自动开始,并且有真人或者是预创建房间
|
||
if len(this.players) >= 2 && (this.GetRealPlayerNum() > 0 || this.IsPreCreateScene()) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *SceneEx) ThirteenWaterCreateRoomInfoPacket(s *base.Scene, p *base.Player) interface{} {
|
||
pack := &thirteen.SCThirteenRoomInfo{
|
||
RoomId: proto.Int(s.GetSceneId()),
|
||
Creator: proto.Int32(s.GetCreator()),
|
||
GameId: proto.Int(s.GetGameId()),
|
||
RoomMode: proto.Int(s.GetSceneMode()),
|
||
SceneType: s.GetDBGameFree().SceneType,
|
||
State: proto.Int(s.GetSceneState().GetState()),
|
||
TimeOut: proto.Int(s.GetSceneState().GetTimeout(s)),
|
||
DisbandGen: proto.Int(this.GetDisbandGen()),
|
||
BaseScore: int32(this.GetBaseScore()),
|
||
LeaveDeduct: this.GetDBGameFree().GetLeaveDeduct(),
|
||
LeaveCombat: this.GetDBGameFree().GetLeaveCombat(),
|
||
Params: common.CopySliceInt64ToInt32(s.Params),
|
||
}
|
||
// 玩家信息
|
||
for _, playerEx := range this.players {
|
||
pd := &thirteen.ThirteenPlayerData{
|
||
SnId: proto.Int32(playerEx.SnId),
|
||
Name: proto.String(playerEx.Name),
|
||
Head: proto.Int32(playerEx.Head),
|
||
Sex: proto.Int32(playerEx.Sex),
|
||
Coin: proto.Int64(playerEx.Coin),
|
||
Pos: proto.Int(playerEx.Pos),
|
||
Flag: proto.Int(playerEx.GetFlag()),
|
||
Longitude: proto.Int32(playerEx.Longitude),
|
||
Latitude: proto.Int32(playerEx.Latitude),
|
||
City: proto.String(playerEx.City),
|
||
AgentCode: proto.String(playerEx.AgentCode),
|
||
HeadOutLine: proto.Int32(playerEx.HeadOutLine),
|
||
VIP: proto.Int32(playerEx.VIP),
|
||
IsStand: proto.Bool(playerEx.isStand),
|
||
IsConfirm: proto.Bool(playerEx.deterMine),
|
||
RoleId: playerEx.PlayerData.GetRoleId(),
|
||
Level: proto.Int64(playerEx.PlayerData.Level),
|
||
Exp: proto.Int64(playerEx.PlayerData.Exp),
|
||
}
|
||
if playerEx.Skin != nil {
|
||
pd.SkinId = playerEx.Skin.ModId
|
||
}
|
||
ppp := &thirteen.Poker{}
|
||
ppp.IndexType = -1
|
||
pd.CardsO = ppp
|
||
if playerEx.cardsO != nil {
|
||
if playerEx.cardsO.PokerType > 0 {
|
||
//确定之后为特殊牌型
|
||
ppp := &thirteen.Poker{}
|
||
ppp.Head = common.CopySliceIntToInt32(playerEx.cards[:3])
|
||
ppp.Mid = common.CopySliceIntToInt32(playerEx.cards[3:8])
|
||
ppp.End = common.CopySliceIntToInt32(playerEx.cards[8:])
|
||
ppp.IndexType = proto.Int32(int32(playerEx.cardsO.PokerType * 1000000))
|
||
pd.CardsO = ppp
|
||
pd.IsDP = playerEx.isDP
|
||
} else if playerEx.cardsO.PokerType == 0 {
|
||
//确定之后为普通牌型
|
||
ppp := &thirteen.Poker{}
|
||
ppp.Head = common.CopySliceIntToInt32(playerEx.cardsO.Head[:])
|
||
ppp.Mid = common.CopySliceIntToInt32(playerEx.cardsO.Mid[:])
|
||
ppp.End = common.CopySliceIntToInt32(playerEx.cardsO.End[:])
|
||
ppp.IndexType = proto.Int32(int32(this.FormatCards(playerEx.cardsO)))
|
||
pd.CardsO = ppp
|
||
pd.IsDP = playerEx.isDP
|
||
}
|
||
}
|
||
if playerEx.cards[0] != -1 {
|
||
pd.Cards = common.CopySliceIntToInt32(playerEx.cards[:])
|
||
}
|
||
if playerEx.allGroup != nil {
|
||
pd.AllCardsO, _ = AllGroupToProto(playerEx.allGroup)
|
||
}
|
||
if p == nil || playerEx.SnId != p.SnId {
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateSendCards ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateOptCard {
|
||
pd.Cards = nil
|
||
pd.AllCardsO = nil
|
||
if pd.CardsO.IndexType > 0 {
|
||
ppp := &thirteen.Poker{}
|
||
ppp.IndexType = 0
|
||
pd.CardsO = ppp
|
||
pd.IsDP = false
|
||
}
|
||
}
|
||
}
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateShowCards ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateHit ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
|
||
pd.Score = playerEx.score[:]
|
||
pd.TableScore = playerEx.tableScore[:]
|
||
var hitScore []*thirteen.HitScore
|
||
for k, v := range playerEx.winThreePos {
|
||
pck := &thirteen.HitScore{
|
||
Pos: proto.Int32(int32(k)),
|
||
Score: proto.Int64(v),
|
||
}
|
||
hitScore = append(hitScore, pck)
|
||
}
|
||
pd.Hit = hitScore
|
||
}
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
|
||
pd.WinCoin = playerEx.gainCoin
|
||
}
|
||
pack.Players = append(pack.Players, pd)
|
||
}
|
||
// 备份的玩家信息
|
||
for _, playerEx := range this.PlayerBackup {
|
||
if playerEx != nil || !playerEx.isBilled {
|
||
continue
|
||
}
|
||
pd := &thirteen.ThirteenPlayerData{
|
||
SnId: proto.Int32(playerEx.SnId),
|
||
Name: proto.String(playerEx.Name),
|
||
Head: proto.Int32(playerEx.Head),
|
||
Sex: proto.Int32(playerEx.Sex),
|
||
Coin: proto.Int64(playerEx.Coin),
|
||
Pos: proto.Int(playerEx.Pos),
|
||
Flag: proto.Int(playerEx.flag),
|
||
Longitude: proto.Int32(playerEx.Longitude),
|
||
Latitude: proto.Int32(playerEx.Latitude),
|
||
City: proto.String(playerEx.City),
|
||
AgentCode: proto.String(playerEx.AgentCode),
|
||
HeadOutLine: proto.Int32(playerEx.HeadOutLine),
|
||
VIP: proto.Int32(playerEx.VIP),
|
||
IsStand: proto.Bool(playerEx.isStand),
|
||
IsConfirm: proto.Bool(playerEx.deterMine),
|
||
IsLeave: true,
|
||
RoleId: playerEx.RoleId,
|
||
SkinId: playerEx.SkinId,
|
||
}
|
||
ppp := &thirteen.Poker{}
|
||
ppp.IndexType = -1
|
||
pd.CardsO = ppp
|
||
if playerEx.cardsO != nil {
|
||
if playerEx.cardsO.PokerType > 0 {
|
||
//确定之后为特殊牌型
|
||
ppp := &thirteen.Poker{}
|
||
ppp.Head = common.CopySliceIntToInt32(playerEx.cards[:3])
|
||
ppp.Mid = common.CopySliceIntToInt32(playerEx.cards[3:8])
|
||
ppp.End = common.CopySliceIntToInt32(playerEx.cards[8:])
|
||
ppp.IndexType = proto.Int32(int32(playerEx.cardsO.PokerType * 1000000))
|
||
pd.CardsO = ppp
|
||
pd.IsDP = playerEx.isDP
|
||
} else if playerEx.cardsO.PokerType == 0 {
|
||
//确定之后为普通牌型
|
||
ppp := &thirteen.Poker{}
|
||
ppp.Head = common.CopySliceIntToInt32(playerEx.cardsO.Head[:])
|
||
ppp.Mid = common.CopySliceIntToInt32(playerEx.cardsO.Mid[:])
|
||
ppp.End = common.CopySliceIntToInt32(playerEx.cardsO.End[:])
|
||
ppp.IndexType = proto.Int32(int32(this.FormatCards(playerEx.cardsO)))
|
||
pd.CardsO = ppp
|
||
pd.IsDP = playerEx.isDP
|
||
}
|
||
}
|
||
if playerEx.cards[0] != -1 {
|
||
pd.Cards = common.CopySliceIntToInt32(playerEx.cards[:])
|
||
}
|
||
if playerEx.allGroup != nil {
|
||
pd.AllCardsO, _ = AllGroupToProto(playerEx.allGroup)
|
||
}
|
||
if p == nil || playerEx.SnId != p.SnId {
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateSendCards ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateOptCard {
|
||
pd.Cards = nil
|
||
pd.AllCardsO = nil
|
||
if pd.CardsO.IndexType > 0 {
|
||
ppp := &thirteen.Poker{}
|
||
ppp.IndexType = 0
|
||
pd.CardsO = ppp
|
||
pd.IsDP = false
|
||
}
|
||
}
|
||
}
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateShowCards ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateHit ||
|
||
s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
|
||
pd.Score = playerEx.score[:]
|
||
pd.TableScore = playerEx.tableScore[:]
|
||
var hitScore []*thirteen.HitScore
|
||
for k, v := range playerEx.winThreePos {
|
||
pck := &thirteen.HitScore{
|
||
Pos: proto.Int32(int32(k)),
|
||
Score: proto.Int64(v),
|
||
}
|
||
hitScore = append(hitScore, pck)
|
||
}
|
||
pd.Hit = hitScore
|
||
}
|
||
if s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
|
||
pd.WinCoin = playerEx.gainCoin
|
||
}
|
||
pack.Players = append(pack.Players, pd)
|
||
}
|
||
|
||
proto.SetDefaults(pack)
|
||
if p != nil {
|
||
p.SyncFlag()
|
||
}
|
||
logger.Logger.Trace("SCThirteenWaterRoomInfo:", pack)
|
||
return pack
|
||
}
|
||
|
||
func (this *SceneEx) GetBaseScore() int64 { //游戏底分
|
||
if this.GetDBGameFree().FreeMode == 1 {
|
||
baseScore := this.GetParam(rule.ParamBaseScore)
|
||
if baseScore > 0 {
|
||
return baseScore
|
||
}
|
||
}
|
||
|
||
if this.GetDBGameFree() != nil {
|
||
return int64(this.GetDBGameFree().GetBaseScore())
|
||
}
|
||
return 1
|
||
}
|
||
|
||
func (this *SceneEx) GetBaiPai() time.Duration {
|
||
s := this.GetParam(rule.ParamBaiPai)
|
||
if s > 0 {
|
||
return time.Duration(s) * time.Second
|
||
}
|
||
return rule.ThirteenWaterOptCardTimeout
|
||
}
|
||
|
||
func (this *SceneEx) HasLaiZi() bool {
|
||
s := this.GetParam(rule.ParamLaiZi)
|
||
if s >= 0 {
|
||
return s == 1
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *SceneEx) AutoCombine() bool {
|
||
s := this.GetParam(rule.ParamAuto)
|
||
if s >= 0 {
|
||
return s == 0
|
||
}
|
||
return true
|
||
}
|
||
|
||
// GetLeaveDeductCoin 离场扣分
|
||
func (this *SceneEx) GetLeaveDeductCoin() int64 {
|
||
return int64(this.GetDBGameFree().GetLeaveDeduct()) * int64(this.GetBaseScore())
|
||
}
|
||
|
||
func (this *SceneEx) GetScore(player *PlayerEx) {
|
||
if player == nil || player.isDP {
|
||
return
|
||
}
|
||
// 计算特殊牌型分数
|
||
ptRate := int64(0)
|
||
//清龙* 一条龙* 十二皇族 三同花顺* 三分天下 全大 全小 凑一色* 四套三条 五对三条 六对半* 三顺子* 三同花
|
||
if player.cardsO.PokerType != 0 {
|
||
this.specialTypeNum++
|
||
//特殊牌处理
|
||
if player.cardsO.PokerType >= 1 && player.cardsO.PokerType <= 13 {
|
||
ptRate = rule.SpecialScore[player.cardsO.PokerType]
|
||
}
|
||
}
|
||
if this.specialTypeNum > 0 {
|
||
for _, p := range this.players {
|
||
if p != nil && p.IsGameing() && player.cardsO.PokerType != 0 {
|
||
if player.Pos == p.Pos {
|
||
continue
|
||
}
|
||
if p.cardsO.PokerType == 0 || p.isDP {
|
||
player.score[3] += ptRate
|
||
p.score[3] -= ptRate
|
||
player.winAllPlayers[p.Pos] += ptRate
|
||
p.winAllPlayers[player.Pos] -= ptRate
|
||
} else if p.cardsO.PokerType != 0 {
|
||
//多个特殊牌型处理
|
||
if player.cardsO.PokerType < p.cardsO.PokerType {
|
||
player.score[3] += ptRate
|
||
p.score[3] -= ptRate
|
||
player.winAllPlayers[p.Pos] += ptRate
|
||
p.winAllPlayers[player.Pos] -= ptRate
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 计算普通牌型分数
|
||
for _, p := range this.players {
|
||
if p != nil && p.IsGameing() && player.cardsO.PokerType == 0 {
|
||
if player.Pos == p.Pos || p.cardsO.PokerType != 0 {
|
||
continue
|
||
}
|
||
s := 0
|
||
score := int64(0) //赢的分数
|
||
//头墩
|
||
rate := int64(1)
|
||
n := this.logic.CompareHead(player.cardsO.Head, p.cardsO.Head)
|
||
h := this.logic.GetType(player.cardsO.Head[:])
|
||
if h == rule.PokersTypeThree {
|
||
rate += 2
|
||
}
|
||
if n == 1 || p.isDP {
|
||
player.score[0] += rate
|
||
p.score[0] -= rate
|
||
score += rate
|
||
s++
|
||
player.winAllPlayers[p.Pos] += rate
|
||
p.winAllPlayers[player.Pos] -= rate
|
||
player.tableScore[3] += rate - 1
|
||
}
|
||
//中墩
|
||
rate = int64(1)
|
||
n = this.logic.CompareFive(player.cardsO.Mid, p.cardsO.Mid)
|
||
m := this.logic.GetType(player.cardsO.Mid[:])
|
||
if m == rule.PokersTypeFullHouse {
|
||
rate += 1
|
||
} else if m == rule.PokersTypeFour {
|
||
rate += 6
|
||
} else if m == rule.PokersTypeStraightFlush {
|
||
rate += 8
|
||
} else if m == rule.PokersTypeFive {
|
||
rate += 10
|
||
}
|
||
if n == 1 || p.isDP {
|
||
player.score[1] += rate
|
||
p.score[1] -= rate
|
||
score += rate
|
||
s++
|
||
player.winAllPlayers[p.Pos] += rate
|
||
p.winAllPlayers[player.Pos] -= rate
|
||
player.tableScore[4] += rate - 1
|
||
}
|
||
//尾墩
|
||
rate = int64(1)
|
||
n = this.logic.CompareFive(player.cardsO.End, p.cardsO.End)
|
||
e := this.logic.GetType(player.cardsO.End[:])
|
||
if e == rule.PokersTypeFour {
|
||
rate += 3
|
||
} else if e == rule.PokersTypeStraightFlush {
|
||
rate += 4
|
||
} else if e == rule.PokersTypeFive {
|
||
rate += 5
|
||
}
|
||
if n == 1 || p.isDP {
|
||
player.score[2] += rate
|
||
p.score[2] -= rate
|
||
score += rate
|
||
s++
|
||
player.winAllPlayers[p.Pos] += rate
|
||
p.winAllPlayers[player.Pos] -= rate
|
||
player.tableScore[5] += rate - 1
|
||
}
|
||
if s == 3 {
|
||
player.winThreePos[p.Pos] = score
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) SendToPlayerCardsBySnid(snid int32) {
|
||
for _, player := range this.players {
|
||
if player != nil && player.IsGameing() && (snid == 0 || player.SnId == snid) {
|
||
all, k := AllGroupToProto(player.allGroup)
|
||
pack := &thirteen.SCThirteenPlayerCards{
|
||
Cards: common.CopySliceIntToInt32(player.cards[:]),
|
||
Pos: proto.Int32(int32(player.Pos)),
|
||
AllCardsO: all,
|
||
}
|
||
// 记录默认牌型
|
||
if k > 0 {
|
||
player.defGroup = player.allGroup[k]
|
||
}
|
||
if len(pack.AllCardsO) == 0 {
|
||
logger.Logger.Warnf("no poker suggest: %v %v", player.cards, rule.PokersShow(player.cards[:]))
|
||
// 没有推荐牌,随便给个数据
|
||
pack.AllCardsO = []*thirteen.Poker{
|
||
{
|
||
IndexType: 90909,
|
||
Head: common.CopySliceIntToInt32(player.cards[:3]),
|
||
Mid: common.CopySliceIntToInt32(player.cards[3:8]),
|
||
End: common.CopySliceIntToInt32(player.cards[8:]),
|
||
},
|
||
}
|
||
}
|
||
proto.SetDefaults(pack)
|
||
logger.Logger.Trace("SCThirteenWaterPlayerCards:", pack)
|
||
player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerCards), pack)
|
||
Send := &thirteen.SCThirteenPlayerCards{
|
||
Pos: proto.Int32(int32(player.Pos)),
|
||
}
|
||
proto.SetDefaults(Send)
|
||
logger.Logger.Trace("SCThirteenWaterPlayerCards:", Send)
|
||
this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerCards), Send, player.GetSid())
|
||
}
|
||
}
|
||
}
|
||
|
||
func AllGroupToProto(allGroup map[int]*rule.Group) ([]*thirteen.Poker, int) {
|
||
var pack []*thirteen.Poker
|
||
for k, v := range allGroup {
|
||
p := &thirteen.Poker{
|
||
Head: common.CopySliceIntToInt32(v.Head[:]),
|
||
Mid: common.CopySliceIntToInt32(v.Mid[:]),
|
||
End: common.CopySliceIntToInt32(v.End[:]),
|
||
IndexType: proto.Int32(int32(k)),
|
||
}
|
||
pack = append(pack, p)
|
||
}
|
||
|
||
sort.Slice(pack, func(i, j int) bool {
|
||
ii := pack[i]
|
||
jj := pack[j]
|
||
// 特殊牌在前面
|
||
if ii.IndexType >= 1000000 && jj.IndexType >= 1000000 {
|
||
return ii.IndexType < jj.IndexType
|
||
}
|
||
if ii.IndexType >= 1000000 {
|
||
return true
|
||
}
|
||
if jj.IndexType >= 1000000 {
|
||
return false
|
||
}
|
||
// 普通牌型,从尾墩到头墩大的在前面
|
||
if ii.IndexType%100 < jj.IndexType%100 {
|
||
return true
|
||
} else if ii.IndexType%100 > jj.IndexType%100 {
|
||
return false
|
||
}
|
||
|
||
if ii.IndexType%10000/100 < jj.IndexType%10000/100 {
|
||
return true
|
||
} else if ii.IndexType%10000/100 > jj.IndexType%10000/100 {
|
||
return false
|
||
}
|
||
|
||
if ii.IndexType/10000 < jj.IndexType/10000 {
|
||
return true
|
||
} else if ii.IndexType/10000 > jj.IndexType/10000 {
|
||
return false
|
||
}
|
||
return false
|
||
})
|
||
|
||
//for _, v := range pack {
|
||
// logger.Logger.Tracef("AllGroupToProto: %v %v %v %v", v.IndexType, rule.PokersShow(common.CopySliceInt32ToInt(v.Head)), rule.PokersShow(common.CopySliceInt32ToInt(v.Mid)), rule.PokersShow(common.CopySliceInt32ToInt(v.End)))
|
||
//}
|
||
if len(pack) > 0 {
|
||
return pack, int(pack[0].IndexType)
|
||
}
|
||
|
||
return pack, 0
|
||
}
|
||
|
||
// CheckIsCanHit 检查是否可以打枪
|
||
func (this *SceneEx) CheckIsCanHit() bool {
|
||
pt := 0 //特殊牌型数量
|
||
isHit := 0 //几个人可以打枪
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
if v.cardsO.PokerType != 0 {
|
||
pt++
|
||
}
|
||
//全垒打: 打枪所有人并且至少打3人
|
||
if len(v.winThreePos) >= 3 && len(v.winThreePos) == this.gamePlayerNum-1 {
|
||
this.isCanAllHitPos = v.Pos
|
||
}
|
||
if len(v.winThreePos) > 0 {
|
||
isHit++
|
||
}
|
||
}
|
||
}
|
||
// 人数至少2人
|
||
if /*pt == 0 &&*/ this.gamePlayerNum >= 2 && isHit > 0 {
|
||
return true
|
||
}
|
||
this.isCanAllHitPos = -1
|
||
return false
|
||
}
|
||
|
||
func (this *SceneEx) SelectCards(p *PlayerEx, indexType int) *rule.Group {
|
||
switch indexType {
|
||
case -1: // 使用特殊牌型
|
||
for k, v := range p.allGroup {
|
||
if k >= 1000000 {
|
||
p.cardsO = v
|
||
break
|
||
}
|
||
}
|
||
case -2: // 使用牌值最大的牌型
|
||
this.GetMaxCardsO(p)
|
||
|
||
// 真人默认选牌规则
|
||
if !p.IsRob && p.defGroup != nil {
|
||
p.cardsO = p.defGroup
|
||
}
|
||
}
|
||
|
||
if indexType > 10000 { // 从推荐牌中选一个
|
||
c := p.allGroup[indexType]
|
||
if c != nil {
|
||
p.cardsO = c
|
||
}
|
||
}
|
||
|
||
// 还没有确认就随机推荐一个
|
||
if p.cardsO == nil || p.cardsO.PokerType == -1 {
|
||
for k, v := range p.allGroup {
|
||
p.cardsO = v
|
||
if k >= 1000000 {
|
||
break
|
||
}
|
||
}
|
||
logger.Logger.Tracef("随机推荐:SnId(%v) %v", p.SnId, p.cardsO)
|
||
}
|
||
return p.cardsO
|
||
}
|
||
|
||
// SendSelectCards 玩家选择特定的牌显示
|
||
func (this *SceneEx) SendSelectCards(player *PlayerEx, indexType int, opcode int64) {
|
||
ShowCardsO := this.SelectCards(player, indexType)
|
||
|
||
pack := &thirteen.SCThirteenPlayerOp{
|
||
OpRetCode: thirteen.OpResultCode_OPRC_Sucess,
|
||
OpCode: int32(opcode),
|
||
Pos: proto.Int32(int32(player.Pos)),
|
||
Cards: &thirteen.Poker{},
|
||
}
|
||
|
||
if indexType == -1 || indexType >= 1000000 { // 特殊牌
|
||
pack.Cards.Head = common.CopySliceIntToInt32(player.cards[:3])
|
||
pack.Cards.Mid = common.CopySliceIntToInt32(player.cards[3:8])
|
||
pack.Cards.End = common.CopySliceIntToInt32(player.cards[8:])
|
||
} else {
|
||
// 自动组牌或玩家自选
|
||
pack.Cards.Head = common.CopySliceIntToInt32(ShowCardsO.Head[:])
|
||
pack.Cards.Mid = common.CopySliceIntToInt32(ShowCardsO.Mid[:])
|
||
pack.Cards.End = common.CopySliceIntToInt32(ShowCardsO.End[:])
|
||
pack.Cards.IsDP = this.logic.IsDP(ShowCardsO.Head, ShowCardsO.Mid, ShowCardsO.End)
|
||
}
|
||
pack.Cards.IndexType = proto.Int32(int32(this.FormatCards(ShowCardsO)))
|
||
pack.Cards.Pos = int32(player.GetPos())
|
||
proto.SetDefaults(pack)
|
||
logger.Logger.Trace("SCThirteenPlayerOp1:", pack)
|
||
player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
|
||
|
||
pack.Cards.Head = nil
|
||
pack.Cards.Mid = nil
|
||
pack.Cards.End = nil
|
||
pack.Cards.IndexType = 0
|
||
pack.Cards.IsDP = false
|
||
logger.Logger.Trace("SCThirteenPlayerOp2:", pack)
|
||
this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, player.GetSid())
|
||
for _, v := range this.seats {
|
||
if v == nil {
|
||
continue
|
||
}
|
||
if v.SnId != player.SnId && v.IsRobot() {
|
||
logger.Logger.Trace("SCThirteenPlayerOpRobot:", pack)
|
||
v.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) FormatCards(cardsO *rule.Group) int {
|
||
num := 0
|
||
if cardsO != nil && cardsO.PokerType != 0 {
|
||
num = cardsO.PokerType * 1000000
|
||
} else if cardsO != nil && cardsO.PokerType == 0 && cardsO.Head[0] != -1 {
|
||
num += this.logic.GetType(cardsO.Head[:]) * 10000
|
||
num += this.logic.GetType(cardsO.Mid[:]) * 100
|
||
num += this.logic.GetType(cardsO.End[:])
|
||
}
|
||
return num
|
||
}
|
||
|
||
// GetMinCards 默认获取玩家最小牌值的类型
|
||
func (this *SceneEx) GetMinCards(player *PlayerEx) {
|
||
min := 1000000
|
||
for v, m := range player.allGroup {
|
||
sum := 0
|
||
if v >= 1000000 {
|
||
continue
|
||
}
|
||
a := v / 10000
|
||
b := (v - a*10000) / 100
|
||
c := v - a*10000 - b*100
|
||
s := []int{a, b, c}
|
||
for _, k := range s {
|
||
if k >= 1 && k <= 20 {
|
||
sum += 20 - k
|
||
}
|
||
}
|
||
if min >= sum {
|
||
min = sum
|
||
player.cardsO = m
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) GetRandsType() (playerCards [13]int) {
|
||
//r := rand.Intn(15) + 1
|
||
//全垒打
|
||
//playerCards = [13]int{9, 9 + 13, 9 + 13*2, 2, 3, 4, 5, 6, 3 + 13, 4 + 13, 5 + 13, 6 + 13, 7 + 13}
|
||
//return
|
||
c := [][13]int{
|
||
//清龙
|
||
{39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51},
|
||
//一条龙
|
||
{13, 14, 28, 29, 30, 44, 45, 7, 34, 9, 23, 11, 51},
|
||
//十二皇族
|
||
{9, 10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51},
|
||
//三同花顺
|
||
{1, 2, 3, 4, 5, 15, 16, 17, 18, 19, 27, 28, 29},
|
||
//三分天下
|
||
{10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51, 13},
|
||
//全大
|
||
{7, 21, 35, 23, 11, 38, 51, 33, 48, 49, 50, 12, 25},
|
||
//全小
|
||
{14, 27, 40, 15, 28, 41, 4, 17, 5, 18, 6, 19, 32},
|
||
//凑一色
|
||
{13, 14, 40, 16, 42, 18, 44, 19, 46, 47, 23, 49, 25},
|
||
//四套三条
|
||
{5, 18, 44, 6, 19, 32, 7, 33, 46, 10, 23, 36, 50},
|
||
//五对三条
|
||
{17, 30, 5, 31, 6, 32, 8, 47, 23, 36, 12, 25, 38},
|
||
//六对半
|
||
{17, 30, 5, 31, 6, 32, 8, 47, 23, 36, 38, 51, 39},
|
||
//三顺子
|
||
{1, 28, 16, 17, 18, 30, 31, 45, 20, 8, 36, 50, 12},
|
||
//三同花
|
||
{2, 3, 6, 4 + 13, 8 + 13, 9 + 13, 13, 25, 31, 34, 27, 28, 29},
|
||
}
|
||
if this.r < 12 {
|
||
this.r++
|
||
} else {
|
||
this.r = 1
|
||
}
|
||
playerCards = c[this.r]
|
||
return
|
||
}
|
||
|
||
// SortCards 把所有牌排序
|
||
//func (this *SceneEx) SortCards() {
|
||
// //确定所有玩家拿可以拿到的最大牌型
|
||
// for _, player := range this.players {
|
||
// if player != nil && player.IsGameing() {
|
||
// this.GetMaxCardsO(player)
|
||
// }
|
||
// }
|
||
// //计算总分数
|
||
// this.CountScore()
|
||
// scoreMap := make(map[int]int64)
|
||
// for _, player := range this.seats {
|
||
// if player != nil && player.IsGameing() {
|
||
// score := int64(0)
|
||
// //计算玩家输赢的分数
|
||
// for _, v := range player.score {
|
||
// score += v
|
||
// }
|
||
// scoreMap[player.Pos] = score
|
||
// }
|
||
// }
|
||
// for i := 0; i < 6; i++ {
|
||
// max := int64(-1000)
|
||
// pos := -1
|
||
// for k, v := range scoreMap {
|
||
// if max <= v {
|
||
// max = v
|
||
// pos = k
|
||
// }
|
||
// }
|
||
// if pos != -1 {
|
||
// delete(scoreMap, pos)
|
||
// this.cardsSlice = append(this.cardsSlice, this.seats[pos].cards)
|
||
// this.seats[pos].cards = [13]int{-1}
|
||
// if len(scoreMap) == 0 {
|
||
// break
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
// GetMaxCardsO 一副牌中拿最大牌值的方案
|
||
func (this *SceneEx) GetMaxCardsO(p *PlayerEx) {
|
||
if p != nil {
|
||
p.cardsO = rule.GetMaxCard(p.allGroup)
|
||
}
|
||
}
|
||
|
||
// cardsSort 按从大到小的排列发牌
|
||
func (this *SceneEx) cardsSort(cardArr [][13]int, cardGroup []map[int]*rule.Group) {
|
||
type P struct {
|
||
i int
|
||
score [6]int64
|
||
cardsO *rule.Group
|
||
cards [13]int
|
||
group map[int]*rule.Group
|
||
winThreePos map[int]int64
|
||
winAllPlayers map[int]int64
|
||
}
|
||
|
||
var ps []*P
|
||
for i := 0; i < len(cardArr); i++ {
|
||
p := &P{
|
||
i: i,
|
||
score: [6]int64{0, 0, 0, 0, 0, 0},
|
||
cardsO: rule.GetMaxCard(cardGroup[i]),
|
||
cards: cardArr[i],
|
||
group: cardGroup[i],
|
||
winThreePos: map[int]int64{},
|
||
winAllPlayers: map[int]int64{},
|
||
}
|
||
ps = append(ps, p)
|
||
}
|
||
|
||
var specialTypeNum int
|
||
for i := 0; i < len(cardArr); i++ {
|
||
player := ps[i]
|
||
|
||
// 计算特殊牌型分数
|
||
ptRate := int64(0)
|
||
if player.cardsO.PokerType != 0 {
|
||
specialTypeNum++
|
||
//特殊牌处理
|
||
if player.cardsO.PokerType >= 1 && player.cardsO.PokerType <= 13 {
|
||
ptRate = rule.SpecialScore[player.cardsO.PokerType]
|
||
}
|
||
}
|
||
|
||
if specialTypeNum > 0 {
|
||
for _, p := range ps {
|
||
if player.cardsO.PokerType != 0 {
|
||
if player.i == p.i {
|
||
continue
|
||
}
|
||
if p.cardsO.PokerType == 0 {
|
||
player.score[3] += ptRate
|
||
p.score[3] -= ptRate
|
||
player.winAllPlayers[p.i] += ptRate
|
||
p.winAllPlayers[player.i] -= ptRate
|
||
} else if p.cardsO.PokerType != 0 {
|
||
//多个特殊牌型处理
|
||
if player.cardsO.PokerType < p.cardsO.PokerType {
|
||
player.score[3] += ptRate
|
||
p.score[3] -= ptRate
|
||
player.winAllPlayers[p.i] += ptRate
|
||
p.winAllPlayers[player.i] -= ptRate
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算普通牌型分数
|
||
for _, p := range ps {
|
||
if player.cardsO.PokerType == 0 {
|
||
if player.i == p.i || p.cardsO.PokerType != 0 {
|
||
continue
|
||
}
|
||
s := 0
|
||
score := int64(0) //赢的分数
|
||
//头墩
|
||
rate := int64(1)
|
||
n := this.logic.CompareHead(player.cardsO.Head, p.cardsO.Head)
|
||
h := this.logic.GetType(player.cardsO.Head[:])
|
||
if h == rule.PokersTypeThree {
|
||
rate += 2
|
||
}
|
||
if n == 1 {
|
||
player.score[0] += rate
|
||
p.score[0] -= rate
|
||
score += rate
|
||
player.winAllPlayers[p.i] += rate
|
||
p.winAllPlayers[player.i] -= rate
|
||
s++
|
||
}
|
||
//中墩
|
||
rate = int64(1)
|
||
n = this.logic.CompareFive(player.cardsO.Mid, p.cardsO.Mid)
|
||
m := this.logic.GetType(player.cardsO.Mid[:])
|
||
if m == rule.PokersTypeFullHouse {
|
||
rate += 1
|
||
} else if m == rule.PokersTypeFour {
|
||
rate += 6
|
||
} else if m == rule.PokersTypeStraightFlush {
|
||
rate += 8
|
||
} else if m == rule.PokersTypeFive {
|
||
rate += 10
|
||
}
|
||
if n == 1 {
|
||
player.score[1] += rate
|
||
p.score[1] -= rate
|
||
score += rate
|
||
player.winAllPlayers[p.i] += rate
|
||
p.winAllPlayers[player.i] -= rate
|
||
s++
|
||
}
|
||
//尾墩
|
||
rate = int64(1)
|
||
n = this.logic.CompareFive(player.cardsO.End, p.cardsO.End)
|
||
e := this.logic.GetType(player.cardsO.End[:])
|
||
if e == rule.PokersTypeFour {
|
||
rate += 3
|
||
} else if e == rule.PokersTypeStraightFlush {
|
||
rate += 4
|
||
} else if e == rule.PokersTypeFive {
|
||
rate += 5
|
||
}
|
||
if n == 1 {
|
||
player.score[2] += rate
|
||
p.score[2] -= rate
|
||
score += rate
|
||
player.winAllPlayers[p.i] += rate
|
||
p.winAllPlayers[player.i] -= rate
|
||
s++
|
||
}
|
||
if s == 3 {
|
||
player.winThreePos[p.i] = score
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 打枪分
|
||
isCanAllHitPos := -1
|
||
pt := 0 //特殊牌型数量
|
||
isHit := 0 //几个人可以打枪
|
||
for _, v := range ps {
|
||
if v.cardsO.PokerType != 0 {
|
||
pt++
|
||
}
|
||
//全垒打: 打枪所有人并且至少打3人
|
||
if len(v.winThreePos) >= 3 && len(v.winThreePos) == this.gamePlayerNum-1 {
|
||
isCanAllHitPos = v.i
|
||
}
|
||
if len(v.winThreePos) > 0 {
|
||
isHit++
|
||
}
|
||
}
|
||
// 可以打枪:没有特殊牌型,人数至少2人
|
||
if pt == 0 && this.gamePlayerNum >= 2 && isHit > 0 {
|
||
for _, playerEx := range ps {
|
||
if len(playerEx.winThreePos) > 0 {
|
||
for k, v := range playerEx.winThreePos {
|
||
// 打枪
|
||
ps[k].score[4] -= v
|
||
ps[k].winAllPlayers[playerEx.i] -= v
|
||
playerEx.score[4] += v
|
||
playerEx.winAllPlayers[k] += v
|
||
// 全垒打分数
|
||
if playerEx.i == isCanAllHitPos {
|
||
ps[k].score[5] -= v
|
||
ps[k].winAllPlayers[playerEx.i] -= v
|
||
playerEx.score[5] += v
|
||
playerEx.winAllPlayers[k] += v
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
sort.Slice(ps, func(i, j int) bool {
|
||
var a, b int64
|
||
for _, v := range ps[i].score {
|
||
a += v
|
||
}
|
||
for _, v := range ps[j].score {
|
||
b += v
|
||
}
|
||
return a > b
|
||
})
|
||
for i := 0; i < len(cardArr); i++ {
|
||
cardArr[i] = ps[i].cards
|
||
cardGroup[i] = ps[i].group
|
||
}
|
||
}
|
||
|
||
// CountScore 计算总分数
|
||
func (this *SceneEx) CountScore() {
|
||
//计算头、中、尾道、特殊牌分数
|
||
for _, player := range this.seats {
|
||
if player != nil && player.IsGameing() {
|
||
this.GetScore(player)
|
||
// 离场补偿分
|
||
if this.LeaveNum > 0 {
|
||
player.score[6] = int64(this.LeaveNum) * int64(this.GetDBGameFree().GetLeaveCombat())
|
||
}
|
||
}
|
||
}
|
||
for _, player := range this.seats {
|
||
if player != nil && player.IsGameing() {
|
||
for i := 0; i < 3; i++ {
|
||
player.tableScore[i] = player.score[i] - player.tableScore[i+3]
|
||
}
|
||
}
|
||
}
|
||
|
||
this.entryHitState = this.CheckIsCanHit()
|
||
|
||
if !this.entryHitState {
|
||
//如果不能进入打枪阶段 不计算打枪和全垒打
|
||
return
|
||
}
|
||
//计算打枪分数
|
||
for _, playerEx := range this.players {
|
||
if playerEx != nil && playerEx.IsGameing() {
|
||
if len(playerEx.winThreePos) > 0 {
|
||
for k, v := range playerEx.winThreePos {
|
||
// 并且都不是特殊牌型
|
||
if playerEx.cardsO.PokerType != 0 || this.seats[k].cardsO.PokerType != 0 {
|
||
continue
|
||
}
|
||
// 打枪
|
||
this.seats[k].score[4] -= v
|
||
this.seats[k].winAllPlayers[playerEx.Pos] -= v
|
||
playerEx.score[4] += v
|
||
playerEx.winAllPlayers[k] += v
|
||
// 全垒打分数
|
||
if playerEx.Pos == this.isCanAllHitPos {
|
||
this.seats[k].score[5] -= v
|
||
this.seats[k].winAllPlayers[playerEx.Pos] -= v
|
||
playerEx.score[5] += v
|
||
playerEx.winAllPlayers[k] += v
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) GetInGameNum() {
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
this.gamePlayerNum++
|
||
if v.IsRob {
|
||
this.robotNum++
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取最小牌
|
||
func (this *SceneEx) GetAllMinCards() (a [13]int) {
|
||
for i := len(this.cardsSlice) - 1; i >= 0; i-- {
|
||
a = this.cardsSlice[i]
|
||
this.cardsSlice[i] = [13]int{-1}
|
||
this.cardsSlice = append(this.cardsSlice[:i], this.cardsSlice[i+1:]...)
|
||
break
|
||
}
|
||
return [13]int{-1}
|
||
}
|
||
|
||
// 获取最大牌
|
||
func (this *SceneEx) GetAllMaxCards() (a [13]int) {
|
||
if this.nowMaxCardsIsIn {
|
||
this.nowMaxCardsIsIn = false
|
||
}
|
||
for i := 0; i < len(this.cardsSlice); i++ {
|
||
a = this.cardsSlice[i]
|
||
this.cardsSlice = append(this.cardsSlice[:i], this.cardsSlice[i+1:]...)
|
||
break
|
||
}
|
||
return [13]int{-1}
|
||
}
|
||
|
||
// 随机拿牌
|
||
func (this *SceneEx) GetRandCards(b bool) (a [13]int) {
|
||
n := len(this.cardsSlice)
|
||
if n == 0 {
|
||
return [13]int{-1}
|
||
}
|
||
r := rand.Intn(n)
|
||
if !b {
|
||
if this.nowMaxCardsIsIn {
|
||
//最大牌还在
|
||
//不带最大牌随机
|
||
if n == 1 {
|
||
//就剩一副牌
|
||
return [13]int{-1}
|
||
}
|
||
if r == 0 {
|
||
//随到最大牌
|
||
r++
|
||
}
|
||
}
|
||
} else {
|
||
//带最大牌随机
|
||
if this.nowMaxCardsIsIn {
|
||
if r == 0 {
|
||
this.nowMaxCardsIsIn = false
|
||
}
|
||
}
|
||
}
|
||
|
||
a = this.cardsSlice[r]
|
||
this.cardsSlice = append(this.cardsSlice[:r], this.cardsSlice[r+1:]...)
|
||
return
|
||
}
|
||
|
||
func (this *SceneEx) ShowCards() {
|
||
var allCards []*thirteen.Poker
|
||
for _, p := range this.players {
|
||
if p != nil && p.IsGameing() && p.cardsO != nil {
|
||
var hitScore []*thirteen.HitScore
|
||
for k, v := range p.winThreePos {
|
||
pck := &thirteen.HitScore{
|
||
Pos: proto.Int32(int32(k)),
|
||
Score: proto.Int64(v),
|
||
}
|
||
hitScore = append(hitScore, pck)
|
||
}
|
||
pk := &thirteen.Poker{
|
||
IndexType: proto.Int32(int32(this.FormatCards(p.cardsO))),
|
||
Head: common.IntSliceToInt32(p.cardsO.Head[:]),
|
||
Mid: common.IntSliceToInt32(p.cardsO.Mid[:]),
|
||
End: common.IntSliceToInt32(p.cardsO.End[:]),
|
||
IsDP: p.isDP,
|
||
Pos: int32(p.GetPos()),
|
||
Score: p.score[:],
|
||
Hit: hitScore,
|
||
TableScore: p.tableScore[:],
|
||
Cards: common.IntSliceToInt32(p.cards[:]),
|
||
}
|
||
allCards = append(allCards, pk)
|
||
}
|
||
}
|
||
|
||
opCode := 0
|
||
if this.GetSceneState().GetState() == rule.ThirteenWaterSceneStateHit {
|
||
opCode = 1 // 打枪
|
||
}
|
||
|
||
pc := &thirteen.SCThirteenShowCards{
|
||
OpCode: proto.Int32(int32(opCode)),
|
||
AllCards: allCards,
|
||
}
|
||
proto.SetDefaults(pc)
|
||
logger.Logger.Trace("SCThirteenWaterShowCards is pc: ", pc)
|
||
this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenShowCards), pc, 0)
|
||
}
|
||
|
||
func (this *SceneEx) CountBilled() {
|
||
var totalWinScore, totalLoseScore int64 // 总赢分
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
// 玩家总分
|
||
v.totalScore = 0
|
||
for _, vv := range v.score[:6] {
|
||
v.totalScore += vv
|
||
}
|
||
v.totalScore *= int64(this.GetBaseScore())
|
||
if v.totalScore > 0 {
|
||
if v.totalScore > v.Coin {
|
||
v.totalScore = v.Coin
|
||
}
|
||
} else if v.totalScore < 0 {
|
||
if v.totalScore < -v.Coin {
|
||
v.totalScore = -v.Coin
|
||
}
|
||
}
|
||
// 总输赢分
|
||
if v.totalScore > 0 {
|
||
totalWinScore += v.totalScore
|
||
} else if v.totalScore < 0 {
|
||
totalLoseScore += -v.totalScore
|
||
}
|
||
logger.Logger.Tracef("玩家[%d]总赢分: %d", v.GetPos(), v.totalScore)
|
||
}
|
||
}
|
||
|
||
if totalWinScore > totalLoseScore {
|
||
// 赢分大,输分玩家分数不需要修改
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
if v.totalScore > 0 {
|
||
v.gainCoin = int64(float64(v.totalScore) * float64(totalLoseScore) / float64(totalWinScore))
|
||
} else if v.totalScore < 0 {
|
||
v.gainCoin = v.totalScore
|
||
}
|
||
}
|
||
}
|
||
} else if totalWinScore < totalLoseScore {
|
||
// 输分大,赢分玩家分数不需要修改
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
if v.totalScore > 0 {
|
||
v.gainCoin = v.totalScore
|
||
} else if v.totalScore < 0 {
|
||
v.gainCoin = int64(float64(v.totalScore) * float64(totalLoseScore) / float64(totalWinScore))
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
for _, v := range this.players {
|
||
if v != nil && v.IsGameing() {
|
||
v.gainCoin = v.totalScore
|
||
}
|
||
}
|
||
}
|
||
|
||
for _, playerEx := range this.players {
|
||
if playerEx == nil || !playerEx.IsGameing() {
|
||
continue
|
||
}
|
||
if playerEx.gainCoin > 0 {
|
||
gainCoin := playerEx.gainCoin
|
||
playerEx.gainCoin = playerEx.gainCoin * int64(10000-this.GetDBGameFree().GetTaxRate()) / 10000
|
||
playerEx.taxCoin = gainCoin - playerEx.gainCoin
|
||
}
|
||
logger.Logger.Tracef("玩家分数 %v, coin:%v tax:%v win:%v", playerEx.SnId, playerEx.gainCoin, playerEx.taxCoin, playerEx.winAllPlayers)
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) BackupPlayer(p *PlayerEx, isBilled bool) {
|
||
testLog := make([]string, len(p.TestLog))
|
||
copy(testLog, p.TestLog)
|
||
skinId := int32(0)
|
||
if p.Skin != nil {
|
||
skinId = p.Skin.ModId
|
||
}
|
||
this.PlayerBackup[p.SnId] = &PlayerData{
|
||
SnId: p.SnId,
|
||
cards: p.cards,
|
||
cardsO: p.cardsO,
|
||
isDP: p.isDP,
|
||
gainCoin: p.gainCoin,
|
||
taxCoin: p.taxCoin,
|
||
deterMine: p.deterMine,
|
||
score: p.score,
|
||
tableScore: p.tableScore,
|
||
winThreePos: p.winThreePos,
|
||
winAllPlayers: p.winAllPlayers,
|
||
isStand: p.isStand,
|
||
isBilled: isBilled,
|
||
IsRob: p.IsRob,
|
||
Pos: p.Pos,
|
||
Coin: p.Coin,
|
||
StartCoin: p.StartCoin,
|
||
Head: p.Head,
|
||
flag: p.GetFlag(),
|
||
Platform: p.Platform,
|
||
Channel: p.Channel,
|
||
PackageID: p.PackageID,
|
||
PromoterTree: p.PromoterTree,
|
||
InviterId: p.InviterId,
|
||
WBLevel: p.WBLevel,
|
||
CurIsWin: p.CurIsWin,
|
||
BeUnderAgentCode: p.BeUnderAgentCode,
|
||
Name: p.Name,
|
||
Sex: p.Sex,
|
||
City: p.City,
|
||
Longitude: p.Longitude,
|
||
Latitude: p.Latitude,
|
||
AgentCode: p.AgentCode,
|
||
HeadOutLine: p.HeadOutLine,
|
||
VIP: p.VIP,
|
||
allGroup: p.allGroup,
|
||
TestLog: testLog,
|
||
RoleId: p.PlayerData.GetRoleId(),
|
||
PlayerPool: p.playerPool,
|
||
SkinId: skinId,
|
||
}
|
||
}
|
||
|
||
func (this *SceneEx) SendHandCardOdds() {
|
||
var realPlayersGood, realPlayersBad, realPlayers, robotPlayers []*PlayerEx
|
||
var G, B int32
|
||
for _, seat := range this.seats {
|
||
if seat != nil && seat.IsGameing() {
|
||
if seat.IsRob {
|
||
robotPlayers = append(robotPlayers, seat)
|
||
} else {
|
||
seat.odds = this.GetPlayerOdds(seat.Player, int(this.GameId), this.robotNum > 0)
|
||
seat.playerPool = int(this.PlayerPoolOdds(seat.Player))
|
||
if seat.odds > 0 {
|
||
realPlayersGood = append(realPlayersGood, seat)
|
||
G += seat.odds
|
||
} else if seat.odds < 0 {
|
||
realPlayersBad = append(realPlayersBad, seat)
|
||
B -= seat.odds
|
||
} else {
|
||
realPlayers = append(realPlayers, seat)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
this.poker.Init()
|
||
|
||
this.cardsArr = make([][13]int, this.poker.N*4)
|
||
this.cardsGroup = make([]map[int]*rule.Group, this.poker.N*4)
|
||
for k := range this.cardsArr {
|
||
this.cardsArr[k] = this.poker.Get13Crads()
|
||
this.cardsGroup[k] = this.logic.Suggest(this.cardsArr[k])
|
||
}
|
||
|
||
f := func(players *[]*PlayerEx) {
|
||
if players == nil || len(*players) == 0 {
|
||
return
|
||
}
|
||
var p *PlayerEx // 发牌给这个玩家
|
||
var a int
|
||
for _, v := range *players {
|
||
a += int(math.Abs(float64(v.odds)))
|
||
}
|
||
n := this.RandInt(a)
|
||
total := 0
|
||
for k, v := range *players {
|
||
total += int(math.Abs(float64(v.odds)))
|
||
if n < total {
|
||
p = (*players)[k]
|
||
*players = append((*players)[:k], (*players)[k+1:]...)
|
||
break
|
||
}
|
||
}
|
||
|
||
var cards [13]int
|
||
var group map[int]*rule.Group
|
||
if p.odds > 0 {
|
||
// 拿好牌
|
||
cards = this.cardsArr[0]
|
||
this.cardsArr = this.cardsArr[1:]
|
||
group = this.cardsGroup[0]
|
||
this.cardsGroup = this.cardsGroup[1:]
|
||
} else {
|
||
// 拿坏牌
|
||
cards = this.cardsArr[len(this.cardsArr)-1]
|
||
this.cardsArr = this.cardsArr[:len(this.cardsArr)-1]
|
||
group = this.cardsGroup[len(this.cardsGroup)-1]
|
||
this.cardsGroup = this.cardsGroup[:len(this.cardsGroup)-1]
|
||
}
|
||
p.cards = cards
|
||
p.allGroup = group
|
||
}
|
||
|
||
// 需要换牌
|
||
isGood := len(realPlayersGood) > 0 && int32(this.RandInt(1000)) < G
|
||
isBad := len(realPlayersBad) > 0 && int32(this.RandInt(1000)) < B
|
||
logger.Logger.Tracef("Thirteen SendHandCardOdds Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B)
|
||
if isBad {
|
||
this.ctrlType = 2
|
||
}
|
||
if isGood && !isBad {
|
||
this.ctrlType = 1
|
||
}
|
||
if isGood || isBad {
|
||
// 按从大到小排序
|
||
this.cardsSort(this.cardsArr, this.cardsGroup)
|
||
|
||
// 发好牌
|
||
if isGood {
|
||
l := len(realPlayersGood)
|
||
for i := 0; i < l; i++ {
|
||
f(&realPlayersGood)
|
||
}
|
||
}
|
||
// 发坏牌
|
||
if isBad {
|
||
l := len(realPlayersBad)
|
||
for i := 0; i < l; i++ {
|
||
f(&realPlayersBad)
|
||
}
|
||
}
|
||
}
|
||
// 随机拿牌
|
||
for _, v := range this.players { // map随机
|
||
if v == nil || !v.IsGameing() || v.cards[0] != -1 {
|
||
continue
|
||
}
|
||
v.cards = this.cardsArr[0]
|
||
v.allGroup = this.cardsGroup[0]
|
||
this.cardsArr = this.cardsArr[1:]
|
||
this.cardsGroup = this.cardsGroup[1:]
|
||
}
|
||
|
||
for _, player := range this.players {
|
||
if player.IsGameing() && !player.IsRob {
|
||
logger.Logger.Trace("snid:", player.SnId)
|
||
player.TestLog = append(player.TestLog, fmt.Sprintf("随机换牌 Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B))
|
||
for _, v := range player.TestLog {
|
||
logger.Logger.Trace(v)
|
||
}
|
||
pack := &thirteen.SCThirteenTest{}
|
||
player.TestLog = append(player.TestLog, fmt.Sprintf("随机换牌 Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B))
|
||
pack.Data = strings.Join(player.TestLog, "\n")
|
||
proto.SetDefaults(pack)
|
||
player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenTest), pack)
|
||
logger.Logger.Trace("SnId: ", player.SnId, ";SCThirteenTest: ", pack)
|
||
}
|
||
}
|
||
}
|