Created
February 24, 2016 15:36
-
-
Save chuwilliamson/b945c49585e79171a0de to your computer and use it in GitHub Desktop.
FSM in c#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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