home *** CD-ROM | disk | FTP | other *** search
- {
- ════════════════════════════════════════════════════════════════════════════
-
- Visionix Finite State Machine (VStateu) Unit
- Version 0.7
- Copyright 1991,92,93 Visionix
- ALL RIGHTS RESERVED
-
- ────────────────────────────────────────────────────────────────────────────
-
- Revision history in reverse chronological order:
-
- Initials Date Comment
- ──────── ──────── ───────────────────────────────────────────────────────
-
- jrt 11/02/93 First logged revision.
-
- ════════════════════════════════════════════════════════════════════════════
- }
-
- (*-
-
- [TEXT]
-
- <Overview>
-
- This unit includes functions to assist in the creation and usage
- of finate state machine based programs. It includes functions to
- create state machines, add states to machines, track states, remove
- states, and execute state machines.
-
- <Interface>
-
- -*)
-
- Unit VStateu;
-
- Interface
-
- Uses
-
- VTypesu;
-
-
- Const
-
- {------------------------------------------}
- { constant returned by a state to tell the }
- { state machine to stop }
- {------------------------------------------}
-
- cstateMachineStop = -1;
-
- {-----------------------}
- { VStateMachineDo flags }
- {-----------------------}
-
- cSmStopOnEveryState = $0001; { explicit stop after EVERY state }
-
- {---------------------------------------}
- { debug messages for the debug function }
- {---------------------------------------}
-
- csmdStateMachineStarted = $0001;
- csmdStatePre = $0002;
- csmdStatePost = $0003;
- csmdStateMachineStopped = $0004;
-
- Type
-
- {---------------------}
- { state function type }
- {---------------------}
-
- TStateFunc = FUNCTION ( StateID : INTEGER;
- nexus : POINTER ) : INTEGER;
-
- {----------------------------}
- { per-state info record type }
- {----------------------------}
-
- TStateName = STRING[40];
-
- TState = RECORD
-
- StateID : INTEGER;
- StateName : TStateName;
- StateFunc : TStateFunc;
-
- END;
-
- PState = ^TState;
-
- {-----------------------------------}
- { state machine debug function type }
- {-----------------------------------}
-
- TStateDebugFunc = FUNCTION ( Msg : LONGINT;
- StateID : INTEGER;
- StateName : TStateName;
- nexus : POINTER ) : INTEGER;
-
-
-
- {------------------------}
- { The state machine type }
- {------------------------}
-
- TStateMachine = RECORD
-
- NumStatesAlloc : INTEGER;
- CurNumStates : INTEGER;
- DebugFunc : TStateDebugFunc;
- State : Array[1..1] of TState;
-
- END;
-
- PStateMachine = ^TStateMachine;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Function VStateMachineNew( Flags : WORD;
- NumStates : INTEGER ) : PStateMachine;
-
- Procedure VStateMachineDispose( SM : PStateMachine );
-
-
- Procedure VStateMachineDebug( SM : PStateMachine;
- DebugFunc : TStateDebugFunc );
-
-
- Procedure VStateMachineAdd( SM : PStateMachine;
- StateID : INTEGER;
- StateName : TStateName;
- StateFunc : TStateFunc );
-
- Function VStateMachineStart( SM : PStateMachine;
- Flags : WORD;
- StartStateID : INTEGER;
- Nexus : POINTER ) : INTEGER;
-
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Implementation
-
- Function VStateMachineNew( Flags : WORD;
- NumStates : INTEGER ) : PStateMachine;
-
- Var
-
- NSM : PStateMachine;
-
- BEGIN
-
- GetMem( NSM, SizeOf( TStateMachine ) +
- ( SizeOf(TState) * (NumStates-1) ) );
-
- NSM^.NumStatesAlloc := NumStates;
-
- NSM^.CurNumStates := 0;
-
- @NSM^.DebugFunc := NIL; { !! version 6.0 bug }
-
- VStateMachineNew := NSM;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VStateMachineDispose( SM : PStateMachine );
-
- BEGIN
-
- FreeMem( SM, SizeOf( TStateMachine ) +
- ( SizeOf(TState) * (SM^.NumStatesAlloc-1) ) );
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VStateMachineDebug( SM : PStateMachine;
- DebugFunc : TStateDebugFunc );
-
- BEGIN
-
- SM^.DebugFunc := DebugFunc;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VStateMachineAdd( SM : PStateMachine;
- StateID : INTEGER;
- StateName : TStateName;
- StateFunc : TStateFunc );
-
- Var
-
- Z : INTEGER;
-
- BEGIN
-
- If SM^.CurNumStates<SM^.NumStatesAlloc Then
- BEGIN
-
- Inc( SM^.CurNumStates );
-
- Z := SM^.CurNumStates;
-
- SM^.State[Z].StateID := StateId;
- SM^.State[Z].StateName := StateName;
- SM^.State[Z].StateFunc := StateFunc;
-
- END;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
-
-
- Function VStateMachineStart( SM : PStateMachine;
- Flags : WORD;
- StartStateID : INTEGER;
- Nexus : POINTER ) : INTEGER;
-
- Var
-
- CurStateID : INTEGER;
- NextStateID : INTEGER;
- Z : INTEGER;
-
- BEGIN
-
- {----------------------------------------------}
- { start off looking for the specified state ID }
- {----------------------------------------------}
-
- NextStateId := StartStateID;
-
- {---------------------------------------------}
- { if a debug proc has been specified, tell it }
- { that we are starting the state machine }
- {---------------------------------------------}
-
- If @SM^.DebugFunc<>NIL Then
- SM^.DebugFunc( csmdStateMachineStarted,
- NextStateId,
- '',
- Nexus );
-
-
- {-----------------------------------------}
- { do the state machine until it says STOP }
- { or stop because the cSMStopOnEveryState }
- { flag is set. }
- {-----------------------------------------}
-
- Repeat
-
- {--------------------------}
- { look for the nextStateID }
- { until we find it or we }
- { checked all the states }
- {--------------------------}
-
- Z := 1;
-
- While (SM^.State[Z].StateID<>NextStateID) and
- (Z<=SM^.CurNumStates ) Do
-
- Inc( Z );
-
-
- {------------------------------}
- { Did we find the nextstateID? }
- {------------------------------}
-
- If SM^.State[Z].StateID=NextStateID Then
- BEGIN
-
- {----------------------}
- { yep, go do the state }
- {----------------------}
-
- CurStateID := NextStateID;
-
- {----------------------------------------------}
- { if a debug proc has been set, tell it we are }
- { before the state }
- {----------------------------------------------}
-
- If @SM^.DebugFunc<>NIL Then
- SM^.DebugFunc( csmdStatePre,
- CurStateId,
- SM^.State[Z].Statename,
- Nexus );
-
-
- NextStateID := SM^.State[Z].StateFunc( CurStateID, Nexus );
-
- {----------------------------------------------}
- { if a debug proc has been set, tell it we are }
- { after the state }
- {----------------------------------------------}
-
- If @SM^.DebugFunc<>NIL Then
- SM^.DebugFunc( csmdStatePost,
- CurStateId,
- SM^.State[Z].Statename,
- Nexus );
-
-
-
- END
- ELSE
- NextStateID := cStateMachineStop;
-
- Until (NextStateID=cStateMachineStop ) or
- (Flags and cSMStopOnEveryState>0);
-
- {----------------------------------------------}
- { if a debug proc has been set, tell it we are }
- { stopping the state machine }
- {----------------------------------------------}
-
- If @SM^.DebugFunc<>NIL Then
- SM^.DebugFunc( csmdStateMachineStopped,
- CurStateId,
- '',
- Nexus );
-
-
- VStateMachineStart := CurStateId;
-
- END;
-
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
-
- BEGIN
-
- END.