79751252

Date: 2025-08-30 15:52:21
Score: 0.5
Natty:
Report link

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Chess vs AI</title>

<style>

body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; margin-top: 20px; }

#status { margin-bottom: 10px; font-weight: bold; }

#chessboard { display: grid; grid-template-columns: repeat(8, 60px); grid-template-rows: repeat(8, 60px); }

.square { width: 60px; height: 60px; display: flex; justify-content: center; align-items: center; font-size: 36px; cursor: pointer; }

.white { background-color: #f0d9b5; }

.black { background-color: #b58863; }

.selected { outline: 3px solid red; }

.threat { outline: 3px solid red; box-sizing: border-box; }

</style>

</head>

<body>

<div id="status">White's turn</div>

<div id="chessboard"></div>

<button onclick="resetBoard()">Reset</button>

<script>

const boardContainer = document.getElementById('chessboard');

const status = document.getElementById('status');

let board = [];

let selected = null;

let whiteTurn = true;

// Unicode pieces

const pieces = {

'r':'♜', 'n':'♞', 'b':'♝', 'q':'♛', 'k':'♚', 'p':'♟',

'R':'♖', 'N':'♘', 'B':'♗', 'Q':'♕', 'K':'♔', 'P':'♙', '':''

};

// Initial board

const initialBoard = [

['r','n','b','q','k','b','n','r'],

['p','p','p','p','p','p','p','p'],

['','','','','','','',''],

['','','','','','','',''],

['','','','','','','',''],

['','','','','','','',''],

['P','P','P','P','P','P','P','P'],

['R','N','B','Q','K','B','N','R']

];

function renderBoard() {

boardContainer.innerHTML = '';

const threatened = getThreatenedSquares('white');

for (let i=0;i<8;i++) {

for (let j=0;j\<8;j++) {

  const square = document.createElement('div');

  square.classList.add('square');

  square.classList.add((i+j)%2 === 0 ? 'white' : 'black');

  square.textContent = pieces\[board\[i\]\[j\]\];

  square.dataset.row = i;

  square.dataset.col = j;

  square.addEventListener('click', handleSquareClick);

  if (selected && selected.row == i && selected.col == j) {

    square.classList.add('selected');

  }

  if (threatened.some(s =\> s\[0\]===i && s\[1\]===j)) {

    square.classList.add('threat');

  }

  boardContainer.appendChild(square);

}

}

}

// =====================

// Player (Black) logic

// =====================

function handleSquareClick(e) {

if (whiteTurn) return;

const row = parseInt(e.currentTarget.dataset.row);

const col = parseInt(e.currentTarget.dataset.col);

const piece = board[row][col];

if (!selected) {

if (piece && piece === piece.toLowerCase()) {

  selected = {row, col};

  renderBoard();

}

return;

}

if (isLegalMove(selected.row, selected.col, row, col, board[selected.row][selected.col])) {

board\[row\]\[col\] = board\[selected.row\]\[selected.col\];

board\[selected.row\]\[selected.col\] = '';

selected = null;

whiteTurn = true;

status.textContent = "White's turn";

renderBoard();

setTimeout(makeWhiteMove, 500);

} else {

selected = null;

renderBoard();

}

}

// =====================

// AI (White) logic

// =====================

function makeWhiteMove() {

const moves = getAllLegalMoves('white');

if (moves.length===0) {

status.textContent = "Black wins!";

return;

}

// prefer captures

let captureMoves = moves.filter(m => board[m.to[0]][m.to[1]] && board[m.to[0]][m.to[1]].toLowerCase());

let move = captureMoves.length ? captureMoves[Math.floor(Math.random()*captureMoves.length)] : moves[Math.floor(Math.random()*moves.length)];

board[move.to[0]][move.to[1]] = board[move.from[0]][move.from[1]];

board[move.from[0]][move.from[1]] = '';

whiteTurn = false;

status.textContent = "Black's turn";

renderBoard();

}

// =====================

// Move generation

// =====================

function getAllLegalMoves(color) {

const moves = [];

for (let i=0;i<8;i++){

for (let j=0;j\<8;j++){

  let piece = board\[i\]\[j\];

  if (!piece) continue;

  if (color==='white' && piece!==piece.toUpperCase()) continue;

  if (color==='black' && piece!==piece.toLowerCase()) continue;

  const legal = getLegalMoves(i,j,piece);

  legal.forEach(to =\> moves.push({from:\[i,j\],to}));

}

}

return moves;

}

function isLegalMove(r1,c1,r2,c2,piece) {

const legal = getLegalMoves(r1,c1,piece);

return legal.some(m => m[0]===r2 && m[1]===c2);

}

function getLegalMoves(r,c,piece) {

const moves = [];

const color = piece===piece.toUpperCase() ? 'white' : 'black';

const direction = color==='white' ? -1 : 1;

switch(piece.toLowerCase()){

case 'p':

  if (board\[r+direction\] && board\[r+direction\]\[c\]==='') moves.push(\[r+direction,c\]);

  if ((r===6 && color==='white') || (r===1 && color==='black')) {

    if (board\[r+direction\]\[c\]==='' && board\[r+2\*direction\]\[c\]==='') moves.push(\[r+2\*direction,c\]);

  }

  if (c\>0 && board\[r+direction\]\[c-1\] && ((color==='white' && board\[r+direction\]\[c-1\].toLowerCase()) || (color==='black' && board\[r+direction\]\[c-1\].toUpperCase()))) moves.push(\[r+direction,c-1\]);

  if (c\<7 && board\[r+direction\]\[c+1\] && ((color==='white' && board\[r+direction\]\[c+1\].toLowerCase()) || (color==='black' && board\[r+direction\]\[c+1\].toUpperCase()))) moves.push(\[r+direction,c+1\]);

  break;

case 'r': moves.push(...linearMoves(r,c,\[\[1,0\],\[-1,0\],\[0,1\],\[0,-1\]\],color)); break;

case 'b': moves.push(...linearMoves(r,c,\[\[1,1\],\[1,-1\],\[-1,1\],\[-1,-1\]\],color)); break;

case 'q': moves.push(...linearMoves(r,c,\[\[1,0\],\[-1,0\],\[0,1\],\[0,-1\],\[1,1\],\[1,-1\],\[-1,1\],\[-1,-1\]\],color)); break;

case 'k':

  for (let dr=-1;dr\<=1;dr++){

    for (let dc=-1;dc\<=1;dc++){

      if(dr===0 && dc===0) continue;

      const nr=r+dr,nc=c+dc;

      if(nr\>=0 && nr\<8 && nc\>=0 && nc\<8 && (!board\[nr\]\[nc\] || (color==='white'?board\[nr\]\[nc\].toLowerCase():board\[nr\]\[nc\].toUpperCase()))) moves.push(\[nr,nc\]);

    }

  }

  break;

case 'n':

  const knightMoves=\[\[2,1\],\[1,2\],\[2,-1\],\[1,-2\],\[-2,1\],\[-1,2\],\[-2,-1\],\[-1,-2\]\];

  knightMoves.forEach(m=\>{

    const nr=r+m\[0\],nc=c+m\[1\];

    if(nr\>=0 && nr\<8 && nc\>=0 && nc\<8 && (!board\[nr\]\[nc\] || (color==='white'?board\[nr\]\[nc\].toLowerCase():board\[nr\]\[nc\].toUpperCase()))) moves.push(\[nr,nc\]);

  });

  break;

}

return moves;

}

function linearMoves(r,c,directions,color){

const moves = [];

directions.forEach(d=>{

let nr=r+d\[0\],nc=c+d\[1\];

while(nr\>=0 && nr\<8 && nc\>=0 && nc\<8){

  if(!board\[nr\]\[nc\]) moves.push(\[nr,nc\]);

  else {

    if((color==='white' && board\[nr\]\[nc\].toLowerCase()) || (color==='black' && board\[nr\]\[nc\].toUpperCase())) moves.push(\[nr,nc\]);

    break;

  }

  nr+=d\[0\]; nc+=d\[1\];

}

});

return moves;

}

// =====================

// Highlight AI threats

// =====================

function getThreatenedSquares(color) {

const moves = getAllLegalMoves(color);

return moves.map(m => m.to);

}

// =====================

// Reset

// =====================

function resetBoard() {

board = JSO

N.parse(JSON.stringify(initialBoard));

selected = null;

whiteTurn = true;

status.textContent = "White's turn";

renderBoard();

setTimeout(makeWhiteMove, 500);

}

resetBoard();

</script>

</body>

</html>

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Filler text (0.5): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Filler text (0): =====================
  • Low reputation (1):
Posted by: Manny Rich Salen