# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.hfsm.dev/quick-tutorial.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
