40 lines
1.7 KiB
JavaScript
40 lines
1.7 KiB
JavaScript
import { rotate, trace, directions } from './model.js';
|
|
|
|
// A run only removes cars reachable in the current orientation. It never turns.
|
|
export function currentDeparture(board, cars) {
|
|
return cars.find(car => trace(board, car, cars).status === 'exit') || null;
|
|
}
|
|
export function drainOrientation(board, cars = board.cars) {
|
|
let remaining = [...cars];
|
|
const departed = [];
|
|
for (let car; (car = currentDeparture(board, remaining));) {
|
|
departed.push(car.id); remaining = remaining.filter(c => c.id !== car.id);
|
|
}
|
|
return { remaining, departed };
|
|
}
|
|
|
|
// Every edge is one player turn followed by a run. Search both directions to
|
|
// measure actual player effort, rather than counting rotations in a car solver.
|
|
export function rotationPlan(board, cars = board.cars) {
|
|
const n = directions(board.kind).length;
|
|
const initial = drainOrientation(board, cars);
|
|
const queue = [{ orientation: 0, remaining: initial.remaining, turns: [], waves: [initial.departed.length] }];
|
|
const visited = new Set();
|
|
for (let head = 0; head < queue.length; head++) {
|
|
const state = queue[head];
|
|
if (!state.remaining.length) return state;
|
|
for (const turn of [-1, 1]) {
|
|
const orientation = (state.orientation + turn + n) % n;
|
|
const next = drainOrientation(rotate(board, orientation), state.remaining);
|
|
const key = `${orientation}:${next.remaining.map(c => c.id).sort().join(',')}`;
|
|
if (visited.has(key)) continue;
|
|
visited.add(key);
|
|
queue.push({ orientation, remaining: next.remaining, turns: [...state.turns, turn], waves: [...state.waves, next.departed.length] });
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export const batchTitles = ['转向开路', '折返放行', '连续调度'];
|
|
export const batchSeeds = { hex: [3, 14, 8], square: [6, 12, 19] };
|