Help
RSS
API
Feed
Maltego
Contact
Domain > chessmaster.online
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2019-03-14
194.58.56.198
(
ClassC
)
2019-03-14
194.58.56.72
(
ClassC
)
2026-03-04
46.202.161.102
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyConnection: Keep-AliveKeep-Alive: timeout5, max100Content-Type: text/htmlContent-Length: 795Date: Wed, 04 Mar 2026 04:26:57 GMTServer: LiteSpeedLocation: https://chessmaster.online/platform: hostingerpanel: hpanelContent-Security-Policy: upgrade-insecure-requests !DOCTYPE html>html styleheight:100%>head>meta nameviewport contentwidthdevice-width, initial-scale1, shrink-to-fitno />title> 301 Moved Permanently/title>style>@media (prefers-color-scheme:dark){body{background-color:#000!important}}/style>/head>body stylecolor: #444; margin:0;font: normal 14px/20px Arial, Helvetica, sans-serif; height:100%; background-color: #fff;>div styleheight:auto; min-height:100%; > div styletext-align: center; width:800px; margin-left: -400px; position:absolute; top: 30%; left:50%;> h1 stylemargin:0; font-size:150px; line-height:150px; font-weight:bold;>301/h1>h2 stylemargin-top:20px;font-size: 30px;>Moved Permanently/h2>p>The document has been permanently moved./p>/div>/div>/body>/html>
Port 443
HTTP/1.1 200 OKConnection: Keep-AliveKeep-Alive: timeout5, max100Content-Type: text/htmlLast-Modified: Sat, 07 Jun 2025 12:39:21 GMTEtag: c0d6-684432f9-6b23e46fcafc3569;;;Accept-Ranges: bytesContent-Length: 49366Date: Wed, 04 Mar 2026 04:26:58 GMTServer: LiteSpeedplatform: hostingerpanel: hpanelRetry-After: 60Content-Security-Policy: upgrade-insecure-requests !DOCTYPE html>html langen>head> meta charsetUTF-8> meta nameviewport contentwidthdevice-width, initial-scale1.0> !-- Website name updated in the title --> title>Chessmaster/title> script srchttps://cdn.tailwindcss.com>/script> link relpreconnect hrefhttps://fonts.googleapis.com> link relpreconnect hrefhttps://fonts.gstatic.com crossorigin> link hrefhttps://fonts.googleapis.com/css2?familyPoppins:wght@400;600;700&familyInter:wght@400;700&displayswap relstylesheet> style> :root { /* Wooden theme for the board */ --light-square: #f0d9b5; --dark-square: #b58863; --board-border: #4a3f37; /* Responsive board size */ --board-size: min(95vw, 80vh, 600px); --square-size: calc(var(--board-size) / 8); } body { font-family: Poppins, sans-serif; background-color: #0f172a; color: #f1f5f9; display: flex; flex-direction: column; min-height: 100vh; } main { flex-grow: 1; display: flex; align-items: center; justify-content: center; } .chess-board { display: grid; grid-template-columns: repeat(8, var(--square-size)); grid-template-rows: repeat(8, var(--square-size)); width: var(--board-size); height: var(--board-size); border: 4px solid var(--board-border); border-radius: 8px; box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.2), 0 8px 10px -6px rgb(0 0 0 / 0.2); } .square { display: flex; align-items: center; justify-content: center; font-size: calc(var(--square-size) * 0.7); -webkit-user-select: none; -ms-user-select: none; user-select: none; position: relative; } .light { background-color: var(--light-square); } .dark { background-color: var(--dark-square); } .piece { cursor: pointer; transition: transform 0.15s ease-in-out; /* Improved piece styling for wooden board */ text-shadow: 0 1px 3px rgba(0,0,0,0.4); } .piece.w { color: #f8f8f8; } .piece.b { color: #2c2c2c; } .selected::after { content: ; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(46, 204, 113, 0.5); border-radius: 4px; box-shadow: inset 0 0 12px rgba(0,0,0,0.4); } .valid-move::after { content: ; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 35%; height: 35%; background-color: rgba(34, 89, 60, 0.7); border-radius: 50%; cursor: pointer; } .valid-move.capture::after { width: 100%; height: 100%; background-color: rgba(239, 68, 68, 0.5); } .in-check::after { content: ; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(239, 68, 68, 0.7); animation: pulse-check 1.5s infinite; } @keyframes pulse-check { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.05); opacity: 0.8; } } /* Modal Styles */ .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(15, 23, 42, 0.8); backdrop-filter: blur(8px); display: flex; justify-content: center; align-items: center; z-index: 1000; transition: opacity 0.3s ease; } .modal-content { background: #1e293b; padding: 2.5rem; border-radius: 12px; box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.4); border: 1px solid #334155; width: 90%; max-width: 450px; } .last-move-highlight { background-color: rgba(251, 191, 36, 0.4) !important; } /style>/head>body classflex flex-col items-center min-h-screen p-2 sm:p-4> header classtext-center py-4> h1 classtext-4xl md:text-5xl font-bold text-slate-100>Chessmaster/h1> /header> main> !-- Game UI --> div idgame-container classw-full max-w-7xl mx-auto hidden flex-col lg:flex-row items-center lg:items-start justify-center gap-4 lg:gap-8> div idboard-container classflex-shrink-0 flex flex-col items-center> div idchess-board classchess-board>/div> div idplayer-color-indicator classmt-4 text-lg font-semibold>/div> /div> div classbg-slate-800 p-4 md:p-6 rounded-xl shadow-lg w-full max-w-sm flex flex-col items-center text-center border border-slate-700> div idstatus classtext-xl font-semibold mb-4 h-14 text-slate-300 flex items-center justify-center>/div> div idgame-id-container classw-full bg-slate-900/50 p-3 rounded-lg mb-4> label forgame-id-display classblock text-sm font-medium text-slate-400>Game ID/label> input idgame-id-display typetext readonly classw-full bg-slate-700 text-slate-200 border-slate-600 rounded-md p-2 text-center font-mono cursor-pointer onclickthis.select()> button idcopy-game-id classmt-2 w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-200 transform hover:scale-105>Copy ID/button> /div> button idnew-game-button classbg-rose-600 hover:bg-rose-700 text-white font-bold py-3 px-6 rounded-lg shadow-md transition-all duration-200 w-full>New Game/button> div classmt-6 w-full> h2 classtext-lg font-semibold text-slate-400 border-b border-slate-600 pb-2 mb-3>Captured Pieces/h2> div classflex justify-between text-left> div classw-1/2 pr-2> h3 classfont-bold text-slate-200>White/h3> div idwhite-captured classflex flex-wrap gap-1 min-h-30px text-2xl>/div> /div> div classw-1/2 pl-2> h3 classfont-bold text-slate-200>Black/h3> div idblack-captured classflex flex-wrap gap-1 min-h-30px text-2xl>/div> /div> /div> /div> div iduser-id-container classmt-4 text-xs text-slate-500 w-full text-center>Your User ID: span iduser-id-display>/span>/div> /div> /div> /main> !-- Lobby / Join Modal --> div idlobby-modal classmodal-overlay> div idmain-menu-view classmodal-content text-center> h2 classtext-3xl font-bold mb-6 text-slate-100>Game Menu/h2> button idplay-with-computer-btn classw-full bg-orange-600 hover:bg-orange-700 text-white font-bold py-3 px-6 rounded-lg mb-4 text-lg transition-transform transform hover:scale-105>Play with Computer/button> button idplay-online-btn classw-full bg-sky-600 hover:bg-sky-700 text-white font-bold py-3 px-6 rounded-lg mb-4 text-lg transition-transform transform hover:scale-105>Play Online/button> button idplay-offline-btn classw-full bg-emerald-600 hover:bg-emerald-700 text-white font-bold py-3 px-6 rounded-lg mb-4 text-lg transition-transform transform hover:scale-105>Play Offline (vs Human)/button> button idabout-btn classw-full bg-slate-600 hover:bg-slate-700 text-white font-bold py-3 px-6 rounded-lg text-lg transition-transform transform hover:scale-105>About/button> /div> div idonline-menu-view classmodal-content text-center hidden> h2 classtext-3xl font-bold mb-6 text-slate-100>Play Online/h2> button idcreate-game-button classw-full bg-emerald-600 hover:bg-emerald-700 text-white font-bold py-3 px-6 rounded-lg mb-4 text-lg transition-transform transform hover:scale-105>Create New Game/button> div classrelative flex py-5 items-center> div classflex-grow border-t border-slate-600>/div>span classflex-shrink mx-4 text-slate-400>OR/span>div classflex-grow border-t border-slate-600>/div> /div> div classspace-y-3> input typetext idjoin-game-input placeholderEnter Game ID to Join classw-full bg-slate-700 text-slate-200 border-slate-600 rounded-md p-3 text-center> button idjoin-game-button classw-full bg-sky-600 hover:bg-sky-700 text-white font-bold py-3 px-6 rounded-lg text-lg transition-transform transform hover:scale-105>Join Game/button> /div> button idback-to-main-menu-btn classmt-6 text-slate-400 hover:text-slate-200 transition>← Back/button> div idlobby-error classtext-red-400 mt-4 h-5>/div> /div> div idabout-view classmodal-content text-left hidden> h2 classtext-3xl font-bold mb-4 text-slate-100 text-center>About Chessmaster/h2> p classtext-slate-300 mb-2>Welcome to Chessmaster, your home for classic chess./p> p classtext-slate-300 mb-4>You can play against a friend online by creating a game and sharing the Game ID, play with someone on the same device in offline mode, or challenge the computer. This project is built with HTML, Tailwind CSS, and Firebase./p> button idback-from-about-btn classmt-6 w-full bg-sky-600 hover:bg-sky-700 text-white font-bold py-3 px-6 rounded-lg text-lg transition-transform transform hover:scale-105>Back to Menu/button> /div> /div> !-- Promotion Modal --> div idpromotion-overlay classmodal-overlay hidden> div classmodal-content flex justify-center gap-6> !-- Pieces will be injected here by JS --> /div> /div> !-- Game Over Modal --> div idgame-over-modal classmodal-overlay hidden> div classmodal-content text-center> h2 idgame-over-status classtext-3xl font-bold mb-6 text-slate-100>/h2> button idplay-again-btn classw-full bg-emerald-600 hover:bg-emerald-700 text-white font-bold py-3 px-6 rounded-lg text-lg transition-transform transform hover:scale-105>Play Again/button> /div> /div> footer classtext-center text-slate-500 py-4 mt-auto> p>© 2025 Chessmaster/p> /footer> script typemodule> import { initializeApp } from https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js; import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js; import { getFirestore, doc, getDoc, setDoc, onSnapshot, collection } from https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js; // --- App and Firebase Config --- const appId typeof __app_id ! undefined ? __app_id : default-chess-app; const firebaseConfig typeof __firebase_config ! undefined ? JSON.parse(__firebase_config) : { apiKey: YOUR_API_KEY, authDomain: YOUR_AUTH_DOMAIN, projectId: YOUR_PROJECT_ID, storageBucket: YOUR_STORAGE_BUCKET, messagingSenderId: YOUR_MESSAGING_SENDER_ID, appId: YOUR_APP_ID }; // --- DOM Elements --- const lobbyModal document.getElementById(lobby-modal); const mainMenuView document.getElementById(main-menu-view); const onlineMenuView document.getElementById(online-menu-view); const aboutView document.getElementById(about-view); const gameOverModal document.getElementById(game-over-modal); const gameOverStatus document.getElementById(game-over-status); const playAgainBtn document.getElementById(play-again-btn); const gameContainer document.getElementById(game-container); const boardElement document.getElementById(chess-board); const statusElement document.getElementById(status); const newGameButton document.getElementById(new-game-button); const whiteCapturedElement document.getElementById(white-captured); const blackCapturedElement document.getElementById(black-captured); const promotionOverlay document.getElementById(promotion-overlay); const promotionModal document.querySelector(#promotion-overlay .modal-content); const createGameButton document.getElementById(create-game-button); const joinGameInput document.getElementById(join-game-input); const joinGameButton document.getElementById(join-game-button); const gameIdContainer document.getElementById(game-id-container); const gameIdDisplay document.getElementById(game-id-display); const copyGameIdButton document.getElementById(copy-game-id); const lobbyError document.getElementById(lobby-error); const playerColorIndicator document.getElementById(player-color-indicator); const userIdContainer document.getElementById(user-id-container); const userIdDisplay document.getElementById(user-id-display); const playOnlineBtn document.getElementById(play-online-btn); const playOfflineBtn document.getElementById(play-offline-btn); const playWithComputerBtn document.getElementById(play-with-computer-btn); const aboutBtn document.getElementById(about-btn); const backToMainMenuBtn document.getElementById(back-to-main-menu-btn); const backFromAboutBtn document.getElementById(back-from-about-btn); // --- Firebase Initialization --- const app initializeApp(firebaseConfig); const auth getAuth(app); const db getFirestore(app); // --- Game State Variables --- let localGameState {}; let selectedPiece null; let validMoves ; let gameId null; let playerColor null; let userId null; let gameUnsubscribe null; let isOfflineMode false; let isComputerMode false; const pieces { w: { K: ♔, Q: ♕, R: ♖, B: ♗, N: ♘, P: ♙ }, b: { K: ♚, Q: ♛, R: ♜, B: ♝, N: ♞, P: ♟︎ } }; // --- Core Game Logic --- function getInitialGameState(player1Id, player2Id null) { return { board: bR, bN, bB, bQ, bK, bB, bN, bR, bP, bP, bP, bP, bP, bP, bP, bP, Array(8).fill(null), Array(8).fill(null), Array(8).fill(null), Array(8).fill(null), wP, wP, wP, wP, wP, wP, wP, wP, wR, wN, wB, wQ, wK, wB, wN, wR, , turn: w, kings: { w: {row: 7, col: 4}, b: {row: 0, col: 4} }, castlingRights: { w: { K: true, Q: true }, b: { K: true, Q: true } }, enPassantTarget: null, gameActive: true, whiteCaptured: , blackCaptured: , status: isComputerMode ? Your Turn : (isOfflineMode ? Whites Turn : Waiting for opponent...), players: { w: player1Id, b: player2Id }, lastMove: null }; } function renderBoard() { if (!localGameState.board) return; boardElement.innerHTML ; clearHighlights(); if (localGameState.lastMove) { document.querySelector(`data-row${localGameState.lastMove.from.row}data-col${localGameState.lastMove.from.col}`)?.classList.add(last-move-highlight); document.querySelector(`data-row${localGameState.lastMove.to.row}data-col${localGameState.lastMove.to.col}`)?.classList.add(last-move-highlight); } const kingInCheck isKingInCheck(localGameState.turn, localGameState); for (let row 0; row 8; row++) { for (let col 0; col 8; col++) { const square document.createElement(div); const isLight (row + col) % 2 0; square.className `square ${isLight ? light : dark}`; square.dataset.row row; square.dataset.col col; const pieceStr localGameState.boardrowcol; if (pieceStr) { const pieceColor pieceStr0; const pieceType pieceStr1; const pieceElement document.createElement(span); pieceElement.className `piece ${pieceColor}`; pieceElement.textContent piecespieceColorpieceType; square.appendChild(pieceElement); if(pieceType K && pieceColor localGameState.turn && kingInCheck) { square.classList.add(in-check); } } boardElement.appendChild(square); } } addSquareListeners(); } function updateUI(state) { localGameState state; statusElement.textContent localGameState.status; whiteCapturedElement.innerHTML localGameState.whiteCaptured.map(p > `span classpiece ${p0}>${piecesp0p1}/span>`).join(); blackCapturedElement.innerHTML localGameState.blackCaptured.map(p > `span classpiece ${p0}>${piecesp0p1}/span>`).join(); boardElement.style.transform ; boardElement.querySelectorAll(.piece).forEach(p > p.style.transform ); if (isComputerMode) { playerColorIndicator.textContent Playing vs Computer; } else if (isOfflineMode) { playerColorIndicator.textContent `Offline Game`; } else if (playerColor) { playerColorIndicator.textContent `You are playing as ${playerColor w ? White : Black}`; if (playerColor b) { boardElement.style.transform rotate(180deg); boardElement.querySelectorAll(.piece).forEach(p > { p.style.transform rotate(180deg); }); } } renderBoard(); } function addSquareListeners() { document.querySelectorAll(.square).forEach(square > { square.addEventListener(click, onSquareClick); }); } function onSquareClick(event) { if (!localGameState.gameActive) return; if (isComputerMode && localGameState.turn ! w) return; if (!isOfflineMode && !isComputerMode && localGameState.turn ! playerColor) return; const square event.currentTarget; const row parseInt(square.dataset.row); const col parseInt(square.dataset.col); const piece localGameState.boardrowcol; const currentTurnColor localGameState.turn; if (selectedPiece) { const isValidMove validMoves.some(move > move.row row && move.col col); if (isValidMove) { movePiece(selectedPiece.row, selectedPiece.col, row, col); } else { clearHighlights(); selectedPiece null; if (piece && piece0 currentTurnColor) { selectPiece(row, col); } } } else if (piece && piece0 currentTurnColor) { selectPiece(row, col); } } function selectPiece(row, col) { selectedPiece { row, col, type: localGameState.boardrowcol }; validMoves getValidMoves(row, col, localGameState); clearHighlights(); document.querySelector(`data-row${row}data-col${col}`).classList.add(selected); highlightValidMoves(); } function clearHighlights() { document.querySelectorAll(.selected, .valid-move, .last-move-highlight, .in-check).forEach(el > { el.classList.remove(selected, valid-move, last-move-highlight, in-check, capture); }); } function highlightValidMoves() { validMoves.forEach(move > { const square document.querySelector(`data-row${move.row}data-col${move.col}`); if (square) { square.classList.add(valid-move); if (localGameState.boardmove.rowmove.col) { square.classList.add(capture); } } }); } function movePiece(startRow, startCol, endRow, endCol) { let newState JSON.parse(JSON.stringify(localGameState)); const piece newState.boardstartRowstartCol; const capturedPiece newState.boardendRowendCol; if (piece1 P && `${endRow},${endCol}` newState.enPassantTarget) { const capturedPawnRow newState.turn w ? endRow + 1 : endRow - 1; const capturedPawn newState.boardcapturedPawnRowendCol; if (capturedPawn) (newState.turn w ? newState.blackCaptured : newState.whiteCaptured).push(capturedPawn); newState.boardcapturedPawnRowendCol null; } else if (capturedPiece) { (newState.turn w ? newState.blackCaptured : newState.whiteCaptured).push(capturedPiece); } newState.enPassantTarget (piece1 P && Math.abs(startRow - endRow) 2) ? `${(startRow + endRow) / 2},${startCol}` : null; newState.boardendRowendCol piece; newState.boardstartRowstartCol null; newState.lastMove { from: {row: startRow, col: startCol}, to: {row: endRow, col: endCol}}; if (piece1 K) { newState.kingsnewState.turn { row: endRow, col: endCol }; if (Math.abs(startCol - endCol) 2) { const rookCol endCol > startCol ? 7 : 0; const newRookCol endCol > startCol ? endCol - 1 : endCol + 1; newState.boardendRownewRookCol newState.boardendRowrookCol; newState.boardendRowrookCol null; } } updateCastlingRights(newState, piece, startRow, startCol); selectedPiece null; validMoves ; if (piece1 P && (endRow 0 || endRow 7)) { newState.gameActive false; handlePawnPromotion(endRow, endCol, newState); return; } switchTurn(newState); if (isOfflineMode || isComputerMode) { const storageKey isComputerMode ? computerChessGame : offlineChessGame; localStorage.setItem(storageKey, JSON.stringify(newState)); updateUI(newState); if (!newState.gameActive) { showGameOverModal(newState.status); } else if (isComputerMode && newState.turn b) { setTimeout(makeComputerMove, 500); } } else { updateGameInFirestore(newState); } } function updateCastlingRights(state, piece, row, col) { const color piece0; if (piece1 K) { state.castlingRightscolor.K false; state.castlingRightscolor.Q false; } else if (piece1 R) { const startRow color w ? 7 : 0; if (col 0 && row startRow) state.castlingRightscolor.Q false; else if (col 7 && row startRow) state.castlingRightscolor.K false; } } function switchTurn(state) { state.turn (state.turn w ? b : w); if (isCheckmate(state.turn, state)) { state.status `Checkmate! ${state.turn w ? Black : White} wins.`; state.gameActive false; } else if (isStalemate(state.turn, state)) { state.status Stalemate! Its a draw.; state.gameActive false; } else { let turnText; if(isComputerMode) { turnText state.turn w ? Your Turn : Computers Turn; } else { turnText state.turn w ? Whites Turn : Blacks Turn; } state.status isKingInCheck(state.turn, state) ? `Check! ${turnText}` : turnText; } } function handlePawnPromotion(row, col, stateToUpdate) { promotionOverlay.classList.remove(hidden); promotionModal.innerHTML ; const promotionPieces Q, R, B, N; promotionPieces.forEach(pType > { const pieceElement document.createElement(span); const turnColor stateToUpdate.turn; pieceElement.className `piece ${turnColor} text-6xl cursor-pointer transition-transform hover:scale-110`; pieceElement.textContent piecesturnColorpType; pieceElement.onclick () > choosePromotion(row, col, pType, stateToUpdate); promotionModal.appendChild(pieceElement); }); } function choosePromotion(row, col, pType, stateToUpdate) { let newState JSON.parse(JSON.stringify(stateToUpdate)); newState.boardrowcol newState.turn + pType; newState.gameActive true; promotionOverlay.classList.add(hidden); switchTurn(newState); if(isOfflineMode || isComputerMode) { const storageKey isComputerMode ? computerChessGame : offlineChessGame; localStorage.setItem(storageKey, JSON.stringify(newState)); updateUI(newState); if (!newState.gameActive) { showGameOverModal(newState.status); } else if (isComputerMode && newState.turn b) { setTimeout(makeComputerMove, 500); } } else { updateGameInFirestore(newState); } } // --- Move Validation (Pure Functions) --- function getValidMoves(row, col, state) { const piece state.boardrowcol; if (!piece) return ; let moves getRawMoves(row, col, state); return moves.filter(move > { let tempState JSON.parse(JSON.stringify(state)); const pieceToMove tempState.boardrowcol; const pieceColor pieceToMove0; tempState.boardmove.rowmove.col pieceToMove; tempState.boardrowcol null; const kingPos pieceToMove1 K ? {row: move.row, col: move.col} : tempState.kingspieceColor; const inCheck isSquareAttacked(kingPos.row, kingPos.col, pieceColor w ? b : w, tempState); return !inCheck; }); } function getKingSimpleMoves(row, col, color, state) { const moves ; const directions -1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1; directions.forEach((dRow, dCol) > { const newRow row + dRow; const newCol col + dCol; if (newRow > 0 && newRow 8 && newCol > 0 && newCol 8) { const targetPiece state.boardnewRownewCol; if (!targetPiece || targetPiece0 ! color) { moves.push({ row: newRow, col: newCol }); } } }); return moves; } function getRawMoves(row, col, state) { const piece state.boardrowcol; if (!piece) return ; const color piece0, type piece1; switch (type) { case P: return getPawnMoves(row, col, color, state); case R: return getSlidingMoves(row, col, color, state, -1, 0, 1, 0, 0, -1, 0, 1); case N: return getKnightMoves(row, col, color, state); case B: return getSlidingMoves(row, col, color, state, -1, -1, -1, 1, 1, -1, 1, 1); case Q: return getSlidingMoves(row, col, color, state, -1, 0, 1, 0, 0, -1, 0, 1, -1, -1, -1, 1, 1, -1, 1, 1); case K: return getKingMoves(row, col, color, state); default: return ; } } function getPawnMoves(row, col, color, state) { const moves , direction color w ? -1 : 1, startRow color w ? 6 : 1; if (row + direction > 0 && row + direction 8 && !state.boardrow + directioncol) { moves.push({ row: row + direction, col }); if (row startRow && !state.boardrow + 2 * directioncol) moves.push({ row: row + 2 * direction, col }); } -1, 1.forEach(dCol > { const newCol col + dCol, newRow row + direction; if (newCol > 0 && newCol 8 && newRow > 0 && newRow 8) { const targetPiece state.boardnewRownewCol; if (targetPiece && targetPiece0 ! color) moves.push({ row: newRow, col: newCol }); if (`${newRow},${newCol}` state.enPassantTarget) moves.push({row: newRow, col: newCol}); } }); return moves; } function getSlidingMoves(row, col, color, state, directions) { const moves ; directions.forEach((dRow, dCol) > { for (let i 1; i 8; i++) { const newRow row + i * dRow, newCol col + i * dCol; if (newRow 0 || newRow > 8 || newCol 0 || newCol > 8) break; const targetPiece state.boardnewRownewCol; if (targetPiece) { if (targetPiece0 ! color) moves.push({ row: newRow, col: newCol }); break; } moves.push({ row: newRow, col: newCol }); } }); return moves; } function getKnightMoves(row, col, color, state) { const moves ; const directions -2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1; directions.forEach((dRow, dCol) > { const newRow row + dRow, newCol col + dCol; if (newRow > 0 && newRow 8 && newCol > 0 && newCol 8) { const targetPiece state.boardnewRownewCol; if (!targetPiece || targetPiece0 ! color) moves.push({ row: newRow, col: newCol }); } }); return moves; } function getKingMoves(row, col, color, state) { const moves getKingSimpleMoves(row, col, color, state); if (!isKingInCheck(color, state)) { const opponent color w ? b : w; if (state.castlingRightscolor.K && !state.boardrowcol+1 && !state.boardrowcol+2 && !isSquareAttacked(row, col, opponent, state) && !isSquareAttacked(row, col + 1, opponent, state) && !isSquareAttacked(row, col + 2, opponent, state)) { moves.push({ row, col: col + 2 }); } if (state.castlingRightscolor.Q && !state.boardrowcol-1 && !state.boardrowcol-2 && !state.boardrowcol-3 && !isSquareAttacked(row, col, opponent, state) && !isSquareAttacked(row, col - 1, opponent, state) && !isSquareAttacked(row, col - 2, opponent, state)) { moves.push({ row, col: col - 2 }); } } return moves; } function isSquareAttacked(row, col, attackerColor, state) { for (let r 0; r 8; r++) { for (let c 0; c 8; c++) { const piece state.boardrc; if (piece && piece0 attackerColor) { const moves piece1 K ? getKingSimpleMoves(r, c, attackerColor, state) : getRawMoves(r, c, state); if (moves.some(move > move.row row && move.col col)) return true; } } } return false; } function isKingInCheck(kingColor, state) { const kingPos state.kingskingColor; if (!kingPos) return false; return isSquareAttacked(kingPos.row, kingPos.col, kingColor w ? b : w, state); } function hasLegalMoves(color, state) { for (let r 0; r 8; r++) { for (let c 0; c 8; c++) { if (state.boardrc && state.boardrc0 color) { if (getValidMoves(r, c, state).length > 0) return true; } } } return false; } function isCheckmate(color, state) { return isKingInCheck(color, state) && !hasLegalMoves(color, state); } function isStalemate(color, state) { return !isKingInCheck(color, state) && !hasLegalMoves(color, state); } // --- Firebase & Game Mode Functions --- function makeComputerMove() { if (!localGameState.gameActive) return; const computerColor b; const allPossibleMoves ; for (let r 0; r 8; r++) { for (let c 0; c 8; c++) { const piece localGameState.boardrc; if (piece && piece0 computerColor) { const moves getValidMoves(r, c, localGameState); if (moves.length > 0) { allPossibleMoves.push(...moves.map(move > ({ from: { row: r, col: c }, to: move }))); } } } } if (allPossibleMoves.length > 0) { const randomMove allPossibleMovesMath.floor(Math.random() * allPossibleMoves.length); movePiece(randomMove.from.row, randomMove.from.col, randomMove.to.row, randomMove.to.col); } } function startComputerGame(savedState null) { isOfflineMode false; isComputerMode true; playerColor w; lobbyModal.classList.add(hidden); gameContainer.classList.remove(hidden); gameContainer.classList.add(flex); gameIdContainer.style.display none; userIdContainer.style.display none; newGameButton.textContent New Game; const gameState savedState || getInitialGameState(You, Computer); if (!savedState) { localStorage.setItem(computerChessGame, JSON.stringify(gameState)); } updateUI(gameState); } function startOfflineGame(savedState null) { isOfflineMode true; isComputerMode false; playerColor w; lobbyModal.classList.add(hidden); gameContainer.classList.remove(hidden); gameContainer.classList.add(flex); gameIdContainer.style.display none; userIdContainer.style.display none; newGameButton.textContent New Game; const gameState savedState || getInitialGameState(White, Black); if (!savedState) { localStorage.setItem(offlineChessGame, JSON.stringify(gameState)); } updateUI(gameState); } function showOnlineMenu() { mainMenuView.classList.add(hidden); onlineMenuView.classList.remove(hidden); } function showAboutMenu() { mainMenuView.classList.add(hidden); aboutView.classList.remove(hidden); } function showGameOverModal(status) { gameOverStatus.textContent status; gameOverModal.classList.remove(hidden); } function showMainMenu() { onlineMenuView.classList.add(hidden); aboutView.classList.add(hidden); mainMenuView.classList.remove(hidden); lobbyError.textContent ; } async function createGame() { if (!userId) { lobbyError.textContent Authenticating...; return; } isOfflineMode false; isComputerMode false; createGameButton.disabled true; lobbyError.textContent Creating game...; const newGameRef doc(collection(db, artifacts, appId, public, data, games)); gameId newGameRef.id.substring(0, 6); const initialState getInitialGameState(userId); try { const stateToSend JSON.parse(JSON.stringify(initialState)); stateToSend.board JSON.stringify(stateToSend.board); const gameRef doc(db, artifacts, appId, public, data, games, gameId); await setDoc(gameRef, stateToSend); playerColor w; await joinGameSession(gameId); } catch (error) { console.error(Error creating game:, error); lobbyError.textContent Could not create game.; createGameButton.disabled false; } } async function joinGame() { if (!userId) { lobbyError.textContent Authenticating...; return; } isOfflineMode false; isComputerMode false; const idToJoin joinGameInput.value.trim(); if (!idToJoin) { lobbyError.textContent Please enter a Game ID.; return; } joinGameButton.disabled true; lobbyError.textContent Joining game...; const gameRef doc(db, artifacts, appId, public, data, games, idToJoin); const gameSnap await getDoc(gameRef); if (gameSnap.exists()) { const gameData gameSnap.data(); if (gameData.players.b null && gameData.players.w ! userId) { gameData.players.b userId; gameData.status Whites Turn; await setDoc(gameRef, gameData); playerColor b; await joinGameSession(idToJoin); } else if (gameData.players.w userId || gameData.players.b userId) { playerColor gameData.players.w userId ? w : b; await joinGameSession(idToJoin); } else { lobbyError.textContent This game is already full.; joinGameButton.disabled false; } } else { lobbyError.textContent Game not found.; joinGameButton.disabled false; } } function joinGameSession(id) { gameId id; if (gameUnsubscribe) gameUnsubscribe(); localStorage.setItem(onlineChessGameId, id); const gameDocRef doc(db, artifacts, appId, public, data, games, gameId); gameUnsubscribe onSnapshot(gameDocRef, (doc) > { selectedPiece null; validMoves ; if (doc.exists()) { if (auth.currentUser) { const gameData doc.data(); playerColor gameData.players.w auth.currentUser.uid ? w : b; localStorage.setItem(onlineChessPlayerColor, playerColor); } const gameState doc.data(); if (gameState.board && typeof gameState.board string) { gameState.board JSON.parse(gameState.board); } lobbyModal.classList.add(hidden); gameContainer.classList.remove(hidden); gameContainer.classList.add(flex); gameIdContainer.style.display block; userIdContainer.style.display block; newGameButton.textContent Leave Game; updateUI(gameState); if (!gameState.gameActive) { showGameOverModal(gameState.status); } } else { leaveGame(); } }, (error) > { console.error(Error listening to game updates:, error); lobbyError.textContent Connection lost to game.; }); } async function updateGameInFirestore(state) { if (!gameId) return; const stateToSend JSON.parse(JSON.stringify(state)); if (Array.isArray(stateToSend.board)) { stateToSend.board JSON.stringify(stateToSend.board); } const gameRef doc(db, artifacts, appId, public, data, games, gameId); await setDoc(gameRef, stateToSend); } function leaveGame() { if (gameUnsubscribe) gameUnsubscribe(); gameId null; playerColor null; gameUnsubscribe null; localGameState {}; isOfflineMode false; isComputerMode false; localStorage.removeItem(onlineChessGameId); localStorage.removeItem(onlineChessPlayerColor); localStorage.removeItem(offlineChessGame); localStorage.removeItem(computerChessGame); gameContainer.classList.add(hidden); lobbyModal.classList.remove(hidden); showMainMenu(); createGameButton.disabled false; joinGameButton.disabled false; } // --- Authentication and Initialization --- async function handleAuthentication() { onAuthStateChanged(auth, async user > { if (user) { userId user.uid; userIdDisplay.textContent userId; await checkForSavedGame(); } else { userId null; userIdDisplay.textContent N/A; await checkForSavedGame(); } }); try { if (typeof __initial_auth_token ! undefined && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (error) { console.error(Authentication failed:, error); lobbyError.textContent `Auth failed: ${error.code}`; lobbyModal.classList.remove(hidden); } } async function checkForSavedGame() { const savedOnlineId localStorage.getItem(onlineChessGameId); const savedOfflineGame localStorage.getItem(offlineChessGame); const savedComputerGame localStorage.getItem(computerChessGame); if (savedOnlineId && auth.currentUser) { lobbyModal.classList.add(hidden); playerColor localStorage.getItem(onlineChessPlayerColor); await joinGameSession(savedOnlineId); } else if (savedComputerGame) { lobbyModal.classList.add(hidden); const gameState JSON.parse(savedComputerGame); startComputerGame(gameState); } else if (savedOfflineGame) { lobbyModal.classList.add(hidden); const gameState JSON.parse(savedOfflineGame); startOfflineGame(gameState); } else { lobbyModal.classList.remove(hidden); } } // --- Event Listeners and Start --- playOnlineBtn.addEventListener(click, showOnlineMenu); playOfflineBtn.addEventListener(click, () > { localStorage.removeItem(offlineChessGame); startOfflineGame(); }); playWithComputerBtn.addEventListener(click, () > { localStorage.removeItem(computerChessGame); startComputerGame(); }); aboutBtn.addEventListener(click, showAboutMenu); backToMainMenuBtn.addEventListener(click, showMainMenu); backFromAboutBtn.addEventListener(click, showMainMenu); createGameButton.addEventListener(click, createGame); joinGameButton.addEventListener(click, joinGame); newGameButton.addEventListener(click, () > { if (isComputerMode) { localStorage.removeItem(computerChessGame); startComputerGame(); } else if (isOfflineMode) { localStorage.removeItem(offlineChessGame); startOfflineGame(); } else { leaveGame(); } }); copyGameIdButton.addEventListener(click, () > { gameIdDisplay.select(); document.execCommand(copy); copyGameIdButton.textContent Copied!; setTimeout(() > { copyGameIdButton.textContent Copy ID; }, 2000); }); playAgainBtn.addEventListener(click, () > { gameOverModal.classList.add(hidden); if (isComputerMode) { localStorage.removeItem(computerChessGame); startComputerGame(); } else if (isOfflineMode) { localStorage.removeItem(offlineChessGame); startOfflineGame(); } else { leaveGame(); } }); handleAuthentication(); /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]