// Trollbot ICS // Configuration: // The name of the div where the chessboard will go var gBoardDiv = 'chessboard'; // The name of the div where the chess game attributes go var gAttributesDiv = 'attributes'; // The name of the div where the chess controls go var gControlsDiv = 'controls'; // The name of the div where the javascript check message goes var gJavascriptCheckDiv = 'javascriptcheck'; // The name of the div where the moves are displayed var gMovesDiv = 'moves'; // Image path for pieces var gImagePath = './images/'; // Display the rank and file on the board var gDisplayRankFile = true; // Don't modify these var gCurMove = 0; var gCurSide = 'white'; var gCurBoard = false; var gBoardStates = false; var gCurBoardTable = false; var gNumMoves = 0; var gStopped = false; function internalNotation(external) { var retval = false; switch (external) { case '1': case 1: retval = 7; break; case '2': case 2: retval = 6; break; case '3': case 3: retval = 5; break; case '4': case 4: retval = 4; break; case '5': case 5: retval = 3; break; case '6': case 6: retval = 2; break; case '7': case 7: retval = 1; break; case '8': case 8: retval = 0; break; case 'a': retval = 0; break; case 'b': retval = 1; break; case 'c': retval = 2; break; case 'd': retval = 3; break; case 'e': retval = 4; break; case 'f': retval = 5; break; case 'g': retval = 6; break; case 'h': retval = 7; break; } return retval; } function externalFileNotation(internal) { var retval = false; switch (internal) { case 0: retval = 8; break; case 1: retval = 7; break; case 2: retval = 6; break; case 3: retval = 5; break; case 4: retval = 4; break; case 5: retval = 3; break; case 6: retval = 2; break; case 7: retval = 1; break; case 8: retval = 0; break; } return retval; } function externalRankNotation(internal) { var retval = false; switch (internal) { case 0: retval = 'a'; break; case 1: retval = 'b'; break; case 2: retval = 'c'; break; case 3: retval = 'd'; break; case 4: retval = 'e'; break; case 5: retval = 'f'; break; case 6: retval = 'g'; break; case 7: retval = 'h'; break; } return retval; } // This takes an existing board state, and calculates the PGN // and returns the resulting board state function pgnToInternalRepresentation(last_state, side, pgn) { // Break the PGN format into the following var dst_rank = false; var dst_file = false; var src_rank = false; var src_file = false; var src_type = false; var capture_flag = false; var check_flag = false; var castle = false; var dis_piece = false; // Castle king's side if (pgn == 'O-O') return; // Castle queen's side if (pgn == 'O-O-O') return; // End game, white won if (pgn == '1-0') return; // End game, black won if (pgn == '0-1') return; // Stalemate/draw if (pgn == '1/2-1/2') return; if (pgn[pgn.length-1] == '+') { check_flag = true; pgn = pgn.substring(0, pgn.length-1); } dst_file = pgn[pgn.length-1]; dst_rank = pgn[pgn.length-2]; pgn = pgn.substring(0, pgn.length-2); // We have disambiguation data while (pgn.length > 0) { var dis_data = pgn[pgn.length-1]; pgn = pgn.substring(0, pgn.length-1); switch (dis_data) { case 'x': capture_flag = true; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': src_rank = dis_data; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': src_file = dis_data; break; case 'K': case 'k': case 'Q': case 'q': case 'R': case 'r': case 'B': case 'b': case 'P': case 'p': case 'N': case 'n': src_type = dis_data; break; default: alert('Unhandled PGN: ' + dis_data); } } // Translate crap into our notation if (dst_file) { dst_file = internalNotation(dst_file); } if (dst_rank) { dst_rank = internalNotation(dst_rank); } if (src_file) { src_file = internalNotation(src_file); } if (src_rank) { src_rank = internalNotation(src_rank); } switch (src_type) { // Brute force it case false: // Try and find pawn first // go through list of other pieces which have a possible move to dst_rank, dst_file var pawn_match = false; if (capture_flag == true) { // can split two ways if ((dst_rank - 1) > 0 && (dst_file + (1 * ((side == 'white') ? -1 : 1))) > 0) { if (last_state[dst_rank-1][dst_file+(1 * ((side == 'white') ? -1 : 1))]) { alert('pawn_match'); pawn_match = true; break; } } else if ((dst_rank + 1) > 0 && (dst_file + (1 * ((side == 'white') ? -1 : 1))) > 0) { if (last_state[dst_rank+(1 * ((side == 'white') ? -1 : 1))][dst_file+1]) { src_rank = dst_rank+(1 * ((side == 'white') ? -1 : 1)); pawn_match = true; break; } } } else { if ((dst_file + (1 * ((side == 'white') ? 1 : -1))) >= 0 && (dst_file + (1 * ((side == 'white') ? 1 : -1))) < 8) { if (last_state[(dst_file + (1 * ((side == 'white') ? 1 : -1)))][dst_rank] == (((side == 'white') ? 'w' : 'b') + 'p')) { src_rank = externalRankNotation(dst_rank); src_file = externalFileNotation((dst_file + (1 * ((side == 'white') ? 1 : -1)))); var newstate = last_state.slice(); newstate[internalNotation(src_file)][internalNotation(src_rank)] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wp' : 'bp'); return newstate; } if ((dst_file + (2 * ((side == 'white') ? 1 : -1))) >= 0 && (dst_file + (2 * ((side == 'white') ? 1 : -1))) < 8) { if (last_state[(dst_file + (2 * ((side == 'white') ? 1 : -1)))][dst_rank] == (((side == 'white') ? 'w' : 'b') + 'p')) { src_rank = externalRankNotation(dst_rank); src_file = externalFileNotation((dst_file + (2 * ((side == 'white') ? 1 : -1)))); var newstate = last_state.slice(); newstate[internalNotation(src_file)][internalNotation(src_rank)] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wp' : 'bp'); return newstate; } } return false; } } break; case 'K': case 'k': // it was a king move, find within 1 of dst_file, dst_rank // \ | / // - K - // / | \ break; case 'Q': case 'q': // it was a queen move, find within +-8 of dst_file, dst_rank // \ | / // - Q - // / | \ for (var i = 0; i < 8; i++) { for (var j = 0; j < 8; j++) { // Diagonal left // if (dst_rank + (i - i <= 0 && } } break; case 'b': case 'B': // it was a bishop move, find within +-8 of dst_file, dst_rank // \ / // B // / \ break; case 'R': case 'r': // it was a rook move, find within +-8 of dst_file, dst_rank // | // - R - // | break; case 'N': case 'n': // It was a knight's move, find within +- 2 dst_rank, +- 1 dst_file // Checks for movement right 2, forward +1 var v = (dst_file + (1 * ((side == 'white') ? 1 : -1))); var h = (dst_rank - (2 * ((side == 'white') ? 1 : -1))); if (v >= 0 && v < 8 && h >= 0 && h < 8) { if (last_state[v][h] == ((side == 'white') ? "wn" : "bn")) { src_rank = externalRankNotation(h); src_file = externalFileNotation(v); var newstate = last_state.slice(); newstate[v][h] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } } // Checks for movement left 2, forward 1 v = (dst_file - (1 * ((side == 'white') ? 1 : -1))); h = (dst_rank - (2 * ((side == 'white') ? 1 : -1))); if (v >= 0 && v < 8 && h >= 0 && h < 8) { if (last_state[v][h] == ((side == 'white') ? "wn" : "bn")) { src_rank = externalRankNotation(h); src_file = externalFileNotation(v); var newstate = last_state.slice(); newstate[v][h] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } } /* // Checks for movement left 2, forward 1 v = (dst_file - (2 * ((side == 'white') ? 1 : -1))); h = (dst_rank - (1 * ((side == 'white') ? 1 : -1))); if (v >= 0 && v < 8 && h >= 0 && h < 8) { alert('duh' + h + v); alert(dst_file); if (last_state[v][h] == ((side == 'white') ? "wn" : "bn")) { src_rank = externalRankNotation(h); src_file = externalFileNotation(v); var newstate = last_state.slice(); newstate[v][h] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } } */ // Checks for movement left 2, back 1 v = (dst_file - (1 * ((side == 'white') ? 1 : -1))); h = (dst_rank + (2 * ((side == 'white') ? 1 : -1))); if (v >= 0 && v < 8 && h >= 0 && h < 8) { if (last_state[v][h] == ((side == 'white') ? "wn" : "bn")) { src_rank = externalRankNotation(h); src_file = externalFileNotation(v); var newstate = last_state.slice(); newstate[v][h] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } } if (((dst_file + (2 * ((side == 'white') ? 1 : -1))) >= 0) || ((dst_file + (2 * ((side == 'white') ? 1 : -1))) >= 0)) { if (last_state[(dst_file + (2 * ((side == 'white') ? 1 : -1)))][dst_rank-1] == ((side == 'white') ? 'wn' : 'bn')) { src_rank = externalRankNotation(dst_rank-1); src_file = externalFileNotation((dst_file + (2 * ((side == 'white') ? 1 : -1)))); var newstate = last_state.slice(); newstate[internalNotation(src_file)][internalNotation(src_rank)] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } else if (last_state[(dst_file + (2 * ((side == 'white') ? 1 : -1)))][dst_rank+1] == ((side == 'white') ? 'wn' : 'bn')) { src_rank = externalRankNotation(dst_rank+1); src_file = externalFileNotation((dst_file + (2 * ((side == 'white') ? 1 : -1)))); var newstate = last_state.slice(); newstate[internalNotation(src_file)][internalNotation(src_rank)] = 't'; newstate[dst_file][dst_rank] = ((side == 'white') ? 'wn' : 'bn'); return newstate; } } alert('We got to the end of the list without handling anything'); gStopped = true; break; } return false; } function prepareBoardStates() { if (gStopped == true) return; // Get number of moves gNumMoves = gChessBoard.total_moves; // Create tables of pieces for each move, for each side gBoardStates = new Array(); gBoardStates[0] = {}; gBoardStates[0].white = gCurBoard.slice(); gBoardStates[0].black = gCurBoard.slice(); var toggle = false; for (var i = 1; i <= gNumMoves; i++) { gBoardStates[i] = new Array(); alert(gBoardStates[0].white); gBoardStates[i].white = pgnToInternalRepresentation(gBoardStates[i-1].black, 'white', gChessBoard.moves[i].white); gBoardStates[i].black = pgnToInternalRepresentation(gBoardStates[i-1].white, 'black', gChessBoard.moves[i].black); } } function resetBoard() { gCurMove = 0; gCurSide = 'white'; gCurBoard = new Array(8); for (var y = 0; y < 8; y++) { gCurBoard[y] = new Array(8); for (var x = 0; x < 8; x++) { switch (y) { case 0: switch (x) { case 0: case 7: gCurBoard[y][x] = "br"; break; case 1: case 6: gCurBoard[y][x] = "bn"; break; case 2: case 5: gCurBoard[y][x] = "bb"; break; case 3: gCurBoard[y][x] = "bq"; break; case 4: gCurBoard[y][x] = "bk"; break; } break; case 1: gCurBoard[y][x] = "bp"; break; case 6: gCurBoard[y][x] = "wp"; break; case 7: switch (x) { case 0: case 7: gCurBoard[y][x] = "wr"; break; case 1: case 6: gCurBoard[y][x] = "wn"; break; case 2: case 5: gCurBoard[y][x] = "wb"; break; case 3: gCurBoard[y][x] = "wq"; break; case 4: gCurBoard[y][x] = "wk"; break; } break; default: gCurBoard[y][x] = "t"; break; } } } } function goBeginningChessBoard() { resetBoard(); reDrawBoard(); } function goEndChessBoard() { } function goForwardChessBoard() { if (gStopped == true) return; if (gCurMove == 0 || gCurSide == 'black') { gCurMove++; gCurSide = 'white'; } else { gCurSide = 'black'; } if (gCurSide == 'white') gCurBoard = gBoardStates[gCurMove-1].white; else gCurBoard = gBoardStates[gCurMove-1].black; // gCurBoard = pgnToInternalRepresentation(gCurBoard, gCurSide, gChessBoard.moves[gCurMove][gCurSide]); if (gCurBoard != false && gStopped != true) reDrawBoard(); } function goBackChessBoard() { if (gCurMove == 0 || gCurMove == 1) return; if (gCurSide == 'white') { gCurMove--; gCurSide = 'black'; } else { gCurSide = 'white'; } //alert(gChessBoard.moves[gCurMove][gCurSide]); // reDrawBoard(); } function buildMoves() { var lDiv = document.getElementById(gMovesDiv); if (lDiv == false) return; var lTable = document.createElement('table'); lTable.border = '1'; var lTr = document.createElement('tr'); var lTh = document.createElement('th'); lTh.innerHTML = 'Move #'; lTr.appendChild(lTh); lTh = document.createElement('th'); lTh.innerHTML = 'White'; lTr.appendChild(lTh); lTh = document.createElement('th'); lTh.innerHTML = 'Black'; lTr.appendChild(lTh); lTable.appendChild(lTr); for (var key in gChessBoard.moves) { lTr = document.createElement('tr'); var lTd = document.createElement('td'); lTd.innerHTML = key; lTr.appendChild(lTd); lTd = document.createElement('td'); lTd.innerHTML = gChessBoard.moves[key].white; lTr.appendChild(lTd); lTd = document.createElement('td'); lTd.innerHTML = gChessBoard.moves[key].black; lTr.appendChild(lTd); lTable.appendChild(lTr); } lDiv.appendChild(lTable); } function buildControls() { var lDiv = document.getElementById(gControlsDiv); if (lDiv == false) return; var lInput = document.createElement('input'); lInput.type = 'button'; lInput.onclick = goBeginningChessBoard; lInput.value = '<<'; lDiv.appendChild(lInput); lInput = document.createElement('input'); lInput.type = 'button'; lInput.onclick = goBackChessBoard; lInput.value = '<'; lDiv.appendChild(lInput); lInput = document.createElement('input'); lInput.type = 'button'; lInput.onclick = goForwardChessBoard; lInput.value = '>'; lDiv.appendChild(lInput); lInput = document.createElement('input'); lInput.type = 'button'; lInput.onclick = goEndChessBoard; lInput.value = '>>'; lDiv.appendChild(lInput); } function buildAttributes() { var lDiv = document.getElementById(gAttributesDiv); if (lDiv == false) return; var lTable = document.createElement('table'); lTable.border = '1'; for (var key in gChessBoard.attributes) { var lTr = document.createElement('tr'); var lTd = document.createElement('th'); lTd.innerHTML = key + ':'; lTr.appendChild(lTd); lTd = document.createElement('td'); lTd.innerHTML = gChessBoard.attributes[key]; lTr.appendChild(lTd); lTable.appendChild(lTr); } lDiv.appendChild(lTable); } function doJavascriptCheck() { var lDiv = document.getElementById(gJavascriptCheckDiv); if (lDiv == false) return; lDiv.innerHTML = ''; } function startItUp() { resetBoard(); doJavascriptCheck(); drawBoard(); buildAttributes(); buildControls(); buildMoves(); prepareBoardStates(); resetBoard(); gStopped = false; } function reDrawBoard() { var lDiv = document.getElementById(gBoardDiv); if (lDiv == false) return; for (var j = 0; j < 8; j++) { for (var i = 0; i < 8; i++) { gCurBoardTable[j][i].src = gImagePath + gCurBoard[j][i] + '.gif'; } } } function drawBoard() { //SetImagePath("alpha30/");//use this function when your images are in another directory var lDiv = document.getElementById(gBoardDiv); if (lDiv == false) return; var lTable = document.createElement('table'); lTable.cellPadding = '1'; lTable.cellSpacing = '0'; gCurBoardTable = new Array(8); for (var j = 0; j < 8; j++) { gCurBoardTable[j] = new Array(8); var lTr = document.createElement('tr'); for (var i = 0; i < 8; i++) { var lTd = document.createElement('td'); //lTd.style.backgroundColor = (((i % 2 == 1) ^ (j % 2 == 1)) ? "white" : "black"); lTd.style.backgroundImage= "url('" + gImagePath + (((i % 2 == 1) ^ (j % 2 == 1)) ? "w" : "b") + '.gif' + "')"; var lSquare = document.createElement('img'); lSquare.src = gImagePath + gCurBoard[j][i] + '.gif'; lSquare.id = (8*j)+i; gCurBoardTable[j][i] = lSquare; lTd.appendChild(lSquare); lTr.appendChild(lTd); } if (gDisplayRankFile == true) { lTd = document.createElement('td'); lTd.style.textAlign = 'center'; lTd.innerHTML = externalFileNotation(j); lTr.appendChild(lTd); } lTable.appendChild(lTr); } // Append an extra tr with tds with rank a-h if (gDisplayRankFile == true) { lTr = document.createElement('tr'); for (i = 0; i < 8; i++) { lTd = document.createElement('td'); lTd.style.textAlign = 'center'; lTd.innerHTML = externalRankNotation(i); lTr.appendChild(lTd); } lTd = document.createElement('td'); lTd.style.textAlign = 'center'; lTd.innerHTML = '#'; lTr.appendChild(lTd); lTable.appendChild(lTr); } lDiv.appendChild(lTable); }