Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Last active April 12, 2021 16:35
Show Gist options
  • Save JettMonstersGoBoom/6f03d5435c2e156e20cb39a59f4b12d8 to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/6f03d5435c2e156e20cb39a59f4b12d8 to your computer and use it in GitHub Desktop.
Simple Finite State machine in C
//
// simple finite state machine in C
//
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// for this example lets have N objects/entities
#define MAX_ENTS 4
// types
typedef struct entity_t
{
int (*current_state)(struct entity_t *self);
int ID;
int counter;
} entity_t;
typedef int (*function_pointer_t)(entity_t *);
// return types to handle
enum return_codes { OK, FAIL, REPEAT, ATTACK};
// transition type
struct transition {
function_pointer_t source_state;
enum return_codes ret_code;
function_pointer_t destination_state;
};
// possible state functions
int OnEnterState(entity_t *self);
int OnIdleState(entity_t *self);
int OnWalkState(entity_t *self);
int OnAttackState(entity_t *self);
int OnExitState(entity_t *self);
// transition from State if code == state to State
struct transition state_transitions[] = {
// if source is entry , we can respond to OK or FAIL states
{OnEnterState, OK, OnIdleState},
{OnEnterState, FAIL, OnExitState},
// if attack state, respond to OK or FAIL
{OnAttackState,OK, OnWalkState},
{OnAttackState,FAIL, OnIdleState},
// if idle state, can repeat, ok , fail , or attack
{OnIdleState, OK, OnWalkState},
{OnIdleState, FAIL, OnExitState},
{OnIdleState, REPEAT, OnIdleState},
{OnIdleState, ATTACK, OnAttackState},
// if walk state, can repeat, ok, or fail
{OnWalkState, OK, OnExitState},
{OnWalkState, FAIL, OnExitState},
{OnWalkState, REPEAT, OnIdleState},
{NULL,OK,NULL}
};
// example states
int OnEnterState(entity_t *self)
{
printf("OnEnterState %x\n",self);
self->counter = 5;
return OK;
}
// idle count down and attack
int OnIdleState(entity_t *self)
{
printf("OnIdleState(%d) %d\n",self->ID,self->counter);
if (self->counter!=0)
{
self->counter--;
return REPEAT;
}
self->counter=1+(rand()&7);
return ATTACK;
}
// another state
int OnWalkState(entity_t *self)
{
printf("OnWalkState(%d)\n",self->ID);
return OK;
}
int OnExitState(entity_t *self)
{
printf("OnExitState(%d) %x\n",self->ID,self);
return OK;
}
int OnAttackState(entity_t *self)
{
printf("OnAttackState(%d)\n",self->ID);
if (rand()<64)
return OK;
return FAIL;
}
int OnInvalidState(entity_t *self)
{
printf("OnInvalidState\n");
return FAIL;
}
function_pointer_t SearchTransitions(function_pointer_t cur_state, enum return_codes rc)
{
function_pointer_t next_state;
next_state = OnInvalidState;
// Searching loop
for(int i=0; state_transitions[i].source_state!=NULL; i++)
{
if ((state_transitions[i].source_state == cur_state) && (state_transitions[i].ret_code == rc))
{
next_state = state_transitions[i].destination_state;
break;
}
}
return(next_state);
}
int main(int argc, char *argv[])
{
enum return_codes rc;
entity_t entities[MAX_ENTS];
for (int q=0;q<MAX_ENTS;q++)
{
entities[q].ID = q;
entities[q].current_state = &OnEnterState;
}
for (;;) {
for (int q=0;q<MAX_ENTS;q++)
{
rc = entities[q].current_state(&entities[q]);
if (OnExitState == (function_pointer_t)entities[q].current_state)
exit(0);
entities[q].current_state = SearchTransitions(entities[q].current_state, rc);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment