Files
JoshHeaps.Net/JoshHeaps.Net/wwwroot/js/ChessScripts/ChessAPI.js
T
2026-06-12 10:51:26 -06:00

131 lines
4.1 KiB
JavaScript

const ChessAPI = {
async joinGame() {
const response = await fetch('/api/chess/JoinGame');
return await response.json();
},
async createCPUGame(difficulty, color = "random") {
const response = await fetch(`/api/chess/new/${difficulty}?color=${color}`);
return await response.json();
},
async getGameState(gameId) {
const response = await fetch(`/api/chess/${gameId}`);
return await response.json();
},
async getPgn(gameId) {
const response = await fetch(`/api/chess/${gameId}/pgn`);
if (!response.ok) throw new Error("PGN unavailable");
return await response.text();
},
async forfeit(gameId, playerId) {
await fetch("/api/chess/forfeit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ GameId: gameId, PlayerId: playerId })
});
},
async getLegalMoves(pieceId) {
const response = await fetch(`/api/chess/${GameState.currentGameId}/legalMoves/${pieceId}`);
if (!response.ok) throw new Error("API failed");
return await response.json();
},
async makeMove(moveDto) {
const response = await fetch("/api/chess/move", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(moveDto)
});
if (!response.ok) {
let message = await response.text();
throw new Error(message || "Invalid move or not your turn.");
}
// The move endpoint returns both the move result and the full resulting
// board state, so the caller can render without a follow-up fetch.
const data = await response.json();
if (!data.result.success) {
throw new Error(data.result.message || "Invalid move or not your turn.");
}
return data;
},
async handleMove(targetRow, targetCol) {
if (!GameState.selectedPiece) return;
const isPawn = GameState.selectedPiece.type === 0;
const reachedEnd = (Number(GameState.selectedPiece.color) === 0 && Number(targetRow) === 0) ||
(Number(GameState.selectedPiece.color) === 1 && Number(targetRow) === 0);
let choice = null;
if (isPawn && reachedEnd) {
choice = await ChessModals.promptPromotion();
if (!choice) return;
}
[targetRow, targetCol] = ChessUtils.flipCoordinates(targetRow, targetCol);
const moveDto = {
GameId: GameState.currentGameId,
PlayerId: GameState.currentPlayerId,
PieceId: GameState.selectedPiece.id,
SourceRow: GameState.selectedPiece.row,
SourceCol: GameState.selectedPiece.col,
TargetRow: targetRow,
TargetCol: targetCol,
PromotionChoice: choice
};
GameState.setPreviousMove([GameState.selectedPiece.row, GameState.selectedPiece.col], [targetRow, targetCol]);
try {
const { result, state } = await this.makeMove(moveDto);
ChessBoard.renderState(state);
GameState.clearSelection();
ChessInteractions.clearHighlights();
this.alertGameStatusChange(result);
} catch (error) {
alert("❌ " + error.message);
}
},
alertGameStatusChange(moveResult) {
setTimeout(async () => {
let gameOver = false;
if (moveResult.isCheck) {
console.log("🛑 Check!");
}
if (moveResult.isCheckmate) {
alert("♟️ Checkmate!");
gameOver = true;
} else if (moveResult.isStalemate) {
alert("🤝 Stalemate!");
gameOver = true;
} else if (moveResult.isThreefoldRepetition) {
alert("🤝 Draw by threefold repetition!");
gameOver = true;
}
if (gameOver) {
showCopyPgn(GameState.currentGameId);
await ChessSignalR.leaveGame();
}
}, 500);
}
};
console.log("ChessAPI.js loaded");