function calcTailPosition(numKnots = 2) {
const knots = [];
for (let i = 0; i < numKnots; i++) {
knots.push({grid: [["s"]], x: 0, y: 0});
}
function updateTailPosition(h, t) {
const dX = h.x - t.x;
const dY = h.y - t.y;
if (dX > 1 && dY > 1) {
t.grid[t.y][t.x] = 1;
t.x = h.x - 1;
t.y = h.y - 1;
t.grid[t.y][t.x] = 8;
} else if (dX > 1 && dY < -1) {
t.grid[t.y][t.x] = 1;
t.x = h.x - 1;
t.y = h.y + 1;
t.grid[t.y][t.x] = 8;
} else if (dX < -1 && dY > 1) {
t.grid[t.y][t.x] = 1;
t.x = h.x + 1;
t.y = h.y - 1;
t.grid[t.y][t.x] = 8;
} else if (dX < -1 && dY < -1) {
t.grid[t.y][t.x] = 1;
t.x = h.x + 1;
t.y = h.y + 1;
t.grid[t.y][t.x] = 8;
} else if (dX > 1 && Math.abs(dY) > 0) {
// Move tail right and vertically
t.grid[t.y][t.x] = 1;
t.x = h.x - 1;
t.y = h.y;
t.grid[t.y][t.x] = 8;
} else if (dX < -1 && Math.abs(dY) > 0) {
// Move tail left and vertically
t.grid[t.y][t.x] = 1;
t.x = h.x + 1;
t.y = h.y;
t.grid[t.y][t.x] = 8;
} else if (dY > 1 && Math.abs(dX) > 0) {
// Move tail up and horizontally
t.grid[t.y][t.x] = 1;
t.x = h.x;
t.y = h.y - 1;
t.grid[t.y][t.x] = 8;
} else if (dY < -1 && Math.abs(dX) > 0) {
// Move tail down
t.grid[t.y][t.x] = 1;
t.x = h.x;
t.y = h.y + 1;
t.grid[t.y][t.x] = 8;
} else if (dY > 1 && dX === 0) {
// Move tail up
t.grid[t.y][t.x] = 1;
// t.x = h.x;
t.y = h.y - 1;
t.grid[t.y][t.x] = 8;
} else if (dY < -1 && dX === 0) {
// Move tail down
t.grid[t.y][t.x] = 1;
// t.x = h.x;
t.y = h.y + 1;
t.grid[t.y][t.x] = 8;
} else if (dX > 1 && dY === 0) {
// Move tail right
t.grid[t.y][t.x] = 1;
t.x = h.x - 1;
// t.y = h.y;
t.grid[t.y][t.x] = 8;
} else if (dX < -1 && dY === 0) {
// Move tail left
t.grid[t.y][t.x] = 1;
t.x = h.x + 1;
// t.y = h.y;
t.grid[t.y][t.x] = 8;
}
}
// for (const [dirIndex, [direction, step]] of testMotions2.slice(0, index).entries()) {
for (const [direction, step] of motions) {
switch (direction) {
case "U":
for (let i = 0; i < step; i++) {
for (let j = 0; j < knots.length - 1; j++) {
const h = knots[j];
const t = knots[j + 1];
if (j === 0) {
// Add row that doesn't exist
if (h.y + 1 > h.grid.length - 1) {
knots.forEach(k => k.grid.push(new Array(knots[0].grid[0].length)));
}
h.grid[h.y][h.x] = 1;
h.y += 1;
h.grid[h.y][h.x] = 8;
}
// Check how new h.y will affect t
updateTailPosition(h, t);
}
}
break;
case "D":
for (let i = 0; i < step; i++) {
for (let j = 0; j < knots.length - 1; j++) {
const h = knots[j];
const t = knots[j + 1];
// Add row that doesn't exist. Adjust coords accordingly.
if (j === 0) {
if (h.y - 1 < 0) {
knots.forEach(k => {
k.grid.unshift(new Array(knots[0].grid[0].length))
k.y++;
});
}
h.grid[h.y][h.x] = 1;
h.y -= 1;
h.grid[h.y][h.x] = 8;
}
// Check how new h.y will affect t
updateTailPosition(h, t);
}
}
break;
case "L":
for (let i = 0; i < step; i++) {
for (let j = 0; j < knots.length - 1; j++) {
const h = knots[j];
const t = knots[j + 1];
// Add cell that doesn't exist. Adjust coords accordingly.
if (j === 0) {
if (h.x - 1 < 0) {
knots.forEach(k => {
k.grid.forEach(row => row.unshift(undefined))
k.x++;
});
}
h.grid[h.y][h.x] = 1;
h.x -= 1;
h.grid[h.y][h.x] = 8;
}
// Check how new h.x will affect t
updateTailPosition(h, t);
}
}
break;
case "R":
for (let i = 0; i < step; i++) {
for (let j = 0; j < knots.length - 1; j++) {
const h = knots[j];
const t = knots[j + 1];
// Add cell that doesn't exist
if (j === 0) {
if (h.x + 1 > h.grid[h.y].length - 1) {
knots.forEach(k => {
k.grid.forEach(row => row.push(undefined))
});
}
h.grid[h.y][h.x] = 1;
h.x += 1;
h.grid[h.y][h.x] = 8;
}
// Check how new h.x will affect t
updateTailPosition(h, t);
}
}
break;
}
}
const knotsDisplay = [];
for (let i = 0; i < knots[0].grid.length; i++) {
knotsDisplay.push(new Array(knots[0].grid[0].length));
}
knots.forEach((k, index) => {
knotsDisplay[k.y][k.x] = index + 1;
});
return knots.at(-1).grid.map(row => Array.from(row, v => v || 0));
// return knotsDisplay.map(row => Array.from(row, v => v || 0));
}