<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Multiplayer Game</title> <link rel="stylesheet" type="text/css" href="mflx.min.css"> <style type="text/css"> .text-with-shadow { text-shadow: -1px -1px 1px #000, 1px -1px 1px #000, -1px 1px 1px #000, 1px 1px 1px #000; color: white; } .div-shadow { box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px; } .puzzleboard { display: grid; grid-template-columns: repeat(12, 1fr); /* 12 columns, equal width */ grid-template-rows: repeat(4, auto); /* 4 rows, height adjusts to content */ gap: 1px; /* Optional: spacing between grid items */ height: 205px; width: 500px; max-width: 100%; /* Optional: ensures grid fits within the container */ max-height: 100%; /* Optional: ensures the grid respects height limits */ } .grid-item { background-image: radial-gradient(circle,#21D375 ,green); /* For visualization */ border: 1px solid black; /* Optional: visual boundary for items */ text-align: center; padding: 1px; border-radius: 5px; } .grid-item-2 { background-color: white; /* For visualization */ border: 1px solid black; /* Optional: visual boundary for items */ text-align: center; padding: 1px; display: flex; justify-content: center; align-items: center; font-size:1.2rem; font-family:'sans'; font-weight:bold; border-radius: 5px; } .category { background-image: radial-gradient(circle,#1f57dd ,#0000ae); color: white; max-width: 500px; font-size:1.2rem; font-family:'sans'; font-weight:bold; border-radius: 5px; text-align: center; } .hidden { display: none; visibility: hidden; } /* Dialog styling */ dialog { border: none; border-radius: 8px; padding: 20px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); font-family: Arial, sans-serif; max-width: 300px; text-align: center; } dialog::backdrop { background-color: rgba(0, 0, 0, 0.5); } dialog h2 { margin-top: 0; font-size: 18px; } .nameInput { text-align: center; } .clipboard { transition: opacity 0.5s ease-in-out; } .btn2 { background-color: #fefefe; } .btn2:active { background-color: #efefef; color: gray; } .footerMsg { text-align: center; } </style> </head> <body> <!-- Dialog --> <dialog class="nameDialog"> <div class="flx(column) space-evenly"> <h2>Change Your Name?</h2> <label for="nameInput">Name:</label> <input type="text" class="nameInput is-round" style="padding: .25rem; "> <div class="mt-4 flx(wrap) space-evenly"> <button class="saveButton btn is-success is-round mr-1 div-shadow">save</button> <button class="closeDialogButton btn is-error is-round ml-1 div-shadow">close</button> </div> <div> </dialog> <!-- Dialog --> <dialog class="solveDialog"> <div class="flx(column) space-evenly"> <h2>Solve the Puzzle?</h2> <label for="solveInput">Answer:</label> <input type="text" class="solveInput is-round" style="padding: .25rem; "> <div class="mt-4 flx(wrap) space-evenly"> <button class="solveButton btn is-success is-round mr-1 div-shadow">Solve</button> <button class="closeSolveDialogButton btn is-error is-round ml-1 div-shadow">close</button> </div> <div> </dialog> <div class="main flx(column) middle center" style="margin: 0 auto; max-width: 500px;"> <button class="btn btn2 div-shadow is-round" id="create-room">Create Room</button> <div class="flx(wrap) center middle mt-3"> <input id="join-code" placeholder="Enter room code" style="line-height: 2; text-align: center; width: 100px;"> <button class="btn btn2 div-shadow is-round" id="join-room">Join Room</button> </div> <div class="flx(wrap) center middle mb-2 roomCodeContainer hidden"> <div class="room-code mr-2"></div> <img class="clipboard btn btn2 div-shadow is-round" src="clipboard.svg" width="15" onclick="copyToClipboard()" /> </div> <div class="flx(wrap) mb-2 players"></div> <div id="status"></div> <div class="flx(wrap) middle space-between is-full mb-3"> <button class="btn btn2 div-shadow is-round" id="start-game" style="display: none;">Start Game</button> <button class="btn btn2 div-shadow is-round" id="spin-wheel" style="display: none;">Spin Wheel</button> <div class="flx(wrap) middle space-between"> <input id="guess-letter" placeholder="Guess a letter" style="display: none; line-height: 2; text-align: center;"> <button class="btn btn2 div-shadow is-round" id="guess-button" style="display: none;">Guess</button> </div> <button class="solve-button btn div-shadow is-round btn2" style="display: none;" onclick="solvePuzzle()">Solve</button> </div> <div class="puzzleboard mb-2"></div> <div class="category mb-5 is-full div-shadow"></div> <canvas id="wheelCanvas" width="500" height="500"></canvas> </div> <footer class="flx(column) middle center is-full mt-5" style=""> <span class="footerMsg mb-3"></span> <a href='https://ko-fi.com/I3I0G1CQM' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi5.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a> </footer> <script> let currentYear = new Date().getFullYear(); console.log(currentYear); document.querySelector('.footerMsg').innerText = `Made by Meleeman 🦊 © ${currentYear}`; //================general Purpose functions=========================================// function cryptoSecureShuffle(array) { const shuffledArray = [...array]; // Create a copy to avoid mutating the original array const n = shuffledArray.length; // Fisher-Yates shuffle for (let i = n - 1; i > 0; i--) { // Generate a cryptographically secure random index let randIndex; do { // Generate a random value in the range [0, 2^32) const randomBuffer = new Uint32Array(1); window.crypto.getRandomValues(randomBuffer); randIndex = randomBuffer[0] >>> 0; // Convert to a non-negative integer } while (randIndex >= Math.floor(2 ** 32 / (i + 1)) * (i + 1)); // Avoid bias // Compute the unbiased index randIndex %= (i + 1); // Swap the elements [shuffledArray[i], shuffledArray[randIndex]] = [shuffledArray[randIndex], shuffledArray[i]]; } return shuffledArray; } //====================making Name Tags/ assigning colors to names================// let nameColors = [ '#ff0000','#ff8700','#ffd300','#deff0a','#a1ff0a', '#0aff99','#0aefff','#147df5','#580aff','#be0aff' ] nameColors = cryptoSecureShuffle(nameColors); function assignColors(names, colors) { console.log(names); let result = []; let n = 0; // Keep track of name index let c = 0; // Keep track of color index if (typeof names[0] !== 'string') { //in which case the data should look like [{...},{...},{...}...] console.log('larger data case here.') if (names.length > colors.length) { // Assign colors cyclically while (n < names.length) { result.push({ name: names[n].name, color: colors[c], score: names[n].points, wins: names[n].wins }); n++; c = (c + 1) % colors.length; // Cycle through the colors } } else { // Assign colors directly, keeping track of indices while (n < names.length) { result.push({ name: names[n].name, color: colors[c], score: names[n].points, wins: names[n].wins }); n++; c++; } } } else { //data looks like this ['asdf','asdf','asdf'] if (names.length > colors.length) { // Assign colors cyclically while (n < names.length) { result.push({ name: names[n], color: colors[c] }); n++; c = (c + 1) % colors.length; // Cycle through the colors } } else { // Assign colors directly, keeping track of indices while (n < names.length) { result.push({ name: names[n], color: colors[c]}); n++; c++; } } } return result; } function copyToClipboard() { console.log('click Copied'); let image = document.querySelector(".clipboard"); image.src = 'clipboardCheckmark.svg'; navigator.clipboard.writeText(window.roomCode).then(() => { console.log("Copied successfully!"); }).catch(err => { console.error("Failed to copy:", err); }); setTimeout(() => { console.log("3 second has passed!"); image.src = 'clipboard.svg'; }, 3000); } //=========================================wheel==========================================// const wheel = [ 'lose a turn', 800, 350, 450, 700, 300, 600, 5000, 300, 600, 300, 500, 800, 550, 400, 300, 900, 500, 'spin again', 900, 'Bankrupt', 600, 400, 300 ]; let canvas = document.getElementById('wheelCanvas'); if(window.innerWidth < 600) { canvas.width = canvas.width / 1.65; canvas.height = canvas.height / 1.65; } console.log(window.innerWidth); const ctx = canvas.getContext('2d'); const radius = canvas.width / 2; let lowestEquivelantAngle = 23.4327090939438 % (2* Math.PI); let fps = 60; const frameDuration = 1000 / fps; // Duration of each frame in milliseconds console.log('lowestEquivelantAngle:',lowestEquivelantAngle); let rotation = lowestEquivelantAngle; //sets the zero index on top let spinning = false; let img = new Image(); img.src = "arrow-down-bold.png"; img.onload = function() { //another check here for mobile sizing if(window.innerWidth < 600) { ctx.drawImage(img, 100, -70, 100,100); } else { ctx.drawImage(img, 200, -50, 100,100); } } // Draw the wheel function drawWheel(drawResult = false) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); ctx.translate(radius, radius); ctx.rotate(rotation); const anglePerSegment = (2 * Math.PI) / wheel.length; console.log('',anglePerSegment) let j = 0; wheel.forEach((value, i) => { const startAngle = i * anglePerSegment; const endAngle = startAngle + anglePerSegment; ctx.beginPath(); ctx.moveTo(0, 0); ctx.arc(0, 0, radius, startAngle, endAngle); ctx.closePath(); ctx.fillStyle = i % 2 === 0 ? '#ffdd99' : '#ffeecc'; // if (j === nameColors.length) { // j = 0; // ctx.fillStyle = nameColors[j]; // } // else { // ctx.fillStyle = nameColors[j]; // j++; // } ctx.fill(); ctx.stroke(); // Add text ctx.save(); ctx.translate( Math.cos(startAngle + anglePerSegment / 2) * radius * 0.7, Math.sin(startAngle + anglePerSegment / 2) * radius * 0.7 ); ctx.rotate(startAngle + anglePerSegment / 2 + Math.PI / 2 - 1.5); ctx.textAlign = 'center'; ctx.fillStyle = '#000'; ctx.font = '14px Arial'; //ctx.fillText(String(i+","+value), 0, 0); //for debug ctx.fillText(String(value), 0, 0); ctx.restore(); }); ctx.restore(); //check here for mobile size if(window.innerWidth < 600) { ctx.drawImage(img, 100, -70, 100,100); } else { ctx.drawImage(img, 200, -50, 100,100); } } // Start spinning function startSpin(targetIndex,message) { if (spinning) return; const totalTime = 8; let c = 1.62; const totalSpins = 2 const anglePerSegment = (2 * Math.PI) / wheel.length; rotation = 0 - (.283*6) let finalDisplacement = (targetIndex[0] * anglePerSegment) - ((2 * Math.PI)*totalSpins); if (targetIndex[0] != 0) { finalDisplacement = ((targetIndex[0] * anglePerSegment)*-1 ) - ((2 * Math.PI)*totalSpins) } console.log('finalDisplacement',finalDisplacement); const timeStep = 1 / fps; // seconds per frame const totalFrames = totalTime * fps; const k = finalDisplacement / Math.log(totalTime + c ); // Calculate `k` for deceleration let currentFrame = 0; let currentAngle = 0; spinning = true; console.log(anglePerSegment); let currentRotation = rotation; // Start from the current rotation function animate(timestamp) { if (currentFrame > totalFrames) { spinning = false; document.getElementById("spin-wheel").disabled = false; document.getElementById("status").classList.remove('hidden') drawPlayers(message); spinSpeed = 0; console.log(`Landed on: ${wheel[targetIndex[0]]}`); console.log(`final frameCount: ${currentFrame} and totalFrames ${totalFrames}`); console.log(`final rotation: ${rotation}`); return; } const t = currentFrame * timeStep; // Logarithmic deceleration velocity: v(t) = k * (1 - ln(t + 1) / ln(T + 1)) const velocity = k * (1 - Math.log(t + c) / Math.log(totalTime + c)); // Update the angle using the velocity rotation += velocity * timeStep; // Increment frame currentFrame++; drawWheel(); // frameCount++; requestAnimationFrame(animate); } animate(); } // Initial draw drawWheel(); //==================================end of Wheel=====================================// function drawPlayers(message) { console.log('in draw players',message); let players = document.querySelector('.players'); //clear the players incase any weird side effects occur players.innerHTML = ``; //assignColors(names, colors) { let processedNametags; if (message?.playerStats) { processedNametags = assignColors(message.playerStats,nameColors); } else { processedNametags = assignColors(message.clients,nameColors); } console.log(processedNametags); const playersHtml = processedNametags.map(client => { if(client.name != window.you) { if (client.name === message.leaderName) { return ` <div class="flx(column) center middle"> <span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};'>⭐ ${client.name} ⭐</span> <span class="score flx center middle mr-2 mt-1 is-round text-with-shadow div-shadow is-half" style='background-color:${client.color};'>${client?.score ? client.score : '0'}</span> </div> ` ; // Highlight the leader with stars } else { return ` <div class="flx(column) center middle"> <span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};'> ${client.name}</span> <span class="score flx center middle mr-2 mt-1 is-round text-with-shadow div-shadow is-half" style='background-color:${client.color};'>${client?.score ? client.score : '0'}</span> </div> `; } } else if (client.name === message.leaderName) { return ` <div class="flx(column) center middle"> <span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};' onclick="changeName()">⭐ ${client.name} ⭐ (you)</span> <span class="score flx center middle mr-2 mt-1 is-round text-with-shadow div-shadow is-half" style='background-color:${client.color};'>${client?.score ? client.score : '0'}</span> </div> `; // Highlight the leader with stars } else { return ` <div class="flx(column) center middle"> <span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};' onclick="changeName()">${client.name} (you)</span> <span class="score flx center middle mr-2 mt-1 is-round text-with-shadow div-shadow is-half" style='background-color:${client.color};'>${client?.score ? client.score : '0'}</span> </div> `; } }).join(""); // Combine all elements into a single string players.innerHTML = playersHtml; } function drawPuzzle(message, gridRows = 4, gridCols = 12) { //legend null = space, "" = white space to guess, "a" is a letter already solved for you. console.log(message.puzzle.puzzle[0]); //wheel of fortune puzzles must fit within a 12x4 grid of letter spaces //first we draw the spaces let puzzle = message.puzzle.puzzle; let puzzleBoard = document.querySelector('.puzzleboard'); let resultingPuzzleBoard = []; //if the first entry of the puzzle is an array and not a string display the puzzle differently if (Array.isArray(message.puzzle.puzzle[0])) { console.log('first entry is an array in this puzzle...'); for (let row of message.puzzle.puzzle) { if (row.length == 0) { resultingPuzzleBoard.push(Array(12).fill(null)); continue; } const nextLine = Array(12).fill(null); const startIndex = Math.floor((12 - row.length) / 2); for (let i = 0; i < row.length; i++) { nextLine[startIndex + i] = row[i]; } resultingPuzzleBoard.push(nextLine); console.log(resultingPuzzleBoard); } //after we've drawn our data for our board,now its time to visualize it to the user puzzleBoard.innerHTML = ``; for(let i of resultingPuzzleBoard) { for (let j in i) { const letter = i[j]; if (letter == null || letter == ' ') { let el = document.createElement('div'); el.classList.add('grid-item'); el.innerHTML = ' '; // el.style.height = '50px'; // el.style.width = '50px'; // el.style.border = 'solid' puzzleBoard.appendChild(el); } else if (letter != null && letter != ' ') { let el = document.createElement('div'); el.classList.add('grid-item-2'); el.innerText = letter; puzzleBoard.appendChild(el); } } } } else if (typeof message.puzzle.puzzle[0] == 'string') { console.log('first entry is a string in this puzzle...'); //if we have a single string we need to return it on the second line from the bottom resultingPuzzleBoard.push(Array(12).fill(null)); resultingPuzzleBoard.push(Array(12).fill(null)); const nextLine = Array(12).fill(null); const startIndex = Math.floor((12 - message.puzzle.puzzle.length) / 2); console.log(startIndex); for (let i = 0; i < message.puzzle.puzzle.length; i++) { nextLine[startIndex + i] = message.puzzle.puzzle[i]; } console.log(nextLine); resultingPuzzleBoard.push(nextLine); resultingPuzzleBoard.push(Array(12).fill(null)); console.log(resultingPuzzleBoard); //after we've drawn our data for our board,now its time to visualize it to the user puzzleBoard.innerHTML = ``; for(let i of resultingPuzzleBoard) { for (let j in i) { const letter = i[j]; if (letter == null || letter == ' ') { let el = document.createElement('div'); el.classList.add('grid-item'); el.innerHTML = ' '; // el.style.height = '50px'; // el.style.width = '50px'; // el.style.border = 'solid' puzzleBoard.appendChild(el); } else if (letter != null && letter != ' ') { let el = document.createElement('div'); el.classList.add('grid-item-2'); el.innerText = letter; puzzleBoard.appendChild(el); } } } } else { console.error('error: ','message does not have correct datatype of string or array'); } //finally draw the category! document.querySelector('.category').classList.add('pt-2','pb-2'); document.querySelector('.category').innerHTML = `${message.puzzle.category}` } function changeName() { console.log('change name hit.'); const nameDialog = document.querySelector('.nameDialog'); const nameInput = document.querySelector('.nameInput'); const saveButton = document.querySelector('.saveButton'); const closeDialogButton = document.querySelector('.closeDialogButton'); nameDialog.showModal(); nameInput.value = window.you; closeDialogButton.addEventListener('click',() => {nameDialog.close()}); saveButton.addEventListener('click',() => { socket.send(JSON.stringify({ type: "change_name", deadName:window.you, newName:nameInput.value })); console.log('you changed your name.'); nameDialog.close(); }); } function solvePuzzle() { const solveDialog = document.querySelector('.solveDialog'); const solveInput = document.querySelector('.solveInput'); const solveButton = document.querySelector('.solveButton'); const closeDialogButton = document.querySelector('.closeSolveDialogButton'); solveInput.value = ''; solveDialog.showModal(); closeDialogButton.addEventListener('click',() => {solveDialog.close()}); solveButton.addEventListener('click',() => { socket.send(JSON.stringify({ type: "solve_puzzle", guess:solveInput.value })); solveInput.value = ''; solveDialog.close(); }); } function changeSpinGuessState(message) { console.log(message.turnState) if(message.turnState == 'spin' && window.yourTurn) { document.getElementById("spin-wheel").style.display = "inline"; document.getElementById("guess-letter").style.display = "none"; document.getElementById("guess-button").style.display = "none"; } if (message.turnState == 'guess' && window.yourTurn) { document.getElementById("spin-wheel").style.display = "none"; document.getElementById("guess-letter").style.display = "inline"; document.getElementById("guess-button").style.display = "inline"; } console.log('changeSpinGuessState activated;') } function changeTurnState() { if (!window.yourTurn) { document.getElementById("guess-letter").style.display = "none"; document.getElementById("spin-wheel").style.display = "none"; document.getElementById("guess-button").style.display = "none"; document.querySelector(".solve-button").style.display = 'none'; } else { document.getElementById("guess-letter").style.display = "inline"; document.getElementById("spin-wheel").style.display = "inline"; document.getElementById("guess-button").style.display = "inline"; document.querySelector(".solve-button").style.display = 'inline'; } console.log('changeTurnState activated;') } const socket = new WebSocket("ws://localhost:8080"); document.getElementById("create-room").onclick = function () { socket.send(JSON.stringify({ type: "create_room" })); this.style.display = 'none'; document.getElementById("join-room").style.display = 'none'; document.getElementById('join-code').style.display = 'none'; }; document.getElementById("join-room").onclick = () => { const roomCode = document.getElementById("join-code").value; socket.send(JSON.stringify({ type: "join_room", roomCode })); document.getElementById("create-room").style.display = 'none'; document.getElementById('join-code').style.display = 'none'; document.getElementById("join-room").style.display = 'none'; }; document.getElementById("start-game").onclick = () => { socket.send(JSON.stringify({ type: "start_game" })); }; document.getElementById("spin-wheel").onclick = () => { if (spinning) return; document.getElementById("spin-wheel").disabled = true; socket.send(JSON.stringify({ type: "spin_wheel" })); }; document.getElementById("guess-button").onclick = () => { const letter = document.getElementById("guess-letter").value; socket.send(JSON.stringify({ type: "guess_letter", letter})); document.getElementById("guess-letter").value = ""; // Clear input }; socket.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === "room_created") { window.you = message.you; document.querySelector(".roomCodeContainer").classList.remove('hidden'); document.querySelector(".room-code").innerText =`Room Code: ${message.roomCode}`; window.roomCode = message.roomCode; document.getElementById("status").innerText = `Room created!`; drawPlayers(message); if (message.isLeader) { document.getElementById("start-game").style.display = "inline"; } } if (message.type === "changed_name_you") { window.you = message.you; console.log('server has changed your name!'); } if (message.type === "changed_name") { drawPlayers(message); console.log('server has changed your name!'); } if (message.type === "joined_room_you") { window.you = message.you; } if (message.type === "joined_room") { drawPlayers(message); const status = message.isLeader ? "You are the party leader!" : "You joined the room!"; // document.querySelector('.players').innerHtml += `<span>${}<span>` document.getElementById("status").innerText = `${status}`; document.querySelector(".roomCodeContainer").classList.remove('hidden'); document.querySelector(".room-code").innerText =`Room Code: ${message.roomCode}`; if (message.isLeader) { changeTurnState() } } if (message.type === "your_turn") { window.yourTurn = true; changeTurnState() } if (message.type === "game_started") { let result = drawPuzzle(message); console.log('game_started', message); console.log(result); document.getElementById("status").innerText = "The game has started!"; document.getElementById("start-game").style.display = "none"; document.querySelector(".roomCodeContainer").classList.add('hidden'); changeSpinGuessState(message); } if (message.type === "new_puzzle") { let result = drawPuzzle(message); console.log('new_puzzle', message); console.log(result); document.getElementById("status").innerText = "New Puzzle!"; document.getElementById("start-game").style.display = "none"; changeSpinGuessState(message); } if (message.type === "spin_result") { document.getElementById("status").classList.add('hidden') console.log('spin result recieved'); if (message.spinResult != 'lose a turn' || message.spinResult != 'Bankrupt' || message.spinResult != 'spin again') { document.getElementById("status").innerText = `Spin result: ${message.spinResult} points (${message.player.name})`; } else document.getElementById("status").innerText = `Spin result: ${message.spinResult} for (${message.player.name})`; //find target index let targetIndexArr = wheel.entries(); let filterResultsArr = []; for(let x of targetIndexArr){ if (x[1] == message.spinResult) { filterResultsArr.push(x); } } console.log(filterResultsArr[0][0]); //if there is multiple entries where the spin exists pick a random index. if(filterResultsArr.length > 1) { console.log('if fra.length > 1',filterResultsArr[0]) startSpin(filterResultsArr[0],message); } else{ console.log('else',filterResultsArr[0]) startSpin(filterResultsArr[0],message); } if (window.yourTurn && message.spinResult != 'lose a turn') { console.log('in spin_result: ',message) // changeTurnState() changeSpinGuessState(message); } else if (window.yourTurn && message.spinResult == 'lose a turn') { window.yourTurn = false; changeTurnState() } else if (window.yourTurn && message.spinResult == 'spin again') { message.turnState = 'spin'; changeSpinGuessState(message); } } if (message.type === "guess_result") { document.getElementById("status").classList.remove('hidden') const outcome = message.correct ? "correct" : "incorrect"; document.getElementById("status").innerText = `Guess '${message.letter}' was ${outcome} (${message.player.name})`; console.log(message); if (message.puzzle) { drawPuzzle(message); } if (message.turnState && message.correct) { console.log(message.turnState); changeSpinGuessState(message); }else { window.yourTurn = false changeTurnState() } drawPlayers(message); } if (message.type === "incorrect_puzzle_guess") { document.getElementById("status").innerText = `${message.message}`; } if (message.type === "next_turn") { if (window.you == message.user) { //send message since socket.send(JSON.stringify({ type: "confirm_id"})); } } if (message.type === "next_turn_confirmed") { //this means its your turn console.log('its your turn, id confirmed'); window.yourTurn = true; changeTurnState() changeSpinGuessState(message) } if (message.type === "next_turn_denied") { //silently deny the user the next turn if trying to assume the same name as another user window.yourTurn = false; console.log('its not your turn yet!'); changeTurnState() } if (message.type === "puzzle_solved") { console.log('puzzle has been solved!!!'); } if (message.type === "new_leader") { console.log('you are the new leader!'); drawPlayers(message); document.getElementById("status").innerText = "You are now the party leader!"; } if (message.type === "game_over") { document.getElementById("status").innerText = message.winner; drawPlayers(message); } if (message.type === "error") { alert(message.message); } }; </script> </body> </html>