package westworldwithwoman import ( "math/rand" "sync" ) // wifesGlobalState is Elsa's global state - its Execute runs on // every single tick of her state machine, in addition to whatever // her current state is doing (see StateMachine.Update). That's what // makes it the right place for "does nature call right now" logic: // the book says that can happen "during any state and at any time," // which is exactly what a global state is for. type wifesGlobalState struct{} var ( wifesGlobalStateInstance *wifesGlobalState wifesGlobalStateOnce sync.Once ) // WifesGlobalState is the Go stand-in for // "WifesGlobalState::Instance()". func WifesGlobalState() *wifesGlobalState { wifesGlobalStateOnce.Do(func() { wifesGlobalStateInstance = &wifesGlobalState{} }) return wifesGlobalStateInstance } var _ State[Elsa] = (*wifesGlobalState)(nil) // Enter and Exit do nothing - a global state is set once, in // NewElsa, and never changed, so these never actually get called. // They only exist to satisfy the State[Elsa] interface. func (s *wifesGlobalState) Enter(e *Elsa) {} func (s *wifesGlobalState) Exit(e *Elsa) {} // bathroomCallChance is a 1-in-N chance, per the chapter's "1 in 10 // chance to change to VisitBathroom state." const bathroomCallChance = 10 // Execute rolls the dice every tick. If it comes up, and Elsa isn't // already in the bathroom (checked with IsInState, so this can't // interrupt a bathroom trip that's already happening), she breaks // off into VisitBathroom. func (s *wifesGlobalState) Execute(e *Elsa) { if !e.FSM().IsInState(VisitBathroom()) && rand.Intn(bathroomCallChance) == 0 { e.ChangeState(VisitBathroom()) } }