Thread View: comp.lang.c.moderated
3 messages
3 total messages
Started by terres
Sun, 31 Mar 1996 16:43
State engine
Author: terres
Date: Sun, 31 Mar 1996 16:43
Date: Sun, 31 Mar 1996 16:43
24 lines
995 bytes
995 bytes
Hello!
I think that when you have complex problem like many conditions, paths
and cases, a traditional program could be to big and inneficient on
execution.
I have seen a system that uses a state engine that triggers some pieces
of code when an encounters take effect between: states & stimuli.
Like this:
Stimuli
State | 1 2 3
1 |
2 |
3 |
When some conditions are acomplished some specific pieces of code are
executed and that pieces send the control to another crosspoint.
I want to know how to implement this idea in C.
Thanks
Austin
Re: State engine
Author: Kazimir Kylheku
Date: Mon, 01 Apr 1996 13:19
Date: Mon, 01 Apr 1996 13:19
178 lines
4386 bytes
4386 bytes
In article <4jmcoa$lri@solutions.solon.com>,
terres <terres@servidor.dgsca.unam.mx> wrote:
>Hello!
>
>I think that when you have complex problem like many conditions, paths
>and cases, a traditional program could be to big and inneficient on
>execution.
>
>I have seen a system that uses a state engine that triggers some pieces
>of code when an encounters take effect between: states & stimuli.
>
>Like this:
> Stimuli
>State | 1 2 3
>1 |
>2 |
>3 |
>
>When some conditions are acomplished some specific pieces of code are
>executed and that pieces send the control to another crosspoint.
>
>I want to know how to implement this idea in C.
There are all kinds of ways. One is to simply have nested switch statements:
switch (state) {
case 1:
switch(stimulus) {
case 1:
do_something();
state = 2;
break;
case 2:
do_something_else();
state = 3;
break;
case 3:
break;
}
break;
case 2:
break;
case 3:
break;
default:
/* shouldn't reach this */
break;
}
You fill in the missing bits from the table. If you move a lot of the work to
functions, you can keep the switch statement manageable.
Another way is to assing to each state/input combination a function. The
functions don't have to be unique. For instance, if you have a lot of
state/input pairs that do nothing, you can assign to them a function called
idle(). To each state/input combination, you also assign a number which tells
it what state to go into next after the action is called:
enum states {
IDLE, HUNGRY, SLEEPING, IRRITATED, NUMSTATES
};
enum inputs {
FOOD, BELL, NEW_AGE_MUSIC, TIMER, NUMINPUTS
};
typedef void (* action_fun)(void);
struct actiongoto {
action_fun action;
int go;
};
void idle(void);
void eat(void);
void salivate(void);
void growl(void);
static struct actiongoto statetable[NUMSTATES][NUMINPUTS] =
{
{ /* IDLE state */
{ idle, IDLE }, /* FOOD input */
{ idle, IDLE }, /* BELL input */
{ idle, SLEEPING }, /* NEW_AGE_MUSIC input */
{ idle, HUNGRY }, /* TIMER input */
},
{ /* HUNGRY state */
{ eat, IDLE }, /* eat FOOD, be idle */
{ salivate, HUNGRY }, /* salivate on BELL */
{ growl, IRRITATED }, /* growl on music */
{ idle, HUNGRY }, /* stay hungry on timer */
}, /* SLEEPING state */
{
{ idle, SLEEPING },
{ idle, IDLE }, /* awake on bell */
{ idle, SLEEPING }, /* stay asleep w/ music */
{ idle, SLEEPING },
}, /* IRRITATED state */
{
{ eat, IDLE }, /* soothing food */
{ growl, IRRITATED }, /* bell is irritating */
{ growl, IRRITATED }, /* so is new age music */
{ idle, HUNGRY }, /* irritation timeout */
}
};
To use the state table, you look at what state you are in, and what the input
is, and lookup the appropriate actiongoto structure in the two-dimensional
table. You invoke the given function pointer, and advance to the given state.
Assuming you start in the IDLE state, and a TIMER input happens, you call
function idle() and advance to the HUNGRY state. Then, when a BELL input
arrives, you salivate() and stay in the HUNGRY state, and so forth:
#include <stdio.h>
unsigned int getnextinput(void)
{
unsigned int input;
char *menu =
"Enter input\n\n"
"0. FOOD\n"
"1. BELL\n"
"2. NEW_AGE_MUSIC\n"
"3. TIMER\n";
puts(menu);
do {
fputs(">",stdout);
scanf("%u",&input);
} while (input >= NUMINPUTS);
return input;
}
int main()
{
unsigned int input;
unsigned int state = 0;
while(1) {
input = getnextinput();
statetable[state][input].action();
state = statetable[state][input].go;
}
return 0;
}
void eat(void)
{
puts("Munch munch!");
}
void salivate(void)
{
puts("drool!");
}
void growl(void)
{
puts("grr!");
}
void idle(void)
{
puts("yawn!");
}
--
Re: State engine
Author: Mike McCarty
Date: Sat, 13 Apr 1996 13:57
Date: Sat, 13 Apr 1996 13:57
58 lines
1869 bytes
1869 bytes
In article <4jmcoa$lri@solutions.solon.com>,
terres <terres@servidor.dgsca.unam.mx> wrote:
)Hello!
)
)I think that when you have complex problem like many conditions, paths
)and cases, a traditional program could be to big and inneficient on
)execution.
)
)I have seen a system that uses a state engine that triggers some pieces
)of code when an encounters take effect between: states & stimuli.
)
)Like this:
) Stimuli
)State | 1 2 3
)1 |
)2 |
)3 |
)
)When some conditions are acomplished some specific pieces of code are
)executed and that pieces send the control to another crosspoint.
)
)I want to know how to implement this idea in C.
)
)Thanks
)
)Austin
typedef enum { InActive, Ready, RarinToGo } State_t;
#define LastState RarinToGo
typedef enum { CountDown, Ignition, LiftOff } Event_t;
#define LastEvent LiftOff
typedef struct {
State_t NextState;
void (*action)(void);
} StMachine_t
void GetReady(void);
StMachine_t StateMachine[LastState+1][LastEvent+1] = {
/* InActive */ {
/* Countdown */ { Ready, GetReady},
/* Ignition */ {
...
}
void HandleState(State_t *State,Event_t Event) {
StateMachine[*State][Event].action();
*State = StateMachine[*State][Event].NextState;
}
--
----
char *p="char *p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}
I don't speak for DSC. <- They make me say that.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads