feat: add social interaction guards to brain and movement systems

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-07 13:05:05 +00:00
parent ac3f26a470
commit 7cfc8c0537
3 changed files with 48 additions and 3 deletions
+40 -1
View File
@@ -4,7 +4,7 @@ import { GameMap } from '../../map/GameMap.js';
import { needsDecaySystem } from '../needsDecaySystem.js';
import { npcBrainSystem } from '../npcBrainSystem.js';
import { movementSystem } from '../movementSystem.js';
import type { Needs, Movement, NPCBrain, Position } from '@dflike/shared';
import type { Needs, Movement, NPCBrain, Position, SocialState } from '@dflike/shared';
import { HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, MOVE_SPEED } from '@dflike/shared';
function createNPC(world: World, x: number, y: number, hunger = 80, energy = 80) {
@@ -16,6 +16,17 @@ function createNPC(world: World, x: number, y: number, hunger = 80, energy = 80)
return e;
}
function addSocialState(world: World, entity: number, phase: SocialState['phase'] = 'none') {
world.addComponent<SocialState>(entity, 'socialState', {
phase,
partnerId: null,
phaseTimer: 10,
outcome: null,
globalCooldown: 0,
pairCooldowns: new Map(),
});
}
describe('needsDecaySystem', () => {
it('decays hunger and energy each tick', () => {
const world = new World();
@@ -76,6 +87,17 @@ describe('npcBrainSystem', () => {
const brain = world.getComponent<NPCBrain>(e, 'npcBrain')!;
expect(brain.currentGoal).toBe('rest');
});
it('skips NPC when socialState phase is not none', () => {
const world = new World();
const map = new GameMap(10, 10);
const e = createNPC(world, 5, 5, 80, 80);
addSocialState(world, e, 'facing');
const brain = world.getComponent<NPCBrain>(e, 'npcBrain')!;
brain.currentGoal = null;
npcBrainSystem(world, map);
expect(brain.currentGoal).toBeNull();
});
});
describe('movementSystem', () => {
@@ -166,4 +188,21 @@ describe('movementSystem', () => {
expect(mov.state).toBe('idle');
expect(mov.moveProgress).toBe(0);
});
it('skips entity when socialState phase is not none', () => {
const world = new World();
const e = world.createEntity();
world.addComponent<Position>(e, 'position', { x: 0, y: 0 });
world.addComponent<Movement>(e, 'movement', {
state: 'walking',
target: { x: 3, y: 0 },
path: [{ x: 1, y: 0 }, { x: 2, y: 0 }, { x: 3, y: 0 }],
direction: 2,
moveProgress: 0.75,
});
addSocialState(world, e, 'pausing');
movementSystem(world);
const pos = world.getComponent<Position>(e, 'position')!;
expect(pos).toEqual({ x: 0, y: 0 });
});
});