/** * @todo Fix all the dang `as any` casts. */ import { ActorModelOptionalFunctionNames, } from './ActorModelOptionalFunctionNames'; import { Epistemology, } from '../epistemology/Epistemology'; import { FindModelArgs, } from '../querying/FindModelArgs'; import { IActorModel, } from './IActorModel'; import { IEpistemology, } from '../epistemology/IEpistemology'; import { ILocationModel, } from './ILocationModel'; import { IModel, } from './IModel'; import { IModelConstructorArgs, } from './IModelConstructorArgs'; import { IObjectModel, } from './IObjectModel'; import { IOntology, } from '../ontology/IOntology'; import { isModel, } from '../typeGuards/isModel'; import { IWorld, } from '../world/IWorld'; import { ModelBase, } from './ModelBase'; import { ModelType, } from './ModelType'; import { OnticTypes, } from '../ontology/OnticTypes'; import { Ontology, } from '../ontology/Ontology'; import { assertValid, } from 'ts-assertions'; export class ActorModel< Being extends OnticTypes, Knowledge extends ModelType, > extends ModelBase implements IActorModel { protected readonly __being: IOntology; public get being() { return this.__being; } protected readonly __knowledge: IEpistemology; public get knowledge() { return this.__knowledge; } public get type(): ModelType.Actor { return ModelType.Actor; } constructor( world: IWorld, args: IModelConstructorArgs, ) { super(world, args); this.__being = new Ontology( this.world, { modelType: this.type }, ); this.__knowledge = new Epistemology( this.world, { modelType: this.type }, ); const actorFuncs = args.actorFuncs; if (actorFuncs) { Object.keys(actorFuncs).forEach((key) => { const isActorFunc = Array.prototype.includes.call( ActorModelOptionalFunctionNames, key, ); const val = actorFuncs[key]; if (isActorFunc && typeof val === 'function') { this[key] = val; } }); } } public readonly drop = ( self: IActorModel, target: IObjectModel, ): void => { let targetModel: typeof target; if (isModel(target)) { targetModel = target; } else { targetModel = assertValid(self.world.find(target)); } self.being.containment!.parent.being!.containment.addChild(targetModel as any); }; public readonly findAllGenerator = ((self: IActorModel) => function* ( args: '*' | FindModelArgs, ): IterableIterator> { yield* self.being.findAllGenerator(args as any) as any; yield* self.knowledge.findAllGenerator(args) as any; })(this); public readonly move = ( self: IActorModel, destination: ILocationModel, ): void => { const parent = self.being.containment.parent; if (parent.being) { parent.being.containment.removeChild(self as any); } destination.being.containment.addChild(self as any); }; readonly observe = ( self: IActorModel, target: IModel, ): void => self.knowledge.awareness.addPerception(target as any); readonly take = ( self: IActorModel, target: IObjectModel, ) => { target.being.containment.parent.being!.containment.removeChild(self as any); target.being.containment.addChild(self as any); }; readonly unobserve = ( self: IActorModel, target: IModel, ): void => self.knowledge.awareness.removePerception(target as any); readonly unwant = ( self: IActorModel, target: IModel, ): void => self.knowledge.thoughts.removeWant(target as any); readonly want = ( self: IActorModel, target: IModel, ): void => self.knowledge.thoughts.addWant(target as any); readonly act?: ( self: IActorModel, target: IModel, ) => void; readonly canAct?: (self: IActorModel) => boolean; readonly canActOn?: ( self: IActorModel, target: IModel, ) => boolean; readonly getActionTargets?: ( self: IActorModel, ) => readonly IModel[]; readonly selectActionTarget?: ( self: IActorModel, targets: IModel | readonly IModel[], ) => IModel; readonly willAct?: (self: IActorModel) => boolean; }