diff options
| author | Yann Granjon <[email protected]> | 2013-06-05 16:13:15 +0200 |
|---|---|---|
| committer | Yann Granjon <[email protected]> | 2013-06-05 16:13:15 +0200 |
| commit | 1ef133c52d12daf3fdad1d979e5a71cb39fa0d2e (patch) | |
| tree | 31e2cd5c6b0497f58762a63e3536dab76654324a /js/AI/boardui.js | |
| download | Chess3D-1ef133c52d12daf3fdad1d979e5a71cb39fa0d2e.tar.xz Chess3D-1ef133c52d12daf3fdad1d979e5a71cb39fa0d2e.zip | |
Initial Commit
Diffstat (limited to 'js/AI/boardui.js')
| -rw-r--r-- | js/AI/boardui.js | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/js/AI/boardui.js b/js/AI/boardui.js new file mode 100644 index 0000000..795958a --- /dev/null +++ b/js/AI/boardui.js @@ -0,0 +1,409 @@ +var g_startOffset = null; +var g_selectedPiece = null; +var moveNumber = 1; + +var g_allMoves = []; +var g_playerWhite = true; +var g_changingFen = false; +var g_analyzing = false; + +var g_uiBoard; +var g_cellSize = 45; + +function UINewGame() { + moveNumber = 1; + + var pgnTextBox = document.getElementById("PgnTextBox"); // + pgnTextBox.value = ""; + + EnsureAnalysisStopped(); // UI (terminate and destroy worker) + ResetGame(); // shouldn't work + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage("go"); + } + g_allMoves = []; + RedrawBoard(); //UI + + // if player is black play the first move + if (!g_playerWhite) { + SearchAndRedraw(); //UI + } +} + +function EnsureAnalysisStopped() { + if (g_analyzing && g_backgroundEngine != null) { + g_backgroundEngine.terminate(); + g_backgroundEngine = null; + } +} + +function UIAnalyzeToggle() { + if (InitializeBackgroundEngine()) { + if (!g_analyzing) { + g_backgroundEngine.postMessage("analyze"); + } else { + EnsureAnalysisStopped(); + } + g_analyzing = !g_analyzing; + document.getElementById("AnalysisToggleLink").innerText = g_analyzing ? "Analysis: On" : "Analysis: Off"; + } else { + alert("Your browser must support web workers for analysis - (chrome4, ff4, safari)"); + } +} + +function UIChangeFEN() { + if (!g_changingFen) { + var fenTextBox = document.getElementById("FenTextBox"); + var result = InitializeFromFen(fenTextBox.value); + if (result.length != 0) { + UpdatePVDisplay(result); + return; + } else { + UpdatePVDisplay(''); + } + g_allMoves = []; + + EnsureAnalysisStopped(); + InitializeBackgroundEngine(); + + g_playerWhite = !!g_toMove; + g_backgroundEngine.postMessage("position " + GetFen()); + + RedrawBoard(); + } +} + +function UIChangeStartPlayer() { + g_playerWhite = !g_playerWhite; + RedrawBoard(); +} + +function UpdatePgnTextBox(move) { + var pgnTextBox = document.getElementById("PgnTextBox"); + if (g_toMove != 0) { + pgnTextBox.value += moveNumber + ". "; + moveNumber++; + } + pgnTextBox.value += GetMoveSAN(move) + " "; +} + +function UIChangeTimePerMove() { + var timePerMove = document.getElementById("TimePerMove"); + g_timeout = parseInt(timePerMove.value, 10); +} + +function FinishMove(bestMove, value, timeTaken, ply) { + if (bestMove != null) { + UIPlayMove(bestMove, BuildPVMessage(bestMove, value, timeTaken, ply)); + } else { + alert("Checkmate!"); + } +} + +function UIPlayMove(move, pv) { + UpdatePgnTextBox(move); + + g_allMoves[g_allMoves.length] = move; + MakeMove(move); + + UpdatePVDisplay(pv); + + UpdateFromMove(move); +} + + +// buggy doesn't update the pgn properly +function UIUndoMove() { + if (g_allMoves.length == 0) { + return; + } + + if (g_backgroundEngine != null) { + g_backgroundEngine.terminate(); + g_backgroundEngine = null; + } + + UnmakeMove(g_allMoves[g_allMoves.length - 1]); + g_allMoves.pop(); + + if (g_playerWhite !== !!g_toMove && g_allMoves.length !== 0) { + UnmakeMove(g_allMoves[g_allMoves.length - 1]); + g_allMoves.pop(); + } + + RedrawBoard(); +} + +function UpdatePVDisplay(pv) { + if (pv != null) { + var outputDiv = document.getElementById("output"); + if (outputDiv.firstChild != null) { + outputDiv.removeChild(outputDiv.firstChild); + } + outputDiv.appendChild(document.createTextNode(pv)); + } +} + +function SearchAndRedraw() { + if (g_analyzing) { + EnsureAnalysisStopped(); + InitializeBackgroundEngine(); + g_backgroundEngine.postMessage("position " + GetFen()); + g_backgroundEngine.postMessage("analyze"); + return; + } + + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage("search " + g_timeout); + } else { + Search(FinishMove, 99, null); // unasynchronous version fall back + } +} + +var g_backgroundEngineValid = true; +var g_backgroundEngine; + +function InitializeBackgroundEngine() { + if (!g_backgroundEngineValid) { + return false; + } + + if (g_backgroundEngine == null) { + g_backgroundEngineValid = true; + try { + g_backgroundEngine = new Worker("js/garbochess.js"); + g_backgroundEngine.onmessage = function (e) { + if (e.data.match("^pv") == "pv") { + UpdatePVDisplay(e.data.substr(3, e.data.length - 3)); + } else if (e.data.match("^message") == "message") { + EnsureAnalysisStopped(); + UpdatePVDisplay(e.data.substr(8, e.data.length - 8)); + } else { + UIPlayMove(GetMoveFromString(e.data), null); + } + } + g_backgroundEngine.error = function (e) { + alert("Error from background worker:" + e.message); + } + g_backgroundEngine.postMessage("position " + GetFen()); + } catch (error) { + g_backgroundEngineValid = false; + } + } + + return g_backgroundEngineValid; +} + +function UpdateFromMove(move) { + var fromX = (move & 0xF) - 4; + var fromY = ((move >> 4) & 0xF) - 2; + var toX = ((move >> 8) & 0xF) - 4; + var toY = ((move >> 12) & 0xF) - 2; + + if (!g_playerWhite) { + fromY = 7 - fromY; + toY = 7 - toY; + fromX = 7 - fromX; + toX = 7 - toX; + } + + if ((move & moveflagCastleKing) || + (move & moveflagCastleQueen) || + (move & moveflagEPC) || + (move & moveflagPromotion)) { + // more than one piece was moved + // or one piece was modified + // -> entire redraw + RedrawPieces(); + } else { + // simply swap piece parents + var fromSquare = g_uiBoard[fromY * 8 + fromX]; + $(g_uiBoard[toY * 8 + toX]) + .empty() + .append($(fromSquare).children()); + } +} + +function RedrawPieces() { + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + var td = g_uiBoard[y * 8 + x]; + var pieceY = g_playerWhite ? y : 7 - y; + var piece = g_board[((pieceY + 2) * 0x10) + (g_playerWhite ? x : 7 - x) + 4]; + var pieceName = null; + switch (piece & 0x7) { + case piecePawn: pieceName = "pawn"; break; + case pieceKnight: pieceName = "knight"; break; + case pieceBishop: pieceName = "bishop"; break; + case pieceRook: pieceName = "rook"; break; + case pieceQueen: pieceName = "queen"; break; + case pieceKing: pieceName = "king"; break; + } + if (pieceName != null) { + pieceName += "_"; + pieceName += (piece & 0x8) ? "white" : "black"; + } + + if (pieceName != null) { + var img = document.createElement("div"); + $(img).addClass('sprite-' + pieceName); + img.style.backgroundImage = "url('img/sprites.png')"; + img.width = g_cellSize; + img.height = g_cellSize; + var divimg = document.createElement("div"); + divimg.appendChild(img); + + $(divimg).draggable({ start: function (e, ui) { + if (g_selectedPiece === null) { + g_selectedPiece = this; + var offset = $(this).closest('table').offset(); + g_startOffset = { + left: e.pageX - offset.left, + top: e.pageY - offset.top + }; + } else { + return g_selectedPiece == this; + } + }}); + + $(divimg).mousedown(function(e) { + if (g_selectedPiece === null) { + var offset = $(this).closest('table').offset(); + g_startOffset = { + left: e.pageX - offset.left, + top: e.pageY - offset.top + }; + e.stopPropagation(); + g_selectedPiece = this; + g_selectedPiece.style.backgroundImage = "url('img/transpBlue50.png')"; + } else if (g_selectedPiece === this) { + g_selectedPiece.style.backgroundImage = null; + g_selectedPiece = null; + } + }); + + $(td).empty().append(divimg); + } else { + $(td).empty(); + } + } + } +} + +function RedrawBoard() { + var div = $("#board")[0]; + + var table = document.createElement("table"); + table.cellPadding = "0px"; + table.cellSpacing = "0px"; + $(table).addClass('no-highlight'); + + var tbody = document.createElement("tbody"); + + g_uiBoard = []; + + var dropPiece = function (e, ui) { + // retrive start -> end move + var endX = e.pageX - $(table).offset().left; + var endY = e.pageY - $(table).offset().top; + + endX = Math.floor(endX / g_cellSize); + endY = Math.floor(endY / g_cellSize); + + var startX = Math.floor(g_startOffset.left / g_cellSize); + var startY = Math.floor(g_startOffset.top / g_cellSize); + + // convert coordinates to white-space + if (!g_playerWhite) { + startY = 7 - startY; + endY = 7 - endY; + startX = 7 - startX; + endX = 7 - endX; + } + + // gather all possible valid moves + var moves = GenerateValidMoves(); + var move = null; + // check if the move is valid + for (var i = 0; i < moves.length; i++) { + if ((moves[i] & 0xFF) == MakeSquare(startY, startX) && + ((moves[i] >> 8) & 0xFF) == MakeSquare(endY, endX)) { + move = moves[i]; + } + } + + // convert coordinates back to black-space + if (!g_playerWhite) { + startY = 7 - startY; + endY = 7 - endY; + startX = 7 - startX; + endX = 7 - endX; + } + + // put the html object back to its original position + // whether the move is valid or not + g_selectedPiece.style.left = 0; + g_selectedPiece.style.top = 0; + + if (!(startX == endX && startY == endY) && move != null) { + // if the move is valid + // we add the move to the png texbox + UpdatePgnTextBox(move); + + // we save the move in our worker + if (InitializeBackgroundEngine()) { + g_backgroundEngine.postMessage(FormatMove(move)); + } + + // we add the move to the move list + g_allMoves[g_allMoves.length] = move; + + // we apply the move + MakeMove(move); + + UpdateFromMove(move); + + // update the fen text box + var fen = GetFen(); + document.getElementById("FenTextBox").value = fen; + + setTimeout("SearchAndRedraw()", 0); + } + // whether the move is valid or not, we remove highlight and clear selection + g_selectedPiece.style.backgroundImage = null; + g_selectedPiece = null; + }; + + for (y = 0; y < 8; ++y) { + var tr = document.createElement("tr"); + + for (x = 0; x < 8; ++x) { + var td = document.createElement("td"); + td.style.width = g_cellSize + "px"; + td.style.height = g_cellSize + "px"; + td.style.backgroundColor = ((y ^ x) & 1) ? "#D18947" : "#FFCE9E"; + tr.appendChild(td); + g_uiBoard[y * 8 + x] = td; + } + + tbody.appendChild(tr); + } + + table.appendChild(tbody); + + $('body').droppable({ drop: dropPiece }); + $(table).mousedown(function(e) { + if (g_selectedPiece !== null) { + dropPiece(e); + } + }); + + RedrawPieces(); + + $(div).empty(); + div.appendChild(table); + + g_changingFen = true; + document.getElementById("FenTextBox").value = GetFen(); + g_changingFen = false; +} |
