Fix simultaneous defense sweep

Refactor Eternal Domination defense to ensure guards move only in a single, simultaneous sweep without randomManifestation. Introduces a deterministic, border-patchwork approach that shifts existing guards along predefined paths, removes ad-hoc scanning, and preserves guard count while updating movement logic to reflect a coordinated defense.

X-Lovable-Edit-ID: edt-cbb19a37-58ea-4c8f-80e1-5d999d4db6dd
This commit is contained in:
gpt-engineer-app[bot] 2026-01-20 08:40:33 +00:00
commit abbfb79cea

View file

@ -282,35 +282,15 @@ const defendAttack = (guards: Set<string>, attack: Position): {
shiftBorderToFillGap(newGuards, movements, currentGap); shiftBorderToFillGap(newGuards, movements, currentGap);
} }
// STEP 3: Check if we need a second chain (Figure 10 shows two chains) // NOTE: The paper's strategy restores the original configuration via the border "patchwork"
// This happens when the attack disrupts multiple domination lines // (complementary paths) rather than ad-hoc re-domination fixes.
//
// Find interior positions that are now undominated and need filling // The previous implementation included an extra "scan for undominated vertices and move a nearby guard"
for (let x = 1; x < COLS - 1; x++) { // step, which can look like guards "manifest" and is not part of the Figure 10 defense.
for (let y = 2; y < ROWS - 2; y++) {
if (!isDominated(x, y, newGuards)) { // Safety: guards are never created/destroyed—only moved.
// Need to get a guard here if (newGuards.size !== guards.size) return null;
const nbs = getHexNeighbors(x, y);
const nearbyGuard = nbs.find(n => newGuards.has(posKey(n)) && isInterior(n.x, n.y));
if (nearbyGuard) {
newGuards.delete(posKey(nearbyGuard));
newGuards.add(posKey({ x, y }));
movements.push({ from: nearbyGuard, to: { x, y }, type: 'interior' });
} else {
// Use border guard
const borderGuard = nbs.find(n => newGuards.has(posKey(n)) && isBorder(n.x, n.y));
if (borderGuard) {
newGuards.delete(posKey(borderGuard));
newGuards.add(posKey({ x, y }));
movements.push({ from: borderGuard, to: { x, y }, type: 'toInterior' });
shiftBorderToFillGap(newGuards, movements, borderGuard);
}
}
}
}
}
return { newGuards, movements }; return { newGuards, movements };
}; };