51 lines
1.6 KiB
Go
51 lines
1.6 KiB
Go
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())
|
|
}
|
|
}
|