aistate

package module
v0.0.0-...-2736d37 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2022 License: GPL-3.0 Imports: 0 Imported by: 2

README

Simple State Machine

This package implements a very naive state machine in go. It's not the greatest thing ever, but if you think that you might be able to contribute some elegant fixes... be my guest. :)

This implementation was inspired by Jason Weimann's excellent Unity Bots with State Machines - Extensible State Machine / FSM video on YouTube.

Principle

You instantiate a new state machines and declare all the different states you might need. Then you set up the transitions and the conditons under which a transition triggers.

TODO

  • Introduce checks that there are no states which are "dead ends"

Example

package main

import (
	"github.com/Flokey82/go_gens/aistate"
	"log"
)

func main() {
	// Set up a new state machine.
	s := aistate.New()

	// Set up new states.
	sFindRes := NewState(StateTypeFindResource)
	sMoveToRes := NewState(StateTypeMoveToResource)
	sCollectRes := NewState(StateTypeCollectResource)
	sFlee := NewState(StateTypeFlee)
	sFight := NewState(StateTypeFight)

	aggressive := true

	s.AddAnySelector(func() aistate.State {
		if aggressive {
			return sFight
		}
		return sFlee
	}, func() bool {
		// Check if there are predators around.
		return false
	})

	s.AddTransition(sFlee, sFindRes, func() bool {
		// Check if we are safe again.
		return true
	})

	s.AddTransition(sFindRes, sMoveToRes, func() bool {
		// Check if we have found a resource.
		return true
	})

	s.AddTransition(sMoveToRes, sCollectRes, func() bool {
		// Check if we have reached the resource.
		return true
	})

	s.AddTransition(sCollectRes, sFindRes, func() bool {
		// Check if we have successfully collected the resource.
		return true
	})

	// Set our initial state.
	s.SetState(sFindRes)

	// Run the simulation for a while.
	for i := 0; i < 100; i++ {
		s.Tick(10)
	}
}

const (
	StateTypeFindResource    aistate.StateType = 0
	StateTypeMoveToResource  aistate.StateType = 1
	StateTypeCollectResource aistate.StateType = 2
	StateTypeFlee            aistate.StateType = 3
	StateTypeFight           aistate.StateType = 4
)

// State is a fake implementation of a generic state.
type State struct {
	t aistate.StateType
}

func NewState(t aistate.StateType) *State {
	return &State{t: t}
}

func (s *State) Type() aistate.StateType {
	return s.t
}

func (s *State) Tick(delta uint64) {
	// Move towards resource, pick up item, etc ...
}

func (s *State) OnEnter() {
	log.Printf("entering state %d", s.t)
}

func (s *State) OnExit() {
	log.Printf("leaving state %d", s.t)
}

Documentation

Overview

Package aistate implements a minimalistic state machine.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type State

type State interface {
	Type() StateType   // Returns the ID of the current state
	Tick(delta uint64) // Advances the state and provides the 'delta' time elapsed.
	OnEnter()          // Hooks executed when transitioning to this state
	OnExit()           // Hooks executed when transitioning from this state
}

State defines an interface for a current state.

type StateMachine

type StateMachine struct {
	Current  State
	Previous State
	// contains filtered or unexported fields
}

StateMachine implements a simple state machine.

func New

func New() *StateMachine

New returns a new state machine.

func (*StateMachine) AddAnySelector

func (s *StateMachine) AddAnySelector(to func() State, predicate func() bool)

AddAnySelector adds a new transition that does not depend on a prior state, but only on the return value of 'predicate' and returns a state returned by to().

func (*StateMachine) AddAnyTransition

func (s *StateMachine) AddAnyTransition(to State, predicate func() bool)

AddAnyTransition adds a new transition that does not depend on a prior state, but only on the return value of 'predicate'.

func (*StateMachine) AddSelector

func (s *StateMachine) AddSelector(from State, to func() State, predicate func() bool)

AddSelector adds a new transition from a state to another returned by to() when predicate returns true.

func (*StateMachine) AddTransition

func (s *StateMachine) AddTransition(from, to State, predicate func() bool)

AddTransition adds a new transition from a state to another when predicate returns true.

func (*StateMachine) GetTransition

func (s *StateMachine) GetTransition() *Transition

GetTransition returns the next valid transition.

func (*StateMachine) RevertToPreviousState

func (s *StateMachine) RevertToPreviousState()

RevertToPreviousState sets the current state of the state machine to its previous state.

func (*StateMachine) SetState

func (s *StateMachine) SetState(state State)

SetState sets the current state of the state machine.

func (*StateMachine) Tick

func (s *StateMachine) Tick(delta uint64)

Tick advances the state machine by 'delta' (time elapsed since last tick).

type StateType

type StateType int

StateType represents the ID of a state.

type Transition

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

Transition represents a transition to a specific state. TODO: Consider two different transition types, one with to as a function and one with to as a specific state (if performance is impacted by to being a function)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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