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