Jump to first and last state
This commit is contained in:
@@ -386,9 +386,9 @@
|
||||
|
||||
// --- STATE & HISTORY ---
|
||||
let ws, myRole, selected = null;
|
||||
let state = null; // Authoritative latest state
|
||||
let history = []; // Array of state snapshots
|
||||
let historyIndex = -1; // Current view index
|
||||
let state = null;
|
||||
let history = [];
|
||||
let historyIndex = -1;
|
||||
|
||||
const pos = { 0: [80, 210], 1: [180, 110], 2: [180, 210], 3: [180, 310], 4: [280, 110], 5: [280, 210], 6: [280, 310], 7: [380, 110], 8: [380, 210], 9: [380, 310], 10: [480, 210] };
|
||||
const edges = [[0, 1], [0, 2], [0, 3], [1, 2], [2, 3], [1, 4], [2, 5], [3, 6], [4, 5], [5, 6], [4, 7], [5, 8], [6, 9], [7, 8], [8, 9], [5, 1], [5, 3], [5, 7], [5, 9], [7, 10], [8, 10], [9, 10]];
|
||||
@@ -398,7 +398,7 @@
|
||||
function initLocalState() {
|
||||
const startState = { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null, lastMove: null };
|
||||
history = [];
|
||||
updateHistory(startState);
|
||||
updateHistory(startState, true);
|
||||
document.getElementById("lobby").classList.add("hidden");
|
||||
document.getElementById("game").classList.remove("hidden");
|
||||
document.getElementById("roomInfo").style.visibility = "hidden";
|
||||
@@ -406,15 +406,20 @@
|
||||
document.getElementById("copyBtn").style.opacity = "0.5";
|
||||
}
|
||||
|
||||
function updateHistory(newState) {
|
||||
// If it's a reset (moveCount 0) or a new move, add to history
|
||||
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;
|
||||
historyIndex = history.length - 1; // Snap to newest
|
||||
// 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;
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
@@ -437,24 +442,36 @@
|
||||
if (msg.type === "state") {
|
||||
myRole = msg.yourRole;
|
||||
document.getElementById("overlay").className = msg.onlineCount < 2 ? "" : "hidden";
|
||||
updateHistory(msg.game);
|
||||
updateHistory(msg.game, msg.game.moveCount === 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Keyboard controls for back/forward
|
||||
// Keyboard controls for Navigation
|
||||
window.addEventListener("keydown", (e) => {
|
||||
if (e.key === "ArrowLeft" && historyIndex > 0) {
|
||||
historyIndex--;
|
||||
render();
|
||||
} else if (e.key === "ArrowRight" && historyIndex < history.length - 1) {
|
||||
historyIndex++;
|
||||
render();
|
||||
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
|
||||
}
|
||||
selected = null; // Clear selection when moving through time
|
||||
render();
|
||||
});
|
||||
|
||||
function handleLocalMove(from, to) {
|
||||
// If moving while viewing history, we branch off
|
||||
const baseState = history[historyIndex];
|
||||
const allowed = (baseState.turn === "wolf") ? bWolf[from] : bSheep[from];
|
||||
if (!allowed?.includes(to) || baseState.sheep.includes(to) || baseState.wolf === to) return;
|
||||
@@ -466,9 +483,9 @@
|
||||
nextState.moveCount++;
|
||||
nextState.winner = checkWinConditions(nextState);
|
||||
|
||||
// Truncate history if we were looking at the past
|
||||
// Branch history
|
||||
history = history.slice(0, historyIndex + 1);
|
||||
updateHistory(nextState);
|
||||
updateHistory(nextState, true);
|
||||
}
|
||||
|
||||
function checkWinConditions(g) {
|
||||
@@ -525,7 +542,6 @@
|
||||
const type = isWolf ? "wolf" : (isSheep ? "sheep" : "empty");
|
||||
const isWinnerPiece = (viewState.winner === "wolf" && isWolf) || (viewState.winner === "sheep" && isSheep);
|
||||
|
||||
// Logic for possible moves
|
||||
const canInteract = isLocal || (!isViewingHistory && state.turn === myRole);
|
||||
const isPossible = canInteract && selected !== null && (viewState.turn === "wolf" ? bWolf[selected] : bSheep[selected]).includes(i) && !isWolf && !isSheep;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user