feat: add optional positionHint to spawnNPC
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { World } from '../../ecs/World.js';
|
||||
import { GameMap } from '../../map/GameMap.js';
|
||||
import { spawnNPC } from '../spawner.js';
|
||||
import type { Position } from '@dflike/shared';
|
||||
|
||||
describe('spawnNPC', () => {
|
||||
it('spawns at random position when no hint given', () => {
|
||||
const world = new World();
|
||||
const map = new GameMap();
|
||||
const entity = spawnNPC(world, map);
|
||||
const pos = world.getComponent<Position>(entity, 'position')!;
|
||||
expect(pos).toBeDefined();
|
||||
expect(pos.x).toBeGreaterThanOrEqual(0);
|
||||
expect(pos.y).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
|
||||
it('spawns at hint position when walkable', () => {
|
||||
const world = new World();
|
||||
const map = new GameMap();
|
||||
const entity = spawnNPC(world, map, { x: 20, y: 20 });
|
||||
const pos = world.getComponent<Position>(entity, 'position')!;
|
||||
expect(pos).toEqual({ x: 20, y: 20 });
|
||||
});
|
||||
|
||||
it('spawns at random position when hint is not walkable', () => {
|
||||
const world = new World();
|
||||
const map = new GameMap();
|
||||
map.setObstacle(20, 20);
|
||||
const entity = spawnNPC(world, map, { x: 20, y: 20 });
|
||||
const pos = world.getComponent<Position>(entity, 'position')!;
|
||||
expect(pos).toBeDefined();
|
||||
expect(pos.x !== 20 || pos.y !== 20).toBe(true);
|
||||
});
|
||||
|
||||
it('creates all required components', () => {
|
||||
const world = new World();
|
||||
const map = new GameMap();
|
||||
const entity = spawnNPC(world, map);
|
||||
expect(world.getComponent(entity, 'position')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'needs')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'movement')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'npcBrain')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'appearance')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'name')).toBeDefined();
|
||||
expect(world.getComponent(entity, 'socialState')).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -4,9 +4,11 @@ import { generateRandomAppearance } from '../spawner/appearanceGenerator.js';
|
||||
import { generateName } from '../spawner/nameGenerator.js';
|
||||
import type { EntityId, Position, Needs, Movement, NPCBrain, Appearance, SocialState } from '@dflike/shared';
|
||||
|
||||
export function spawnNPC(world: World, map: GameMap): EntityId {
|
||||
export function spawnNPC(world: World, map: GameMap, positionHint?: Position): EntityId {
|
||||
const entity = world.createEntity();
|
||||
const pos = map.getRandomWalkable();
|
||||
const pos = positionHint && map.isWalkable(positionHint.x, positionHint.y)
|
||||
? positionHint
|
||||
: map.getRandomWalkable();
|
||||
|
||||
world.addComponent<Position>(entity, 'position', pos);
|
||||
world.addComponent<Needs>(entity, 'needs', {
|
||||
|
||||
Reference in New Issue
Block a user