import type { EventBus, IsometricTileMap } from '@rpg/engine';
import { CombatWorld } from '../systems/combat/CombatWorld';
import { type EnemyBrain, type EnemySenses } from '../systems/combat/EnemyBrain';
/**
* Тестовые фикстуры боевого мира (без Pixi и браузера). Импортировать только
* из *.test.ts — в прод-бандл эти файлы не попадают.
*/
/** Фейковая карта w×h травы, проходима всюду (по умолчанию 20×20). */
export function fakeMap(w = 20, h = 20): IsometricTileMap {
const data = {
width: w,
height: h,
tiles: new Array(w * h).fill(0),
blocked: [],
tall: undefined
};
// width/height наверху — контракт Grid для движковых коллизий.
return { width: w, height: h, data, isWalkable: () => true } as unknown as IsometricTileMap;
}
/** Боевой мир над фейковой картой: события глушатся, герой в заданной точке. */
export function fakeWorld(playerPos: { x: number; y: number }): CombatWorld {
return new CombatWorld({
map: fakeMap(),
events: { emit: () => {} } as unknown as EventBus,
getPlayerPos: () => playerPos,
damagePlayer: () => {}
});
}
/** Тик ИИ на 1/60 с; возвращает последнее намерение. */
export function run(
b: EnemyBrain,
seconds: number,
senses: EnemySenses
): ReturnType<EnemyBrain['update']> {
let intent: ReturnType<EnemyBrain['update']> = { type: 'idle' };
for (let i = 0; i < Math.round(seconds * 60); i++) intent = b.update(1 / 60, senses);
return intent;
}
/** Сенсоры «герой далеко и не виден» (для патрульных сценариев). */
export function far(pos: { x: number; y: number }): EnemySenses {
return {
dist: 30,
dirToPlayer: { x: 1, y: 0 },
pos,
canSee: false,
home: { x: 10.5, y: 7.5 },
hpFraction: 1
};
}