Skip to content

Instantly share code, notes, and snippets.

@chuwilliamson
Created February 24, 2016 15:36
Show Gist options
  • Save chuwilliamson/b945c49585e79171a0de to your computer and use it in GitHub Desktop.
Save chuwilliamson/b945c49585e79171a0de to your computer and use it in GitHub Desktop.
FSM in c#
//written by Ryan adaire aka the boss aka commit dis aka ya boy aka holla at
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
public class FSM<T>
{
private List<TransitionObject> good_transitions;
private IEnumerator<T> States;
private bool any_state_exists;
private bool reflexive_transitions_allowed;
private T any_state;
private T current_state;
public FSM(bool reflexive_transitions = false)
{
if (typeof(T).BaseType != typeof(Enum))
throw new InvalidCastException();
else
{
InitializeFSM();
any_state_exists = false;
reflexive_transitions_allowed = reflexive_transitions;
}
}
public FSM(T anystate, bool reflexive_transitions = false)
{
if (typeof(T).BaseType != typeof(Enum))
throw new InvalidCastException();
else
{
InitializeFSM();
any_state_exists = true;
any_state = anystate;
reflexive_transitions_allowed = reflexive_transitions;
}
}
private void InitializeFSM()
{
good_transitions = new List<TransitionObject>();
States = Enum.GetValues(typeof(T)).Cast<T>().GetEnumerator();
if (!States.MoveNext())
{
throw new SystemException("Cannot construct an empty FSM.");
}
current_state = States.Current;
}
public void AddTransition(T start, T end, Action transition_function = null)
{
if (any_state_exists)
{
if (Equals(any_state, end) || Equals(start, any_state))
{
if (Equals(start, any_state))
{
States.Reset();
while (States.MoveNext())
{
if (Equals(States.Current, any_state))
continue;
else
{
T current_iteration = States.Current;
AddTransition(States.Current, end, transition_function);
SetIteration(current_iteration);
}
}
}
else if (Equals(any_state, end))
{
States.Reset();
while (States.MoveNext())
{
if (Equals(States.Current, any_state))
continue;
else
{
AddTransition(start, States.Current, transition_function);
}
}
}
return;
}
}
if (SearchTransition(start, end) == -1)
{
if (reflexive_transitions_allowed)
{
good_transitions.Add(new TransitionObject(start, end, transition_function));
}
else if (!Equals(start, end))
{
good_transitions.Add(new TransitionObject(start, end, transition_function));
}
}
}
private void SetIteration(T enumeration)
{
States.Reset();
while (States.MoveNext())
{
if (Equals(States.Current, enumeration))
return;
}
}
private int SearchTransition(T start, T end)
{
for (int i = 0; i < good_transitions.Count; i++)
{
if (Equals(good_transitions[i].Start, start) && Equals(good_transitions[i].End, end))
{
return i;
}
}
return -1;
}
public bool CheckTransition(T start, T end)
{
if (SearchTransition(start, end) != -1)
return true;
else
{
return false;
}
}
public bool Transition(T state)
{
int transition_index = SearchTransition(Current_State, state);
if (transition_index != -1)
{
current_state = state;
if (good_transitions[transition_index].transition_function != null)
{
good_transitions[transition_index].transition_function.Invoke();
}
return true;
}
else
{
return false;
}
}
public T Current_State
{
get { return current_state; }
}
private bool Equals(T a, T b)
{
return Enum.GetName(typeof(T), a) == Enum.GetName(typeof(T), b);
}
private struct TransitionObject
{
public T new_state;
public Action transition_function;
public TransitionObject(T start, T end, Action trans_func)
{
start_state = start;
end_state = end;
transition_function = trans_func;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment