@awesome-ecs/ai
v0.32.1
Published
Extension of the @awesome-ecs framework with design-patterns useful for AI implementations.
Maintainers
Readme
Awesome ECS - AI Package
Overview
The AI package provides design patterns and abstractions for building intelligent AI systems within the ECS framework. It focuses on state machines rather than specific AI algorithms, allowing flexible composition of AI behaviors.
Key capabilities:
- Finite State Machines (FSM) for behavior control
- State transitions and state factories
- Integration with core ECS entities and systems
Core Concepts
State Machine (src/abstract/state-machine.ts)
The State Machine pattern provides non-linear execution of system middlewares:
export interface IStateMachine<TEntity extends IEntity> {
readonly currentState?: IState<TEntity>;
readonly globalState?: IState<TEntity>;
readonly previousState?: IState<TEntity>;
setCurrentState(uid: StateUid): void;
setGlobalState(uid: StateUid): void;
changeState(uid: StateUid): void;
revertState(): void;
isInState(uid: StateUid): boolean;
update(context: ISystemContext<TEntity>): void;
}Key difference from Pipelines:
- Pipelines execute middleware in a linear, ordered sequence
- State Machines execute only the active state — non-linear, branched execution
State (src/abstract/state.ts)
States represent discrete behaviors that an entity can be in:
export interface IState<TEntity extends IEntity> {
readonly uid: StateUid;
enter?(context: ISystemContext<TEntity>): void; // Called on transition in
execute(context: ISystemContext<TEntity>): void; // Called every frame while active
exit?(context: ISystemContext<TEntity>): void; // Called on transition out
}State Factory (src/abstract/state-factory.ts)
Factory pattern for creating and managing states:
export interface IStateFactory<TEntity extends IEntity> {
create(uid: StateUid): IState<TEntity>;
get(uid: StateUid): IState<TEntity>;
}Helpers (src/helpers/)
Utility functions for state machine construction and common state operations.
Usage Pattern
1. Define States
export enum CreatureState { idle = 'IDLE', moving = 'MOVING', attacking = 'ATTACKING' }
export class IdleState implements IState<CreatureEntity> {
readonly uid = CreatureState.idle;
execute(context: ISystemContext<CreatureEntity>): void {
// Check conditions and transition if needed
context.entity.stateMachine.changeState(CreatureState.attacking);
}
}
export class MovingState implements IState<CreatureEntity> {
readonly uid = CreatureState.moving;
execute(context: ISystemContext<CreatureEntity>): void { /* movement logic */ }
exit(context: ISystemContext<CreatureEntity>): void { /* cleanup */ }
}2. Create State Factory
export class CreatureStateFactory implements IStateFactory<CreatureEntity> {
private states = new Map<StateUid, IState<CreatureEntity>>([
[CreatureState.idle, new IdleState()],
[CreatureState.moving, new MovingState()],
[CreatureState.attacking, new AttackingState()],
]);
create(uid: StateUid): IState<CreatureEntity> { return this.states.get(uid)!; }
get(uid: StateUid): IState<CreatureEntity> { return this.states.get(uid)!; }
}3. Drive from a System Middleware
export class CreatureStateMachineSystem implements ISystemMiddleware<CreatureEntity> {
action(context: ISystemContext<CreatureEntity>): void {
context.entity.stateMachine.update(context);
}
}Register in the update phase of the creature module.
Package Structure
src/
├── abstract/ # IStateMachine, IState, IStateFactory interfaces
└── helpers/ # StateMachine implementation and utilitiesWhen to Use State Machines
✅ Good for:
- Discrete entity behaviors (idle, moving, attacking)
- Clear state transitions
- Non-linear execution (not every frame doing everything)
❌ Not ideal for:
- Linear pipelines (use Pipelines instead)
- Simple data transformations (use Systems instead)
Relationship to Other Packages
- Uses:
@awesome-ecs/abstract - Works with:
@awesome-ecs/workersfor offloading AI calculations to background threads
