Skip to content
Open
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
47 changes: 33 additions & 14 deletions src/components/ChessBoard.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

<script setup lang="ts">

import {ref, onMounted} from 'vue'
import BoardSquare from './BoardSquare.vue';
import { ChessPiece } from '@/ChessPiece';
import type { TileSquare } from '@/types/tilesquare.ts';
import { getKnightMoves, getWhitePawnMoves, getBlackPawnMoves, getRookMoves, getBishopMoves, getQueenMoves, getKingMoves, isKingInCheck } from '@/services/ChessRules';
import { getKnightMoves, getWhitePawnMoves, getBlackPawnMoves, getRookMoves, getBishopMoves, getQueenMoves, getKingMoves, isKingInCheck, enPassantPossible } from '@/services/ChessRules';


const board = ref<TileSquare[]>([]); // ref([])
Expand All @@ -28,14 +27,9 @@ const initialPieces: Record<number, ChessPiece> = {
59: ChessPiece.WHITE_QUEEN, 60: ChessPiece.WHITE_KING, 61: ChessPiece.WHITE_BISHOP,
62: ChessPiece.WHITE_KNIGHT, 63: ChessPiece.WHITE_ROOK
};
// const initialPieces: Record<NumericKeys, string> = {
// 0: "♜", 1: "♞", 2: "♝", 3: "♛", 4: "♚", 5: "♝", 6: "♞", 7: "♜",
// 8: "♟", 9: "♟", 10: "♟", 11: "♟", 12: "♟", 13: "♟", 14: "♟", 15: "♟",
// 48: "♙", 49: "♙", 50: "♙", 51: "♙", 52: "♙", 53: "♙", 54: "♙", 55: "♙",
// 56: "♖", 57: "♘", 58: "♗", 59: "♕", 60: "♔", 61: "♗", 62: "♘", 63: "♖"
// };

const isWhiteTurn = ref(true);
const lastMove = ref<{ from: number; to: number; piece: string } | undefined>(undefined);

const initializeBoard = () => {
board.value = Array.from({length: 64}, (_,i) => ({
Expand All @@ -52,22 +46,37 @@ const movePiece = ({ from, to }: { from: TileSquare; to: TileSquare }) => {

// If the piece exists at the source square
if (board.value[fromIndex].piece) {
const movingPiece = board.value[fromIndex].piece;

// Get valid moves for the piece
const validMoves = getValidMoves(board.value[fromIndex].piece, from.row, from.col);
const validMoves = getValidMoves(movingPiece, from.row, from.col);

// Check if the target square is a valid move
if (validMoves.some(move => move.row === to.row && move.col === to.col)) {
// Check if the move is valid (doesn't leave the king in check)
if (isValidBoard(fromIndex, toIndex)) {
// Check if this is an en passant capture
const epCaptures = enPassantPossible(board.value, lastMove.value);
if (epCaptures) {
const epMove = epCaptures.find(ep => ep.attackerIndex === fromIndex && ep.captureIndex === toIndex);
if (epMove) {
// Remove the captured pawn
board.value[epMove.victimIndex].piece = null;
}
}

// Update the board
board.value[toIndex].piece = board.value[fromIndex].piece;
board.value[fromIndex].piece = null;

// Record this move for en passant detection
lastMove.value = { from: fromIndex, to: toIndex, piece: movingPiece };

// Switch turns
isWhiteTurn.value = !isWhiteTurn.value;

console.log(
`Moved ${board.value[toIndex].piece} from ${board.value[fromIndex].notation} to ${board.value[toIndex].notation}`
`Moved ${board.value[toIndex].piece} from ${from.notation} to ${to.notation}`
);
} else {
console.log("Invalid move: King would be in check.");
Expand All @@ -83,11 +92,20 @@ const isValidBoard = (fromIndex: number, toIndex: number): boolean => {
const boardCopy = board.value.map(tile => ({ ...tile }));

// Simulate the move
boardCopy[toIndex].piece = boardCopy[fromIndex].piece;
const movingPiece = boardCopy[fromIndex].piece;
boardCopy[toIndex].piece = movingPiece;
boardCopy[fromIndex].piece = null;

const isWhiteKing = isWhiteTurn.value;
// Simulate en passant capture if applicable
const epCaptures = enPassantPossible(board.value, lastMove.value);
if (epCaptures) {
const epMove = epCaptures.find(ep => ep.attackerIndex === fromIndex && ep.captureIndex === toIndex);
if (epMove) {
boardCopy[epMove.victimIndex].piece = null;
}
}

const isWhiteKing = isWhiteTurn.value;
const isCheck = isKingInCheck(boardCopy, isWhiteKing);

return !isCheck;
Expand All @@ -100,9 +118,9 @@ const getValidMoves = (piece: ChessPiece, row: number, col: number): TileSquare[
case ChessPiece.BLACK_KNIGHT:
return getKnightMoves(row, col, board.value);
case ChessPiece.WHITE_PAWN:
return getWhitePawnMoves(row, col, board.value);
return getWhitePawnMoves(row, col, board.value, lastMove.value);
case ChessPiece.BLACK_PAWN:
return getBlackPawnMoves(row, col, board.value);
return getBlackPawnMoves(row, col, board.value, lastMove.value);
case ChessPiece.WHITE_ROOK:
case ChessPiece.BLACK_ROOK:
return getRookMoves(row, col, board.value);
Expand Down Expand Up @@ -137,6 +155,7 @@ const handleTileClick = (tile: TileSquare) => {
function resetChessBoard() {
initializeBoard()
isWhiteTurn.value = true;
lastMove.value = undefined;
}

onMounted(initializeBoard);
Expand Down
66 changes: 64 additions & 2 deletions src/services/ChessRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,44 @@ const isSquareUnderAttack = (row:number, col: number, board: TileSquare[], isWhi
return false;
};

// new implementation, lets see if it works
export const enPassantPossible = (board: TileSquare[], lastMove?: { from: number, to: number, piece: string }) => {
if (!lastMove) return null;

const movedPiece = lastMove?.piece;
if (movedPiece !== ChessPiece.WHITE_PAWN && movedPiece !== ChessPiece.BLACK_PAWN) return null;

const fromRow = Math.floor(lastMove.from / 8);
const toRow = Math.floor(lastMove.to / 8);

const toCol = lastMove.to % 8;

if (Math.abs(fromRow - toRow) !== 2) return null;

const attackerPiece = movedPiece === ChessPiece.WHITE_PAWN ? ChessPiece.BLACK_PAWN : ChessPiece.WHITE_PAWN;

const captureToRow = movedPiece === ChessPiece.WHITE_PAWN ? toRow + 1 : toRow - 1;

if (captureToRow < 0 || captureToRow > 7) return null;

const results: { attackerIndex: number; victimIndex: number; captureIndex: number}[] = [];

for (const dc of [-1,1]) {
const attackerCol = toCol + dc;
if (attackerCol < 0 || attackerCol > 7) continue;

const attackerIndex = toRow * 8 + attackerCol;
if (board[attackerIndex].piece === attackerPiece) {
const captureToIndex = captureToRow * 8 + toCol;

if (!board[captureToIndex].piece) {
results.push({attackerIndex, victimIndex: lastMove.to, captureIndex: captureToIndex})
}
}
}
return results.length ? results : null;
}


export const isKingInCheck = (board: TileSquare[], isWhiteKing: boolean): boolean => {
// Find the king's position
Expand Down Expand Up @@ -117,7 +155,7 @@ export const getKnightMoves = (row: number, col: number, board: TileSquare[]): T
return moves;
}

export const getWhitePawnMoves = (row: number, col: number, board: TileSquare[]): TileSquare[] => {
export const getWhitePawnMoves = (row: number, col: number, board: TileSquare[], lastMove?: { from: number; to: number; piece: string }): TileSquare[] => {
const moves: TileSquare[] = [];

const piece = board[row * 8 + col].piece;
Expand Down Expand Up @@ -151,10 +189,22 @@ export const getWhitePawnMoves = (row: number, col: number, board: TileSquare[])
moves.push(board[captureRightIndex]);
}
}

// Check for en passant
const epCaptures = enPassantPossible(board, lastMove);
if (epCaptures) {
const currentIndex = row * 8 + col;
for (const ep of epCaptures) {
if (ep.attackerIndex === currentIndex) {
moves.push(board[ep.captureIndex]);
}
}
}

return moves;
}

export const getBlackPawnMoves = (row: number, col: number, board: TileSquare[]): TileSquare[] => {
export const getBlackPawnMoves = (row: number, col: number, board: TileSquare[], lastMove?: { from: number; to: number; piece: string }): TileSquare[] => {
const moves: TileSquare[] = [];

const piece = board[row * 8 + col].piece;
Expand Down Expand Up @@ -188,6 +238,18 @@ export const getBlackPawnMoves = (row: number, col: number, board: TileSquare[])
moves.push(board[captureRightIndex]);
}
}

// Check for en passant
const epCaptures = enPassantPossible(board, lastMove);
if (epCaptures) {
const currentIndex = row * 8 + col;
for (const ep of epCaptures) {
if (ep.attackerIndex === currentIndex) {
moves.push(board[ep.captureIndex]);
}
}
}

return moves;
}

Expand Down