state

package
v0.0.0-...-20810c9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2024 License: MIT Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

The area for state machine identifiers - to keep maps in this package as small as fast as possible.

Functions

This section is empty.

Types

type Condition

type Condition[Input any] func(Input) bool

A transition is taken when the condition returns true.

type Effector

type Effector[Input any, Effect any] func(Input) Effect

The amount a state effects a subject based on input can be evaluated at state creation or on each update. The effect can be a simple weight or a complex object.

type InitializeSub

type InitializeSub int

A way to control when (if at all) a states sub-machine is initialized.

const (
	// Initialize the sub machine before we even call Start.
	InitializeSubBeforeStart InitializeSub = iota
	// Initialize the sub after start is called and returns true.
	InitializeSubAfterStart
	// Initialze the sub once we active the state on the machine.
	InitializeSubAfterQueue
	// Never initialize the sub, behave normally and let the first Update handle it.
	InitializeSubNever
)

type Logic

type Logic[Subject any, Input any, StateData any, TransitionData any, Effect any] struct {
	// The logic that would return true if the given state is done and the non-live transitions out of it should be evaluted for the next state.
	IsDone func(*Subject, State[Subject, Input, StateData, TransitionData, Effect]) bool
	// Starts the given state on the subject, possible from a transition and possible where an unfinished state needs to be outroed so that it may eventually return true for IsDone and
	// be removed from the active states.
	Start func(*Subject, State[Subject, Input, StateData, TransitionData, Effect], *Transition[Input, TransitionData], *State[Subject, Input, StateData, TransitionData, Effect]) bool
	// The logic invoked to apply the active states on the subject. See other Applied properties.
	Apply func(*Subject, []State[Subject, Input, StateData, TransitionData, Effect])
	// If non-zero, no more than this many states should be sent to be applied to the subject.
	AppliedMax int
	// If non-nil and there's an applied max that will affect the applied states - this function will sort the states so the preferred states are applied.
	AppliedPriority func(a State[Subject, Input, StateData, TransitionData, Effect], b State[Subject, Input, StateData, TransitionData, Effect]) bool
	// If true all active states in all sub machines should be passed to apply - otherwise just the active states in the root machine are sent.
	AppliedDeep bool
	// If true only this number of states can be active at a time. Once a queue of possible active states is determined from transitions
	// only the states that can fit will be added to the active states.
	ActiveMax int
	// If non-nil and there's an active max this will sort the states in the queue to prefer the ones at the top.
	ActivePriority func(a State[Subject, Input, StateData, TransitionData, Effect], b State[Subject, Input, StateData, TransitionData, Effect]) bool
	// If true all states in the machine are always active and no transition logic is done. Only state updating.
	ActiveFully bool
	// If true when active states are removed - should the current order of the active states be preserved or does order not matter?
	ActiveOrdered bool
	// If true after transitions are evaluated in an update - should we add any to the active states so they are available in the apply?
	// If not the active queue will be processed at the start of the next update.
	ProcessQueueImmediately bool
	// Timing for when (if at all) a sub machine should be initialized (active states be determined).
	InitializeSub InitializeSub
}

The logic and options used by a state machine to process states. This allows for fuzzy and finite machines to coexist and also provides prioritized multiple state reduction for both finite and fuzzy machines. A state has data or it's own sub machine.

type Machine

type Machine[Subject any, Input any, StateData any, TransitionData any, Effect any] struct {
	Definition  *MachineDefinition[Subject, Input, StateData, TransitionData, Effect]
	Active      id.DenseMap[State[Subject, Input, StateData, TransitionData, Effect], uint16, uint8]
	ActiveQueue []State[Subject, Input, StateData, TransitionData, Effect]
	Applicable  []State[Subject, Input, StateData, TransitionData, Effect]
}

func NewMachine

func NewMachine[Subject any, Input any, StateData any, TransitionData any, Effect any](def *MachineDefinition[Subject, Input, StateData, TransitionData, Effect]) Machine[Subject, Input, StateData, TransitionData, Effect]

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) Apply

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) Apply(subject *Subject)

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) Init

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) Init(subject *Subject, input Input)

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) ProcessQueue

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) ProcessQueue(subject *Subject, input Input)

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) Transitions

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) Transitions(transitions []Transition[Input, TransitionData], subject *Subject, input Input, onlyLive bool, outro *State[Subject, Input, StateData, TransitionData, Effect]) int

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) Update

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) Update(subject *Subject, input Input)

func (*Machine[Subject, Input, StateData, TransitionData, Effect]) UpdateActive

func (m *Machine[Subject, Input, StateData, TransitionData, Effect]) UpdateActive(subject *Subject, input Input)

type MachineDefinition

type MachineDefinition[Subject any, Input any, StateData any, TransitionData any, Effect any] struct {
	Logic       Logic[Subject, Input, StateData, TransitionData, Effect]
	States      id.DenseMap[StateDefinition[Subject, Input, StateData, TransitionData, Effect], uint16, uint8]
	Transitions []Transition[Input, TransitionData]
}

A machine definition describes the logic, states, and transitions for a machine.

func NewMachineDefinition

func NewMachineDefinition[Subject any, Input any, StateData any, TransitionData any, Effect any](logic Logic[Subject, Input, StateData, TransitionData, Effect]) MachineDefinition[Subject, Input, StateData, TransitionData, Effect]

func (MachineDefinition[Subject, Input, StateData, TransitionData, Effect]) AddState

func (md MachineDefinition[Subject, Input, StateData, TransitionData, Effect]) AddState(s StateDefinition[Subject, Input, StateData, TransitionData, Effect])

Add the state to the definition.

func (MachineDefinition[Subject, Input, StateData, TransitionData, Effect]) AddTransition

func (md MachineDefinition[Subject, Input, StateData, TransitionData, Effect]) AddTransition(t Transition[Input, TransitionData])

Add the transition to the definition. This should only be done after the states are added, otherwise it will panic.

type State

type State[Subject any, Input any, StateData any, TransitionData any, Effect any] struct {
	Definition *StateDefinition[Subject, Input, StateData, TransitionData, Effect]
	Effect     Effect
	Sub        *Machine[Subject, Input, StateData, TransitionData, Effect]
}

func (State[Subject, Input, StateData, TransitionData, Effect]) IsDone

func (a State[Subject, Input, StateData, TransitionData, Effect]) IsDone(subject *Subject, logic Logic[Subject, Input, StateData, TransitionData, Effect]) bool

func (*State[Subject, Input, StateData, TransitionData, Effect]) Update

func (a *State[Subject, Input, StateData, TransitionData, Effect]) Update(subject *Subject, input Input)

type StateDefinition

type StateDefinition[Subject any, Input any, StateData any, TransitionData any, Effect any] struct {
	ID             id.Identifier
	Data           StateData
	EffectGet      func(Input) Effect
	EffectConstant Effect
	EffectLive     bool
	Transitions    []Transition[Input, TransitionData]
	Sub            *MachineDefinition[Subject, Input, StateData, TransitionData, Effect]
}

A state definition is identifiable, has data, may have a way to compute it's effect (or has a constant effect), has transitions out of it, and possibly a sub-machine.

func (StateDefinition[Subject, Input, StateData, TransitionData, Effect]) GetEffect

func (d StateDefinition[Subject, Input, StateData, TransitionData, Effect]) GetEffect(input Input) Effect

func (StateDefinition[Subject, Input, StateData, TransitionData, Effect]) IsEffectLive

func (d StateDefinition[Subject, Input, StateData, TransitionData, Effect]) IsEffectLive() bool

type Transition

type Transition[Input any, TransitionData any] struct {
	// The start state if any.
	Start id.Identifier
	// The ending state.
	End id.Identifier
	// The condition that determines whether we should take this transition.
	// This is optional and when not specified it's considered to be true.
	Condition func(Input) bool
	// If the transition should be evaluated on each update.
	Live bool
	// The data associated with this transition - used for applying it to the subject.
	Data TransitionData
}

A transition in a state machine has an ending and optionally a start. A transition without a start is considered global and exists on the machine level (as opposed to state) and is possibly evaluated on init or when the machine has no active or queued states. A transition can be live or dormant. A dormant transition is only evaluated when a state is finished or a machine is empty while a live transition is evaluated on each update.

func (Transition[Input, TransitionData]) IsReady

func (t Transition[Input, TransitionData]) IsReady(input Input) bool

Based on the input - should the transition be taken?

type UserData

type UserData struct {
	// contains filtered or unexported fields
}

func NewUserData

func NewUserData(props ...UserDataPropertyBase) UserData

type UserDataPropertyBase

type UserDataPropertyBase interface {
	Bytes() int
	Write(data UserData)
	SetIndex(index int)
}

type UserDataPropertyTyped

type UserDataPropertyTyped[V any] interface {
	UserDataPropertyBase
	Get(data UserData) V
	Set(data UserData, value V)
}

func Bool

func Bool(defaultValue bool) UserDataPropertyTyped[bool]

func Float

func Float(defaultValue float32) UserDataPropertyTyped[float32]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL