Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024
-
4 déc. 2018 à 10:00
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024
-
11 déc. 2018 à 19:09
Bonjour,
Question se rapportant à un jeu d'échecs.
Comme indiqué dans le titre de cette question, vous trouverez en ligne 48 de ce fichier nommé board.js une instruction qui ne se fait pas.
Celle ci dépend de la condition:
countMoves(myColor) qui doit être égal à zéro et de type numérique à mon avis.
function getObject(obj) {
if (document.getElementById) { // Mozilla, FireFox, Explorer 5+, Opera 5+, Konqueror, Safari, iCab, Ice, OmniWeb 4.5
if (typeof obj == "string") {
if (document.getElementById(obj)) {
return document.getElementById(obj);
} else {
return document.getElementsByName(obj)[0];
}
} else {
return obj.style;
}
}
if (document.all) { // Explorer 4+, Opera 6+, iCab, Ice, Omniweb 4.2-
if (typeof obj == "string") {
return document.all(obj);
} else {
return obj.style;
}
}
if (document.layers) { // Netscape 4, Ice, Escape, Omniweb 4.2-
if (typeof obj == "string") {
return document.layers(obj);
} else {
return obj.style;
}
}
alert('Objet non trouvé : ' + obj);
return false;
}
function isGameDrawn( )
{
var i,j;
// Stalemate? // is all this needed, it is generated in php, so...est tout ce qui est nécessaire, il est généré en php, alors ...
if (gameState == 'stalemate')
{
var myColor = WHITE;
if (0 <= numMoves && 'b' == FEN[FEN.length - 1].split(' ')[1])
{
myColor = BLACK;
}
if (0 == countMoves(myColor))
{
alert('Nulle (pat)\nVous devriez offrir la nulle à votre adversaire.');
}
return "stalemate";
}
// Is the game drawn due to insufficient material to checkmate?
var count = 0;
var canCheckmate = false;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
if (board[i][j] != 0 && (board[i][j] & COLOR_MASK) != KING)
{
if ((board[i][j] & COLOR_MASK) != KNIGHT && (board[i][j] & COLOR_MASK) != BISHOP)
canCheckmate = true;
else
count++;
}
}
}
if (count < 2 && ! canCheckmate)
{
alert('Nulle (materiel insuffisant pour mater)\nVous devriez offrir la nulle à votre adversaire.');
return "material";
}
// Is the game drawn because this is the third time that the exact same position arises?
if (numMoves >= 0 && isThirdTimePosDraw(FEN))
{
alert('Nulle (cette position a été rencontrée trois fois)\nVous devriez offrir la nulle à votre adversaire.');
return "3";
}
// Draw because of no capture or pawn move for the last 50 moves?
if (numMoves >= 0 && isFiftyMoveDraw(FEN[FEN.length-1]))
{
alert('Nulle (règle des 50 coups)\nVous devriez offrir la nulle à votre adversaire.');
return "50";
}
return false;
}
function displayCaptPieces( )
{
var i,j;
var color = 'white';
var html = '<div>';
var piece = '';
var item;
for(i = 0; i < captPieces.length; i++)
{
for(j = 0; j < captPieces[i].length; j++)
{
piece = color + '_' + captPieces[i][j];
html += '<img src="images/' + currentTheme + '/' + piece + '.' + ((-1 !== currentTheme.indexOf('gnuchess')) ? 'png' : 'gif') + '" width="';
html += parseInt(50 * 3 / 5) + '" height="' + parseInt(50 * 3 / 5) + '" alt="' + piece + '" />';
}
html += "</div>\n<div>";
color = 'black';
}
html += '</div>';
getObject('captures').innerHTML = html;
}
if (0 < numMoves) { // if we have not made a move yet, don't get the previous move
var prevMove = new previousMove( ); // the previous move info as object
}
var takenPiece = 0; // the captured piece img in the captures section
var captEnPass = 0; // the square the en passant captured pawn was on
function unhighlightCurMove( )
{
unhighlight(getObject('tsq' + prevMove.fromSq));
unhighlight(getObject('tsq' + prevMove.toSq));
if (takenPiece) // if we have a captured piece highlighted
{
unhighlight(takenPiece); // unhighlight it
takenPiece = 0; // and erase the var so we don't keep highlighting it
}
if (captEnPass) // if we have an en passant capture
{
unhighlight(captEnPass); // unhighlight it
captEnPass = 0; // and erase the var so we don't keep highlighting it
}
}
function highlightCurMove( )
{
var item;
// check for en passant move
if (undefined != prevMove.captSq && prevMove.captSq != prevMove.toSq)
{
captEnPass = getObject('tsq' + prevMove.captSq);
}
if (prevMove.captPiece)
{
if ('w' == pieceColor[prevMove.captPiece])
{
item = 'white_' + pieceLtrToName[prevMove.captPiece.toLowerCase( )];
}
else
{
item = 'black_' + pieceLtrToName[prevMove.captPiece.toLowerCase( )];
}
var capt = getObject('captures').getElementsByTagName('img');
var i;
for (i = 0; i < capt.length; i++)
{
if (capt[i].alt == item)
{
takenPiece = capt[i];
break;
}
}
}
highlight(getObject('tsq' + prevMove.fromSq), 'highlighted');
setTimeout('highlightCurMoveTo( )', 300);
setTimeout('unhighlightCurMove( )', 900);
}
function highlightCurMoveTo( )
{
if (takenPiece)
{
highlight(takenPiece, 'taken_highlighted');
if (captEnPass)
{
highlight(captEnPass, 'taken_highlighted');
highlight(getObject('tsq' + prevMove.toSq), 'highlighted');
}
else
{
highlight(getObject('tsq' + prevMove.toSq), 'taken_highlighted');
}
}
else
{
highlight(getObject('tsq' + prevMove.toSq), 'highlighted');
}
}
function displayCurFEN(moveIdx)
{
if (undefined != moveIdx)
{
getObject('FENblock').innerHTML = FEN[moveIdx];
}
else
{
getObject('FENblock').innerHTML = FEN[FEN.length - 1];
}
}
// these will throw errors, but initializing them as 'undefined' is the
// only way to ensure all-around compatibility no matter what the original colors are.
function moveTo(objMoveId)
{
var theBoard;
if (0 < currMoveIdx) // don't try to reset the empty span, it throws errors
{
unhighlight(getObject('m' + currMoveIdx)); // reset the previous move box background color
}
currMoveIdx = parseInt(objMoveId.id.slice(1)); // get the move number
FENToBoard(FEN[currMoveIdx]); // convert that FEN to the board var
displayCurFEN(currMoveIdx); // display that FEN
FENToCapt(currMoveIdx); // get the captures up to that point
displayCaptPieces( ); // display those captures
theBoard = htmlBoard( ); // convert the board var to html code
getObject('chessboard').innerHTML = theBoard; // display that board
highlight(getObject('m' + currMoveIdx), 'curmove_highlighted'); // change the move box background color
}
function moveJmp(moveDelta)
{
var moveIdx = currMoveIdx;
if (moveIdx + moveDelta > FEN.length - 1)
{
moveIdx = FEN.length - 1;
}
else if (moveIdx + moveDelta < 0)
{
moveIdx = 0;
}
else
{
moveIdx += moveDelta;
}
moveTo(getObject('m' + moveIdx + ''));
}
function displayMoves(replay)
{
var i;
var alt = '';
var objGamebody = getObject('gamebody');
var theMoves = '\n<span id="m0"></span>';
var moveId = 1;
theMoves += '\n<table class="moveList">\n';
for (i = 0; i < moves.length; i++)
{
if ( (i + 1) % 2 == 0)
{
alt = ' class="alt"';
}
else
{
alt = '';
}
if ('1' == isGameOver || replay || 'mate' == gameState)
{
theMoves += '<tr'+alt+'>\n<td class="mn">' + (i+1) + '.</td>\n';
theMoves += '<td id="m' + (moveId) + '" class="wm" onclick="moveTo(this);">' + moves[i][0] + '</td>\n';
theMoves += '<td id="m' + (moveId+1) + '" class="bm" onclick="moveTo(this);">' + moves[i][1] + '</td>\n</tr>';
moveId = moveId + 2;
}
else
{
theMoves += '<tr'+alt+'>\n<td class="mn">' + (i+1) + '.</td>\n<td class="wm">';
theMoves += moves[i][0] + '</td>\n<td class="bm">' + moves[i][1] + '</td>\n</tr>';
}
}
theMoves += '\n</table>\n';
if ('' != result)
{
theMoves += '<span class="ctr">Result: ' + result + '</span>\n';
}
objGamebody.innerHTML = theMoves;
element = document.getElementById('gamebody');
element.scrollTop = element.scrollHeight;
}
function toggleInvert( )
{
if ('black' == perspective)
perspective = 'white';
else
perspective = 'black';
theBoard = htmlBoard( );
getObject('chessboard').innerHTML = theBoard;
}
function htmlBoard( )
{ // Returns the HTML-code for the current chessboard (Note: Fixed square size and theme)
var i,j,k;
var classWSquare;
var classBSquare;
var classHeader;
var fileLabel;
var xtra;
var mtra;
var colorside;
var invertBoard = (perspective == 'black');
var rank = 8;
var rankLabel = rank;
if ('' == isBoardDisabled && ! watchgame)
{
classWSquare = 'light_enabled';
classBSquare = 'dark_enabled';
classHeader = 'header_enabled';
}
else
{
classWSquare = 'light_disabled';
classBSquare = 'dark_disabled';
classHeader = 'header_disabled';
}
var sqBackground = [classBSquare, classWSquare];
if (invertBoard)
{
rankLabel = 1;
colorside = "white";
}
else
{
colorside = "black";
}
j = 1;
//changement du plateau selon le nombre de parteis gagnées
if(parties_gagnees < 100){
theBoard = '\n<div id="theBoard" style="background: url(./images/bois.png);">\n';
var couleur = 'style="color:#111;"'; //correspond aux lettres et chiffres du bord de l'échiquier
}else if(parties_gagnees >= 100){
theBoard = '\n<div id="theBoard" style="background: url(./images/marbre.png);">\n';
var couleur = 'style="color:#555;"'; //correspond aux lettres et chiffres du bord de l'échiquier
}
theBoard += '<div class="' + classHeader + ' ' + colorside + 'corner"> <\/div>\n';
for(i = 0; i < 8; i++)
{
if(invertBoard)
fileLabel = Files[7-i];
else
fileLabel = Files[i];
theBoard += '<div '+couleur+' id="file_t' + i + '" class="' + classHeader + ' horz">' + fileLabel + '<\/div>\n';
}
theBoard += '<div class="' + classHeader + ' ' + colorside + 'corner"> <\/div>\n';
theBoard += '<div '+couleur+' id="rank_l' + rank-- + '" class="' + classHeader + ' vert">' + rankLabel + '</div>\n';
for (k = 63; k >= 0; k--)
{
if ((k+1) % 8 == 0)
{
i = k - 7;
if (invertBoard)
i = 63 - i;
}
else
{
if (invertBoard)
i--;
else
i++;
}
var row = parseInt(i / 8);
var col = i % 8;
if (prevMove && row == prevMove.fromRow && col == prevMove.fromCol && '' == isBoardDisabled && ! watchgame && lastMoveIndicator)
xtra = " fromSquare";
else if (prevMove && row == prevMove.toRow && col == prevMove.toCol && '' == isBoardDisabled && ! watchgame && lastMoveIndicator)
xtra = " toSquare";
else
xtra = "";
theBoard += '<div id="tsq' + i + '" class="' + sqBackground[j] + xtra + '">';
var piece = '';
var source = '';
if(board[row][col] != 0)
{
piece = getPieceColor(board[row][col]) + '_' + getPieceName(board[row][col]);
source = 'images/' + currentTheme + '/' + piece + '.' + ((-1 !== currentTheme.indexOf('gnuchess')) ? 'png' : 'gif'); // Update the square
theBoard += '<img alt="' + piece + '" id="sq' + i + '" ';
theBoard += 'src="' + source + '" width="50" height="50" />';
}
else
{
theBoard += '';
}
theBoard += '<\/div>\n';
if ( (k % 8) === 0 )
{
theBoard += '<div '+couleur+' id="rank_r' + (rank+1) + '" class="' + classHeader + ' vert">' + rankLabel + '<\/div>\n';
if (k != 0)
{
if(invertBoard)
rankLabel = 9 - rank;
else
rankLabel = rank;
theBoard += '<div '+couleur+' id="rank_l' + rank-- + '" class="' + classHeader + ' vert">' + rankLabel + '</div>\n';
}
}
else
{
j = 1 - j;
}
}
if ("white" == colorside)
colorside = "black";
else
colorside = "white";
theBoard += '<div '+couleur+' class="' + classHeader + ' ' + colorside + 'corner"> <\/div>\n';
for (i = 0; i < 8; i++)
{
if (invertBoard)
fileLabel = Files[7-i];
else
fileLabel = Files[i];
xtra = "";mtra = ""; // erase any previous values
if ("518" != id960 && "header_disabled" != classHeader) // if we are not in a normal game and not disabled
{
if ("c" == fileLabel || "g" == fileLabel)
{
xtra = "<span class=\"kingto\">K</span>";
mtra = "<span class=\"spacer\">K</span>";
}
else if ("d" == fileLabel)
{
xtra = "<span class=\"rookato\">R</span>";
mtra = "<span class=\"spacer\">R</span>";
}
else if ("f" == fileLabel)
{
xtra = "<span class=\"rookhto\">R</span>";
mtra = "<span class=\"spacer\">R</span>";
}
var LorigARookPos = origARookPos;
var LorigKingPos = origKingPos;
var LorigHRookPos = origHRookPos;
if (invertBoard)
{
LorigARookPos = 7 - LorigARookPos;
LorigKingPos = 7 - LorigKingPos;
LorigHRookPos = 7 - LorigHRookPos;
}
if (i == LorigARookPos)
fileLabel = '<span class="origarook">' + fileLabel + '</span>';
else if (i == LorigKingPos)
fileLabel = '<span class="origking">' + fileLabel + '</span>';
else if (i == LorigHRookPos)
fileLabel = '<span class="orighrook">' + fileLabel + '</span>';
}
theBoard += '<div '+couleur+' id="file_b' + i + '" class="' + classHeader + ' horz">' + mtra + fileLabel + xtra + '<\/div>\n';
}
theBoard += '<div class="' + classHeader + ' ' + colorside + 'corner"> <\/div>\n<\/div>\n';
return theBoard;
}
// only do disabled = true for btnWakeUp, it is set as disabled if no email is present.
FENToBoard(FEN[FEN.length - 1]); // save the last entry in the FEN array to the board
var theBoard = htmlBoard( ); // The HTML code for the board
var currMoveIdx = 0;
var intervalId = 0;
window.onload = function( )
{
var i;
var lastMove;
var navButtons;
var gameIdDisplay;
var invertBoard = (perspective == 'black');
getObject('chessboard').innerHTML = theBoard;
//displayCurFEN( );
FENToCapt(numMoves);
displayCaptPieces( );
if (0 != gameId) // is it a database game ?
{
gameIdDisplay = 'Partie ' + gameId;
getObject('btnPGN').disabled = false;
}
else // or a PGN file game
{
gameIdDisplay = 'PGN Game';
}
if ( ! watchgame)
{
if ('518' != id960) // if it's a Chess960 game
{
gameIdDisplay += ' - ' + id960 // display the id
}
else // or a regular game
{
getObject("castle").style.display = 'none';
}
}
if ('1' != isBoardDisabled && ! watchgame)
{
if (0 < numMoves)
{
getObject("btnUndo").disabled = false;
}
getObject("btnDraw").disabled = false;
getObject("btnResign").disabled = false;
//document.querySelector('btnResign').disabled = false;
}
if ( ! watchgame) // are we playing the game
{
displayMoves( );
getObject("btnReload").disabled = false;
getObject("btnReplay").disabled = false;
getObject("btnReload").onclick = function( ) { reloadPage(this); };
getObject("btnReplay").onclick = function( ) { replay( ); };
if (0 < moves.length) // if there are moves
{
lastMove = moves.length + '-'; // get the move number
if ('' != moves[moves.length-1][1]) // if we are showing a black move
{
getObject('curmove').innerHTML = lastMove + ' ... ' + moves[moves.length-1][1];
}
else // we are showing a white move
{
getObject('curmove').innerHTML = lastMove + ' ' + moves[moves.length-1][0];
}
if ('1' != isGameOver)
{
getObject("curmove").onclick = function( ) { highlightCurMove( ); };
}
}
if ('check' == gameState)
{
getObject('checkmsg').style.display = '';
getObject('checkmsg').innerHTML = 'Echec !';
// convert the board border to red if in check
var divs = document.all ? document.all : document.getElementById("theBoard").getElementsByTagName("div");
for ( var i = 0; i < divs.length; i++)
{
if (divs[i].className.match(/.*?(horz|vert).*?/))
{
divs[i].style.backgroundColor = "#BF2F35"; // TODO : stylefix
}
}
}
if ('' != statusMessage)
{
getObject('statusmsg').style.display = '';
getObject('statusmsg').innerHTML = statusMessage;
// if the statusMessage says anything about undo's
// prevent multiple undo's from being requested
if (statusMessage.match(/ undo /i))
{
getObject('btnUndo').disabled = true;
}
}
}
else // or just watching the game
{
displayMoves(true);
}
getObject('gameid').innerHTML = gameIdDisplay;
getObject('players').innerHTML = players;
//getObject('btnMainMenu').disabled = false;
getObject('btnPGN').disabled = false;
//getObject('btnMainMenu').onclick = function( ) { displayMainmenu( ); };
getObject('btnPGN').onclick = function( ) { downloadPGN( ); };
if ( ! watchgame)
{
getObject("btnUndo").onclick = function() {
alert("Votre demande d'annulation de coup est en attente.");
undo();
};
getObject("btnDraw").onclick = function() {
alert("Votre demande de match nul est en attente.");
draw();
};
getObject("btnResign").onclick = function() {
alert("Votre demande d'abandon est validée.");
resigngame();
};
}
if ('1' == isGameOver || watchgame || 'mate' == gameState) // Allow game replay
{
if ( ! watchgame)
{
getObject('gamebuttons').style.display = 'none';
getObject('btnWakeUp').disabled = true;
getObject('btnReload').disabled = true;
getObject('btnReplay').disabled = true;
}
currMoveIdx = FEN.length - 1;
navButtons = '<form id="navigation" action="">';
navButtons += '<span id="navbuttons">';
navButtons += '<input id="start" title="Début de la partie" type="button" value="Start" />';
navButtons += '<input id="jmpback" title="Retour en arrière de 5 demi-coups" type="button" value=" << " />';
navButtons += '<input id="prev" title="Retour en arrière d\'un demi-coup" type="button" value=" < " />';
navButtons += '<input id="next" title="Avancer d\'un demi-coup" type="button" value=" > " />';
navButtons += '<input id="jmpfwd" title="Avancer de 5 demi-coups" type="button" value=" >> " />';
navButtons += '<input id="end" title="Fin de la partie" type="button" value="End" /> <br> ';
navButtons += '<input style="width:100px" id="invert" title="Inverser" type="button" value="< Tourner" />';
navButtons += '<input style="width:100px" id="invert2" title="Inverser" type="button" value="Tourner >" disabled />';
navButtons += '</span>';
navButtons += '</form>';
function invert1(){ /*toggleInvert( )*/
document.getElementById("invert").disabled = true;
document.getElementById("invert2").disabled = false;
document.getElementById("theBoard").style.transform = "rotate(180deg)";
document.getElementById("theBoard").style.transition = ".3s";
for (var i=0; i < 64; i++) {
var element = document.getElementById("sq"+i);
if (typeof(element) != 'undefined' && element != null)
{
document.getElementById("sq"+i).style.transform = "rotate(180deg)";
}
}
};
function invert2(){ /*toggleInvert( )*/
document.getElementById("invert2").disabled = true;
document.getElementById("invert").disabled = false;
document.getElementById("theBoard").style.transform = "rotate(0deg)";
document.getElementById("theBoard").style.transition = ".3s";
for (var i=0; i < 64; i++) {
var element = document.getElementById("sq"+i);
if (typeof(element) != 'undefined' && element != null)
{
document.getElementById("sq"+i).style.transform = "rotate(0deg)";
//document.getElementById("theBoard").style.transition = ".3s";
}
}
//document.getElementById("invert").style.display = "block";
//document.getElementById("invert2").style.display = "none";
};
getObject('gamenav').innerHTML = navButtons;
getObject("start").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(-10000);invert1();}else{moveJmp(-10000)} ;};
getObject("jmpback").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(-5);invert1();}else{moveJmp(-5)};};
getObject("prev").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(-1);invert1();}else{moveJmp(-1)};};
getObject("next").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(1);invert1();}else{moveJmp(1)};};
getObject("jmpfwd").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(5);invert1();}else{moveJmp(5)};};
getObject("end").onclick = function( ){if(document.getElementById("invert").disabled == true){invert2();moveJmp(10000);invert1();}else{moveJmp(10000)};};
getObject("invert").onclick = function( ){invert1()};
getObject("invert2").onclick = function( ){invert2()};
}
else // game is not over and we are not replaying it - le jeu n'est pas terminé et nous ne le rejouons pas
{
isGameDrawn( ); // Alert the players it's stalemate, 50 move draw or the same position has occurred three times - Avertissez les joueurs que c'est dans l'impasse, 50 coups ou la même position s'est produite trois fois
if (true == isPlayersTurn)
{ // No need to set event handlers unless it's the player's move - Pas besoin de définir des gestionnaires d'événements à moins que ce ne soit le coup du joueur
for(i = 0; i < 64; i++)
{
getObject('tsq' + i).onclick = function( ) { squareClicked(this); };
}
getObject('btnWakeUp').disabled = true;
}
if (autoreload > 0 && ! DEBUG) // if we need the board refreshed - si nous avons besoin de rafraîchir le jeu.
{
intervalId = setTimeout("window.location.replace('chess.php')", autoreload * 1000); // start the refresh loop
}
}
}
A savoir que countMoves(myColor) est une fonction permettant de définir le nombre de mouvements de pièces possible pour un joueur bien défini.Et que si ce joueur ne peut plus jouer (il est pat aux jeu d'échecs) countMoves(myColor) est égal à zéro.
Cette fonction se trouve ici en ligne 1347 du fichier validation.js:
// these functions are used to test the validity of moves
// DEBUG = false;
// global vars
var knightMove = [[-1, -2], [+1, -2], [-2, -1], [-2, +1], [-1, +2], [+1, +2], [+2, -1], [+2, +1]];
var diagonalMove = [[-1, -1], [-1, +1], [+1, +1], [+1, -1]];
var horzVertMove = [[-1, 0], [0, +1], [+1, 0], [0, -1]];
// The array 'direction' is a combination of diagonalMove and horzVertMove
// It could also be created using 'var direction = horzVertMove.concat(diagonalMove)'
// although the order of the elements would be different
var direction = [[-1, -1], [-1, 0], [-1, +1], [0, +1], [+1, +1], [+1, 0], [+1, -1], [0, -1]];
var pawnMove = [[+1, -1], [+1, 0], [+2, 0], [+1, +1]];
// object definition (used by isSafe)
function GamePiece( )
{
this.piece = 0;
this.dist = 0;
}
/* isSafe tests whether the square at testRow, testCol is safe */
/* for a piece of color testColor to travel to */
function isSafe(testRow, testCol, testColor)
{
var i;
var fromRow;
var fromCol;
var pieceFound = new Array( );
var tmpPiece;
var kingRow;
var kingCol;
var tmpIsSafe;
/* NOTE: if a piece occupies the square itself,
that piece does not participate in determining the safety of the square */
/* IMPORTANT: note that if we're checking to see if the square is safe for a pawn
we're moving, we need to verify the safety for En-passant */
/* OPTIMIZE: cache results (if client-side game only, invalidate cache after each move) */
/* AI NOTE: just because a square isn't entirely safe doesn't mean we don't want to
move there; for instance, we may be protected by another piece */
/* DESIGN NOTE: this function is mostly designed with CHECK checking in mind and
may not be suitable for other purposes */
my_alert("in isSafe(" + testRow + ", " + testCol + ", " + testColor + ")");
var enemyColor = 0;
if ('white' == testColor)
{
enemyColor = 128; /* 1000 0000 */
}
/* check for knights first */
for (i = 0; i < 8; i++) // Check all eight possible knight moves
{
fromRow = testRow + knightMove[i][0];
fromCol = testCol + knightMove[i][1];
if (isInBoard(fromRow,fromCol))
{
if (board[fromRow][fromCol] == (KNIGHT | enemyColor)) // Enemy knight found
{
my_alert("isSafe -> knight found @ " + fromRow + "," + fromCol)
return false;
}
}
}
/* tactic: start at test pos and check all 8 directions for an attacking piece */
/* directions:
black
-----
0 1 2
7 * 3
6 5 4
-----
white
*/
for (i = 0; i < 8; i++)
pieceFound[i] = new GamePiece( );
for (i = 1; i < 8; i++)
{
if ((testRow - i) >= 0 && (testCol - i) >= 0)
if (0 == pieceFound[0].piece && board[testRow - i][testCol - i] != 0)
{
pieceFound[0].piece = board[testRow - i][testCol - i];
pieceFound[0].dist = i;
my_alert("isSafe -> pieceFound[0] = " + board[testRow - i][testCol - i] + "\ndist = " + i);
}
if ((testRow - i) >= 0)
if (0 == pieceFound[1].piece && board[testRow - i][testCol] != 0)
{
pieceFound[1].piece = board[testRow - i][testCol];
pieceFound[1].dist = i;
my_alert("isSafe -> pieceFound[1] = " + board[testRow - i][testCol] + "\ndist = " + i);
}
if ((testRow - i) >= 0 && (testCol + i) < 8)
if (0 == pieceFound[2].piece && board[testRow - i][testCol + i] != 0)
{
pieceFound[2].piece = board[testRow - i][testCol + i];
pieceFound[2].dist = i;
my_alert("isSafe -> pieceFound[2] = " + board[testRow - i][testCol + i] + "\ndist = " + i);
}
if ((testCol + i) < 8)
if (0 == pieceFound[3].piece && board[testRow][testCol + i] != 0)
{
pieceFound[3].piece = board[testRow][testCol + i];
pieceFound[3].dist = i;
my_alert("isSafe -> pieceFound[3] = " + board[testRow][testCol + i] + "\ndist = " + i);
}
if (((testRow + i) < 8) && ((testCol + i) < 8))
if ((pieceFound[4].piece == 0) && (board[testRow + i][testCol + i] != 0))
{
pieceFound[4].piece = board[testRow + i][testCol + i];
pieceFound[4].dist = i;
my_alert("isSafe -> pieceFound[4] = " + board[testRow + i][testCol + i] + "\ndist = " + i);
}
if ((testRow + i) < 8)
if ((pieceFound[5].piece == 0) && (board[testRow + i][testCol] != 0))
{
pieceFound[5].piece = board[testRow + i][testCol];
pieceFound[5].dist = i;
my_alert("isSafe -> pieceFound[5] = " + board[testRow + i][testCol] + "\ndist = " + i);
}
if (((testRow + i) < 8) && ((testCol - i) >= 0))
if ((pieceFound[6].piece == 0) && (board[testRow + i][testCol - i] != 0))
{
pieceFound[6].piece = board[testRow + i][testCol - i];
pieceFound[6].dist = i;
my_alert("isSafe -> pieceFound[6] = " + board[testRow + i][testCol - i] + "\ndist = " + i);
}
if (testCol - i >= 0)
if (0 == pieceFound[7].piece && board[testRow][testCol - i] != 0)
{
pieceFound[7].piece = board[testRow][testCol - i];
pieceFound[7].dist = i;
my_alert("isSafe -> pieceFound[7] = " + board[testRow][testCol - i] + "\ndist = " + i);
}
}
/* check pieces found for possible threats */
for (i = 0; i < 8; i++)
{
if (pieceFound[i].piece != 0 && (pieceFound[i].piece & BLACK) == enemyColor)
{
switch (i)
{
/* diagonally: queen, bishop, pawn, king */
case 0:
case 2:
case 4:
case 6:
if ((pieceFound[i].piece & COLOR_MASK) == QUEEN
|| (pieceFound[i].piece & COLOR_MASK) == BISHOP)
{
my_alert("isSafe -> notKnight -> diagonal -> Q or B -> " + getPieceColor(pieceFound[i].piece) + " " + getPieceName(pieceFound[i].piece) + "\ndist = " + pieceFound[i].dist + "\ndir = " + i);
return false;
}
if (1 == pieceFound[i].dist
&& (pieceFound[i].piece & COLOR_MASK) == PAWN)
{
my_alert("isSafe -> notKnight -> diagonal -> Pawn -> " + getPieceColor(pieceFound[i].piece) + " " + getPieceName(pieceFound[i].piece) + "\ndist = " + pieceFound[i].dist + "\ndir = " + i);
if (WHITE == enemyColor && (0 == i || 2 == i) )
{
return false;
}
else if (BLACK == enemyColor && (4 == i || 6 == i) )
{
return false;
}
}
if (1 == pieceFound[i].dist
&& (pieceFound[i].piece & COLOR_MASK) == KING)
{
my_alert("isSafe -> notKnight -> diagonal -> King -> " + getPieceColor(pieceFound[i].piece) + " " + getPieceName(pieceFound[i].piece) + "\ndist = " + pieceFound[i].dist + "\ndir = " + i);
/* Are the kings next to each other? */
if ((board[testRow][testCol] & COLOR_MASK) == KING)
{
return false;
}
/* save current board destination */
tmpPiece = board[testRow][testCol];
/* update board with move (client-side) */
board[testRow][testCol] = pieceFound[i].piece;
kingRow = 0;
kingCol = 0;
switch (i)
{
case 0:
kingRow = testRow - 1;
kingCol = testCol - 1;
break;
case 1:
kingRow = testRow - 1;
kingCol = testCol;
break;
case 2:
kingRow = testRow - 1;
kingCol = testCol + 1;
break;
case 3:
kingRow = testRow;
kingCol = testCol + 1;
break;
case 4:
kingRow = testRow + 1;
kingCol = testCol + 1;
break;
case 5:
kingRow = testRow + 1;
kingCol = testCol;
break;
case 6:
kingRow = testRow + 1;
kingCol = testCol - 1;
break;
case 7:
kingRow = testRow;
kingCol = testCol - 1;
break;
}
board[kingRow][kingCol] = 0;
/* if king needs to move into check to capture piece, isSafe( ) is true */
tmpIsSafe = isInCheck(getOtherColor(testColor));
/* restore board to previous state */
board[kingRow][kingCol] = pieceFound[i].piece;
board[testRow][testCol] = tmpPiece;
/* if king CAN eat target without moving into check, return false */
/* otherwise, continue checking other piecesFound */
if ( ! tmpIsSafe)
{
return false;
}
}
break;
/* horizontally/vertically: queen, rook, king */
case 1:
case 3:
case 5:
case 7:
if ((pieceFound[i].piece & COLOR_MASK) == QUEEN
|| (pieceFound[i].piece & COLOR_MASK) == ROOK)
{
my_alert("isSafe -> notKnight -> horiz/vert -> Q or R -> " + getPieceColor(pieceFound[i].piece) + " " + getPieceName(pieceFound[i].piece) + "\ndist = " + pieceFound[i].dist + "\ndir = " + i);
return false;
}
if (1 == pieceFound[i].dist
&& (pieceFound[i].piece & COLOR_MASK) == KING)
{
my_alert("isSafe -> notKnight -> horiz/vert -> King -> " + getPieceColor(pieceFound[i].piece) + " " + getPieceName(pieceFound[i].piece) + "\ndist = " + pieceFound[i].dist + "\ndir = " + i);
/* Are the kings next to each other? */
if ((board[testRow][testCol] & COLOR_MASK) == KING)
{
return false;
}
/* save current board destination */
tmpPiece = board[testRow][testCol];
/* update board with move (client-side) */
board[testRow][testCol] = pieceFound[i].piece;
kingRow = 0;
KingCol = 0;
switch (i)
{
case 0:
kingRow = testRow - 1; kingCol = testCol - 1;
break;
case 1:
kingRow = testRow - 1; kingCol = testCol;
break;
case 2:
kingRow = testRow - 1; kingCol = testCol + 1;
break;
case 3:
kingRow = testRow; kingCol = testCol + 1;
break;
case 4:
kingRow = testRow + 1; kingCol = testCol + 1;
break;
case 5:
kingRow = testRow + 1; kingCol = testCol;
break;
case 6:
kingRow = testRow + 1; kingCol = testCol - 1;
break;
case 7:
kingRow = testRow; kingCol = testCol - 1;
break;
}
board[kingRow][kingCol] = 0;
/* if king needs to move into check to capture piece, isSafe( ) is true */
tmpIsSafe = isInCheck(getOtherColor(testColor));
/* restore board to previous state */
board[kingRow][kingCol] = pieceFound[i].piece;
board[testRow][testCol] = tmpPiece;
/* if king CAN eat target without moving into check, return false */
/* otherwise, continue checking other piecesFound */
if (!tmpIsSafe)
{
return false;
}
}
break;
}
}
}
my_alert("isSafe is true");
return true;
}
function isValidMoveKing(fromRow, fromCol, toRow, toCol, tmpColor, castleSide)
{
var i;
var atkColor;
// the king cannot move to a square occupied by a friendly piece
// although the space may be occupied by the rook if it's a castle move
if ( ! castleSide && 0 != board[toRow][toCol] && getPieceColor(board[toRow][toCol]) == tmpColor)
{
return false;
}
// if it's a castle move, every square between
// the king and the final king location must
// be empty and checked for attacking pieces
if ('a' == castleSide || 'h' == castleSide)
{
// check to see if castling is valid before doing anything
var CM = FEN[numMoves].split(' ')[2];
my_alert(CM);
my_alert(castleSide);
// set the final locations of the castling pieces
// and the original rook position
var origRookPos;
var finlRookPos;
var finlKingPos;
var dirK; var dirR;
if ('a' == castleSide)
{
origRookPos = initpos.indexOf('R');
finlRookPos = 3;
finlKingPos = 2;
if (2 != origKingPos)
{
dirK = (finlKingPos - origKingPos) / Math.abs(finlKingPos - origKingPos);
}
else
{
dirK = 0;
}
if (3 != origRookPos)
{
dirR = (finlRookPos - origRookPos) / Math.abs(finlRookPos - origRookPos);
}
else
{
dirR = 0;
}
}
else if ('h' == castleSide)
{
origRookPos = initpos.lastIndexOf('R');
finlRookPos = 5;
finlKingPos = 6;
if (6 != origKingPos)
{
dirK = (finlKingPos - origKingPos) / Math.abs(finlKingPos - origKingPos);
}
else
{
dirK = 0;
}
if (5 != origRookPos)
{
dirR = (finlRookPos - origRookPos) / Math.abs(finlRookPos - origRookPos);
}
else
{
dirR = 0;
}
}
my_alert('origRookPos = '+origRookPos+'\nfinlRookPos = '+finlRookPos+'\nfinlKingPos = '+finlKingPos+'\ndirK = '+dirK+'\ndirR = '+dirR);
var cSide;
var cValid = true;
if ('white' == tmpColor)
{
// if it's a-side, check to make sure that the Q is present in the castle indicator
// and that the toCol is the same location as the original rook. this removes errors
// from having both rooks on the same side as well
if ('a' == castleSide)
{
my_alert('white a = '+castleSide);
cSide = CM.indexOf('Q');
if ((-1 == cSide) || (toCol != origRookPos))
{
cValid = false;
}
}
// for h-side look for the K and the rook location, same as above
else if ('h' == castleSide)
{
my_alert('white h = '+castleSide);
cSide = CM.indexOf('K');
if ((-1 == cSide) || (toCol != origRookPos))
{
cValid = false;
}
}
}
else // black
{
if ('a' == castleSide)
{
my_alert('black a = '+castleSide);
cSide = CM.indexOf('q');
if ((-1 == cSide) || (toCol != origRookPos))
{
cValid = false;
}
}
else if ('h' == castleSide)
{
my_alert('black h = '+castleSide);
cSide = CM.indexOf('k');
if ((-1 == cSide) || (toCol != origRookPos))
{
cValid = false;
}
}
}
if ( ! cValid)
{
errMsg = "You can only castle if the king or the castling rook has not moved yet";
return false;
}
my_alert('cSide = ' + cSide + '\ncharAt = ' + CM.charAt(cSide + 1) +
'\nindexOf = ' + files.indexOf(CM.charAt(cSide + 1)))
if (-1 != files.indexOf(CM.charAt(cSide + 1)) && '' != CM.charAt(cSide + 1))
{
my_alert('Rooks are NOT fine as they are\nThey must be checked');
origRookPos = files.indexOf(CM.charAt(cSide + 1));
}
else
{
my_alert('Rooks are fine as they are');
}
// check every square between the king and the final king location
for (var i = origKingPos; i != (finlKingPos + dirK); i += dirK)
{
if (i < 0 || i > 7) // just a simple test in case things do get out of hand
break;
my_alert('i = ' + i + '\ndirK = ' + dirK + '\noK+d = ' + parseInt(origKingPos + dirK) + '\nfK+d = ' + parseInt(finlKingPos + dirK) +
'\nboard = ' + board[fromRow][i] + '\norigRookPos = ' + origRookPos);
if (board[fromRow][i] && (i != origRookPos) && (i != origKingPos))
{
errMsg = "Le roque ne peut pas se faire en sautant par dessus d'autres pièces.";
return false;
}
if ( ! isSafe(fromRow,i,tmpColor))
{
errMsg = "Pour roquer, le roi ne peut doit être en échec, ne doit pas se mettre en échec et ne peut pas non plus traverser une case où il le serais.";
return false;
}
} // end of king for loop
// check every square between the rook and the final rook location
for (i = (origRookPos + dirR); i != (finlRookPos + dirR); i += dirR)
{
my_alert('i = ' + i + '\ndirR = ' + dirR + '\noR+d = ' + parseInt(origRookPos + dirR) + '\nfR+d = ' + parseInt(finlRookPos + dirR) +
'\nboard = ' + board[fromRow][i] + '\norigRookPos = ' + origRookPos);
if (board[fromRow][i] && i != origKingPos)
{
errMsg = "Le roque ne peut pas se faire en sautant par dessus d'autres pièces.";
return false;
}
} // end of rook for loop
my_alert('All castle tests PASSED\n\nso far...');
return true;
} // end of castle tests
/* temporarily move king to destination to see if in check */
var tmpPiece = board[toRow][toCol];
board[toRow][toCol] = board[fromRow][fromCol];
board[fromRow][fromCol] = 0;
/* The king does not move to a square that is attacked by an enemy piece */
if ('white' == tmpColor)
atkColor = BLACK;
else
atkColor = WHITE;
if (isInCheck(tmpColor))
{
/* return king to original position */
board[fromRow][fromCol] = board[toRow][toCol];
board[toRow][toCol] = tmpPiece;
my_alert("king -> destination not safe!");
errMsg = "Vous êtes en échec.";
return false;
}
/* return king to original position */
board[fromRow][fromCol] = board[toRow][toCol];
board[toRow][toCol] = tmpPiece;
/* NORMAL MOVE: */
if (1 >= Math.abs(toRow - fromRow) && 1 >= Math.abs(toCol - fromCol))
{
my_alert("king -> normal move");
return true;
}
/* CASTLING: leave this here for orthodox castling moves in normal games */
else if ( (518 != id960 && (-1 == fromCol || -2 == fromCol)) || (518 == id960 && fromRow == toRow && 4 == fromCol && Math.abs(toCol - fromCol) == 2) )
{
/*
The following conditions must be met:
* The King and rook must occupy the same rank (or row).
* The rook that makes the castling move has not yet moved in the game.
* The king has not yet moved in the game
* all these conditions are checked for in the creation of the FEN, so just use the data there.
*/
my_alert("isValidMoveKing -> Castling");
var rookCol = 0;
if (toCol - fromCol == 2)
rookCol = 7;
// check to see if castling is valid before doing anything
var CM = FEN[numMoves].split(' ')[2];
var cSide;
var cValid = true;
if ('white' == tmpColor)
{
// see above castling for comments
if (2 == toCol && -1 == (cSide = CM.indexOf('Q')))
cValid = false;
else if (6 == toCol && -1 == (cSide = CM.indexOf('K')))
cValid = false;
}
else // black
{
if (2 == toCol && -1 == (cSide = CM.indexOf('q')))
cValid = false;
else if (6 == toCol && -1 == (cSide = CM.indexOf('k')))
cValid = false;
}
if ( ! cValid)
{
errMsg = "You can only castle if the king or the castling rook has not moved yet";
return false;
}
/*
* All squares between the rook and king before the castling move are empty.
*/
var tmpStep = (toCol - fromCol) / 2;
for (i = 4 + tmpStep; i != rookCol; i += tmpStep)
if (board[fromRow][i] != 0)
{
my_alert("king -> castling -> square not empty");
errMsg = "Le roque ne peut pas se faire en sautant par dessus d'autres pièces.";
return false;
}
/*
* The king is not in check.
* The king does not move over a square that is attacked by an enemy piece during the castling move
*/
/* NOTE: the king's destination has already been checked, so */
/* all that's left is it's initial position and it's final one */
if (isSafe(fromRow, fromCol, tmpColor)
&& isSafe(fromRow, fromCol + tmpStep, tmpColor))
{
my_alert("king -> castling -> VALID!");
return true;
}
else
{
my_alert("king -> castling -> moving over attacked square");
errMsg = "Le roque ne peut pas se faire en sautant par dessus d'autres pièces.";
return false;
}
}
/* INVALID MOVE */
else
{
my_alert("king -> completely invalid move\nfrom " + fromRow + ", " + fromCol + "\nto " + toRow + ", " + toCol);
errMsg = "Le roi ne peut pas aller là.";
return false;
}
if (DEBUG)
{
alert("king -> unknown error");
return false;
}
}
/* checks whether a pawn is making a valid move */
function isValidMovePawn(fromRow,fromCol,toRow,toCol,tmpDir,epCol)
{
if (arguments.length < 6) // Was epCol not passed as a parameter to this function?
epCol = -1; // Make sure that epCol is defined
if ( ( (toRow - fromRow) / Math.abs(toRow - fromRow) ) != tmpDir)
{
errMsg = "Le pion ne peut pas aller là.";
return false;
}
/* standard move */
if ((tmpDir * (toRow - fromRow) == 1) && (toCol == fromCol) && (board[toRow][toCol] == 0))
return true;
/* first move double jump - white */
if ((tmpDir == 1) && (fromRow == 1) && (toRow == 3) && (toCol == fromCol) && (board[2][toCol] == 0) && (board[3][toCol] == 0))
return true;
/* first move double jump - black */
if ((tmpDir == -1) && (fromRow == 6) && (toRow == 4) && (toCol == fromCol) && (board[5][toCol] == 0) && (board[4][toCol] == 0))
return true;
/* standard eating DJ-NOTE: Shouldn't we check that the pawn being eaten is of the correct color? */
else if ((tmpDir * (toRow - fromRow) == 1) && (Math.abs(toCol - fromCol) == 1) && (board[toRow][toCol] != 0))
return true;
/* en passant - white */
else if ((tmpDir == 1) && (fromRow == 4) && (toRow == 5) && (board[4][toCol] == (PAWN | BLACK)))
{
/* can only move en passant if last move is the one where the black pawn moved up two */
if (epCol == toCol ||
(numMoves >= 0 && prevMove.fromRow == 6 && prevMove.toRow == 4
&& prevMove.toCol == toCol))
return true;
else
{
errMsg = "Le pion ne peut par aller là.";
return false;
}
}
/* en passant - black */
else if ((tmpDir == -1) && (fromRow == 3) && (toRow == 2) && (board[3][toCol] == PAWN))
{
/* can only move en passant if last move is the one where the white pawn moved up two */
if ( 0 <= numMoves && files.charAt(toCol) == FEN[numMoves].split(' ')[3].charAt(0))
return true;
else
{
errMsg = "Le pion ne peut par aller là.";
return false;
}
}
else
{
errMsg = "Le pion ne peut par aller là.";
return false;
}
}
/* checks whether a knight is making a valid move */
function isValidMoveKnight(fromRow, fromCol, toRow, toCol)
{
errMsg = "Le cavalier ne peut pas aller là.";
if (Math.abs(toRow - fromRow) == 2)
{
if (Math.abs(toCol - fromCol) == 1)
return true;
else
return false;
}
else if (Math.abs(toRow - fromRow) == 1)
{
if (Math.abs(toCol - fromCol) == 2)
return true;
else
return false;
}
else
{
return false;
}
}
/* checks whether a bishop is making a valid move */
function isValidMoveBishop(fromRow, fromCol, toRow, toCol)
{
var i;
if (Math.abs(toRow - fromRow) == Math.abs(toCol - fromCol))
{
if (toRow > fromRow)
{
if (toCol > fromCol)
{
for (i = 1; i < (toRow - fromRow); i++)
if (board[fromRow + i][fromCol + i] != 0)
{
errMsg = "Le fou ne peut pas aller là.";
return false;
}
}
else
{
for (i = 1; i < (toRow - fromRow); i++)
if (board[fromRow + i][fromCol - i] != 0)
{
errMsg = "Le fou ne saute pas par dessus les pièces.";
return false;
}
}
return true;
}
else
{
if (toCol > fromCol)
{
for (i = 1; i < (fromRow - toRow); i++)
if (board[fromRow - i][fromCol + i] != 0)
{
errMsg = "Le fou ne saute pas par dessus les pièces.";
return false;
}
}
else
{
for (i = 1; i < (fromRow - toRow); i++)
if (board[fromRow - i][fromCol - i] != 0)
{
errMsg = "Le fou ne saute pas par dessus les pièces.";
return false;
}
}
return true;
}
}
else
{
errMsg = "Le fou ne peut pas aller là.";
return false;
}
}
/* checks wether a rook is making a valid move */
function isValidMoveRook(fromRow, fromCol, toRow, toCol)
{
var i;
if (toRow == fromRow)
{
if (toCol > fromCol)
{
for (i = (fromCol + 1); i < toCol; i++)
{
if (board[fromRow][i] != 0)
{
errMsg = "La tour ne saute pas par dessus les pièces.";
return false;
}
}
}
else
{
for (i = (toCol + 1); i < fromCol; i++)
{
if (board[fromRow][i] != 0)
{
errMsg = "La tour ne saute pas par dessus les pièces.";
return false;
}
}
}
return true;
}
else if (toCol == fromCol)
{
if (toRow > fromRow)
{
for (i = (fromRow + 1); i < toRow; i++)
{
if (board[i][fromCol] != 0)
{
errMsg = "La tour ne saute pas par dessus les pièces.";
return false;
}
}
}
else
{
for (i = (toRow + 1); i < fromRow; i++)
{
if (board[i][fromCol] != 0)
{
errMsg = "La tour ne saute pas par dessus les pièces.";
return false;
}
}
}
return true;
}
else
{
errMsg = "La tour ne peut pas aller là.";
return false;
}
}
/* this function checks whether a queen is making a valid move */
function isValidMoveQueen(fromRow, fromCol, toRow, toCol)
{
if (isValidMoveRook(fromRow, fromCol, toRow, toCol) || isValidMoveBishop(fromRow, fromCol, toRow, toCol))
return true;
if (errMsg.search("jump") == -1)
errMsg = "La reine ne peut pas aller là.";
else
errMsg = "La reine ne saute pas par dessus les pièces.";
return false;
}
/* this functions checks to see if curColor is in check */
function isInCheck(curColor)
{
var i,j;
var targetKing = getPieceCode(curColor, "king");
/* find king */
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
if (board[i][j] == targetKing)
{
/* verify it's location is safe */
return ! isSafe(i, j, curColor);
}
}
}
/* the next lines will hopefully NEVER be reached */
errMsg = "ERREUR CRITIQUE : LE ROI N'EST PAS LA !"
return false;
}
/* Ignoring pins, could the piece on the from-square move to the to-square? */
function isValidNoPinMove(fromRow, fromCol, toRow, toCol, epCol, castleSide)
{
var isValid;
var tmpDir = 1;
var curColor = "white";
if (board[fromRow][fromCol] & BLACK)
{
tmpDir = -1;
curColor = "black";
}
isValid = false;
my_alert("isValidNoPinMove -> " + (board[fromRow][fromCol] & COLOR_MASK));
switch(board[fromRow][fromCol] & COLOR_MASK)
{
case PAWN:
isValid = isValidMovePawn(fromRow, fromCol, toRow, toCol, tmpDir, epCol);
break;
case KNIGHT:
isValid = isValidMoveKnight(fromRow, fromCol, toRow, toCol);
break;
case BISHOP:
isValid = isValidMoveBishop(fromRow, fromCol, toRow, toCol);
break;
case ROOK:
isValid = isValidMoveRook(fromRow, fromCol, toRow, toCol);
break;
case QUEEN:
isValid = isValidMoveQueen(fromRow, fromCol, toRow, toCol);
break;
case KING:
isValid = isValidMoveKing(fromRow, fromCol, toRow, toCol, curColor, castleSide);
break;
default: /* ie: not implemented yet */
my_alert("unknown game piece");
}
return isValid;
}
function isValidMove(fromRow, fromCol, toRow, toCol, epCol, castleSide)
{
var curColor;
var isValid;
var tmpPiece;
var tmpEnPassant;
if ( ! isValidNoPinMove(fromRow, fromCol, toRow, toCol, epCol, castleSide) )
return false; // The piece on the from-square doesn't even move in this way
/* now that we know the move itself is valid, let's make sure we're not moving into check */
/* NOTE: we don't need to check for the king since it's covered by isValidMoveKing( ) */
curColor = "white";
if (board[fromRow][fromCol] & BLACK)
curColor = "black";
isValid = true;
if ((board[fromRow][fromCol] & COLOR_MASK) != KING)
{
my_alert("isValidMove -> are we moving into check?");
/* save current board destination */
tmpPiece = board[toRow][toCol];
/* is it an en passant capture? Then remove the captured pawn */
tmpEnPassant = 0;
if (((board[fromRow][fromCol] & COLOR_MASK) == PAWN) && (Math.abs(toCol - fromCol) == 1) && (tmpPiece == 0))
{
tmpEnPassant = board[fromRow][toCol];
board[fromRow][toCol] = 0;
}
/* update board with move (client-side) */
board[toRow][toCol] = board[fromRow][fromCol];
board[fromRow][fromCol] = 0;
/* are we in check now? */
if (isInCheck(curColor))
{
my_alert("isValidMove -> moving into check -> CHECK!");
/* if so, invalid move */
errMsg = "Vous êtes en échec.";
isValid = false;
}
/* restore board to previous state */
board[fromRow][fromCol] = board[toRow][toCol];
board[toRow][toCol] = tmpPiece;
if (tmpEnPassant != 0)
{
board[fromRow][toCol] = tmpEnPassant;
}
}
my_alert("isValidMove returns " + isValid);
return isValid;
}
function canSquareBeBlocked(testRow, testCol, testColor)
{
var i,j;
var fromRow;
var fromCol;
/*
NOTE: This function is similar to isSafe( ); however, the pawn detection
is different. While the original function checks pawns moving diagonally
or en-passant, this function doesn't.
Since this function is intended for checkmate detection, specifically the
canBlockAttacker( ) function, it must validate pawns moving forward.
Also, king is not /allowed/ to block a square.
NOTE: testColor is the attacker color!
*/
//var DEBUG=true;
my_alert("in canSquareBeBlocked(" + testRow + ", " + testCol + ", " + testColor + ")");
var enemyColor = WHITE; // Attacking
var myColor = BLACK; // Blocking
if (testColor == 'black')
{
enemyColor = BLACK; /* 1000 0000 */
myColor = WHITE;
}
/* check for knights first */
for (i = 0; i < 8; i++) // Check all eight possible knight moves
{
fromRow = testRow + knightMove[i][0];
fromCol = testCol + knightMove[i][1];
if (isInBoard(fromRow, fromCol))
if (board[fromRow][fromCol] == (KNIGHT | myColor)) // Knight found
if (isValidMove(fromRow, fromCol, testRow, testCol))
return true; // It can move and block the attack
}
/* tactic: start at test pos and check all 8 directions for an attacking piece */
/* directions: BLACK: WHITE:
0 1 2 2 1 0 6 5 4
7 * 3 3 * 7 7 * 3
6 5 4 4 5 6 0 1 2
*/
for (j = 0; j < 8; j++) // Look for pieces in all directions
{
fromRow = testRow;
fromCol = testCol;
for (i = 1; i < 8; i++) // Distance from the test square
{
fromRow += direction[j][0];
fromCol += direction[j][1];
if (isInBoard(fromRow, fromCol))
{ // if square is in board..
if (board[fromRow][fromCol] != 0)
{ // We found the first piece in this direction
if ((board[fromRow][fromCol] & BLACK) == myColor)
{ // It is my piece
if (isValidMove(fromRow, fromCol, testRow, testCol))
return true; // It can move and block the attack
}
break; // No need to look further in this direction
}
}
else
break; // We fell off the edge of the board
}
}
return false; // The attack cannot be blocked
}
/* canBeCaptured returns true if the piece at testRow, testCol can be captured */
function canBeCaptured(testRow, testCol, epCol)
{
var i;
var tmpDir = -1;
var enemyColor = BLACK;
/* DESIGN NOTE: this function is designed only with CAPTURE checking in mind and should
not be used for other purposes, e.g. if there is no piece (or a king) on the given square */
/* Both normal captures and en passant captures are checked. The epCol parameter
should contain the column number of the en passant square or -1 if there is none.
If epCol >= 0 it indicates that we are replying to a pawn double advance move */
if (board[testRow][testCol] & BLACK)
{
tmpDir = 1;
enemyColor = WHITE;
}
var thePiece = getPieceName(board[testRow][testCol]);
var atkSquare = getAttackers(testRow, testCol, enemyColor); // Find all attackers
for (i = 0; i < atkSquare.length; i++) // Are the attackers pinned or can they capture?
if(isValidMove(atkSquare[i][0], atkSquare[i][1], testRow, testCol))
return true; // The piece can be captured
// If thePiece is a pawn can it by captured en passant?
if (thePiece == 'pawn' && ((testRow == 3 && enemyColor == BLACK) || (testRow == 4 && enemyColor == WHITE)))
{ // The pawn is on the correct row for a possible e.p. capture
if (testCol > 0 && board[testRow][testCol-1] == (PAWN | enemyColor))
if (board[testRow + tmpDir][testCol] == 0) // It's not a regular capture
if (isValidMove(testRow, testCol-1, testRow + tmpDir, testCol, epCol))
return true; // En passant capture
if (testCol < 7 && board[testRow][testCol+1] == (PAWN | enemyColor))
if (board[testRow + tmpDir][testCol] == 0) // It's not a regular capture
if (isValidMove(testRow, testCol+1, testRow + tmpDir, testCol. epCol))
return true; // En passant capture
}
return false; // The piece cannot be captured
}
/* Find all pieces of color atkColor that attack the given square */
/* Note: Even if a piece attacks a square it may not be able to move there */
/* Note: En passant captures are not considered by this function */
function getAttackers(toRow, toCol, atkColor)
{
var i,j;
var fromRow;
var fromCol;
var atkSquare = new Array( );
/* check for knights first */
for (i = 0; i < 8; i++) { // Check all eight possible knight moves
fromRow = toRow + knightMove[i][0];
fromCol = toCol + knightMove[i][1];
if (isInBoard(fromRow, fromCol))
if (board[fromRow][fromCol] == (KNIGHT | atkColor)) // Enemy knight found
atkSquare[atkSquare.length] = [fromRow, fromCol];
}
/* tactic: start at test square and check all 8 directions for an attacking piece */
/* directions:
0 1 2
7 * 3
6 5 4
*/
for (j = 0; j < 8; j++) // Look in all directions
{
fromRow = toRow;
fromCol = toCol;
for (i = 1; i < 8; i++) // Distance from thePiece
{
fromRow += direction[j][0];
fromCol += direction[j][1];
if (isInBoard(fromRow, fromCol))
{
if (board[fromRow][fromCol] != 0)
{ // We found the first piece in this direction
if((board[fromRow][fromCol] & BLACK) == atkColor) // It is an enemy piece
{
if(isAttacking(board[fromRow][fromCol], fromRow, fromCol, getPieceColor(board[fromRow][fromCol]), toRow, toCol))
atkSquare[atkSquare.length] = [fromRow, fromCol]; // An attacker found
}
break; // No need to look further in this direction
}
}
else
break;
}
}
return atkSquare;
}
/* Is the given square attacked by a piece of color atkColor? */
function isAttacked(toRow, toCol, atkColor)
{
return getAttackers(toRow, toCol, atkColor).length > 0;
}
/* Generate moves for a rook, bishop or queen placed at the from-square */
function genSlideMoves(fromRow, fromCol, moveDir)
{
var i,j;
var toRow;
var toCol;
var toSquare = new Array( ); // Store the generated moves
var enemyColor = BLACK;
if (board[fromRow][fromCol] & BLACK)
{
enemyColor = WHITE;
}
for (j = 0; j < moveDir.length; j++) // Check all (valid) directions
{
toRow = fromRow;
toCol = fromCol;
for (i = 1; i < 8; i++) // Distance from the piece
{
toRow += moveDir[j][0];
toCol += moveDir[j][1];
if (isInBoard(toRow, toCol))
{
if (board[toRow][toCol] != 0)
{ // We found the first piece in this direction
if((board[toRow][toCol] & BLACK) == enemyColor) // It's an enemy piece
{
if(isValidMove(fromRow, fromCol, toRow, toCol))
toSquare[toSquare.length] = [toRow, toCol]; // A capture
}
break; // No need to look further in this direction
}
else // an empty square
{
if(isValidMove(fromRow, fromCol, toRow, toCol))
toSquare[toSquare.length] = [toRow, toCol]; // Move to an empty square
}
}
else
break;
}
}
return toSquare;
}
/* Generate all moves for the piece at the given square */
/* Currently this function is only used to test for stalemate.
Therefore castling moves are not checked as they are not relevant
for that purpose */
function genPieceMoves(fromRow, fromCol)
{
var i;
var thePiece;
var toSquare;
var forwardDir;
var toRow;
var toCol;
var enemyColor = BLACK;
if (board[fromRow][fromCol] & BLACK)
{
enemyColor = WHITE;
}
thePiece = board[fromRow][fromCol];
toSquare = new Array( );
switch(thePiece & COLOR_MASK)
{
case PAWN:
forwardDir = 1;
if (enemyColor == WHITE)
forwardDir = -1;
for (i = 0; i < 4; i++) {
toRow = fromRow + pawnMove[i][0] * forwardDir;
toCol = fromCol + pawnMove[i][1];
if (isInBoard(toRow, toCol))
if (board[toRow][toCol] == 0 || (board[toRow][toCol] & BLACK) == enemyColor)
if(isValidMove(fromRow, fromCol, toRow, toCol))
toSquare[toSquare.length] = [toRow, toCol];
}
break;
case ROOK:
toSquare = genSlideMoves(fromRow, fromCol, horzVertMove);
break;
case KNIGHT:
for (i = 0; i < 8; i++) { // Check all eight possible knight moves
toRow = fromRow + knightMove[i][0];
toCol = fromCol + knightMove[i][1];
if (isInBoard(toRow, toCol))
if (board[toRow][toCol] == 0 || (board[toRow][toCol] & BLACK) == enemyColor)
if(isValidMove(fromRow, fromCol, toRow, toCol))
toSquare[toSquare.length] = [toRow, toCol];
}
break;
case BISHOP:
toSquare = genSlideMoves(fromRow, fromCol, diagonalMove);
break;
case QUEEN:
toSquare = genSlideMoves(fromRow, fromCol, direction);
break;
case KING:
for (i = 0; i < 8; i++) { // Check all eight possible king moves
toRow = fromRow + direction[i][0];
toCol = fromCol + direction[i][1];
if (isInBoard(toRow, toCol))
if (board[toRow][toCol] == 0 || (board[toRow][toCol] & BLACK) == enemyColor)
if(isValidMove(fromRow, fromCol, toRow, toCol))
toSquare[toSquare.length] = [toRow, toCol];
}
break;
}
return toSquare;
}
/* Generate all possible moves for the side indicated by the myColor parameter */
function genAllMoves(myColor)
{
var i,j;
var moves = new Array( );
for (i = 0; i < 8; i++) // For all board rows
{
for (j = 0; j < 8; j++) // Check all columns
{
if(board[i][j] != 0 && ((board[i][j] & BLACK) == myColor))
{
if(typeof moves[i] == 'undefined') {
moves[i] = new Array( );
}
moves[i][j] = genPieceMoves(i, j);
}
}
}
return moves;
}
/* Count how many different moves are possible in the current position for myColor */
function countMoves(myColor)
{
var i,j;
var moves = genAllMoves(myColor);
var count = 0;
for (i in moves) // For all board rows
{
for (j in moves[i]) // Check all columns
{
count += moves[i][j].length;
}
}
return count;
}
function isFiftyMoveDraw(FEN)
{ // Returns true if the game is drawn due to the fifty move draw rule (no captures or pawn moves)
return FEN.split(' ')[4] >= 100;
}
function isThirdTimePosDraw(FEN)
{ // Returns true if this is the third time that the exact same position arises with the same side to move
var i;
var currentPos = FEN[FEN.length - 1].split(' ')[0];
var count = 0;
for (i = 0; i < FEN.length - 1; i++)
{
if(currentPos == FEN[i].split(' ')[0])
{
count++;
}
}
return count >= 2;
}
function my_alert(thing)
{
if (DEBUG)
{
alert(thing);
}
}
Merci de bien vouloir m'aider à y voir plus clair dans cette enquête.
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 4 déc. 2018 à 10:27
Bonjour,
une instruction qui ne se fait pas.
Celle ci dépend de la condition:
countMoves(myColor) qui doit être égal à zéro et de type numérique à mon avis.
Tu as déjà ta réponse.... ce n'est pas l'instruction "alert" qui ne se fait pas.... juste que ton IF n'entre jamais à cette ligne...
As tu vérifié que
countMoves(myColor)
retournait zéro ?
Pour ça, tu n'as qu'à placer un console.log ou un alert AVANT le IF avec ta variable pour le savoir....
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 4 déc. 2018 à 17:26
A la lecture de la console, countMoves(myColor) ne retourne rien apparemment.
D'ailleurs voici en image le résultat des consoles:
Je pense qu'il faille désormais s'orienter vers ligne 1347 du fichier validation.js.
Dont la variable count
var count = 0;
, si je ne me trompe, devrait obtenir la valeur zéro pour correspondre au fait qu' un des joueurs ne puissent plus jouer.Rendant ainsi la partie nulle ou pat en terme échiquéen.
Quelle recherche puis je entreprendre à partir de ce constat?
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 4 déc. 2018 à 18:01
Déjà... comment as tu testé la console ?
Tu n'as pas juste saisie la commande dedans mais bien placée dans ton code juste avant ton if hein ?? rassures moi...
Pourrais tu poster le code contenant ton "console.log" ?
Ca serait bien également de nous dire où sont déclarées (et comment.. avec quelles lignes de code...) les variables WHITE et BLACK ...
Sachant que, comme le montre ton imprime écran... tu as une jolie erreur concernant ta variable myColor ...
Tu peux également faire un console.log de cette variable...
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 4 déc. 2018 à 18:53
Déjà... comment as tu testé la console ?
Tu n'as pas juste saisie la commande dedans mais bien placée dans ton code juste avant ton if hein ??
Si j'ai placé le scrypt suivant dans la console:
consol.log(countMoves(myColor));
et non pas dans le fichier avant le if.
Je viens de le faire comme indiqué ci dessous mais c'est pire car aucune information n'est retournée.
Je ne demande pas mieux de te rassurer.Mais pour cela il faudrait que tu m'aides d'avantage en m'indiquant le code exact que je dois écrire avant le if (ligne 35 du fichier board.js).
Pour l'instant est ce cela en ligne 4 ci dessous?
function isGameDrawn( )
{
var i,j;
consol.log(countMoves(myColor));
// Stalemate? // is all this needed, it is generated in php, so... - Pat est tout ce qui est nécessaire, il est généré en php, alors ...
if (gameState == 'stalemate')
{
var myColor = WHITE;
if (0 <= numMoves && 'b' == FEN[FEN.length - 1].split(' ')[1])
{
myColor = BLACK;
}
if (0 == countMoves(myColor))
{
alert('Nulle (pat)\nVous devriez offrir la nulle à votre adversaire.');
}
return "stalemate";
}
// Is the game drawn due to insufficient material to checkmate?
var count = 0;
var canCheckmate = false;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
if (board[i][j] != 0 && (board[i][j] & COLOR_MASK) != KING)
{
if ((board[i][j] & COLOR_MASK) != KNIGHT && (board[i][j] & COLOR_MASK) != BISHOP)
canCheckmate = true;
else
count++;
}
}
}
if (count < 2 && ! canCheckmate)
{
alert('Nulle (materiel insuffisant pour mater)\nVous devriez offrir la nulle à votre adversaire.');
return "material";
}
// Is the game drawn because this is the third time that the exact same position arises?
if (numMoves >= 0 && isThirdTimePosDraw(FEN))
{
alert('Nulle (cette position a été rencontrée trois fois)\nVous devriez offrir la nulle à votre adversaire.');
return "3";
}
// Draw because of no capture or pawn move for the last 50 moves?
if (numMoves >= 0 && isFiftyMoveDraw(FEN[FEN.length-1]))
{
alert('Nulle (règle des 50 coups)\nVous devriez offrir la nulle à votre adversaire.');
return "50";
}
return false;
}
A la lecture de la console sous Firefox, je ne le crois pas:
Car aucune information n'est présenté cette fois ci.
Si mon code est bon ligne 4, c'est que je ne sais pas me servir de la console alors!Ou utiliser le site pour lire le fichier Board.js.
En tout ca j' essaie de comprendre ce qui ne va pas à ce stade de la recherche.
Rassures moi aussi que je vais pouvoir arriver à résoudre ce problème avec ton aide si tu le veux bien.
Pour ma part, j'ai la volonté de le résoudre et prêt à y passer le temps qu'il faudra pour cela.A te présenter ce que tu me demandes (des images, les codes utilisés ou tout autres de tes demandes comme je me suis toujours efforcé à le faire).Et qui a toujours abouti à la résolution des problèmes!
Pour te rassurer, j' apprends beaucoup par ta lecture. Et je garde précieusement tes écrits.
Prenons notre temps.
Rien ne presse car ce n'est que du loisir finalement.
A demain matin pour la suite de cette "enquête" si tu veux bien.
Merci.
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 4 déc. 2018 à 19:59
La programmation (comme le debogage...) c'est une question de logique....
Ton souci concerne, d'après ce que tu nous as indiqué, le code
if (0 == countMoves(myColor))
{
alert('Nulle (pat)\nVous devriez offrir la nulle à votre adversaire.');
}
Donc c'est bien avant ce IF que tu dois placer tes console.log
console.log('myColor',myColor);
console.log('countMoves(myColor)',countMoves(myColor));
if (0 == countMoves(myColor)) {
alert('Nulle (pat)\nVous devriez offrir la nulle à votre adversaire.');
}
Bien entendu, tu feras dérouler le script pour arriver jusqu'au moment où tu es sensé avoir ce message... sinon ça n'a aucun intérêt !
Et pour être sûr que tes modifications de JS sont bien prises en compte... il faut absolument, (après chaque modification....), VIDER le cache de ton navigateur.
Pour être sûr que tu modifies bien le bon fichier ET que ta console peut bien afficher des infos... tu placeras également au tout début de ton fichier board.js la ligne de code
console.log("Board.js : OK");
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 5 déc. 2018 à 13:01
Bonjour,
J'ai du chercher un peu pour me servir de la console Firefox mais finalement je suis parvenu à l'utiliser correctement.
(Voici une adresse concernant Firefox s'dressant aux développeur:
https://www.mozilla.org/fr/firefox/developer/ )
Maintenant je te soumets les résultats du débogage:
+
J'attends tes instructions.
No stress.
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 5 déc. 2018 à 13:36
En sélectionnant JS:
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 Modifié le 5 déc. 2018 à 13:38
Tu ne dois pas afficher la console en ouvrant le fichier js... Mais en allant sur ton site.... (Chess.php)
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 5 déc. 2018 à 13:56
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 6 déc. 2018 à 16:36
Bonjour,
Après avoir rapidement regardé les fichiers de ton site...
La variable gameState est générée dans le fichier "echecs\includes\gui.inc.php"
dans la fonction getStatus()
Fonction appellée elle même dans le fichier "echecs\chess.php" à la ligne 337
Puis de dérouler une partie jusqu'au PAT afin de voir, dans la console, ce qui s'affiche.
(l'idéal étant d'avoir coché, dans la console, la case "conserver les journaux" afin de garder dans la console tout ce qui se passe même après le rechargement de la page)
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 7 déc. 2018 à 09:41
Voici d'abord la configuration de la console sous Firefox:
J'ai coché la case "Activer les journaux persistants".
J'ai placé la partie en pat.
Empêché le rafraichissement de la page en modifiant la ligne 59 du fichier includes/config.inc.php:
$CFG_MINAUTORELOAD = 2500; // Minimum number of secs between automatic page reloads (0 to disable)
Car sinon la page concernant le jeu ne présentait plus la partie.
Puis ensuite mis en oeuvre les modifications que tu m'as indiqué en ligne 337 du fichier chess.php.
Alors voici le résultat de la console:
Cela te convient il?
Ou est ce que j'ai ma procédure est erronée?
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719 7 déc. 2018 à 11:06
Tu me postes le code de ton fichier chess.php ?
Tu as bien fais les modifications ? Je ne les vois pas sur ton site
Tu pourrais également me donner l' ID de la partie que tu testes ?
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 7 déc. 2018 à 11:25
Je viens de te poster le fichier.
Bien sur que les modifs sont faites.
Mais je suis obligé de les annuler après le test.
ID 391
La configuration de la console est correcte?
jordane45
Messages postés38347Date d'inscriptionmercredi 22 octobre 2003StatutModérateurDernière intervention24 décembre 20244 719
>
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 7 déc. 2018 à 12:04
pourquoi dois tu les annuler ?
ça ne fait qu'afficher des infos dans la console...... tu dois donc pouvoir les y laisser . Sinon je ne peux pas voir (sur ton site) ce qui s'affiche....
Max747
Messages postés258Date d'inscriptionvendredi 11 juillet 2014StatutMembreDernière intervention11 janvier 2024 7 déc. 2018 à 12:07
Ok je remets durant 15 minutes.Pour éviter les site hors service.
4 déc. 2018 à 17:26
D'ailleurs voici en image le résultat des consoles:
Je pense qu'il faille désormais s'orienter vers ligne 1347 du fichier validation.js.
Dont la variable count
, si je ne me trompe, devrait obtenir la valeur zéro pour correspondre au fait qu' un des joueurs ne puissent plus jouer.Rendant ainsi la partie nulle ou pat en terme échiquéen.
Quelle recherche puis je entreprendre à partir de ce constat?
4 déc. 2018 à 18:01
Tu n'as pas juste saisie la commande dedans mais bien placée dans ton code juste avant ton if hein ?? rassures moi...
Pourrais tu poster le code contenant ton "console.log" ?
Ca serait bien également de nous dire où sont déclarées (et comment.. avec quelles lignes de code...) les variables WHITE et BLACK ...
Sachant que, comme le montre ton imprime écran... tu as une jolie erreur concernant ta variable myColor ...
Tu peux également faire un console.log de cette variable...