game_sync/gamesrv/tienlen/scenedata_tienlen.go

2162 lines
67 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tienlen
import (
"encoding/json"
"fmt"
"math"
"math/rand"
"sort"
"strings"
"time"
"mongo.games.com/goserver/core/logger"
tienlenApi "mongo.games.com/game/api3th/smart/tienlen"
"mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/tienlen"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/tienlen"
"mongo.games.com/game/srvdata"
)
type BilledInfo struct {
Round int32 // 第几局
ChangeScore int64 // 积分变化
Score int64 // 结算后积分
}
type Item struct {
Id int32
Num int64
}
// 房间上的额外数据
type TienLenSceneData struct {
*base.Scene //场景
players map[int32]*TienLenPlayerData //玩家信息
seats [4]*TienLenPlayerData //玩家
poker *rule.Poker //扑克牌对象
curGamingPlayerNum int //当前在玩玩家数量
lastGamingPlayerNum int //上局参与游戏的人数
lastOpPos int32 //前一个出牌的玩家位置
currOpPos int32 //当前等待出牌的玩家位置
lastBombPos int32 //上一个出炸弹的玩家位置
curBombPos int32 //当前出炸弹的玩家位置
roundScore int32 //小轮分
startOpPos int32 //开始操作的玩家,拿最小牌的先出牌
curMinCard int32 //当局最小牌值
tianHuSnids []int32 //天胡玩家id
winSnids []int32 //赢家id
lastWinSnid int32 //上局赢家id
masterSnid int32 //房主
delCards [][]int32 //已出牌
delOrders []int32 //出牌顺序
isKongBomb bool //是否空放,打出炸弹没人能接
bombToEnd int //空放炸弹致底分翻倍次数
card_play_action_seq []string //出牌历史记录
card_play_action_seq_int32 [][]int32 //出牌历史记录
lastPos int32 //前一个玩家位置
isAllRob bool //是否是纯AI场
robotGamingNum int // 机器人玩家数量
allPlayerCards [][]int32 //所有玩家的牌
recordId string // 牌局记录id
testPokers []int32 // 发指定的牌,用于测试
cHintCards []int32 //客户端提示出牌记录
isCardsKu bool //是否是牌库
cardsKuId int32 //牌库ID
ctrlType int // 1控赢 2控输 0不控
BilledList map[int32]*[]*BilledInfo // 多轮结算记录, 玩家id:每局结算记录
RoundEndTime []int64 // 每局结束时间
RoundLogId []string // 每局牌局记录id
CustomLogSave bool // 是否已经保存日志
PlayerAward map[int32]*[]*model.Item // 房卡场最终奖励
}
func NewTienLenSceneData(s *base.Scene) *TienLenSceneData {
sceneEx := &TienLenSceneData{
Scene: s,
poker: rule.NewPoker(),
players: make(map[int32]*TienLenPlayerData),
BilledList: map[int32]*[]*BilledInfo{},
PlayerAward: make(map[int32]*[]*model.Item),
}
sceneEx.Clear()
return sceneEx
}
func (this *TienLenSceneData) init() bool {
this.tianHuSnids = []int32{}
this.winSnids = []int32{}
this.roundScore = 0
this.currOpPos = rule.InvalidePos
this.lastOpPos = rule.InvalidePos
this.curBombPos = rule.InvalidePos
this.lastBombPos = rule.InvalidePos
this.lastPos = rule.InvalidePos
this.UnmarkPass()
this.curGamingPlayerNum = 0
this.curMinCard = 0
this.delCards = [][]int32{}
this.delOrders = []int32{}
this.card_play_action_seq = []string{}
this.card_play_action_seq_int32 = [][]int32{}
this.bombToEnd = 0
this.allPlayerCards = [][]int32{}
this.ctrlType = 0
this.recordId, _ = model.AutoIncGameLogId()
if this.GetPlayerNum() == 0 {
this.SetPlayerNum(rule.MaxNumOfPlayer)
}
this.cHintCards = []int32{}
return true
}
func (this *TienLenSceneData) Clear() {
this.tianHuSnids = []int32{}
this.winSnids = []int32{}
this.roundScore = 0
this.currOpPos = rule.InvalidePos
this.lastOpPos = rule.InvalidePos
this.curBombPos = rule.InvalidePos
this.lastBombPos = rule.InvalidePos
this.lastPos = rule.InvalidePos
this.curGamingPlayerNum = 0
this.curMinCard = 0
this.UnmarkPass()
this.delCards = [][]int32{}
this.delOrders = []int32{}
this.card_play_action_seq = []string{}
this.card_play_action_seq_int32 = [][]int32{}
this.bombToEnd = 0
this.isAllRob = false
this.robotGamingNum = 0
this.allPlayerCards = [][]int32{}
this.ctrlType = 0
this.recordId, _ = model.AutoIncGameLogId()
for _, player := range this.players {
if player != nil {
player.UnmarkFlag(base.PlayerState_WaitNext)
}
}
this.cHintCards = []int32{}
}
func (this *TienLenSceneData) CanStart() bool {
if this.GetGaming() == true {
return false
}
nPlayerCount := this.GetPlayerCnt()
nRobotCount := this.GetRobotCnt()
if this.IsMatchScene() {
if nRobotCount == 4 {
this.isAllRob = true
}
if nPlayerCount == 4 { // 比赛场4人开赛
return true
} else {
return false
}
}
if this.IsCustom() {
return this.IsAllReady() && this.GetPlayerCnt() >= this.GetPlayerNum()
}
// 房间人数>=2开始,并且有真人或者是预创建房间,并且有房主
if nPlayerCount >= 2 && (this.GetRealPlayerNum() > 0 || this.IsPreCreateScene()) { //人数>=2开始
return true
}
return false
}
func (this *TienLenSceneData) GetPlayerCnt() int {
var cnt int
for i := 0; i < this.GetPlayerNum(); i++ {
playerEx := this.seats[i]
if playerEx == nil {
continue
}
cnt++
}
return cnt
}
func (this *TienLenSceneData) GetGameingPlayerCnt() int {
var cnt int
for i := 0; i < this.GetPlayerNum(); i++ {
playerEx := this.seats[i]
if playerEx == nil {
continue
}
if playerEx.IsGameing() {
cnt++
}
}
return cnt
}
func (this *TienLenSceneData) GetRobotCnt() int {
var cnt int
for i := 0; i < this.GetPlayerNum(); i++ {
playerEx := this.seats[i]
if playerEx == nil {
continue
}
if playerEx.IsRob {
cnt++
}
}
return cnt
}
func (this *TienLenSceneData) GetGameingRobotCnt() int {
var cnt int
for i := 0; i < this.GetPlayerNum(); i++ {
playerEx := this.seats[i]
if playerEx == nil {
continue
}
if playerEx.IsRob && playerEx.IsGameing() {
cnt++
}
}
return cnt
}
func (this *TienLenSceneData) GetSeatPlayerCnt() int {
var cnt int
for i := 0; i < this.GetPlayerNum(); i++ {
playerEx := this.seats[i]
if playerEx == nil {
continue
}
cnt++
}
return cnt
}
func (this *TienLenSceneData) BroadcastPlayerLeave(p *base.Player, reason int) {
scLeavePack := &tienlen.SCTienLenPlayerLeave{
Pos: proto.Int(p.GetPos()),
}
proto.SetDefaults(scLeavePack)
logger.Logger.Trace("SCTienLenPlayerLeave: ", p.SnId, " scLeavePack: ", scLeavePack)
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenPlayerLeave), scLeavePack, p.GetSid())
}
func (this *TienLenSceneData) BroadcastAudienceNum(p *base.Player) {
pack := &tienlen.SCTienLenUpdateAudienceNum{
AudienceNum: proto.Int(this.GetAudiencesNum()),
}
proto.SetDefaults(pack)
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenUpdateAudienceNum), pack, p.GetSid())
}
func (this *TienLenSceneData) delPlayer(p *base.Player) {
if p, exist := this.players[p.SnId]; exist {
this.seats[p.GetPos()] = nil
delete(this.players, p.SnId)
}
}
func (this *TienLenSceneData) OnPlayerLeave(p *base.Player, reason int) {
// 清除上局赢家id
if this.lastWinSnid == p.SnId {
this.lastWinSnid = 0
}
this.delPlayer(p)
this.BroadcastPlayerLeave(p, reason)
if !p.IsRob { //真人离开
hadSeat := false
for _, seat := range this.seats {
if seat != nil {
hadSeat = true
break
}
}
if !hadSeat { //座位上没有人了,把观众踢出去
audiences := this.GetAudiences()
for _, audience := range audiences {
if audience != nil {
this.AudienceLeave(audience, common.PlayerLeaveReason_RoomClose)
}
}
}
}
}
func (this *TienLenSceneData) SceneDestroy(force bool) {
this.SaveCustomLog()
//销毁房间
this.Scene.Destroy(force)
}
// 广播房主更换
func (this *TienLenSceneData) BroadcastUpdateMasterSnid() {
pack := &tienlen.SCTienLenUpdateMasterSnid{
MasterSnid: proto.Int32(this.masterSnid),
}
proto.SetDefaults(pack)
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenUpdateMasterSnid), pack, 0)
logger.Logger.Trace("BroadcastUpdateMasterSnid ", pack)
}
// 广播当前操作的玩家位置
func (this *TienLenSceneData) BroadcastOpPos() {
if this.currOpPos != rule.InvalidePos && this.seats[this.currOpPos] != nil && this.seats[this.currOpPos].IsRobot() {
//计算其它人手牌,所有牌-出过的牌-自己手牌
othercards := []int32{}
handcards := []int32{}
/* for i := int32(0); i < 52; i++ {
othercards = append(othercards, i)
}*/
for _, cards := range this.allPlayerCards {
for _, card := range cards {
if card != -1 {
othercards = append(othercards, tienlenApi.CardToAiCard[card])
}
}
}
logger.Logger.Info("--------------------------------------othercards = ", othercards)
card_play_action_seqs := []string{}
for _, cards := range this.card_play_action_seq_int32 {
//转棋牌到AI中的牌
aicards := []int32{}
for _, card := range cards {
aicards = append(aicards, tienlenApi.CardToAiCard[card])
}
card_play_action_seqs = append(card_play_action_seqs, common.Int32SliceToString(aicards, ","))
othercards = common.DelSliceIn32s(othercards, aicards)
}
//删除手牌
for _, v := range this.seats[this.currOpPos].cards {
if v != -1 {
aicard := tienlenApi.CardToAiCard[v]
othercards = common.DelSliceInt32(othercards, aicard)
handcards = append(handcards, aicard)
}
}
//logger.Logger.Infof("%v出牌历史记录%v",this.currOpPos,this.card_play_action_seq)
//logger.Logger.Infof("%v出牌历史记录%v",this.currOpPos,common.StringSliceToString(card_play_action_seqs,"|"))
//logger.Logger.Infof("%v手牌%v 数量:%v",this.currOpPos,handcards,len(handcards))
//logger.Logger.Infof("%v其它人牌%v 数量:%v",this.currOpPos,othercards,len(othercards))
lastmove := make(map[int][]int32)
numCardsLeft := make(map[int]int)
playedCards := make(map[int][]int32)
for pos, v := range this.seats {
if v != nil && v.IsGameing() {
//出过的牌
delcards := []int32{}
for _, cards := range v.delCards {
for _, card := range cards {
aicard := tienlenApi.CardToAiCard[card]
delcards = append(delcards, aicard)
}
}
//logger.Logger.Infof("%v出过的牌%v",pos,delcards)
//logger.Logger.Infof("%v剩余的牌%v",pos,13-len(delcards))
playedCards[pos] = delcards
numCardsLeft[pos] = 13 - len(delcards)
last := len(v.delCards)
if last > 0 {
aicards := []int32{}
for _, card := range v.delCards[last-1] {
aicards = append(aicards, tienlenApi.CardToAiCard[card])
}
//logger.Logger.Infof("%v最后一次出牌%v",pos,aicards)
lastmove[pos] = aicards
} else {
//logger.Logger.Infof("%v最后一次出牌%v",pos,"")
lastmove[pos] = []int32{}
}
} else {
numCardsLeft[pos] = 0
}
}
isFirstHand := false
if this.lastOpPos == rule.InvalidePos { //首出玩家
//有赢家,赢家先出,出牌不受限制
//无赢家,手持最小牌先出,最小牌必先出
winPos := this.FindWinPos()
if winPos == -1 { //无赢家
isFirstHand = true
}
}
isWin := true
B := int32(0)
for _, seat := range this.seats {
if seat != nil && seat.IsGameing() {
if !seat.IsRob {
seat.odds = this.GetPlayerOdds(seat.Player, int(this.GameId), this.robotGamingNum > 0)
if seat.odds < 0 {
B -= seat.odds
}
}
}
}
if B < 0 {
isWin = false
}
isTienLenYule := this.IsTienLenYule()
pack := &tienlen.SCTienLenAIData{
BombNum: 0, //炸弹数量
CardPlayActionSeq: proto.String(strings.Replace(common.StringSliceToString(card_play_action_seqs, "|"), "-1", "", -1)),
LastMove_0: proto.String(common.Int32SliceToString(lastmove[0], ",")),
LastMove_1: proto.String(common.Int32SliceToString(lastmove[1], ",")),
LastMove_2: proto.String(common.Int32SliceToString(lastmove[2], ",")),
LastMove_3: proto.String(common.Int32SliceToString(lastmove[3], ",")),
NumCardsLeft_0: proto.Int32(int32(numCardsLeft[0])),
NumCardsLeft_1: proto.Int32(int32(numCardsLeft[1])),
NumCardsLeft_2: proto.Int32(int32(numCardsLeft[2])),
NumCardsLeft_3: proto.Int32(int32(numCardsLeft[3])),
OtherHandCards: proto.String(common.Int32SliceToString(othercards, ",")),
PlayedCards_0: proto.String(common.Int32SliceToString(playedCards[0], ",")),
PlayedCards_1: proto.String(common.Int32SliceToString(playedCards[1], ",")),
PlayedCards_2: proto.String(common.Int32SliceToString(playedCards[2], ",")),
PlayedCards_3: proto.String(common.Int32SliceToString(playedCards[3], ",")),
PlayerHandCards: proto.String(common.Int32SliceToString(handcards, ",")),
PlayerPosition: proto.Int32(this.currOpPos),
IsTienLenYule: proto.Bool(isTienLenYule),
IsFirstHand: proto.Bool(isFirstHand),
CardsLeft_0: this.GetPlayerCards(0),
CardsLeft_1: this.GetPlayerCards(1),
CardsLeft_2: this.GetPlayerCards(2),
CardsLeft_3: this.GetPlayerCards(3),
LastPos: proto.Int32(this.lastOpPos),
IsEnd: this.IsTienLenToEnd(),
WinSnids: this.winSnids,
IsWin: isWin,
}
proto.SetDefaults(pack)
this.seats[this.currOpPos].SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenAI), pack)
logger.Logger.Infof("--------------------Send Robot AI Data:%v", pack)
}
pack := &tienlen.SCTienLenCurOpPos{
Pos: proto.Int32(this.currOpPos),
IsNew: proto.Bool(this.currOpPos == this.lastOpPos || this.lastOpPos == rule.InvalidePos),
}
lastOpPlayer := this.GetLastOpPlayer()
if lastOpPlayer != nil && this.currOpPos != this.lastOpPos {
if len(lastOpPlayer.delCards) > 0 {
lastDelCards := lastOpPlayer.delCards[len(lastOpPlayer.delCards)-1]
for _, card := range lastDelCards {
if card != rule.InvalideCard {
pack.Cards = append(pack.Cards, card)
}
}
}
}
if this.lastPos != rule.InvalidePos && this.lastOpPos == this.lastPos {
// 特殊牌型才去添加额外延迟时间
if rule.NeedExDelay(pack.Cards) {
pack.ExDelay = proto.Int32(int32(rule.DelayCanOp))
}
}
proto.SetDefaults(pack)
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenCurOpPos), pack, 0)
logger.Logger.Trace("(this *TienLenSceneData) BroadcastOpPos TienLenPacketID_PACKET_SCTienLenCurOpPos", this.GetSceneId(), ";pack:", pack)
}
// 获取玩家剩余的牌
func (this *TienLenSceneData) GetPlayerCards(pos int32) []int32 {
data := []int32{}
if len(this.allPlayerCards)-1 < int(pos) {
return data
}
cards := this.allPlayerCards[pos]
//去除值为-1的牌
for _, card := range cards {
if card != -1 {
data = append(data, card)
}
}
return data
}
// 出牌
func (this *TienLenSceneData) DelCards(playerEx *TienLenPlayerData, cards []int32) bool {
if playerEx != nil && len(cards) != 0 {
cs := make([]int32, len(cards))
copy(cs, cards)
for _, delCard := range cs {
for i, hcard := range playerEx.cards {
if delCard == hcard && hcard != rule.InvalideCard {
playerEx.cards[i] = rule.InvalideCard
continue
}
}
}
rule.MinSortCards(cs)
playerEx.delCards = append(playerEx.delCards, cs)
this.delCards = append(this.delCards, cs)
this.delOrders = append(this.delOrders, playerEx.SnId)
this.card_play_action_seq = append(this.card_play_action_seq, fmt.Sprintf("%v-%v", playerEx.GetPos(), common.Int32SliceToString(cs, ",")))
this.card_play_action_seq_int32 = append(this.card_play_action_seq_int32, cs)
return true
}
return false
}
func (this *TienLenSceneData) PlayerCanOp(pos int32) bool {
if pos < 0 || pos >= int32(this.GetPlayerNum()) {
return false
}
if this.seats[pos] != nil && this.seats[pos].CanOp() {
return true
}
this.card_play_action_seq = append(this.card_play_action_seq, fmt.Sprintf("%v-过", pos))
this.card_play_action_seq_int32 = append(this.card_play_action_seq_int32, []int32{-1})
return false
}
func (this *TienLenSceneData) AllPlayerEnterGame() {
for i := 0; i < this.GetPlayerNum(); i++ {
if this.seats[i] == nil {
continue
}
if this.seats[i].IsMarkFlag(base.PlayerState_GameBreak) == false {
this.seats[i].UnmarkFlag(base.PlayerState_WaitNext)
this.seats[i].SyncFlag()
}
}
}
// 娱乐版
func (this *TienLenSceneData) IsTienLenYule() bool {
return common.IsTienLenYuLe(this.GetGameId())
}
// 打到底
func (this *TienLenSceneData) IsTienLenToEnd() bool {
return common.IsTienLenToEnd(this.GetGameId())
}
func (this *TienLenSceneData) GetFreeGameSceneType() int32 {
return this.GetSceneType()
}
// 比赛场发牌
// 纯真人,随机发牌
// 有机器人和真人,真人拿好牌
func (this *TienLenSceneData) SendHandCard_Match() {
this.poker.Shuffle()
buf := this.poker.GetPokerBuf()
cardss := map[int][]int32{}
for i, card := range buf {
if int32(card) != rule.InvalideCard {
index := i / 13
cardss[index] = append(cardss[index], int32(card))
}
}
realPlayers := []*TienLenPlayerData{}
robotPlayers := []*TienLenPlayerData{}
for _, seat := range this.seats {
if seat != nil && seat.IsGameing() {
if seat.IsRob {
robotPlayers = append(robotPlayers, seat)
} else {
realPlayers = append(realPlayers, seat)
}
}
}
if len(realPlayers) > 0 && len(robotPlayers) > 0 {
type gradeInfo struct {
id int
grade int
cards []int32
}
grades := []gradeInfo{}
for i, card13 := range cardss {
cardTmp := make([]int32, 13)
copy(cardTmp, card13)
grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
gi := gradeInfo{
id: i,
grade: grade,
cards: card13,
}
grades = append(grades, gi)
}
realWin := 1 //-1最差 0正常 1最好
switch realWin {
case -1:
sort.Slice(grades, func(i, j int) bool {
return grades[i].grade > grades[j].grade
})
case 0:
case 1:
sort.Slice(grades, func(i, j int) bool {
return grades[i].grade < grades[j].grade
})
}
for i, gi := range grades {
cardss[i] = gi.cards
}
}
minCard := int32(999)
if len(robotPlayers) > 0 {
for i, seat := range robotPlayers {
for index, card := range cardss[i] {
seat.cards[index] = card
if rule.Value(card) < rule.Value(minCard) {
this.startOpPos = int32(seat.GetPos())
minCard = card
this.curMinCard = minCard
} else if rule.Value(card) == rule.Value(minCard) {
if rule.Color(card) < rule.Color(minCard) {
this.startOpPos = int32(seat.GetPos())
minCard = card
this.curMinCard = minCard
}
}
}
cardTmp := make([]int32, 13)
copy(cardTmp, cardss[i])
grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
logger.Logger.Trace("SnId: ", seat.SnId, ";grade: ", grade)
pack := &tienlen.SCTienLenCard{}
for j := int32(0); j < rule.HandCardNum; j++ {
pack.Cards = append(pack.Cards, seat.cards[j])
}
pack.IsOutRecord = seat.CanUseRecordItem()
proto.SetDefaults(pack)
seat.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
logger.Logger.Trace("SnId: ", seat.SnId, ";SCTienLenCard: ", pack.Cards)
pack.SnId = seat.SnId
this.BroadcastToAudience(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
}
}
if len(realPlayers) > 0 {
for i, seat := range realPlayers {
for index, card := range cardss[len(robotPlayers)+i] {
seat.cards[index] = card
if rule.Value(card) < rule.Value(minCard) {
this.startOpPos = int32(seat.GetPos())
minCard = card
this.curMinCard = minCard
} else if rule.Value(card) == rule.Value(minCard) {
if rule.Color(card) < rule.Color(minCard) {
this.startOpPos = int32(seat.GetPos())
minCard = card
this.curMinCard = minCard
}
}
}
cardTmp := make([]int32, 13)
copy(cardTmp, cardss[len(robotPlayers)+i])
grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
logger.Logger.Trace("SnId: ", seat.SnId, ";grade: ", grade)
pack := &tienlen.SCTienLenCard{}
for j := int32(0); j < rule.HandCardNum; j++ {
pack.Cards = append(pack.Cards, seat.cards[j])
}
pack.IsOutRecord = seat.CanUseRecordItem()
proto.SetDefaults(pack)
seat.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
logger.Logger.Trace("SnId: ", seat.SnId, ";SCTienLenCard: ", pack.Cards)
pack.SnId = seat.SnId
this.BroadcastToAudience(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
}
}
}
// Shuffle 发牌
// offGrade 需要牌分最少差值(非打到底牌分最大的一组牌和最小的一组牌的分差;打到底,分数最少的两组牌的分差)
// num 函数内部使用,限制搜索次数
// maxOff 函数内部使用
func (this *TienLenSceneData) Shuffle(offGrade, num, maxOff int) {
this.poker.Shuffle()
buf := this.poker.GetPokerBuf()
cardss := map[int][]int32{}
for i, card := range buf {
if int32(card) != rule.InvalideCard {
index := i / 13
cardss[index] = append(cardss[index], int32(card))
}
}
type gradeInfo struct {
id int
grade int
cards []int32
}
grades := []gradeInfo{}
for i, card13 := range cardss {
cardTmp := make([]int32, 13)
copy(cardTmp, card13)
cardsTypeMap := rule.GetCardsType(cardTmp, this.IsTienLenYule())
grade, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardTmp)
gi := gradeInfo{
id: i,
grade: grade,
cards: card13,
}
grades = append(grades, gi)
}
sort.Slice(grades, func(i, j int) bool {
return grades[i].grade < grades[j].grade
})
if grades[len(grades)-1].grade == 9999 && !this.poker.IsTianhuPoker() { //天胡
this.poker.TianhuPokerBuf()
}
if this.IsTienLenToEnd() {
//所有值都比最小值大offGrade分
off := grades[1].grade - grades[0].grade
if off > maxOff {
maxOff = off
this.poker.CopyPokerBuf()
}
if offGrade == 0 || off >= offGrade || num > 10000 {
if num > 10000 {
if this.poker.IsTianhuPoker() && rand.Intn(100) < 20 {
this.poker.UnTianhuPokerBuf()
} else {
this.poker.UncopyPokerBuf()
}
}
return
}
} else {
//最大值比最小值大offGrade分
off := grades[len(grades)-1].grade - grades[0].grade
if off > maxOff && grades[len(grades)-1].grade != 9999 {
maxOff = off
this.poker.CopyPokerBuf()
}
if offGrade == 0 || off >= offGrade || num > 10000 {
if num > 10000 {
if this.poker.IsTianhuPoker() && rand.Intn(100) < 20 {
this.poker.UnTianhuPokerBuf()
} else {
this.poker.UncopyPokerBuf()
}
}
return
}
}
num++
this.Shuffle(offGrade, num, maxOff)
}
/*
公共房:赔率发牌
私人房:随机发牌
比赛场:
纯真人,随机发牌
有机器人和真人,真人拿好牌
纯机器人,随机发牌
赔率发牌
1.52张牌随机分成4组评估牌好坏
2.找出个人赔率最低的玩家
3.只有一个真实玩家
1.该玩家个人赔率≤80%30%概率给予玩家最好牌70%概率随机发牌
2.该玩家 80%个人赔率≤95%,随机发牌
3.该玩家 95%个人赔率≤98%50%概率给予玩家最小牌50%概率随机发牌
4.该玩家 个人赔率98%给予玩家最小牌切保证最大牌型和最小牌型之间的分差≥5代码里对应50
4.多个真实玩家
1.纯真人
50%概率给予最大牌50%概率随机发牌
2.有机器人
1.该玩家个人赔率≤90%50%概率给予玩家最好牌50%概率随机发牌
2.该玩家 90%个人赔率98%,随机发牌
3.该玩家 个人赔率98%,给予机器人最大牌
5.根据赔率最低玩家发牌,如果被控人拿最小牌,机器人拿最大牌,其余玩家随机发牌
*/
// SendHandCard_LoseRate 按照赔率发牌
//func (this *TienLenSceneData) SendHandCard_LoseRate() {
// var minLoseRateSnid int32 //snid
// var realPlayerType int //-1最小牌 0正常随机 1最大牌
// var offGrade int //需求分值差
//
// realPlayers := []*TienLenPlayerData{}
// robotPlayers := []*TienLenPlayerData{}
// for _, seat := range this.seats {
// if seat != nil && seat.IsGameing() {
// if seat.IsRob {
// robotPlayers = append(robotPlayers, seat)
// } else {
// realPlayers = append(realPlayers, seat)
// }
// }
// }
// if len(realPlayers) > 0 {
// //找出个人赔率最低的玩家
// minLoseRate := realPlayers[0].LoseRate(this.GetGameFreeId(), int32(this.GetGameId()))
// minLoseRateSnid = realPlayers[0].SnId
// for _, player := range realPlayers {
// loseRate := player.LoseRate(this.GetGameFreeId(), int32(this.GetGameId()))
// logger.Logger.Trace("snid: ", player.SnId, " loseRate: ", loseRate)
// if loseRate < minLoseRate {
// minLoseRate = loseRate
// minLoseRateSnid = player.SnId
// }
// }
// if !this.IsMatchScene() && !this.IsPrivateScene() { //比赛场或者私有房间纯随机
// //一个真实玩家
// if len(realPlayers) == 1 {
// //1.该玩家个人赔率≤80%30%概率给予玩家最好牌70%概率随机发牌
// if minLoseRate <= 0.8 {
// if rand.Int31n(100) < 30 {
// realPlayerType = 1
// } else {
// realPlayerType = 0
// }
// } else if minLoseRate <= 0.95 { //2.该玩家 80%个人赔率≤95%,随机发牌
// realPlayerType = 0
// } else if minLoseRate <= 0.98 { //3.该玩家 95%个人赔率≤98%50%概率给予玩家最小牌50%概率随机发牌
// if rand.Int31n(100) < 50 {
// realPlayerType = -1
// } else {
// realPlayerType = 0
// }
// } else { //3.该玩家 个人赔率98%给予玩家最小牌切保证最大牌型和最小牌型之间的分差≥5代码里对应50
// realPlayerType = -1
// offGrade = 40
// }
// } else { //多个真人
// if len(robotPlayers) == 0 { //纯真人
// if this.IsPrivateScene() { //私有房间纯随机
// realPlayerType = 0
// } else {
// if rand.Int31n(100) < 50 { //50%概率给予最大牌50%概率随机发牌
// realPlayerType = 1
// } else {
// realPlayerType = 0
// }
// }
// } else {
// //1.该玩家个人赔率≤90%50%概率给予玩家最好牌50%概率随机发牌
// if minLoseRate <= 0.9 {
// if rand.Int31n(100) < 50 {
// realPlayerType = 1
// } else {
// realPlayerType = 0
// }
// } else if minLoseRate < 0.98 { //2.该玩家 90%个人赔率98%,随机发牌
// realPlayerType = 0
// } else { //3.该玩家 个人赔率98%,给予机器人最大牌
// realPlayerType = -1
// }
// }
// }
// }
// }
//
// this.Shuffle(offGrade, 0, 0)
//
// buf := this.poker.GetPokerBuf()
// cardss := map[int][]int32{}
// for i, card := range buf {
// if int32(card) != rule.InvalideCard {
// index := i / 13
// cardss[index] = append(cardss[index], int32(card))
// }
// }
//
// type gradeInfo struct {
// id int
// grade int
// cards []int32
// }
// grades := []gradeInfo{}
// for i, card13 := range cardss {
// cardTmp := make([]int32, 13)
// copy(cardTmp, card13)
// grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
// gi := gradeInfo{
// id: i,
// grade: grade,
// cards: card13,
// }
// grades = append(grades, gi)
// }
// if realPlayerType != 0 {
// sort.Slice(grades, func(i, j int) bool {
// return grades[i].grade > grades[j].grade
// })
// }
//
// for i, gi := range grades {
// cardss[i] = gi.cards
// }
//
// Grades := make(map[int32]int)
// minCard := int32(999)
// // 被控人
// for snid, player := range this.players {
// if player.IsGameing() && snid == minLoseRateSnid {
// cards := cardss[0] //最大
// if realPlayerType == -1 {
// cards = cardss[len(cardss)-1] //最小
// delete(cardss, len(cardss)-1)
// } else {
// delete(cardss, 0)
// }
// switch realPlayerType {
// case -1:
// logger.Logger.Trace("player get min grade !")
// case 0:
// logger.Logger.Trace("player get rand grade !")
// case 1:
// logger.Logger.Trace("player get max grade !")
// }
// for index, card := range cards {
// player.cards[index] = card
// if rule.Value(card) < rule.Value(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// } else if rule.Value(card) == rule.Value(minCard) {
// if rule.Color(card) < rule.Color(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// }
// }
// }
//
// cardTmp := make([]int32, 13)
// copy(cardTmp, cards)
// grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
// logger.Logger.Trace("SnId: ", player.SnId, ";grade: ", grade)
// Grades[player.SnId] = grade
//
// pack := &tienlen.SCTienLenCard{}
// for j := int32(0); j < rule.HandCardNum; j++ {
// pack.Cards = append(pack.Cards, player.cards[j])
// }
// proto.SetDefaults(pack)
// player.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
// logger.Logger.Trace("SnId: ", player.SnId, ";SCTienLenCard: ", pack)
// break
// }
// }
// if realPlayerType == -1 { //被控人拿最小牌,机器人拿最大牌
// snids := []int32{}
// for snid, player := range this.players {
// if player.IsRob && player.IsGameing() && snid != minLoseRateSnid && player.cards[0] == rule.InvalideCard {
// snids = append(snids, snid)
// }
// }
// if len(snids) > 0 {
// snid := snids[rand.Intn(len(snids))]
// player := this.players[snid]
// if player != nil {
// cards := cardss[0] //最大
// delete(cardss, 0)
// for index, card := range cards {
// player.cards[index] = card
// if rule.Value(card) < rule.Value(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// } else if rule.Value(card) == rule.Value(minCard) {
// if rule.Color(card) < rule.Color(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// }
// }
// }
//
// cardTmp := make([]int32, 13)
// copy(cardTmp, cards)
// grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
// logger.Logger.Trace("SnId: ", player.SnId, ";grade: ", grade)
// Grades[player.SnId] = grade
//
// pack := &tienlen.SCTienLenCard{}
// for j := int32(0); j < rule.HandCardNum; j++ {
// pack.Cards = append(pack.Cards, player.cards[j])
// }
// proto.SetDefaults(pack)
// player.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
// logger.Logger.Trace("SnId: ", player.SnId, ";SCTienLenCard: ", pack)
// }
// }
// }
// for _, cards := range cardss {
// for snid, player := range this.players {
// if player.IsGameing() && snid != minLoseRateSnid && player.cards[0] == rule.InvalideCard {
// for index, card := range cards {
// player.cards[index] = card
// if rule.Value(card) < rule.Value(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// } else if rule.Value(card) == rule.Value(minCard) {
// if rule.Color(card) < rule.Color(minCard) {
// this.startOpPos = int32(player.GetPos())
// minCard = card
// this.curMinCard = minCard
// }
// }
// }
//
// cardTmp := make([]int32, 13)
// copy(cardTmp, cards)
// grade := rule.GetCardsGrade(cardTmp, this.IsTienLenYule())
// logger.Logger.Trace("SnId: ", player.SnId, ";grade: ", grade)
// Grades[player.SnId] = grade
//
// pack := &tienlen.SCTienLenCard{}
// for j := int32(0); j < rule.HandCardNum; j++ {
// pack.Cards = append(pack.Cards, player.cards[j])
// }
// proto.SetDefaults(pack)
// player.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
// logger.Logger.Trace("SnId: ", player.SnId, ";SCTienLenCard: ", pack)
// break
// }
// }
// }
//
// // 测试数据
// for snid, player := range this.players {
// if player.IsGameing() && !player.IsRob {
// pack := &tienlen.SCTienLenCardTest{}
// if snid == minLoseRateSnid {
// switch realPlayerType {
// case -1:
// pack.Type = 1
// case 0:
// pack.Type = 2
// case 1:
// pack.Type = 3
// }
// }
// pack.Totalout, pack.Totalin = player.TotalOutIn(int32(this.GetGameId()))
// pack.LoseRate = player.LoseRate(this.GetGameFreeId(), int32(this.GetGameId()))
// if Grades != nil {
// pack.Grades = make(map[int32]int32)
// for id, grade := range Grades {
// pack.Grades[id] = int32(grade)
// }
// }
// proto.SetDefaults(pack)
// player.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCardTest), pack)
// logger.Logger.Trace("SnId: ", player.SnId, ";SCTienLenCardTest: ", pack)
// }
// }
//}
// SendHandCardOdds 调控发牌
/*
1.计算玩家调控概率
新手天胡体验发牌 end
2.根据玩家调控概率随机获得需要控输或控赢的玩家
1.有控输玩家
1.机器人发天胡 end
2.分差发牌,机器人发好牌 end
2.有控赢,给控赢的玩家发好牌,其余随机发牌 end
*/
func (this *TienLenSceneData) SendHandCardOdds() {
var realPlayersGood, realPlayersBad, realPlayers, robotPlayers, novicePlayers, notNoviceRealPlayers []*TienLenPlayerData
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.robotGamingNum > 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)
}
_, isNovice := seat.NoviceOdds(int(this.GameId))
if isNovice {
novicePlayers = append(novicePlayers, seat)
} else {
notNoviceRealPlayers = append(notNoviceRealPlayers, seat)
}
}
}
}
var Grades = make(map[int32]int32)
var minCard = int32(999)
f1 := func(p *TienLenPlayerData, cards []int32) { // 发牌方法
cardsTypeMap := rule.GetCardsType(cards, this.IsTienLenYule())
score, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cards)
Grades[p.SnId] = int32(score) // 测试用
for index, card := range cards {
p.cards[index] = card
if rule.Value(card) < rule.Value(minCard) {
this.startOpPos = int32(p.GetPos())
minCard = card
this.curMinCard = minCard
} else if rule.Value(card) == rule.Value(minCard) {
if rule.Color(card) < rule.Color(minCard) {
this.startOpPos = int32(p.GetPos())
minCard = card
this.curMinCard = minCard
}
}
}
pack := &tienlen.SCTienLenCard{}
for j := int32(0); j < rule.HandCardNum; j++ {
pack.Cards = append(pack.Cards, p.cards[j])
}
pack.IsOutRecord = p.CanUseRecordItem()
proto.SetDefaults(pack)
p.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
logger.Logger.Trace("SnId: ", p.SnId, ";SCTienLenCard: ", pack)
}
// 新手天胡体验
// 前两局不能天胡,之后根据概率给一次天胡,至少天胡一次
noviceTianHu := false
noviceCtrl := false
//config := srvdata.PBDB_NewPlayerMgr.GetData(int32(this.GameId))
//if config != nil && config.GetTianHuRate() > 0 && len(this.testPokers) == 0 { // 启用新手天胡体验
// rand.Shuffle(len(novicePlayers), func(i, j int) {
// novicePlayers[i], novicePlayers[j] = novicePlayers[j], novicePlayers[i]
// })
// keyNovice := common.GetKeyNoviceGameId(this.GameId)
// for _, v := range novicePlayers {
// data, ok := v.GDatas[keyNovice]
// if !ok {
// data = &model.PlayerGameInfo{FirstTime: time.Now()}
// v.GDatas[keyNovice] = data
// }
// // 前两局不能天胡
// if data.Statics.GameTimes < 2 {
// continue
// }
// if int(config.GetTianHuRate()) > this.RandInt(1000) {
// var allcs []int32
// for i := 0; i < 52; i++ {
// allcs = append(allcs, int32(i))
// }
// rand.Shuffle(len(allcs), func(i, j int) {
// allcs[i], allcs[j] = allcs[j], allcs[i]
// })
// cs, _ := rule.GetTianHu()
// allcs = common.DelSliceIn32s(allcs, cs)
// for _, seat := range this.seats {
// if seat != nil && seat.IsGameing() {
// if seat != v {
// f1(seat, allcs[:13])
// allcs = allcs[13:]
// } else {
// f1(seat, cs)
// }
// }
// }
// v.TestLog = append(v.TestLog, fmt.Sprintf("新手天胡体验,玩家:%d 发天胡 num:%v", v.SnId, data.Statics.GameTimes))
// logger.Logger.Tracef("新手天胡体验,玩家:%d 发天胡", v.SnId)
// noviceTianHu = true
// noviceCtrl = true
// }
// }
// if !noviceTianHu {
// // 没有新手玩家天胡,随机一个非新手玩家,如果没有天胡过,给一次天胡
// rand.Shuffle(len(notNoviceRealPlayers), func(i, j int) {
// notNoviceRealPlayers[i], notNoviceRealPlayers[j] = notNoviceRealPlayers[j], notNoviceRealPlayers[i]
// })
// for _, v := range notNoviceRealPlayers {
// data, ok := v.GDatas[keyNovice]
// if !ok {
// data = &model.PlayerGameInfo{FirstTime: time.Now()}
// v.GDatas[keyNovice] = data
// }
//
// if data.Statics.GetInt(rule.StaticsTianHuTimes) == 0 {
// var allcs []int32
// for i := 0; i < 52; i++ {
// allcs = append(allcs, int32(i))
// }
// rand.Shuffle(len(allcs), func(i, j int) {
// allcs[i], allcs[j] = allcs[j], allcs[i]
// })
// cs, _ := rule.GetTianHu()
// allcs = common.DelSliceIn32s(allcs, cs)
// for _, seat := range this.seats {
// if seat != nil && seat.IsGameing() {
// if seat != v {
// f1(seat, allcs[:13])
// allcs = allcs[13:]
// } else {
// f1(seat, cs)
// }
// }
// }
// v.TestLog = append(v.TestLog, fmt.Sprintf("新手阶段没有天胡过,玩家:%d 发天胡 num:%v", v.SnId, data.Statics.GameTimes))
// logger.Logger.Tracef("新手阶段没有天胡过,玩家:%v 发天胡", v.SnId)
// noviceCtrl = true
// }
// }
// }
//}
// 全局配置
gameConfig := base.ConfigMgrInst.GetConfig(this.Platform).GameConfig
// testPokers 用于测试
isTestPoker := false
if len(this.testPokers) > 1 {
var allcs []int32
for i := 0; i < 52; i++ {
allcs = append(allcs, int32(i))
}
rand.Shuffle(len(allcs), func(i, j int) {
allcs[i], allcs[j] = allcs[j], allcs[i]
})
if len(this.testPokers) > 14 {
this.testPokers = this.testPokers[:14]
}
if len(this.testPokers) < 14 {
allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
this.testPokers = append(this.testPokers, allcs[:14-len(this.testPokers)]...)
allcs = allcs[14-len(this.testPokers):]
}
allcs = common.DelSliceIn32s(allcs, this.testPokers[1:])
for _, seat := range this.seats {
if seat != nil && seat.IsGameing() {
if seat.SnId == this.testPokers[0] {
f1(seat, this.testPokers[1:])
} else {
f1(seat, allcs[:13])
allcs = allcs[13:]
}
}
}
this.testPokers = nil
isTestPoker = true
}
// testPokers
// 需要换牌
isGood := len(realPlayersGood) > 0 && int32(this.RandInt(1000)) < G
isBad := len(realPlayersBad) > 0 && int32(this.RandInt(1000)) < B
logger.Logger.Tracef("TienLen SendHandCardOdds Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B)
if isBad && !isTestPoker && len(robotPlayers) > 0 && !noviceCtrl && !noviceTianHu {
this.ctrlType = 2
gf := base.ConfigMgrInst.GetConfig(this.Platform).GameConfig
items := []int32{gf.GetTianHu(), gf.GetPaiKu(), gf.GetFenCha()}
score := this.RandInt(int(gf.GetTianHu() + gf.GetPaiKu() + gf.GetFenCha()))
sum := int32(0)
tp := 0
for k, v := range items {
sum += v
if int32(score) < sum {
tp = k
break
}
}
logger.Logger.Tracef("TienLen SendHandCardOdds TianHu:%v PaiKu:%v FenCha:%v, tp:%v", items[0], items[1], items[2], tp)
switch tp {
case 0: // 天胡发牌
logger.Logger.Tracef("TienLen SendHandCardOdds TianHuRate")
p := robotPlayers[0]
th, _ := rule.GetTianHu()
if len(th) == rule.Hand_CardNum {
// 机器人发天胡,其它玩家随机发牌
f1(p, th)
var allCards []int32
for i := 0; i < rule.POKER_CNT; i++ {
allCards = append(allCards, int32(i))
}
allCards = common.DelSliceIn32s(allCards, th)
rand.Shuffle(len(allCards), func(i, j int) {
allCards[i], allCards[j] = allCards[j], allCards[i]
})
for _, v := range this.players { // map随机
if v == nil || !v.IsGameing() || v.cards[0] != rule.InvalideCard {
continue
}
f1(v, allCards[:rule.Hand_CardNum])
allCards = allCards[rule.Hand_CardNum:]
}
}
p.TestLog = append(p.TestLog, fmt.Sprintf("天胡发牌 snid%v 权重%v", p.SnId, gameConfig.GetTianHu()))
case 1: // 牌库发牌
logger.Logger.Tracef("TienLen SendHandCardOdds 牌库")
//todo 牌库
random := rand.Intn(10000) + 1
var cardsArr [][]int32
this.isCardsKu = true
this.cardsKuId = int32(random)
if this.IsTienLenYule() {
cardsPool := srvdata.PBDB_CardsYuLeMgr.GetData(int32(random))
logger.Logger.Tracef("娱乐牌库发牌!!!!!! 随机到的牌库id = %d\n,db_CardsYuLe = %v\n", cardsPool.Id, cardsPool)
var numbers []int32
err := json.Unmarshal([]byte(cardsPool.Card1), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card2), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card3), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card4), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
//排序
sort.Slice(cardsArr, func(i, j int) bool {
cardsTypeMap := rule.GetCardsType(cardsArr[i], this.IsTienLenYule())
score1, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[i])
cardsTypeMap2 := rule.GetCardsType(cardsArr[j], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[j])
return score1 > score2
})
if isGood {
sort.Slice(realPlayersGood, func(i, j int) bool {
return realPlayersGood[i].odds > realPlayersGood[j].odds
})
for _, v := range realPlayersGood {
f1(v, cardsArr[0])
cardsArr = cardsArr[1:]
}
}
if isBad {
sort.Slice(realPlayersBad, func(i, j int) bool {
return realPlayersBad[i].odds < realPlayersBad[j].odds
})
for _, v := range realPlayersBad {
f1(v, cardsArr[len(cardsArr)-1])
cardsArr = cardsArr[:len(cardsArr)-1]
}
}
//机器人发牌和不调控的人
for _, v := range append(robotPlayers, realPlayers...) {
f1(v, cardsArr[0])
cardsArr = cardsArr[1:]
}
} else {
cardsPool := srvdata.PBDB_CardsJDMgr.GetData(int32(random))
logger.Logger.Tracef("经典牌库发牌!!!!!! 随机到的牌库id = %d\n,db_CardsYuLe = %v\n", cardsPool.Id, cardsPool)
var numbers []int32
err := json.Unmarshal([]byte(cardsPool.Card1), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card2), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card3), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
numbers = []int32{}
err = json.Unmarshal([]byte(cardsPool.Card4), &numbers)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
cardsArr = append(cardsArr, numbers)
//排序
sort.Slice(cardsArr, func(i, j int) bool {
cardsTypeMap := rule.GetCardsType(cardsArr[i], this.IsTienLenYule())
score1, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[i])
cardsTypeMap2 := rule.GetCardsType(cardsArr[j], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[j])
return score1 > score2
})
if isGood {
sort.Slice(realPlayersGood, func(i, j int) bool {
return realPlayersGood[i].odds > realPlayersGood[j].odds
})
for _, v := range realPlayersGood {
f1(v, cardsArr[0])
cardsArr = cardsArr[1:]
}
}
if isBad {
sort.Slice(realPlayersBad, func(i, j int) bool {
return realPlayersBad[i].odds < realPlayersBad[j].odds
})
for _, v := range realPlayersBad {
f1(v, cardsArr[len(cardsArr)-1])
cardsArr = cardsArr[:len(cardsArr)-1]
}
}
//机器人发牌和不调控的人
for _, v := range append(robotPlayers, realPlayers...) {
f1(v, cardsArr[0])
cardsArr = cardsArr[1:]
}
}
case 2: // 分差发牌
logger.Logger.Tracef("TienLen SendHandCardOdds 分差发牌")
for i := 0; i <= 20; i++ {
allCards := rand.Perm(rule.POKER_CNT)
var cardsArr [][]int32
for i := 0; i < 4; i++ {
cardsArr = append(cardsArr, common.CopySliceIntToInt32(allCards[:13]))
allCards = allCards[13:]
}
sort.Slice(cardsArr, func(i, j int) bool {
cardsTypeMap := rule.GetCardsType(cardsArr[i], this.IsTienLenYule())
score, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[i])
cardsTypeMap2 := rule.GetCardsType(cardsArr[j], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[j])
return score > score2
})
if len(cardsArr) > 0 {
cardsTypeMap := rule.GetCardsType(cardsArr[0], this.IsTienLenYule())
score, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[0])
cardsTypeMap2 := rule.GetCardsType(cardsArr[len(cardsArr)-1], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[len(cardsArr)-1])
if score-score2 > int(gameConfig.GetFenChaScore()) {
logger.Logger.Tracef("分差发牌,分差:%v", score-score2)
for _, v := range robotPlayers {
if v == nil || !v.IsGameing() || v.cards[0] != rule.InvalideCard {
continue
}
f1(v, cardsArr[0])
cardsArr = cardsArr[1:]
}
for _, v := range this.players { // map随机
if v == nil || !v.IsGameing() || v.cards[0] != rule.InvalideCard {
continue
}
f1(v, cardsArr[len(cardsArr)-1])
cardsArr = cardsArr[:len(cardsArr)-1]
v.TestLog = append(v.TestLog, fmt.Sprintf("分差发牌 snid%v 权重%v 需要分差%v 真实分差%v", v.SnId,
gameConfig.GetFenCha(), gameConfig.GetFenChaScore(), score-score2))
}
break
}
}
}
}
}
this.Shuffle(0, 0, 0)
buf := this.poker.GetPokerBuf()
cardsArr := make([][]int32, 4)
for i, card := range buf {
if int32(card) != rule.InvalideCard {
index := i / 13
cardsArr[index] = append(cardsArr[index], int32(card))
}
}
f2 := func(players *[]*TienLenPlayerData) {
if players == nil || len(*players) == 0 {
return
}
var p *TienLenPlayerData // 发牌给这个玩家
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 []int32
if p.odds > 0 {
// 拿好牌
cards = cardsArr[0]
cardsArr = cardsArr[1:]
} else {
// 拿坏牌
cards = cardsArr[len(cardsArr)-1]
cardsArr = cardsArr[:len(cardsArr)-1]
}
if p.cards[0] == rule.InvalideCard {
f1(p, cards)
}
}
if !isBad && !isTestPoker && !noviceCtrl && !noviceTianHu { // 天胡调控没有生效
if isGood {
this.ctrlType = 1
// 牌平分,按从大到小排序
// 使用分差配置,最好牌和最差牌的牌型分差大于分差配置
for i := 0; i < 20; i++ { // 尝试20次如果还不能满足分差配置则直接发牌
cardsArr = cardsArr[:0]
allCards := rand.Perm(rule.POKER_CNT)
for i := 0; i < 4; i++ {
cardsArr = append(cardsArr, common.CopySliceIntToInt32(allCards[:13]))
allCards = allCards[13:]
}
sort.Slice(cardsArr, func(i, j int) bool {
cardsTypeMap := rule.GetCardsType(cardsArr[i], this.IsTienLenYule())
score, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[i])
cardsTypeMap2 := rule.GetCardsType(cardsArr[j], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[j])
return score > score2
})
if len(cardsArr) > 0 {
cardsTypeMap := rule.GetCardsType(cardsArr[0], this.IsTienLenYule())
score, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardsArr[0])
cardsTypeMap2 := rule.GetCardsType(cardsArr[len(cardsArr)-1], this.IsTienLenYule())
score2, _ := rule.GetCardTypeScore(cardsTypeMap2, this.IsTienLenYule(), cardsArr[len(cardsArr)-1])
if score-score2 > int(gameConfig.GetGoodFenCha()) {
break
}
}
}
// 排序
type gradeInfo struct {
grade int
cards []int32
}
var grades []gradeInfo
for _, card13 := range cardsArr {
cardTmp := make([]int32, 13)
copy(cardTmp, card13)
cardsTypeMap := rule.GetCardsType(cardTmp, this.IsTienLenYule())
grade, _ := rule.GetCardTypeScore(cardsTypeMap, this.IsTienLenYule(), cardTmp)
gi := gradeInfo{
grade: grade,
cards: card13,
}
grades = append(grades, gi)
}
sort.Slice(grades, func(i, j int) bool {
return grades[i].grade > grades[j].grade
})
for i, gi := range grades {
cardsArr[i] = gi.cards
}
// 发好牌
if isGood {
l := len(realPlayersGood)
for i := 0; i < l; i++ {
f2(&realPlayersGood)
}
}
// 发坏牌
if isBad {
l := len(realPlayersBad)
for i := 0; i < l; i++ {
f2(&realPlayersBad)
}
}
}
}
// 随机拿牌
for _, v := range this.players { // map随机
if v == nil || !v.IsGameing() || v.cards[0] != rule.InvalideCard {
continue
}
f1(v, cardsArr[len(cardsArr)-1])
cardsArr = cardsArr[:len(cardsArr)-1]
}
// 测试
for _, player := range this.players {
if player.IsGameing() && !player.IsRob {
pack := &tienlen.SCTienLenCardTest{}
pack.Totalout, pack.Totalin = player.TotalOutIn(int32(this.GetGameId()))
if Grades != nil {
pack.Grades = make(map[int32]int32)
for id, grade := range Grades {
pack.Grades[id] = int32(grade)
}
}
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))
pack.Data = strings.Join(player.TestLog, "\n")
proto.SetDefaults(pack)
player.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCardTest), pack)
//logger.Logger.Trace("SnId: ", player.SnId, ";SCTienLenCardTest: ", pack)
for _, v := range player.TestLog {
logger.Logger.Trace(v)
}
}
}
}
func (this *TienLenSceneData) SendHandCardTest() {
this.poker.Shuffle()
buf := this.poker.GetPokerBuf()
//牌序- 2, A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3
//红桃- 51,50,49,48,47,46,45,44,43,42,41,40,39
//方片- 38,37,36,35,34,33,32,31,30,29,28,27,26
//梅花- 25,24,23,22,21,20,19,18,17,16,15,14,13
//黑桃- 12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
test1 := []int32{35, 34, 33, 32, 31, 30, 0}
test2 := []int32{42,
29,
16,
3}
test3 := []int32{}
test4 := []int32{}
need1 := rule.HandCardNum - int32(len(test1))
need2 := rule.HandCardNum - int32(len(test2))
need3 := rule.HandCardNum - int32(len(test3))
need4 := rule.HandCardNum - int32(len(test4))
tmpBuf := []int32{}
for i, card := range buf {
for _, card1 := range test1 {
if int32(card) == card1 {
buf[i] = rule.Card(rule.InvalideCard)
}
}
for _, card1 := range test2 {
if int32(card) == card1 {
buf[i] = rule.Card(rule.InvalideCard)
}
}
for _, card1 := range test3 {
if int32(card) == card1 {
buf[i] = rule.Card(rule.InvalideCard)
}
}
for _, card1 := range test4 {
if int32(card) == card1 {
buf[i] = rule.Card(rule.InvalideCard)
}
}
}
for _, card := range buf {
if int32(card) != rule.InvalideCard {
tmpBuf = append(tmpBuf, int32(card))
}
}
var n int
minCard := int32(999)
for _, seatPlayerEx := range this.seats {
if seatPlayerEx != nil {
bb := []int32{}
for i := n * rule.Hand_CardNum; i < (n+1)*rule.Hand_CardNum; i++ {
bb = append(bb, int32(buf[i]))
}
bb = []int32{}
switch seatPlayerEx.GetPos() {
case 0:
for _, card := range test1 {
bb = append(bb, card)
}
for i := int32(0); i < need1; i++ {
bb = append(bb, tmpBuf[i])
}
tmpBuf = append(tmpBuf[need1:])
case 1:
for _, card := range test2 {
bb = append(bb, card)
}
for i := int32(0); i < need2; i++ {
bb = append(bb, tmpBuf[i])
}
tmpBuf = append(tmpBuf[need2:])
case 2:
for _, card := range test3 {
bb = append(bb, card)
}
for i := int32(0); i < need3; i++ {
bb = append(bb, tmpBuf[i])
}
tmpBuf = append(tmpBuf[need3:])
case 3:
for _, card := range test4 {
bb = append(bb, card)
}
for i := int32(0); i < need4; i++ {
bb = append(bb, tmpBuf[i])
}
tmpBuf = append(tmpBuf[need4:])
}
//排下序,正常应该客户端排序
sort.Slice(bb, func(i, j int) bool {
v_i := rule.Value(int32(bb[i]))
v_j := rule.Value(int32(bb[j]))
c_i := rule.Color(int32(bb[i]))
c_j := rule.Color(int32(bb[j]))
if v_i > v_j {
return false
} else if v_i == v_j {
return c_i < c_j
}
return true
})
for idx, card := range bb {
seatPlayerEx.cards[idx] = int32(card)
if rule.Value(int32(card)) < rule.Value(minCard) {
this.startOpPos = int32(seatPlayerEx.GetPos())
minCard = int32(card)
this.curMinCard = minCard
} else if rule.Value(int32(card)) == rule.Value(minCard) {
if rule.Color(int32(card)) < rule.Color(minCard) {
this.startOpPos = int32(seatPlayerEx.GetPos())
minCard = int32(card)
this.curMinCard = minCard
}
}
}
pack := &tienlen.SCTienLenCard{}
for j := int32(0); j < rule.HandCardNum; j++ {
pack.Cards = append(pack.Cards, int32(seatPlayerEx.cards[j]))
}
pack.IsOutRecord = seatPlayerEx.CanUseRecordItem()
proto.SetDefaults(pack)
seatPlayerEx.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenCard), pack)
logger.Logger.Trace("player_id", seatPlayerEx.SnId, ";SCTienLenCard", pack.Cards)
n++
}
}
}
func (this *TienLenSceneData) SetCurOpPos(pos int32) {
this.currOpPos = pos
}
func (this *TienLenSceneData) GetCurOpPos() int32 {
return this.currOpPos
}
func (this *TienLenSceneData) GetCurOpPlayer() *TienLenPlayerData {
if this.currOpPos < 0 || this.currOpPos >= int32(this.GetPlayerNum()) {
return nil
}
return this.seats[this.currOpPos]
}
func (this *TienLenSceneData) SetLastOpPos(pos int32) {
this.lastOpPos = pos
//this.RefreshPlayerHandLimitTimeOut()
}
func (this *TienLenSceneData) GetLastOpPos() int32 {
return this.lastOpPos
}
func (this *TienLenSceneData) GetLastOpPlayer() *TienLenPlayerData {
if this.lastOpPos < 0 || this.lastOpPos >= int32(this.GetPlayerNum()) {
return nil
}
return this.seats[this.lastOpPos]
}
func (this *TienLenSceneData) GetLastBombPlayer() *TienLenPlayerData {
if this.lastBombPos < 0 || this.lastBombPos >= int32(this.GetPlayerNum()) {
return nil
}
return this.seats[this.lastBombPos]
}
func (this *TienLenSceneData) GetCurBombPlayer() *TienLenPlayerData {
if this.curBombPos < 0 || this.curBombPos >= int32(this.GetPlayerNum()) {
return nil
}
return this.seats[this.curBombPos]
}
// 逆时针找一个空位
func (this *TienLenSceneData) FindOnePos() int {
for i := 0; i < this.GetPlayerNum(); i++ {
if this.seats[i] == nil {
return i
}
}
return int(rule.InvalidePos)
}
// 刷新玩家出牌时间
func (this *TienLenSceneData) RefreshPlayerHandLimitTimeOut() {
CurPlayer := this.GetCurOpPlayer()
if CurPlayer == nil {
return
}
if CurPlayer.IsRobot() {
return
}
//curCpCards := []int32{}
//for _, card := range CurPlayer.cards {
// if card != rule.InvalideCard {
// curCpCards = append(curCpCards, card)
// }
//}
lastOpPlayer := this.GetLastOpPlayer()
if lastOpPlayer != nil && len(lastOpPlayer.delCards) != 0 {
// lastDelCards := lastOpPlayer.delCards[len(lastOpPlayer.delCards)-1]
//logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer snid: ", lastOpPlayer.SnId, " lastDelCards", lastDelCards)
//recmCards := rule.RecommendCardsWithLastCards(lastDelCards, curCpCards)
//if this.IsTienLenYule() {
// recmCards = rule.RecommendCardsWithLastCards_yl(lastDelCards, curCpCards)
//}
//canDel, _, _ := rule.CanDel(lastDelCards, recmCards, this.IsTienLenToEnd())
//if this.IsTienLenYule() {
// canDel, _, _ = rule.CanDel_yl(lastDelCards, recmCards, this.IsTienLenToEnd())
//}
//logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer snid: ", lastOpPlayer.SnId, " ThinkLongCnt:", lastOpPlayer.ThinkLongCnt, " flag:", lastOpPlayer.GetFlag())
if int32(CurPlayer.GetPos()) != this.lastOpPos {
//if !canDel { // 压不住别人
// //CurPlayer.curHandLimitTimeOut = rule.TienLenHandNotExceedTimeLimit
// //CurPlayer.isNotOverLastHand = true
// //logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer snid: ", lastOpPlayer.SnId, " CurPlayerSnid: ", CurPlayer.SnId, " ---压不住")
//} else {
// //CurPlayer.RefreshCurHandLimitTimeOut()
// //CurPlayer.isNotOverLastHand = false
// //logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer snid: ", lastOpPlayer.SnId, " CurPlayerSnid: ", CurPlayer.SnId, " ---可以压住")
//}
CurPlayer.RefreshCurHandLimitTimeOut()
CurPlayer.isNotOverLastHand = false
} else {
CurPlayer.RefreshCurHandLimitTimeOut()
CurPlayer.isNotOverLastHand = false
//logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer snid: ", lastOpPlayer.SnId, " CurPlayerSnid: ", CurPlayer.SnId, " ---本轮自己首出牌")
}
//logger.Logger.Trace("(this *TienLenSceneData) RefreshPlayerHandLimitTimeOut lastOpPlayer lastOpPos: ", this.lastOpPos, " currOpPos: ", CurPlayer.GetPos())
}
}
func (this *TienLenSceneData) DoNext(pos int32) int32 {
nextPos := this.GetNextOpPos(pos)
if nextPos != rule.InvalidePos {
this.SetCurOpPos(nextPos)
this.StateStartTime = time.Now()
}
this.lastPos = pos
//this.RefreshPlayerHandLimitTimeOut()
//logger.Logger.Trace("(this *TienLenSceneData) DoNext pos: ", pos, " nextPos:", nextPos, " StateStartTime:", this.StateStartTime)
this.cHintCards = []int32{}
return nextPos
}
func (this *TienLenSceneData) GetNextOpPos(pos int32) int32 {
if pos == rule.InvalidePos {
return rule.InvalidePos
}
if pos < 0 || pos >= int32(this.GetPlayerNum()) {
return rule.InvalidePos
}
for i := pos + 1; i < int32(this.GetPlayerNum()); i++ {
if this.PlayerCanOp(i) {
return i
}
}
for i := int32(0); i < pos; i++ {
if this.PlayerCanOp(i) {
return i
}
}
return rule.InvalidePos
}
func (this *TienLenSceneData) UnmarkPass() {
for i := 0; i < this.GetPlayerNum(); i++ {
if this.seats[i] != nil {
this.seats[i].isPass = false
}
}
}
func (this *TienLenSceneData) FindWinPos() int {
winPos := -1
if this.lastGamingPlayerNum != 0 && this.curGamingPlayerNum != 0 && this.lastWinSnid != 0 {
haveLastWinPos := -1
for i := 0; i < this.GetPlayerNum(); i++ {
if this.seats[i] != nil {
if this.seats[i].SnId == this.lastWinSnid {
haveLastWinPos = i
break
}
}
}
if haveLastWinPos != -1 {
if this.lastGamingPlayerNum > 2 {
winPos = haveLastWinPos
} else if this.lastGamingPlayerNum == 2 {
if this.curGamingPlayerNum == 2 {
winPos = haveLastWinPos
}
}
}
}
return winPos
}
func (this *TienLenSceneData) TrySmallGameBilled() {
// 看是不是炸弹,是炸弹结算分
if this.isKongBomb {
this.bombToEnd++
this.isKongBomb = false
}
if this.roundScore > 0 && this.curBombPos != rule.InvalidePos && this.lastBombPos != rule.InvalidePos {
winPlayer := this.GetCurBombPlayer()
losePlayer := this.GetLastBombPlayer()
baseScore := this.GetBaseScore()
var rankScore = int64(this.roundScore)
score := int64(this.roundScore) * int64(baseScore)
if this.IsTienLenToEnd() {
score = int64(this.roundScore) * int64(baseScore) / 100 //百分比
}
losePlayerCoin := losePlayer.GetCoin()
if !this.IsMatchScene() && losePlayerCoin < score { //输完
score = losePlayerCoin
}
//判断宠物技能生不生效
if losePlayer.PetUseSkill() {
score = 0
//通知客户端宠物技能生效 炸弹不扣分
pack := &tienlen.SCTienLenPetSkillRes{}
pack.Snid = losePlayer.SnId
pack.Pos = int32(losePlayer.Pos)
pack.PetSkillRes = true
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenPetSkillRes), pack, 0)
logger.Logger.Trace("宠物技能抵挡炸弹生效,发送消息 SCTienLenPetSkillRes: ", pack)
}
if score != 0 {
taxRate := this.GetDBGameFree().GetTaxRate() //万分比
gainScore := int64(float64(score) * float64(10000-taxRate) / 10000.0) //税后
bombTaxScore := score - gainScore
// win
if this.IsMatchScene() {
winPlayer.AddCoinNoLog(gainScore, 0)
} else {
winPlayer.AddCoin(gainScore, common.GainWay_CoinSceneWin, 0, "system", this.GetSceneName())
}
winPlayer.winCoin += gainScore
winPlayer.bombScore += gainScore
winPlayer.bombTaxScore += bombTaxScore
if this.IsTienLenToEnd() {
winPlayer.bombRankScore += int64(float64(rankScore) / 100.0 * float64(rule.RankBaseScoreToEnd))
} else {
winPlayer.bombRankScore += rankScore * rule.RankBaseScore
}
//lose
if this.IsMatchScene() {
losePlayer.AddCoinNoLog(-score, 0)
} else {
losePlayer.AddCoin(-score, common.GainWay_CoinSceneLost, 0, "system", this.GetSceneName())
}
losePlayer.winCoin -= score
losePlayer.bombScore -= score
if this.IsTienLenToEnd() {
losePlayer.bombRankScore -= int64(float64(rankScore) / 100.0 * float64(rule.RankBaseScoreToEnd))
} else {
losePlayer.bombRankScore -= rankScore * rule.RankBaseScore
}
pack := &tienlen.SCTienLenSmallGameBilled{
WinPos: proto.Int(winPlayer.GetPos()),
WinPosCoin: proto.Int64(winPlayer.GetCoin()),
WinCoin: proto.Int64(gainScore),
LosePos: proto.Int(losePlayer.GetPos()),
LosePosCoin: proto.Int64(losePlayer.GetCoin()),
LoseCoin: proto.Int64(score),
}
proto.SetDefaults(pack)
this.Broadcast(int(tienlen.TienLenPacketID_PACKET_SCTienLenSmallGameBilled), pack, 0)
logger.Logger.Trace("SCTienLenSmallGameBilled: ", pack)
}
}
this.curBombPos = rule.InvalidePos
this.lastBombPos = rule.InvalidePos
this.roundScore = 0
this.UnmarkPass()
}
func (this *TienLenSceneData) IsTianhuPlayer(snid int32) bool {
for _, tianhusnid := range this.tianHuSnids {
if snid == tianhusnid {
return true
}
}
return false
}
func (this *TienLenSceneData) IsWinPlayer(snid int32) bool {
for _, winSnid := range this.winSnids {
if snid == winSnid {
return true
}
}
return false
}
// SystemCoinOut 系统投入产出都要扣税
func (this *TienLenSceneData) SystemCoinOut() int64 {
systemGain := int64(0)
taxRate := this.GetDBGameFree().GetTaxRate()
for i := 0; i < this.GetPlayerNum(); i++ {
playerData := this.seats[i]
if playerData != nil && playerData.IsGameing() && playerData.IsRob {
gain := playerData.winCoin - playerData.bombScore
if playerData.bombScore > 0 && gain > 0 {
// 小结算赢,局结算都赢
systemGain += playerData.winCoin
} else if playerData.bombScore > 0 && gain < 0 {
// 小结算赢,局结算输
systemGain += playerData.bombScore - int64(float64(gain)*float64(10000-taxRate)/10000.0)
} else if playerData.bombScore < 0 && gain > 0 {
// 小结算输,局结算赢
systemGain += int64(float64(playerData.bombScore)*float64(10000-taxRate)/10000.0) + gain
} else if playerData.bombScore < 0 && gain < 0 {
// 小结算输,局结算输
systemGain += int64(float64(playerData.bombScore)*float64(10000-taxRate)/10000.0) + int64(float64(gain)*float64(10000-taxRate)/10000.0)
}
}
}
return systemGain
}
func (this *TienLenSceneData) SendFirstGiveTimeItem(p *base.Player) {
if p.IsRobot() {
return
}
if !p.PlayerData.IsTakeExpireItem {
itemID := int32(60001)
itemData := srvdata.GameItemMgr.Get(p.Platform, itemID)
if itemData == nil {
return
}
p.PlayerData.IsTakeExpireItem = true
if p.ItemRecExpireTime <= 0 {
p.ItemRecExpireTime = time.Now().Unix() + int64(itemData.Time)*3600*1
} else {
if p.ItemRecExpireTime >= time.Now().Unix() {
p.ItemRecExpireTime += int64(itemData.Time) * 3600 * 1
} else {
p.ItemRecExpireTime = time.Now().Unix() + int64(itemData.Time)*3600*1
}
}
pack := &tienlen.SCTienLenPlayerFirstGiveItemItem{}
pack.ItemId = itemID
pack.ItemRecExpireTime = p.ItemRecExpireTime
p.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenFirstGiveItemItem), pack)
}
}
// SaveCustomLog 保存竞技馆对局记录
func (this *TienLenSceneData) SaveCustomLog() {
if this.CustomLogSave || !this.IsCustom() {
return
}
this.CustomLogSave = true
state := int32(0)
if len(this.RoundEndTime) < int(this.TotalOfGames) {
state = 1
}
log := &model.CustomLog{
CycleId: this.CycleID,
RoomConfigId: this.GetCustom().GetRoomConfigId(),
RoomId: this.SceneId,
StartTs: this.GameStartTime.Unix(),
EndTs: time.Now().Unix(),
State: state,
GameFreeId: this.GetGameFreeId(),
TotalRound: this.TotalOfGames,
Password: this.GetCustom().GetPassword(),
CostType: this.GetCustom().GetCostType(),
Voice: this.GetCustom().GetVoice(),
}
for snid := range this.BilledList {
var items []*model.Item
if this.PlayerAward[snid] != nil {
items = *this.PlayerAward[snid]
}
log.SnId = append(log.SnId, model.PlayerInfo{
SnId: snid,
Awards: items,
})
}
sort.Slice(log.SnId, func(i, j int) bool {
p1 := base.PlayerMgrSington.GetPlayerBySnId(log.SnId[i].SnId)
p2 := base.PlayerMgrSington.GetPlayerBySnId(log.SnId[j].SnId)
return p1.GetCoin() > p2.GetCoin()
})
for k, v := range this.RoundEndTime {
score := make([]int64, len(this.BilledList))
for kk, vv := range log.SnId {
if k < len(*this.BilledList[vv.SnId]) {
score[kk] = (*this.BilledList[vv.SnId])[k].ChangeScore
}
}
log.List = append(log.List, model.RoundInfo{
Round: int32(k + 1),
Ts: v,
Score: score,
LogId: this.RoundLogId[k],
})
}
base.LogChannelSingleton.WriteLog(log)
}