84 lines
3.4 KiB
TypeScript
84 lines
3.4 KiB
TypeScript
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);
|
|
});
|
|
});
|