Files
bootle/app/static/js/sliding.js
T

148 lines
5.4 KiB
JavaScript
Executable File

// Alchemy Potion Sliding Block Puzzle (Schieberätsel)
(function() {
const gridEl = document.getElementById('slidingGrid');
if (!gridEl) return;
const movesVal = document.getElementById('slidingMoves');
const timerVal = document.getElementById('slidingTimer');
const modalBackdrop = document.getElementById('modalBackdrop');
const modalTitle = document.getElementById('modalTitle');
const modalText = document.getElementById('modalText');
const modalBtn = document.getElementById('modalBtn');
const btnScramble = document.getElementById('btnScramble');
const SIZE = 3; // 3x3 sliding puzzle (8 tiles + 1 blank)
let tiles = [];
let blankIndex = 8;
let moves = 0;
let timerInterval = null;
let secondsElapsed = 0;
let isSolved = false;
// Tile images / potion runes
const tileSymbols = [
{ id: 1, icon: "🧪", name: "Alraune", color: "#2ecc71" },
{ id: 2, icon: "🍷", name: "Brennnesselwein", color: "#e74c3c" },
{ id: 3, icon: "⚡", name: "Blitzphiole", color: "#f1c40f" },
{ id: 4, icon: "🔮", name: "Phönix-Träne", color: "#9b59b6" },
{ id: 5, icon: "🐉", name: "Drachenblut", color: "#e67e22" },
{ id: 6, icon: "💀", name: "Tobsuchtsgift", color: "#1abc9c" },
{ id: 7, icon: "💎", name: "Elixier des Lebens", color: "#3498db" },
{ id: 8, icon: "🕯️", name: "Ewige Flamme", color: "#d35400" },
{ id: 0, icon: "", name: "Leerer Runen-Sockel", color: "transparent" } // Blank
];
function init() {
tiles = [1, 2, 3, 4, 5, 6, 7, 8, 0];
blankIndex = 8;
moves = 0;
secondsElapsed = 0;
isSolved = false;
if (movesVal) movesVal.innerText = moves;
if (timerVal) timerVal.innerText = '0s';
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(() => {
if (!isSolved) {
secondsElapsed++;
if (timerVal) timerVal.innerText = secondsElapsed + 's';
}
}, 1000);
scramble();
render();
}
function scramble() {
// Perform 60 random valid moves from blank to ensure solvability
for (let i = 0; i < 60; i++) {
const neighbors = getNeighbors(blankIndex);
const randomNeighbor = neighbors[Math.floor(Math.random() * neighbors.length)];
tiles[blankIndex] = tiles[randomNeighbor];
tiles[randomNeighbor] = 0;
blankIndex = randomNeighbor;
}
moves = 0;
if (movesVal) movesVal.innerText = moves;
}
function getNeighbors(idx) {
const row = Math.floor(idx / SIZE);
const col = idx % SIZE;
const res = [];
if (row > 0) res.push(idx - SIZE); // Up
if (row < SIZE - 1) res.push(idx + SIZE); // Down
if (col > 0) res.push(idx - 1); // Left
if (col < SIZE - 1) res.push(idx + 1); // Right
return res;
}
function render() {
gridEl.innerHTML = '';
tiles.forEach((val, idx) => {
const tile = document.createElement('div');
tile.className = 'sliding-tile' + (val === 0 ? ' blank' : '');
tile.dataset.index = idx;
if (val !== 0) {
const info = tileSymbols.find(s => s.id === val);
tile.innerHTML = `
<span class="tile-icon">${info.icon}</span>
<span class="tile-num">${val}</span>
<span class="tile-name">${info.name}</span>
`;
tile.style.borderColor = info.color;
}
tile.addEventListener('click', () => onTileClick(idx));
gridEl.appendChild(tile);
});
}
function onTileClick(idx) {
if (isSolved) return;
const neighbors = getNeighbors(idx);
if (neighbors.includes(blankIndex)) {
// Swap with blank
tiles[blankIndex] = tiles[idx];
tiles[idx] = 0;
blankIndex = idx;
moves++;
if (movesVal) movesVal.innerText = moves;
if (window.soundFX) window.soundFX.playStoneSlide();
render();
checkWin();
}
}
function checkWin() {
const winning = [1, 2, 3, 4, 5, 6, 7, 8, 0];
const match = tiles.every((v, i) => v === winning[i]);
if (match) {
isSolved = true;
clearInterval(timerInterval);
if (window.soundFX) window.soundFX.playMagicSuccess();
fetch('/api/sliding/complete', { method: 'POST' }).catch(console.error);
modalTitle.innerText = "✨ Schieberätsel gelöst!";
modalText.innerHTML = `Mit geschicktem Schieben hast du alle 8 alchemistischen Phiolen in die perfekte harmonische Ordnung gebracht!<br><br>
<strong>Züge:</strong> ${moves}<br>
<strong>Zeit:</strong> ${secondsElapsed} Sekunden<br><br>
Die Runenplatte leuchtet golden auf und der Weg zur Flammenkammer öffnet sich!`;
modalBtn.innerText = "Zur Flammenkammer 🧪";
modalBtn.onclick = () => { window.location.href = '/bottles'; };
modalBackdrop.classList.add('show');
}
}
if (btnScramble) {
btnScramble.addEventListener('click', () => {
if (window.soundFX) window.soundFX.playStoneSlide();
init();
});
}
init();
})();