import { describe, it, expect, beforeEach } from 'vitest'; import { EntityManager } from '../EntityManager'; import { type World, type Actor } from '../../core/types'; describe('EntityManager', () => { let mockWorld: World; let entityManager: EntityManager; beforeEach(() => { mockWorld = { width: 10, height: 10, tiles: new Array(100).fill(0), actors: new Map(), exit: { x: 9, y: 9 } }; entityManager = new EntityManager(mockWorld); }); it('should add an actor and update the grid', () => { const actor: Actor = { id: 1, category: 'combatant', type: 'player', pos: { x: 2, y: 3 }, isPlayer: true } as any; entityManager.addActor(actor); expect(mockWorld.actors.has(1)).toBe(true); expect(entityManager.getActorsAt(2, 3).map(a => a.id)).toContain(1); expect(entityManager.isOccupied(2, 3)).toBe(true); }); it('should remove an actor and update the grid', () => { const actor: Actor = { id: 1, category: 'combatant', type: 'player', pos: { x: 2, y: 3 }, isPlayer: true } as any; entityManager.addActor(actor); entityManager.removeActor(1); expect(mockWorld.actors.has(1)).toBe(false); expect(entityManager.getActorsAt(2, 3).map(a => a.id)).not.toContain(1); expect(entityManager.isOccupied(2, 3)).toBe(false); }); it('should update the grid when an actor moves', () => { const actor: Actor = { id: 1, category: 'combatant', type: 'player', pos: { x: 2, y: 3 }, isPlayer: true } as any; entityManager.addActor(actor); entityManager.moveActor(1, { x: 2, y: 3 }, { x: 4, y: 5 }); expect(actor.pos.x).toBe(4); expect(actor.pos.y).toBe(5); expect(entityManager.isOccupied(2, 3)).toBe(false); expect(entityManager.isOccupied(4, 5)).toBe(true); expect(entityManager.getActorsAt(4, 5).map(a => a.id)).toContain(1); }); it('should correctly identify occupied tiles while ignoring specific types', () => { const orb: Actor = { id: 1, category: 'collectible', type: 'exp_orb', pos: { x: 2, y: 2 } } as any; const enemy: Actor = { id: 2, category: 'combatant', type: 'rat', pos: { x: 5, y: 5 } } as any; entityManager.addActor(orb); entityManager.addActor(enemy); expect(entityManager.isOccupied(2, 2)).toBe(true); expect(entityManager.isOccupied(2, 2, 'exp_orb')).toBe(false); expect(entityManager.isOccupied(5, 5)).toBe(true); expect(entityManager.isOccupied(5, 5, 'exp_orb')).toBe(true); }); it('should generate the next available ID by scanning current actors', () => { mockWorld.actors.set(10, { id: 10, pos: { x: 0, y: 0 } } as any); mockWorld.actors.set(15, { id: 15, pos: { x: 1, y: 1 } } as any); // Create new manager to trigger scan since current one has stale lastId const manager = new EntityManager(mockWorld); expect(manager.getNextId()).toBe(16); }); it('should handle multiple actors at the same position', () => { const actor1: Actor = { id: 1, pos: { x: 1, y: 1 } } as any; const actor2: Actor = { id: 2, pos: { x: 1, y: 1 } } as any; entityManager.addActor(actor1); entityManager.addActor(actor2); const atPos = entityManager.getActorsAt(1, 1); expect(atPos.length).toBe(2); expect(atPos.map(a => a.id)).toContain(1); expect(atPos.map(a => a.id)).toContain(2); entityManager.removeActor(1); expect(entityManager.getActorsAt(1, 1).map(a => a.id)).toEqual([2]); }); });