import { describe, it, expect } from 'vitest'; import { findPathAStar } from '../world/pathfinding'; import { type World } from '../../core/types'; import { TileType } from '../../core/terrain'; describe('Pathfinding', () => { const createTestWorld = (width: number, height: number, tileType: number = TileType.EMPTY): World => ({ width, height, tiles: new Array(width * height).fill(tileType), actors: new Map(), exit: { x: 0, y: 0 } }); it('should find a path between two reachable points', () => { const world = createTestWorld(10, 10); const seen = new Uint8Array(100).fill(1); const path = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }); expect(path.length).toBe(4); // 0,0 -> 0,1 -> 0,2 -> 0,3 expect(path[0]).toEqual({ x: 0, y: 0 }); expect(path[3]).toEqual({ x: 0, y: 3 }); }); it('should return empty array if target is a wall', () => { const world = createTestWorld(10, 10); world.tiles[30] = TileType.WALL; // Wall at 0,3 const seen = new Uint8Array(100).fill(1); const path = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }); expect(path).toEqual([]); }); it('should return empty array if no path exists', () => { const world = createTestWorld(10, 10); // Create a wall blockage for(let x=0; x<10; x++) world.tiles[10 + x] = TileType.WALL; const seen = new Uint8Array(100).fill(1); const path = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 5 }); expect(path).toEqual([]); }); it('should respect ignoreBlockedTarget option', () => { const world = createTestWorld(10, 10); // Place an actor at target world.actors.set(1, { id: 1, pos: { x: 0, y: 3 }, type: 'rat', category: 'combatant' } as any); const seen = new Uint8Array(100).fill(1); // Without option, it should be blocked (because actor is there) // Wait, default pathfinding might treat actors as blocking unless specified. // Let's check `isBlocked` usage in `pathfinding.ts`. // It calls `isBlocked` which checks actors. // However, findPathAStar has logic: // if (!options.ignoreBlockedTarget && isBlocked(w, end.x, end.y, options.em)) return []; const pathBlocked = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }); expect(pathBlocked).toEqual([]); const pathIgnored = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }, { ignoreBlockedTarget: true }); expect(pathIgnored.length).toBeGreaterThan(0); expect(pathIgnored[pathIgnored.length - 1]).toEqual({ x: 0, y: 3 }); }); it('should respect ignoreSeen option', () => { const world = createTestWorld(10, 10); const seen = new Uint8Array(100).fill(0); // Nothing seen // Without ignoreSeen, should fail because target/path is unseen const pathUnseen = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }); expect(pathUnseen).toEqual([]); // With ignoreSeen, should succeed const pathSeenIgnored = findPathAStar(world, seen, { x: 0, y: 0 }, { x: 0, y: 3 }, { ignoreSeen: true }); expect(pathSeenIgnored.length).toBe(4); }); });