Win on stuck sheep

This commit is contained in:
2026-02-10 12:58:49 +01:00
parent c4cbf42e73
commit 35f8999958

View File

@@ -408,18 +408,13 @@
function updateHistory(newState, forceJump = false) {
const isAtEnd = historyIndex === history.length - 1;
if (newState.moveCount === 0) {
history = [JSON.parse(JSON.stringify(newState))];
} else if (!state || newState.moveCount > state.moveCount) {
history.push(JSON.parse(JSON.stringify(newState)));
}
state = newState;
// Only jump the view to the latest state if the player was already at the end or if forced (like on restart)
if (isAtEnd || forceJump) {
historyIndex = history.length - 1;
}
if (isAtEnd || forceJump) historyIndex = history.length - 1;
render();
}
@@ -427,7 +422,6 @@
if (isLocal) return initLocalState();
const protocol = location.protocol === "https:" ? "wss" : "ws";
ws = new WebSocket(`${protocol}://${location.host}?room=${roomId}&sessionId=${sessionId}`);
ws.onopen = () => document.getElementById("dot").classList.add("conn-online");
ws.onmessage = e => {
const msg = JSON.parse(e.data);
@@ -447,27 +441,16 @@
};
}
// Keyboard controls for Navigation
window.addEventListener("keydown", (e) => {
if (history.length === 0) return;
switch (e.key) {
case "ArrowLeft":
if (historyIndex > 0) historyIndex--;
break;
case "ArrowRight":
if (historyIndex < history.length - 1) historyIndex++;
break;
case "ArrowUp": // Jump to Present
historyIndex = history.length - 1;
break;
case "ArrowDown": // Jump to Start
historyIndex = 0;
break;
default:
return; // Exit if other key
case "ArrowLeft": if (historyIndex > 0) historyIndex--; break;
case "ArrowRight": if (historyIndex < history.length - 1) historyIndex++; break;
case "ArrowUp": historyIndex = history.length - 1; break;
case "ArrowDown": historyIndex = 0; break;
default: return;
}
selected = null; // Clear selection when moving through time
selected = null;
render();
});
@@ -482,24 +465,33 @@
nextState.moveCount++;
nextState.winner = checkWinConditions(nextState);
// Branch history
history = history.slice(0, historyIndex + 1);
updateHistory(nextState, true);
}
function checkWinConditions(g) {
// 1. Wolf reaches sheep starting line (Row 0)
if (g.wolf === 0) return "wolf";
// 2. Max moves reached
if (g.moveCount >= 40) return "wolf";
// 3. Wolf is trapped
const canWolfMove = bWolf[g.wolf].some(to => !g.sheep.includes(to));
if (!canWolfMove) return "sheep";
// 4. Sheep are trapped (Wolf wins)
const canAnySheepMove = g.sheep.some(sPos => {
return bSheep[sPos].some(to => to !== g.wolf && !g.sheep.includes(to));
});
if (!canAnySheepMove) return "wolf";
return null;
}
function render() {
const viewState = history[historyIndex];
if (!viewState) return;
const isViewingHistory = historyIndex < history.length - 1;
const svg = document.querySelector("svg");
svg.innerHTML = "";
@@ -541,7 +533,6 @@
const isSheep = viewState.sheep.includes(i);
const type = isWolf ? "wolf" : (isSheep ? "sheep" : "empty");
const isWinnerPiece = (viewState.winner === "wolf" && isWolf) || (viewState.winner === "sheep" && isSheep);
const canInteract = isLocal || (!isViewingHistory && state.turn === myRole);
const isPossible = canInteract && selected !== null && (viewState.turn === "wolf" ? bWolf[selected] : bSheep[selected]).includes(i) && !isWolf && !isSheep;
@@ -549,7 +540,6 @@
g.onclick = () => {
if (viewState.winner || (!isLocal && isViewingHistory)) return;
if (!isLocal && state.turn !== myRole) return;
const isMine = (viewState.turn === "wolf" && isWolf) || (viewState.turn === "sheep" && isSheep);
if (isMine) selected = i;
else if (isPossible) {