# Quick Tutorial

1\. Include the C/C++ headers

```cpp
#include <assert.h>
```

2\. Configure optional [HFSM2](https://hfsm.dev/) functionality using `#define`s\
(in this case we're using Plans to make transition cycle more straightforward):

```cpp
#define HFSM2_ENABLE_PLANS
```

3\. Include [HFSM2](https://hfsm.dev/) header:

```cpp
#include <hfsm2/machine.hpp>
```

4\. Define interface class between the state machine and its host\
(also ok to use the host object itself):

```cpp
struct Context {
    bool powerOn;
};
```

5\. (Optional) Define type config:

```cpp
using Config = hfsm2::Config::ContextT<Context>;
```

6\. (Optional, recommended) Define`hfsm2::Machine` for convenience:

```cpp
using M = hfsm2::MachineT<Config>;
```

7\. Declare state machine structure.\
States need to be forward declared, e.g. with a magic macro:

```cpp
#define S(s) struct s

using FSM = M::PeerRoot<
                S(Off),                                // initial top-level state
                M::Composite<S(On),                    // sub-machine region with a head state (On) and and 3 sub-states
                    S(Red),                            // initial sub-state of the region
                    S(Yellow),
                    S(Green)
                >,
                S(Done)
            >;

#undef S
```

8\. (Optional) While [HFSM2](https://hfsm.dev/) transitions aren't event-based, events can be used to have FSM react to external stimuli:

```cpp
struct Event {};
```

9\. Define states and override required state methods:

```cpp
struct Off
    : FSM::State
{
    void entryGuard(FullControl& control) {            // called before state activation, use to re-route transitions
        if (control.context().powerOn)                 // access shared data
            control.changeTo<On>();                    // initiate a transition into 'On' region
    }
};
```

```cpp
struct On
    : FSM::State
{
    void enter(PlanControl& control) {                 // called on state activation
        auto plan = control.plan();                    // access the plan for the region

        plan.change<Red, Yellow>();                    // sequence plan steps, executed when the previous state succeeds
        plan.change<Yellow, Green>();
        plan.change<Green, Yellow>();
        plan.change<Yellow, Red>();
    }

    void exit(PlanControl& /*control*/) {}             // called on state deactivation

    void planSucceeded(FullControl& control) {         // called on the successful completion of all plan steps
        control.changeTo<Done>();
    }

    void planFailed(FullControl& /*control*/) {}       // called if any of the plan steps fails
};
```

```cpp
struct Red
    : FSM::State
{
    void update(FullControl& control) {                // called on periodic state machine updates
        control.succeed();                             // notify successful completion of the plan step
    }                                                  // plan will advance to the 'Yellow' state
};
```

```cpp
struct Yellow
    : FSM::State
{
    void update(FullControl& control) {
        control.succeed();                             // plan will advance to the 'Green' state on the first entry
                                                       // and 'Red' state on the second one
    }
};
```

```cpp
struct Green
    : FSM::State
{
    void react(const Event&, FullControl& control) {   // called on external events
        control.succeed();                             // advance to the next plan step
    }
};
```

```cpp
struct Done
    : FSM::State
{};
```

10\. Write the client code to use your new state machine:

```cpp
int main() {
```

11\. Create context and state machine instances:

```cpp
    Context context;
    context.powerOn = true;

    FSM::Instance fsm{context};
    assert(fsm.isActive<On>());                        // activated by Off::entryGuard()
    assert(fsm.isActive<Red>());                       // On's initial sub-state
```

12\. Call `FSM::update()` for the FSM to process transitions:

```cpp
    fsm.update();
    assert(fsm.isActive<Yellow>());                    // 1st setp of On's plan

    fsm.update();
    assert(fsm.isActive<Green>());                     // 2nd setp of On's plan
```

13\. (Optional) Event reactions also cause transitions to be processed:

```cpp
    fsm.react(Event{});
    assert(fsm.isActive<Yellow>());                    // 3rd setp of On's plan
```

14\. Keep updating the FSM for as long as necessary:

```cpp
    fsm.update();
    assert(fsm.isActive<Red>());                       // 4th setp of On's plan

    fsm.update();
    assert(fsm.isActive<Done>());                      // activated by On::planSucceeded()

    return 0;
}
```

## See Also

[snippets/wiki\_tutorial.cpp](https://github.com/andrew-gresyk/HFSM2/blob/master/examples/snippets/wiki_tutorial.cpp)
