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) } }