Close door after walking through again, and add more test coverage
This commit is contained in:
83
src/engine/__tests__/pathfinding.test.ts
Normal file
83
src/engine/__tests__/pathfinding.test.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
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' } 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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user