Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some final tweaks #5

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chessical</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css">
</head>
<body>
Expand Down
180 changes: 180 additions & 0 deletions scripts/board.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let whiteKingsideRookMoved = false;
let whiteQueensideRookMoved = false;
let blackKingsideRookMoved = false;
let blackQueensideRookMoved = false;
let selectedPiece = null;
let selectedSquare = null;

function initBoard() {
const initialBoard = [
Expand Down Expand Up @@ -64,6 +66,8 @@ function initBoard() {
document.querySelectorAll('.piece').forEach(piece => {
piece.addEventListener('dragstart', handleDragStart);
});

initializeTouchAndClickEvents();
}

function handleDragStart(event) {
Expand Down Expand Up @@ -160,6 +164,7 @@ function handleDrop(event) {
}

targetSquare.appendChild(draggedPiece);
handlePawnPromotion(targetSquare, draggedPiece);

const currentPosition = getCurrentPosition();

Expand All @@ -174,6 +179,16 @@ function handleDrop(event) {

updateTurn();
updateEvaluationBar();

// Add checkmate detection here
const pieceColor = draggedPiece.getAttribute('data-piece').split('_')[0];
const opponentIsWhite = pieceColor === 'black';

if (isCheckmate(opponentIsWhite)) {
setTimeout(() => {
showGameEndModal(`${pieceColor.charAt(0).toUpperCase() + pieceColor.slice(1)} wins by checkmate!`);
}, 100); // Small delay to ensure the UI updates first
}
}

draggedPiece.classList.remove('dragging');
Expand Down Expand Up @@ -560,3 +575,168 @@ function doesMoveResolveCheck(piece, sourceIndex, targetIndex) {

// Initialize the board with pieces and listeners
initBoard();

// Add this function after handleDrop
function handlePawnPromotion(square, piece) {
const row = Math.floor(parseInt(square.getAttribute('data-index')) / 8);
const pieceColor = piece.getAttribute('data-piece').split('_')[0];

// Check if pawn reached the opposite end
if (piece.getAttribute('data-piece').includes('pawn') &&
((pieceColor === 'white' && row === 0) || (pieceColor === 'black' && row === 7))) {

// Create and show promotion modal
const modal = document.createElement('div');
modal.className = 'promotion-modal';

// Add promotion piece options
const pieces = ['queen', 'rook', 'bishop', 'knight'];
pieces.forEach(pieceType => {
const option = document.createElement('img');
option.src = `${piecesFolder}${pieceColor}_${pieceType}.png`;
option.className = 'promotion-option';
option.addEventListener('click', () => {
// Update the piece
piece.src = option.src;
piece.setAttribute('data-piece', `${pieceColor}_${pieceType}`);
modal.remove();
updateBoardState();
updateEvaluationBar();
});
modal.appendChild(option);
});

document.body.appendChild(modal);
}
}

// Add these functions after your existing isKingInCheck function
function isCheckmate(isWhiteKing) {
// First verify the king is in check
const kingPos = findKingPosition(isWhiteKing);
if (!kingPos || !isKingInCheck(kingPos.row, kingPos.col, isWhiteKing)) {
return false;
}

// Generate all possible moves
const allMoves = generateAllPossibleMoves(isWhiteKing);

// Try each move to see if it gets out of check
for (const move of allMoves) {
const sourceSquare = document.querySelector(`[data-index="${move.from}"]`);
const piece = sourceSquare.querySelector('.piece');
if (doesMoveResolveCheck(piece, move.from, move.to)) {
return false;
}
}

return true;
}

function showGameEndModal(message) {
const modal = document.createElement('div');
modal.className = 'promotion-modal'; // Reuse the promotion modal styling

const messageElement = document.createElement('p');
messageElement.textContent = message;
messageElement.style.textAlign = 'center';
messageElement.style.marginBottom = '10px';

const newGameButton = document.createElement('button');
newGameButton.textContent = 'New Game';
newGameButton.style.padding = '5px 10px';
newGameButton.onclick = () => {
location.reload();
};

modal.appendChild(messageElement);
modal.appendChild(newGameButton);
document.body.appendChild(modal);
}

function initializeTouchAndClickEvents() {
// Add click handlers to all squares
document.querySelectorAll('.square').forEach(square => {
square.addEventListener('click', handleSquareClick);
});
}

function handleSquareClick(event) {
const square = event.currentTarget;
const piece = square.querySelector('.piece');

// If no piece is selected
if (!selectedPiece) {
if (piece) {
// Select the piece
selectedPiece = piece;
selectedSquare = square;
square.classList.add('selected-square');
}
return;
}

// If a piece is already selected
if (selectedPiece) {
const sourceIndex = parseInt(selectedSquare.getAttribute('data-index'));
const targetIndex = parseInt(square.getAttribute('data-index'));

// Clear previous selection
selectedSquare.classList.remove('selected-square');

// If clicking the same square, deselect the piece
if (square === selectedSquare) {
selectedPiece = null;
selectedSquare = null;
return;
}

// Try to make the move
if (isValidMove(selectedPiece, sourceIndex, targetIndex)) {
const targetPiece = square.querySelector('.piece');

// Handle capture
if (targetPiece) {
const capturedPieceColor = targetPiece.getAttribute('data-piece').split('_')[0];
if (capturedPieceColor === selectedPiece.getAttribute('data-piece').split('_')[0]) {
selectedPiece = null;
selectedSquare = null;
return;
}
targetPiece.remove();

if (capturedPieceColor === 'white') {
capturedWhitePieces.push(targetPiece);
} else {
capturedBlackPieces.push(targetPiece);
}

displayCapturedPieces();
}

// Move the piece
square.appendChild(selectedPiece);
handlePawnPromotion(square, selectedPiece);

const currentPosition = getCurrentPosition();
positionHistory.push(currentPosition);

updateTurn();
updateEvaluationBar();

// Check for checkmate
const pieceColor = selectedPiece.getAttribute('data-piece').split('_')[0];
const opponentIsWhite = pieceColor === 'black';

if (isCheckmate(opponentIsWhite)) {
setTimeout(() => {
showGameEndModal(`${pieceColor.charAt(0).toUpperCase() + pieceColor.slice(1)} wins by checkmate!`);
}, 100);
}
}

// Reset selection
selectedPiece = null;
selectedSquare = null;
}
}
88 changes: 88 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,92 @@ h1{
background: rgba(255, 255, 255, 0.8);
padding: 2px 4px;
border-radius: 3px;
}

.promotion-modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border: 2px solid #333;
border-radius: 8px;
display: flex;
gap: 10px;
z-index: 1000;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}

.promotion-option {
width: 60px;
height: 60px;
cursor: pointer;
transition: transform 0.2s;
}

.promotion-option:hover {
transform: scale(1.1);
}

/* Add responsive design */
@media (max-width: 768px) {
#board {
width: 100vw;
height: 100vw;
max-width: 640px;
max-height: 640px;
}

.square {
width: 12.5vw;
height: 12.5vw;
max-width: 80px;
max-height: 80px;
}

.piece {
width: 100%;
height: 100%;
}

#evaluation-bar {
right: 10px;
height: 300px;
}

.captured-pieces {
padding: 2px;
}

.captured-pieces .piece {
width: 30px;
height: 30px;
}
}

/* Add touch support */
@media (hover: none) {
.square:hover {
background-color: inherit;
}

.square.touch-selected {
background-color: #c8e6c9;
}
}

.selected-square {
background-color: rgba(255, 255, 0, 0.4) !important;
}

/* Improve touch targets */
@media (hover: none) {
.square:hover {
background-color: inherit;
}

.piece {
-webkit-tap-highlight-color: transparent;
}
}