{"id":18918797,"url":"https://github.com/nathhb/nbsm","last_synced_at":"2025-09-04T23:31:59.409Z","repository":{"id":75993690,"uuid":"397554244","full_name":"nathhB/nbsm","owner":"nathhB","description":"nbsm is a tiny c99 library for building finite state machines.","archived":false,"fork":false,"pushed_at":"2021-11-06T09:13:11.000Z","size":369,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-08T10:50:21.042Z","etag":null,"topics":["c99","single-header","state-machine"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nathhB.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-18T10:03:49.000Z","updated_at":"2024-08-05T03:37:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"abb4ee70-ca05-4ac9-bd95-9fdffad9356a","html_url":"https://github.com/nathhB/nbsm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathhB%2Fnbsm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathhB%2Fnbsm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathhB%2Fnbsm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nathhB%2Fnbsm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nathhB","download_url":"https://codeload.github.com/nathhB/nbsm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232005259,"owners_count":18459033,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c99","single-header","state-machine"],"created_at":"2024-11-08T10:33:46.364Z","updated_at":"2024-12-31T15:54:08.657Z","avatar_url":"https://github.com/nathhB.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nbsm\n\n*nbsm* is a tiny single header C99 library for building finite state machines. It comes with a built-in JSON support to load state\nmachines from JSON files generated with the [nbsm editor](). You can see a video of the editor [here](https://www.youtube.com/watch?v=f7_d8UYtxwI\u0026ab_channel=NathanBIAGINI).\n\n![nbsm_editor](https://github.com/nathhB/nbsm/blob/main/editor_screenshot.png)\n\n*Disclaimer* : the nbsm editor is still a WIP.\n\n1. [How to use](https://github.com/nathhB/nbsm#how-to-use)\n3. [nbsm editor](https://github.com/nathhB/nbsm#nbsm-editor)\n## How to use\n\nYou can look at the [test suite](https://github.com/nathhB/nbsm/blob/main/tests/suite.c) for examples of using the *nbsm*'s API, but here is a quick overview.\n\n### Creating state machines\n\n```\nNBSM_Machine *m = NBSM_Create();\n```\n\n### Creating states\n\n```\nNBSM_AddState(m, \"foo\", true); // this is the initial state\nNBSM_AddState(m, \"bar\", false);\nNBSM_AddState(m, \"plop\", false);\n```\n\n### Accessing the current state\n\n`m-\u003ecurrent_state; // current state machine's state`\n\n### Creating transitions between states\n\n```\nNBSM_AddTransition(m, \"foo\", \"bar\"); // create a transition between the \"foo\" state and the \"bar\" state\nNBSM_AddTransition(m, \"bar\", \"plop\"); // create a transition between the \"bar\" state and the \"plop\" state\n```\n\n### Creating variables\n\nVariables can be used to define conditions for transitions. The variable type can be either `integer`, `float` or `boolean`.\n\n```\nNBSM_Value *v1 = NBSM_AddInteger(m, \"v1\");\nNBSM_Value *v2 = NBSM_AddFloat(m, \"v2\");\nNBSM_Value *v3 = NBSM_AddBoolean(m, \"v3\");\n```\n\n`integer` and `float` variables are initialized to zero; `boolean` variables are initialized to `false`.\n\nVariables can be updated as follow:\n\n```\nNBSM_SetInteger(v1, 42);\nNBSM_SetFloat(v2, 42.5f);\nNBSM_SetBoolean(v3, true);\n```\n\n### Adding conditions to a transition\n\n```\nNBSM_Transition *t1 = NBSM_AddTransition(m, \"foo\", \"bar\");\n\nNBSM_AddCondition(m, t1, \"v1\", NBSM_EQ, NBSM_CONST_I(42)); // variable \"v1\" equals 42 (integer constant)\nNBSM_AddCondition(m, t1, \"v2\", NBSM_LT, NBSM_VAR(m, \"v4\")); // variable \"v2\" is lower than variable \"v4\"\n```\n\nHere are the supported condition types:\n\n```\ntypedef enum\n{\n    NBSM_EQ,    // equal\n    NBSM_NEQ,   // not equal\n    NBSM_LT,    // lower than\n    NBSM_LTE,   // lower or equal than\n    NBSM_GT,    // greater than\n    NBSM_GTE    // greater or equal than\n} NBSM_ConditionType;\n```\n\nFor a transition to be executed, all of its conditions must be true. If a transition has no condition, it will always be executed.\n\n### Updating\n\n```\nNBSM_Update(m);\n```\n\nIt needs to be called every frame to evaluate the current state's transitions.\n\n### State hooks\n\nThere are three types of state hooks:\n\n* `OnEnter` : called when a new state is entered\n* `OnExit` : called when the current state is exited\n* `OnUpdate` : called when the current state is updated (every time `NBSM_Update` is called)\n\nState hooks are just callbacks; here is the prototype:\n\n`typedef void (*NBSM_StateHookFunc)(NBSM_Machine *machine, void *user_data);`\n\nTo set a state's hooks:\n\n```\nNBSM_OnStateEnter(m, \"foo\", OnEnterFunc); // set the \"OnEnter\" hook of the \"foo\" state\nNBSM_OnStateExit(m, \"foo\", OnExitFunc); // set the \"OnExit\" hook of the \"foo\" state\nNBSM_OnStateUpdate(m, \"foo\", OnExitFunc); // set the \"OnUpdate\" hook of the \"foo\" state\n```\n\nThe `user_data` parameter of the hook callback is set to the state's user data (see below).\n\n### User data\n\nGeneric user data can be attached to both the state machine itself or any of the states:\n\n`NBSM_AttachDataToState(m, \"foo\", some_data_ptr); // assign a generic data to the \"foo\" state`\n\n`m-\u003euser_data = some_data_ptr; // assign a generic data to a state machine`\n\n### Machine builder\n\nA machine builder is used to generate state machines. Machine builders are used as interfaces between external state machine descriptions (such as a JSON file) and actual state machines.\n\n*nbsm* comes with a built-in JSON machine builder.\n\n#### JSON\n\nJSON supports is made possible thanks to the [json.h](https://github.com/sheredom/json.h) library. To use it in your project, you need to grab the `file.h` header, put it next to the `nbsm.h` header, and define the `NBSM_JSON_BUILDER` before including `nbsm.h` (see the [test suite](https://github.com/nathhB/nbsm/blob/main/tests/suite.c) for an example).\n\n```\nNBSM_MachineBuilder *builder = NBSM_CreateBuilderFromJSON(json);\nNBSM_Machine *m = NBSM_Build(builder);\n```\n\nThe JSON file format is pretty straightforward, simply looking at the [json file](https://github.com/nathhB/nbsm/blob/main/tests/test.json) from the test suite should give you all the information you need.\n\n### Pooling\n\nIf you plan to create many instances of the same state machine, you can use pooling to avoid reallocating memory every time you need to spawn a new state machine. A machine pool is associated with a machine builder to create new state machines when the pool capacity has been reached.\n\n```\nNBSM_MachineBuilder *builder = NBSM_CreateBuilderFromJSON(json);\nNBSM_MachinePool *pool = NBSM_CreatePool(builder, 2); // pool is created with 2 state machines\n\nNBSM_Machine *m1 = NBSM_GetFromPool(pool);\nNBSM_Machine *m2 = NBSM_GetFromPool(pool);\nNBSM_Machine *m3 = NBSM_GetFromPool(pool); // the pool size will be increated to 4 (size * 2)\n\nNBSM_Recycle(pool, m1); // recycle a state machine that is no longer needed and put it back into the pool.\n```\n\n**IMPORTANT** : variables will not be automatically reinitialized when using pooling; so, don't forget to initialize the state machine's variables after grabbing it from the pool.\n\n### Cleaning up\n\nCall `NBSM_Destroy` to clean up the memory allocated for a state machine.\n\nCall `NBSM_DestroyBuilder` to clean up the memory allocated for a machine builder.\n\nWhen using pooling, call `NBSM_DestroyPool` to clean up the memory allocated for the whole pool. Do not use `NBSM_Destroy`.\n\n## nbsm editor\n\n### Compiling\n\nThe nbsm editor relies on [raylib](https://github.com/raysan5/raylib) and [json-c](https://github.com/json-c/json-c), you need to compile both; then (using CMake):\n\n```\ncd editor\nmkdir build\ncd build\ncmake -DRAYLIB_LIBRARY_PATH=\u003cPATH TO RAYLIB LIB FILE\u003e -DRAYLIB_INCLUDE_PATH=\u003cPATH TO RAYLIB INCLUDE DIR\u003e -DJSONC_LIBRARY_PATH=\u003cPATH TO JSONC-C LIB FILE\u003e -DJSONC_INCLUDE_PATH=\u003cPATH TO JSON-C INCLUDE DIR\u003e ..\n```\n\nIf you want to compile for the web, use `emcmake` (also make sure you compiled raylib and json-c for the web as well).\n\n### Using the editor\n\nEither open the generated HTML file in your browser if you compiled for the web or use the command line:\n\n`./nbsm_editor /path/to/test.json`\n\nit will crate a new JSON file if the specified one does not exist or load it if it does exist.\n\n### TODO\n\nHere is a list of editor features yet to to be implemented:\n\n* rename states\n* use variables as the right operand of a condition\n* host a web version of the editor\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathhb%2Fnbsm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnathhb%2Fnbsm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnathhb%2Fnbsm/lists"}