// Adds a machine (located in path) to this GAIA_Manager
 // Returns:
 // 1 if OK
 //-1 if an GAIA_Parser is required to use this method
 //-2 if cannot be added (wrong parameters or repeated FA)
 //-3 if there are errors parsing file located in path
 public int addFSM(string path)
 {
     if (this.parser == null)
     {
         return(-1);
     }
     else
     {
         //Invoke parser with path
         FA_Classic parsedfsm = parser.ParsePath(path);
         if (parsedfsm != null)
         {
             try
             {
                 FSM_dic.Add(new Tuple(parsedfsm.getTag(), parsedfsm.getFAid()), parsedfsm);
                 return(1);
             }
             catch (Exception e)
             {
                 return(-2);
             }
         }
         else
         {
             return(-3);
         }
     }
 }
Exemple #2
0
 // <summary>
 // Adds a submachine to this State or changes the one that is already attached
 // </summary>
 // <param name="subFA"> FA_Classic object (any FA is valid)</param>
 // <returns>
 // 1 if OK
 //-1 if cannot be attached
 //</returns>
 // <remarks></remarks>
 public int addFA(FA_Classic subFA)
 {
     try{
         this.subFA = subFA;
         return(1);
     }catch (Exception e) {
         return(-1);
     }
 }
 // Removes a machine that had been added to this GAIA_Manager
 // Returns:
 // 1 if OK
 //-1 if cannot remove that machine (corrupted fsm object or it does not exist)
 public int deleteFSM(FA_Classic fsm)
 {
     try
     {
         FSM_dic.Remove(new Tuple(fsm.getTag(), fsm.getFAid()));
         return(1);
     }
     catch (Exception e)
     {
         return(-1);
     }
 }
 // Add a machine (passed as FA parameter) to this GAIA_Manager
 // Returns:
 // 1 if OK
 //-1 if cannot be added
 public int addFSM(FA_Classic fsm)
 {
     try
     {
         //Add the FA to the attribute FSM_dic
         FSM_dic.Add(new Tuple(fsm.getTag(), fsm.getFAid()), fsm);
         return(1);
     }
     catch (Exception e)
     {
         return(-1);
     }
 }
        // <summary>
        // Initializes a new instance of the <see cref="T:FSM.FSM_Machine">FSM_Machine</see> class.
        // </summary>
        // <param name="fsm">FA object</param>
        // <param name="character">Character that demands this FSM based on fsm param</param>
        // <remarks>FSM_Manager uses this method to initialize a machine</remarks>
        public FSM_Machine(FA_Classic fsm, System.Object character)
        {
            this.Character = character;
            FSM            = fsm;

            CurrentState = FSM.getInitialState();
            MaxEnabled   = 1;

            DoActions     = new List <int>();
            FSM_Stack     = new List <Stack <FA_Classic> >();
            ControlStack  = new List <Stack <State> >();
            SuperiorStack = new List <Stack <State> >();
            EnabledStates = new List <State>();

            //Concurrent
            if (FSM.getTag() == Tags.CONCURRENT_STATES)
            {
                MaxEnabled = (FSM as FA_Concurrent_States).getMaxConcurrent();
                for (int i = 0; i < (FSM as FA_Concurrent_States).getMaxConcurrent(); i++)
                {
                    SuperiorStack.Add(new Stack <State>());
                    FSM_Stack.Add(new Stack <FA_Classic>());
                    this.FSM_Stack[i].Push(FSM);
                    ControlStack.Add(new Stack <State>());
                    ControlStack[i].Push(CurrentState);
                }
                EnabledStates = (FSM as FA_Concurrent_States).getInitials().ToList();
                StatesCredits = (FSM as FA_Concurrent_States).getCreditsDic();
            }
            else      //The others
            {
                MaxEnabled = 1;
                SuperiorStack.Add(new Stack <State>());
                FSM_Stack.Add(new Stack <FA_Classic>());
                this.FSM_Stack[0].Push(FSM);
                ControlStack.Add(new Stack <State>());
                ControlStack[0].Push(CurrentState);

                EnabledStates.Add(FSM.getInitialState());
            }

            rnd           = new System.Random();
            UpdateEnabled = false;
            inertialTimer = new Stopwatch();
        }
        // <summary>
        // Updates situation of current/s FSM
        // </summary>
        // <returns>A List of integer value actions to do</returns>
        // <remarks></remarks>
        public List <int> UpdateFSM()
        {
            //List of actions is cleared to return another filled one.
            DoActions.Clear();

            //Copy of enabled States
            EnabledStatesCopy = EnabledStates.ToList();

            //Executed states in currentCycle
            List <State> onCycle = new List <State>();

            //Routine for this FSM_Machine
            MethodInfo EventsRoutine = this.Character.GetType().GetMethod(FSM.getCallback(), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            List <int> Events        = (List <int>)EventsRoutine.Invoke(this.Character, null);

            //Counter in next foreach
            int es = 0;

            //Browsing enabled states
            foreach (State s in EnabledStates)
            {
                t_aux     = null;
                change    = false;
                stackable = false;
                FSM       = this.FSM_Stack[es].Peek();               //FSM in top of FSM_stack;

                //FSM calls the method that has the pertinent events to current FSM
                if (FSM_Stack[es].Count > 1)
                {
                    EventsRoutine = this.Character.GetType().GetMethod(FSM.getCallback(), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
                    Events        = (List <int>)EventsRoutine.Invoke(this.Character, null);
                }

                //Only one event by default
                int CEvent = Events[0];


                if (CEvent == null)
                {
                    return(null);                     //if there is not an event, this method returns the null value
                }
                //According to FSM TAG, FSM_Machine works in one way or another
                switch (this.FSM.getTag())
                {
                case Tags.CLASSIC:              //PROBABILISTIC LOGIC
                    #region Classic machine logic

                    #region Classic selection

                    if (FSM.isProbabilistic())            //PROBABILISTIC (NO DETERMINISTIC FSM)

                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            this.RandomNumber = rnd.Next(99);
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent)
                                {
                                    //Test if there's
                                    if (this.RandomNumber < t.getProbability())
                                    {
                                        t_aux = t;
                                        if (CurrentState.getTag() != t_aux.getFinal().getTag())
                                        {
                                            change = true;
                                        }
                                        else
                                        {
                                            change = false;
                                        }
                                        break;
                                    }
                                }
                            }                    //end foreach events
                            if (t_aux != null)
                            {
                                break;
                            }
                        }             //end foreach transitions of currentstate
                    }
                    else              //NOT PROBABILISTIC (DETERMINISTIC FSM)
                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent && CurrentState.getTag() == t.getFinal().getTag() && t_aux == null)                   //exist to myself
                                {
                                    t_aux = t;
                                }
                                else if (ev.getEventTag() == CEvent && CurrentState.getTag() != t.getFinal().getTag() && t_aux == null)                    //exist but to another
                                {
                                    t_aux  = t;
                                    change = true;
                                }
                            }
                        }
                    }
                    #endregion

                    #region Classic Update
                    //Exist a change
                    if (change)
                    {
                        //Exist submachine
                        if (t_aux.getFinal().getSubFA() != null)
                        {
                            DoActions.Add(CurrentState.getOutAction());                                                                         //Out action of currentState
                            DoActions.Add(t_aux.getAction());                                                                                   //Action of transition of triggered transition
                            SuperiorStack[es].Push(t_aux.getFinal());                                                                           //Push currentState in superiorStack
                            this.FSM_Stack[es].Push(t_aux.getFinal().getSubFA());                                                               //Push current FSM in FSM_Stack

                            //Do something if FSM is Concurrent_States
                            if (t_aux.getFinal().getSubFA().getTag() == Tags.CONCURRENT_STATES)
                            {
                                foreach (State sta in (t_aux.getFinal().getSubFA() as FA_Concurrent_States).getInitials())
                                {
                                    DoActions.Add(sta.getInAction());
                                }
                            }
                            else                                                              //Do something if not
                            {
                                CurrentState = t_aux.getFinal().getSubFA().getInitialState(); //Update currentState to subinitial state
                                DoActions.Add(CurrentState.getInAction());                    //in action of new currentState
                            }
                        }
                        else
                        {
                            DoActions.Add(CurrentState.getOutAction());                     //Out action of currentState
                            DoActions.Add(t_aux.getAction());                               //Action of transition of triggered transition
                            CurrentState = t_aux.getFinal();                                //Update currentState
                            DoActions.Add(CurrentState.getInAction());                      //In action of new currentState
                        }
                    }
                    else                   //No change
                    {
                        if (t_aux == null) //No transition to go
                        //Check if there is a submachine
                        {
                            if (SuperiorStack[es].Count > 0)
                            {
                                CurrentState = SuperiorStack[es].Pop();                        //CurrentState is updated to inmediately following one in SuperiorStack
                                FSM_Stack[es].Pop();                                           //The FSM that is in top of FSM_Stack is unstacked (updated in next loop repetition)
                            }
                            else
                            {
                                //By default
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                        else
                        {
                            //Loop to myself
                            DoActions.Add(CurrentState.getAction());
                        }
                    }
                    #endregion
                    //restart auxiliar transition
                    t_aux = null;
                    #endregion
                    break;

                case Tags.INERTIAL:                             //INERTIAL LOGIC
                    #region Inertial machine logic

                    //Check if the last event is the same that the new one. If not, FSM has to reset its timer.
                    try{            //try-catch to avoid inconsistence of first cycle
                        if (CEvent != lastEvent)
                        {
                            inertialTimer.Reset();
                        }
                    }catch (Exception e) {}

                    #region Inertial selection
                    if (FSM.isProbabilistic())            //(INERTIAL-PROBABILISTIC FSM)

                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            this.RandomNumber = rnd.Next(99);
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent)
                                {
                                    //if there's
                                    if (this.RandomNumber < t.getProbability())
                                    {
                                        t_aux = t;
                                        if (CurrentState.getTag() != t_aux.getFinal().getTag())
                                        {
                                            change = true;
                                            inertialTimer.Start();
                                        }
                                        else
                                        {
                                            change = false;
                                        }
                                        break;
                                    }
                                }
                            }                    //end foreach events
                            if (t_aux != null)
                            {
                                break;
                            }
                        }             //end foreach transitions of currentstate
                    }
                    else              //(INERTIAL-DETERMINISTIC FSM)
                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent && CurrentState.getTag() == t.getFinal().getTag() && t_aux == null)                   //exist to myself
                                {
                                    t_aux = t;
                                }
                                else if (ev.getEventTag() == CEvent && CurrentState.getTag() != t.getFinal().getTag() && t_aux == null)                    //exist but to another
                                {
                                    t_aux  = t;
                                    change = true;
                                    inertialTimer.Start();                             //Start inertial timer
                                }
                            }
                        }
                    }
                    #endregion

                    #region Inertial Update
                    //There is a change
                    if (change)
                    {
                        //There is a submachine
                        if (t_aux.getFinal().getSubFA() != null)
                        {
                            //Check latency of current state
                            if (inertialTimer.ElapsedMilliseconds > CurrentState.getLatency())
                            {
                                DoActions.Add(CurrentState.getOutAction());                                                                                     //Out action of currentState
                                DoActions.Add(t_aux.getAction());                                                                                               //Action of transition of triggered transition
                                SuperiorStack[es].Push(t_aux.getFinal());                                                                                       //Push currentState in superiorStack
                                this.FSM_Stack[es].Push(t_aux.getFinal().getSubFA());                                                                           //Push current FSM in FSM_Stack
                                //For Concurrent States
                                if (t_aux.getFinal().getSubFA().getTag() == Tags.CONCURRENT_STATES)
                                {
                                    foreach (State sta in (t_aux.getFinal().getSubFA() as FA_Concurrent_States).getInitials())
                                    {
                                        DoActions.Add(sta.getInAction());
                                    }
                                }
                                else
                                {
                                    CurrentState = t_aux.getFinal().getSubFA().getInitialState();                                                       //Update currentState to subinitial state
                                    DoActions.Add(CurrentState.getInAction());                                                                          //In action of new currentState
                                }

                                inertialTimer.Stop(); inertialTimer.Reset();                                                                                            //Stop and reset the timer
                            }
                            else
                            {
                                //By default
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                        else                   //No change

                        {
                            if (inertialTimer.ElapsedMilliseconds > CurrentState.getLatency())
                            {
                                DoActions.Add(CurrentState.getOutAction());                             //Out action of currentState
                                DoActions.Add(t_aux.getAction());                                       //Action of transition of triggered transition
                                CurrentState = t_aux.getFinal();                                        //Update currentState
                                DoActions.Add(CurrentState.getInAction());                              //In action of new currentState
                                inertialTimer.Stop(); inertialTimer.Reset();                            //Stop and reset the timer
                            }
                            else
                            {
                                //By default
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                    }
                    else
                    {
                        if (t_aux == null)                 //No transition to go
                        //Check if there is a submachine
                        {
                            if (SuperiorStack[es].Count > 0)
                            {
                                CurrentState = SuperiorStack[es].Pop();                         //CurrentState is updated to inmediately following one in SuperiorStack
                                FSM_Stack[es].Pop();                                            //The FSM that is in top of FSM_Stack is unstacked (updated in next loop repetition)
                            }
                            else
                            {
                                //By default
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                        else
                        {
                            //By default
                            DoActions.Add(CurrentState.getAction());
                        }
                    }
                    #endregion

                    //Store last event
                    lastEvent = CEvent;
                    //Restart auxiliar transition
                    t_aux = null;
                    #endregion
                    break;

                case Tags.STACK_BASED:         //TO THIS FSM, IT IS NECESSARY THAT EVERY STATE HAS A TRANSITION TO ITSELF****************
                    #region Stack-based machine logic

                    #region Stack-based selection
                    if (FSM.isProbabilistic())            //(STACK-PROBABILISTIC FSM)

                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            this.RandomNumber = rnd.Next(99);
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent)
                                {
                                    //Test if there's
                                    if (this.RandomNumber < t.getProbability())
                                    {
                                        t_aux = t;
                                        if (CurrentState.getTag() != t_aux.getFinal().getTag())
                                        {
                                            change = true;
                                            if (ev.getEventType() == 1 && (t.getFinal().getPriority() > CurrentState.getPriority()))                                    //if EVENT IS STACKABLE
                                            {
                                                stackable = true;
                                            }
                                        }
                                        else
                                        {
                                            change = false;
                                        }
                                        break;
                                    }
                                }
                            }                    //end foreach events
                            if (t_aux != null)
                            {
                                break;
                            }
                        }             //end foreach transitions of currentstate
                    }
                    else              //(STACK-DETERMINISTIC FSM)
                    {
                        foreach (Transition t in CurrentState.getTransitions())
                        {
                            List <FSM_Event> t_events = t.getEvents();
                            foreach (FSM_Event ev in t_events)
                            {
                                if (ev.getEventTag() == CEvent && CurrentState.getTag() == t.getFinal().getTag() && t_aux == null)                   //Exist but to myself
                                {
                                    t_aux = t;
                                }
                                else if (ev.getEventTag() == CEvent && CurrentState.getTag() != t.getFinal().getTag() && t_aux == null)                    //Exist but to another
                                {
                                    t_aux  = t;
                                    change = true;
                                    if (ev.getEventType() == 1 && (t.getFinal().getPriority() > CurrentState.getPriority()))                            //if EVENT IS STACKABLE
                                    {
                                        stackable = true;
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                    #region Stack-based Update
                    //UPDATE FSM
                    if (change)             //If there is a change of State
                    {
                        if (stackable)      //EVENT THAT COMES CAN STACK CURRENTSTATE
                        //Check if destination State has a submachine
                        {
                            if (t_aux.getFinal().getSubFA() != null)
                            {
                                //If there is a submachine, makes Push() in SuperiorState and in FSM_Stack (Hierarchical) and Pop() and Push in ControlStack (Stack-based)
                                DoActions.Add(CurrentState.getOutAction());                                                                                     //out action of currentState
                                DoActions.Add(t_aux.getAction());                                                                                               //action of transition of triggered transition
                                SuperiorStack[es].Push(t_aux.getFinal());                                                                                       //Push currentState in superiorStack
                                this.FSM_Stack[es].Push(t_aux.getFinal().getSubFA());                                                                           //Push current FSM in FSM_Stack

                                if (t_aux.getFinal().getSubFA().getTag() == Tags.CONCURRENT_STATES)
                                {
                                    foreach (State sta in (t_aux.getFinal().getSubFA() as FA_Concurrent_States).getInitials())
                                    {
                                        DoActions.Add(sta.getInAction());
                                    }
                                }
                                else
                                {
                                    CurrentState = t_aux.getFinal().getSubFA().getInitialState();                                                       //Update currentState to subinitial state
                                    DoActions.Add(CurrentState.getInAction());                                                                          //in action of new currentState
                                }
                                //This FSM is Stack-based:
                                //stackable
                                ControlStack[es].Push(CurrentState);        //Push the new one
                            }
                            else                                            //if not, machine updates position giving 3 actions (out/transition/in), makes Pop() and Push() in ControlStack (Stack-based)
                            {
                                DoActions.Add(CurrentState.getOutAction()); //Out action of currentState
                                DoActions.Add(t_aux.getAction());           //Action of transition of triggered transition
                                CurrentState = t_aux.getFinal();            //Update currentState
                                DoActions.Add(CurrentState.getInAction());  //In action of new currentState
                                //This FSM is Stack-based:
                                //stackable
                                ControlStack[es].Push(CurrentState);                                            //Push the new one
                            }
                        }
                        else
                        {
                            if (t_aux.getFinal().getSubFA() != null)
                            {
                                //If there is a submachine, makes Push() in SuperiorState and in FSM_Stack (Hierarchical) and Pop() and Push in ControlStack (Stack-based)
                                DoActions.Add(CurrentState.getOutAction());                                                                             //Out action of currentState
                                DoActions.Add(t_aux.getAction());                                                                                       //Action of transition of triggered transition
                                SuperiorStack[es].Push(t_aux.getFinal());                                                                               //Push currentState in superiorStack
                                this.FSM_Stack[es].Push(t_aux.getFinal().getSubFA());                                                                   //Push current FSM in FSM_Stack

                                //For concurrent_states
                                if (t_aux.getFinal().getSubFA().getTag() == Tags.CONCURRENT_STATES)
                                {
                                    foreach (State sta in (t_aux.getFinal().getSubFA() as FA_Concurrent_States).getInitials())
                                    {
                                        DoActions.Add(sta.getInAction());
                                    }
                                }
                                else
                                {
                                    CurrentState = t_aux.getFinal().getSubFA().getInitialState();                                                       //Update currentState to subinitial state
                                    DoActions.Add(CurrentState.getInAction());                                                                          //In action of new currentState
                                }
                                //This FSM is Stack-based:
                                ControlStack[es].Pop();                     //Pop top state
                                ControlStack[es].Push(CurrentState);        //Push the new one
                            }
                            else                                            //if not, machine updates position giving 3 actions (out/transition/in), makes Pop() and Push() in ControlStack (Stack-based)
                            {
                                DoActions.Add(CurrentState.getOutAction()); //out action of currentState
                                DoActions.Add(t_aux.getAction());           //action of transition of triggered transition
                                CurrentState = t_aux.getFinal();            //Update currentState
                                DoActions.Add(CurrentState.getInAction());  //in action of new currentState
                                //This FSM is Stack-based:
                                //No stackable
                                ControlStack[es].Pop();                                                         //Pop top state
                                ControlStack[es].Push(CurrentState);                                            //Push the new one
                            }
                        }
                    }
                    else               //If there is not a change

                    //PRIORITY OF PERFORMANCE IN THIS FMS:  ** ControlStack > SuperiorStack > Default **
                    {
                        if (ControlStack[es].Count > 1)                  //If(ControlStack > 1) means that some State has interrupted previously
                        {
                            if (t_aux == null)                           //FSM did not find a transition
                            {
                                ControlStack[es].Pop();                  //CurrentState is unstacked and FSM passes to check the last State in ControlStack
                                CurrentState = ControlStack[es].Peek();  //Update CurrentState
                                DoActions.Add(CurrentState.getAction()); //FSM has to return CurrentState action
                            }
                            else                                         //FSM found a transition (to myself)
                            //FSM has to return CurrentState action
                            {
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                        else                                    //if there is not a transition, the FSM tries to find a potentially activation of a prioritary State with the CEvent
                        //Check if FSM is in a Submachine
                        {
                            if (SuperiorStack[es].Count > 0)                     //if it is...
                            {
                                if (t_aux == null)
                                {
                                    CurrentState = SuperiorStack[es].Pop();                            //CurrentState is updated to inmediately following one in SuperiorStack
                                    FSM_Stack[es].Pop();                                               //The FSM that is in the top of FSM_Stack is unstacked (updated in the next program cycle)
                                }
                                else                                                                   //if not
                                //FSM has to return CurrentState action
                                {
                                    DoActions.Add(CurrentState.getAction());
                                }
                            }
                            else
                            {
                                //UNKNOWN, by default
                                DoActions.Add(CurrentState.getAction());
                            }
                        }
                    }

                    #endregion

                    #endregion
                    break;

                //...///
                case Tags.CONCURRENT_STATES:
                    #region Concurrent-states machine logic

                    //Foreach of events (this FSM_Machine allows to check more than one)
                    foreach (int CurrentEvent in Events)
                    {
                        t_aux  = null;
                        change = false;

                        //Check if currentState can execute its logic or if it has spent its credits on current cycle
                        if (StatesCredits[EnabledStatesCopy[es].getTag()] > 0)
                        {
                            #region Concurrent-states Selection
                            if (FSM.isProbabilistic())                    //(CONCURRENT-PROBABILISTIC FSM)

                            {
                                foreach (Transition t in EnabledStatesCopy[es].getTransitions())
                                {
                                    this.RandomNumber = rnd.Next(99);
                                    List <FSM_Event> t_events = t.getEvents();
                                    foreach (FSM_Event ev in t_events)
                                    {
                                        if (ev.getEventTag() == CEvent)
                                        {
                                            //Test if there's
                                            if (this.RandomNumber < t.getProbability())
                                            {
                                                t_aux = t;
                                                if (EnabledStatesCopy[es].getTag() != t_aux.getFinal().getTag())
                                                {
                                                    change = true;
                                                }
                                                else
                                                {
                                                    change = false;
                                                }
                                                break;
                                            }                    /*else{
                                                                  *     Accumulate += t.getProbability();
                                                                  * }*/
                                        }
                                    }                            //end foreach events
                                    if (t_aux != null)
                                    {
                                        break;
                                    }
                                }                     //end foreach transitions of currentstate
                            }
                            else                      //(CONCURRENT-DETERMINISTIC FSM)
                            {
                                foreach (Transition t in EnabledStatesCopy[es].getTransitions())
                                {
                                    foreach (FSM_Event ev in t.getEvents())
                                    {
                                        if (ev.getEventTag() == CurrentEvent && EnabledStatesCopy[es].getTag() == t.getFinal().getTag())                                     //exist but to myself
                                        {
                                            t_aux = t;
                                            break;
                                        }
                                        else if (ev.getEventTag() == CurrentEvent && EnabledStatesCopy[es].getTag() != t.getFinal().getTag())                                     //exist but to another
                                        {
                                            t_aux  = t;
                                            change = true;
                                            break;
                                        }
                                    }
                                    if (t_aux != null)
                                    {
                                        break;
                                    }
                                }
                            }
                            #endregion

                            #region Concurrent-states Update
                            //There is a change
                            if (change)
                            {
                                if (!onCycle.Contains(t_aux.getFinal()))                         //Destination is not onCycle
                                {
                                    int CurrentCredits = StatesCredits[EnabledStatesCopy[es].getTag()];
                                    //If I've got more than one credit, or I've got one and I'm not on current cycle...
                                    if (StatesCredits[EnabledStatesCopy[es].getTag()] > 1 || (StatesCredits[EnabledStatesCopy[es].getTag()] == 1 && !onCycle.Contains(EnabledStatesCopy[es])))
                                    {
                                        if (t_aux.getFinal().getSubFA() != null)
                                        {
                                            DoActions.Add(EnabledStatesCopy[es].getOutAction());                                                                                        //out action of currentState
                                            StatesCredits[EnabledStatesCopy[es].getTag()] = StatesCredits[EnabledStatesCopy[es].getTag()] - 1;                                          //CurrentState LOSES one credit

                                            DoActions.Add(t_aux.getAction());                                                                                                           //action of transition of triggered transition
                                            SuperiorStack[es].Push(t_aux.getFinal());                                                                                                   //Push currentState in superiorStack[i]
                                            this.FSM_Stack[es].Push(t_aux.getFinal().getSubFA());                                                                                       //Push current FSM in FSM_Stack[i]

                                            StatesCredits[t_aux.getFinal().getTag()] = StatesCredits[t_aux.getFinal().getTag()] + 1;                                                    //CurrentState WINS one credit

                                            //For concurrent_states
                                            if (t_aux.getFinal().getSubFA().getTag() == Tags.CONCURRENT_STATES)
                                            {
                                                foreach (State sta in (t_aux.getFinal().getSubFA() as FA_Concurrent_States).getInitials())
                                                {
                                                    DoActions.Add(sta.getInAction());
                                                }
                                            }
                                            else
                                            {
                                                EnabledStatesCopy[es] = t_aux.getFinal().getSubFA().getInitialState();                                                                  //Update currentState to subinitial state
                                                DoActions.Add(EnabledStatesCopy[es].getInAction());                                                                                     //in action of new currentState
                                            }

                                            onCycle.Add(t_aux.getFinal());                                              //FSM has processed the destination once in this cycle, so it is added to OnCycle list.
                                        }
                                        else
                                        {
                                            DoActions.Add(EnabledStatesCopy[es].getOutAction());                                               //Out action of currentState
                                            StatesCredits[EnabledStatesCopy[es].getTag()] = StatesCredits[EnabledStatesCopy[es].getTag()] - 1; //CurrentState LOSES one credit
                                            DoActions.Add(t_aux.getAction());                                                                  //Action of transition of triggered transition
                                            EnabledStatesCopy[es] = t_aux.getFinal();                                                          //Update currentState
                                            StatesCredits[EnabledStatesCopy[es].getTag()] = StatesCredits[EnabledStatesCopy[es].getTag()] + 1; //CurrentState WINS one credit
                                            DoActions.Add(EnabledStatesCopy[es].getInAction());                                                //In action of new currentState

                                            onCycle.Add(t_aux.getFinal());                                                                     //FSM has processed the destination once in this cycle, so it is added to OnCycle lis
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (t_aux == null)                         //No transition to go
                                //Check if there is a submachine
                                {
                                    if (SuperiorStack[es].Count > 0)
                                    {
                                        EnabledStatesCopy[es] = SuperiorStack[es].Pop(); //CurrentState is updated to inmediately following one in SuperiorStack
                                        FSM_Stack[es].Pop();                             //The FSM that is in top of FSM_Stack is unstacked (updated in next loop repetition)
                                    }
                                    else                                                 //DEFAULT
                                    {
                                        if (!onCycle.Contains(EnabledStatesCopy[es]))
                                        {
                                            onCycle.Add(EnabledStatesCopy[es]);
                                            DoActions.Add(EnabledStates[es].getAction());
                                        }
                                    }
                                }
                                else                          //DEFAULT
                                {
                                    if (!onCycle.Contains(EnabledStatesCopy[es]))
                                    {
                                        onCycle.Add(EnabledStatesCopy[es]);
                                        DoActions.Add(EnabledStates[es].getAction());
                                    }
                                }
                            }
                            #endregion
                        }
                        else                  //If currentState has not got any credits, its has to stop its execution in this cycle
                        {
                            break;
                        }
                    }            //end FOREACH EVENTS

                    UpdateEnabled = true;
                    #endregion
                    break;
                }         //END Switch FSM.tag

                //UPDATE COUNTER
                es++;
            }    //END Loop for EnabledStates
                 //*********************************************************************************

            //Concurrent Machine has to update Enabled States List
            if (UpdateEnabled)
            {
                UpdateEnabled = false;
                EnabledStates.Clear();
                EnabledStates = onCycle.ToList();
                if (EnabledStates.Count == 0)
                {
                    //foreach(State s in FSM.getStatesList()){
                    foreach (KeyValuePair <int, int> entry in StatesCredits)
                    {
                        // do something with entry.Value or entry.Key
                        if (entry.Value > 0)
                        {
                            EnabledStates.Add(FSM.getStateByTag(entry.Key));
                        }
                    }
                }
            }
            //Here we could browse the list of actions:
            /*(...)*/

            //FSM_Machine returns a list of actions to its assigned object (usually a character)
            return(DoActions);
        }