/fsm

:bookmark_tabs: Simple and lightweight Hierarchical/Finite-State Machine (H-FSM) class (C++11)

Primary LanguageC++zlib LicenseZlib

fsm

FSM is a lightweight finite-state machine class. Both Hierarchical FSM and simple FSM implementations are provided.

Features

  • Expressive. Basic usage around on(state,trigger) -> do lambda expression.
  • Tiny, cross-platform, stand-alone, header-only.
  • ZLIB/libPNG licensed.

Links

Finite-State Machines: Theory and Implementation

Showcase

// basic hfsm sample

#include <iostream>
#include "fsm.hpp"

// custom states (gerunds) and actions (infinitives)

enum {
    walking = 'WALK',
    defending = 'DEFN',

    tick = 'tick',
};

struct ant_t {
    fsm::stack fsm;
    int health, distance, flow;

    ant_t() : health(0), distance(0), flow(1) {
        // define fsm transitions: on(state,trigger) -> do lambda
        fsm.on(walking, 'init') = [&]( const fsm::args &args ) {
            std::cout << "initializing" << std::endl;
        };
        fsm.on(walking, 'quit') = [&]( const fsm::args &args ) {
            std::cout << "exiting" << std::endl;
        };
        fsm.on(walking, 'push') = [&]( const fsm::args &args ) {
            std::cout << "pushing current task." << std::endl;
        };
        fsm.on(walking, 'back') = [&]( const fsm::args &args ) {
            std::cout << "back from another task. remaining distance: " << distance << std::endl;
        };
        fsm.on(walking, tick) = [&]( const fsm::args &args ) {
            std::cout << "\r" << "\\|/-"[ distance % 4 ] << " walking " << (flow > 0 ? "-->" : "<--") << " ";
            distance += flow;
            if( 1000 == distance ) {
                std::cout << "at food!" << std::endl;
                flow = -flow;
            }
            if( -1000 == distance ) {
                std::cout << "at home!" << std::endl;
                flow = -flow;
            }
        };
        fsm.on(defending, 'init') = [&]( const fsm::args &args ) {
            health = 1000;
            std::cout << "somebody is attacking me! he has " << health << " health points" << std::endl;
        };
        fsm.on(defending, tick) = [&]( const fsm::args &args ) {
            std::cout << "\r" << "\\|/-$"[ health % 4 ] << " health: (" << health << ")   ";
            --health;
            if( health < 0 ) {
                std::cout << std::endl;
                fsm.pop();
            }
        };

        // set initial fsm state
        fsm.set( walking );
    }
};

int main() {
    ant_t ant;
    for(int i = 0; i < 12000; ++i) {
        if( 0 == rand() % 10000 ) {
            ant.fsm.push(defending);
        }
        ant.fsm.command(tick);
    }
}

Changelog

  • v1.0.0 (2015/11/29): Code revisited to use fourcc integers (much faster); clean ups suggested by Chang Qian
  • v0.0.0 (2014/02/15): Initial version