game_sync/gamesrv/slotspkg/slots/entity/rand.go

171 lines
5.5 KiB
Go

package entity
import (
"github.com/tomas-qstarrs/boost/randx"
"math"
"math/rand"
"mongo.games.com/game/gamesrv/slotspkg/internal/generic/key"
"mongo.games.com/game/gamesrv/slotspkg/internal/module/shared"
"mongo.games.com/goserver/core/logger"
)
type RandState struct {
randx *randx.Randx
source rand.Source
tracker *shared.RandxTracker
enableTracker bool
}
func NewRandState() *RandState {
return &RandState{
tracker: &shared.RandxTracker{},
}
}
func (e *Entity) Randx() *randx.Randx {
return e.RandState.randx
}
func (e *Entity) PrepareRand() {
var mode string
switch {
case e.NextNode().Type != key.BaseSpin:
mode = e.NodeTree.Mode // 不是BaseSpin 延续上一次的随机情况
case e.NodeTree.Act.Stay:
mode = key.MachineModeLive
case e.NodeTree.Act.Mode == "":
mode = key.MachineModeLive
default:
mode = e.NodeTree.Act.Mode
}
e.NodeTree.Mode = mode
var source rand.Source
switch mode {
case key.MachineModeLive:
source = e.source()
case key.MachineModeRecorder:
if e.NextNode().Type == key.BaseSpin {
// 录制开始
if e.NodeTree.Act.Vector != nil {
e.NodeTree.RandVector.Vector = e.NodeTree.Act.Vector
e.NodeTree.RandVector.VectorIndex = e.NodeTree.Act.VectorIndex
e.NodeTree.RandVector.VectorType = e.NodeTree.Act.VectorType
} else {
e.NodeTree.RandVector.Vector = []int64{e.source().Int63()}
}
e.NodeTree.Act.Vector = nil
e.NodeTree.Act.VectorIndex = 0
e.NodeTree.Act.VectorType = 0
e.NodeTree.RandVector.Index = 0
}
source = randx.NewLcgVectorPlayer(e.NodeTree.RandVector.Vector, int(e.NodeTree.RandVector.Index))
case key.MachineModePlayer:
if e.NextNode().Type == key.BaseSpin {
// 播放开始
e.NodeTree.RandVector.Index = 0
e.NodeTree.RandVector.Vector = e.NodeTree.Act.Vector
e.NodeTree.RandVector.VectorIndex = e.NodeTree.Act.VectorIndex
e.NodeTree.RandVector.VectorType = e.NodeTree.Act.VectorType
e.NodeTree.RandVector.ExpectedWinCoin = e.NodeTree.Act.ExpectedWinCoin
e.NodeTree.Act.Vector = nil
e.NodeTree.Act.VectorIndex = 0
e.NodeTree.Act.VectorType = 0
e.NodeTree.Act.ExpectedWinCoin = 0
}
source = randx.NewLcgVectorPlayer(e.NodeTree.RandVector.Vector, int(e.NodeTree.RandVector.Index))
default:
logger.Logger.Errorf("slots unknown mode: %s", mode)
}
e.RandState.source = source
e.RandState.randx = randx.New(source)
switch mode {
case key.MachineModeLive:
e.NodeTree.RandVector.EnableRandxTracker = false
e.NodeTree.RandVector.RandxTracker = &shared.RandxTracker{}
e.NodeTree.RandVector.RecorderRandxTracker = &shared.RandxTracker{}
case key.MachineModeRecorder:
if e.NextNode().Type == key.BaseSpin {
e.NodeTree.RandVector.EnableRandxTracker = e.NodeTree.Act.EnableRandxTracker
e.NodeTree.Act.EnableRandxTracker = false
e.NodeTree.RandVector.RandxTracker = &shared.RandxTracker{}
e.NodeTree.RandVector.RecorderRandxTracker = &shared.RandxTracker{}
}
case key.MachineModePlayer:
if e.NextNode().Type == key.BaseSpin {
e.NodeTree.RandVector.EnableRandxTracker = e.NodeTree.Act.EnableRandxTracker
e.NodeTree.Act.EnableRandxTracker = false
e.NodeTree.RandVector.RandxTracker = &shared.RandxTracker{}
e.NodeTree.RandVector.RecorderRandxTracker = e.NodeTree.Act.RecorderRandxTracker
e.NodeTree.Act.RecorderRandxTracker = &shared.RandxTracker{}
}
default:
logger.Logger.Errorf("slots unknown mode: %s", mode)
}
e.RandState.enableTracker = e.NodeTree.RandVector.EnableRandxTracker
e.RandState.tracker = e.NodeTree.RandVector.RandxTracker
}
func (e *Entity) source() rand.Source {
var source rand.Source
if v := e.Session.Value(key.SessionMachineSource); v == nil {
seed := randx.Int63n(math.MaxInt64)
source = rand.NewSource(seed)
e.Session.Set(key.SessionMachineSource, source)
} else {
source = v.(rand.Source)
}
return source
}
func (e *Entity) RandxTracker() *shared.RandxTracker {
return e.RandState.tracker
}
func (e *Entity) CompareRandx() (bool, string, string) {
if !e.RandState.enableTracker {
return false, "", ""
}
playerTracker := e.RandState.tracker
recorderTracker := e.NodeTree.RandVector.RecorderRandxTracker
if len(recorderTracker.Items) < len(playerTracker.Items) {
for i, item := range recorderTracker.Items {
if item.Index != playerTracker.Items[i].Index {
return true, recorderTracker.Items[i-1].Tag, item.Tag
}
}
return true, playerTracker.Items[len(recorderTracker.Items)-1].Tag, playerTracker.Items[len(recorderTracker.Items)].Tag
} else if len(recorderTracker.Items) > len(playerTracker.Items) {
for i, item := range playerTracker.Items {
if item.Index != recorderTracker.Items[i].Index {
return true, playerTracker.Items[i-1].Tag, item.Tag
}
}
return true, recorderTracker.Items[len(playerTracker.Items)-1].Tag, recorderTracker.Items[len(playerTracker.Items)].Tag
} else {
for i, item := range recorderTracker.Items {
if item.Index != playerTracker.Items[i].Index {
return true, recorderTracker.Items[i-1].Tag, item.Tag
}
}
}
return false, "", ""
}
func (e *Entity) SyncRand() {
switch e.NodeTree.Mode {
case key.MachineModeRecorder, key.MachineModePlayer:
e.NodeTree.RandVector.Vector = e.RandState.source.(*randx.LcgVectorPlayer).Vector
e.NodeTree.RandVector.Index = int64(e.RandState.source.(*randx.LcgVectorPlayer).Index)
e.NodeTree.RandVector.RandxTracker = e.RandState.tracker
e.NodeTree.RandVector.EnableRandxTracker = e.RandState.enableTracker
case key.MachineModeLive:
// Do nothing
default:
logger.Logger.Errorf("slots unknown mode: %s", e.NodeTree.Mode)
}
}