{
let k = (cellHeight - 1) * cellWidth, q = 0;
const width = cellWidth * (cellSize + cellSpacing) + cellSpacing;
const height = cellHeight * (cellSize + cellSpacing) + cellSpacing;
const context = DOM.context2d(width, height, 1);
context.canvas.style.imageRendering = "pixelated";
context.fillStyle = "#777";
context.fillRect(0, 0, width, height);
context.fillStyle = "#fff";
fillCells(context);
const maxPaths = 50;
obstacles.clear();
const totalCells = cellHeight * cellWidth
const obstacleCount = Math.round(totalCells * obstacleRatio);
obstacleWeights.clear();
while (obstacles.size < obstacleCount) {
const i = Math.floor(Math.random()*totalCells);
obstacles.add(i);
obstacleWeights.set(i, 1+Math.floor(Math.random()*20));
}
for (let sim=1; sim<=4; sim++) {
const frontier2 = new Queue();
const parent2 = Object.assign(new Array(cellHeight * cellWidth), {[k]: -1});
for (const j of explore(k, parent2, frontier2)) {
if (score(j) === 0) {
context.fillStyle = "#ddd";
let p = j;
while (p>=0 && p != k) {
if (sim==4) fillCell(context, p);
else if (Math.random() < 0.1 && !obstacles.has(p)) {
obstacles.add(p);
obstacleWeights.set(p, 4);
}
p = parent2[p];
}
yield context.canvas;
break;
}
}
}
obstacles.forEach(i => fillCircle(context,i));
const frontier = new Queue();
const parent = Object.assign(new Array(cellHeight * cellWidth), {[k]: -1});
let found = false;
let lastPath = null;
for (const j of explore(k, parent, frontier)) {
const removedNodes = [];
const dirty = new Set();
const paths = {};
if (lastPath) paths[0] = lastPath;
let rank = 1;
while (frontier.length > 0 && rank <= (found ? (maxPaths * 5) : maxPaths)) {
const score = frontier.peekValue();
const bestIndex = frontier.pop();
removedNodes.push([bestIndex, score]);
if (!paths[rank]) paths[rank] = new Set();
let p = bestIndex;
while (p >= 0 && !dirty.has(p)) {
paths[rank].add(p);
dirty.add(p);
p = parent[p];
}
if (found && paths[rank].size <= 1) paths[rank] = new Set();
else rank += 1;
// rank += 1;
}
let maxRank = rank-1;
removedNodes.forEach(arr => frontier.push(arr[0], arr[1]));
Object.keys(paths).forEach(rank => {
// context.fillStyle = `rgba(0,0,0,${0.2 + 0.8*(maxPaths+1-rank)/maxPaths}`;
// context.fillStyle = colors[rank-1];
// context.fillStyle = d3.interpolateViridis(1 - (0.2 + 0.8*(maxPaths+1-rank)/maxPaths));
// const fillColor = rank == 1 ? "#000" : d3.interpolateViridis(1 - (maxPaths+1-rank)/maxPaths)
const fillColor = rank <= 1 ? "#000" : d3.interpolateViridis(1 - (maxRank+1-rank)/maxRank)
context.fillStyle = fillColor;
paths[rank].forEach(i => {
// fillCircle(context, i);
fillCell(context, i);
if (obstacles.has(i)) {
fillCircle(context,i);
context.fillStyle = fillColor;
}
});
})
yield context.canvas;
// await sleep(50);
if (found) {lastPath = paths[1]; break};
if (score(j) === 0) found=true;
context.fillStyle = "#FFF";
// dirty.forEach(i => fillCircle(context,i, true));
dirty.forEach(i => {
fillCell(context,i);
if (obstacles.has(i)) {
fillCircle(context,i);
context.fillStyle = "#FFF";
}
})
}
}