-//progcomp.ucc.asn.au/cgi-bin/qchess.cgi?r=start\r
-//progcomp.ucc.asn.au/cgi-bin/qchess.cgi?r=quit\r
-//progcomp.ucc.asn.au/cgi-bin/qchess.cgi?x=X&y=Y (0 indexed)\r
+/**\r
+ * qwebchess.js\r
+ * jQuery interface for Quantum Chess\r
+ *\r
+ * @authors Sam Moore and Mitch Pomery\r
+ */\r
\r
pieceSelected = ""; // currently selected piece\r
-piece = "";\r
-colour = "W"; // colour of this player\r
-canClick = true;\r
+playerColour = "W"; // colour of this player\r
\r
// Unicode representations of chess pieces\r
pieceChar = {"W" : { "p" : "\u2659", "h" : "\u2658", "b" : "\u2657", "r" : "\u2656", "q" : "\u2655", "k" : "\u2654", "?" : "?"},\r
\r
emptyHTML = "<!--0--> <big> <bold> </bold> </big> "\r
\r
-// Select (or move) a piece\r
-function selectPiece(loc) {\r
- if (!canClick)\r
- return;\r
-\r
- x = (""+loc).charAt(1);\r
- y = (""+loc).charAt(0);\r
- //alert(loc);\r
+gameStarted = false;\r
+canClick = true;\r
\r
- // work out whether to select or move based on the comment tag for the clicked location\r
- // It is either "<!--W-->" (white; select) or <!--B-->" (black) or "<!--0-->" (empty)\r
- if (pieceSelected == "") \r
+// jQuery foo goes in here\r
+$(document).ready(function()\r
+{\r
+ // Click the start/quit button\r
+ $("#start").click(function() \r
{\r
- square = document.getElementById(loc);\r
- if (square.innerHTML.charAt(4) == colour) \r
+ if (gameStarted === false)\r
{\r
- console.log("Piece Selected: " + loc);\r
- pieceSelected = loc;\r
- ajaxUpdate("x=" + x + "&y=" + y);\r
- if ((+x + +y) % 2 == 0)\r
- square.style.background = "#DFD";\r
- else\r
- square.style.background = "#8F8";\r
- }\r
- }\r
- else {\r
- //alert("pieceMoved");\r
- if (validMove(pieceSelected, piece, loc)) {\r
- doMove(pieceSelected, loc);\r
- ajaxUpdate("x=" + x + "&y=" + y);\r
+ gameStarted = true;\r
+ $("#board").boardLoad();\r
+ $("#welcome").hide();\r
+ $("#status").show();\r
+ $("#status").html("white SELECT?");\r
+ $("#start").html("Quit Game");\r
pieceSelected = "";\r
+ canClick = true;\r
+ $.ajax({url : "/cgi-bin/qchess.cgi", data : {r : "force_quit"}, success : function() {}});\r
+ $.ajax({url : "/cgi-bin/qchess.cgi", data : {r : "start"}}).done(function(data) {$(this).update(data)});\r
+ \r
+ \r
}\r
- else {\r
- console.log("Invalid Move");\r
+ else\r
+ {\r
+ gameStarted = false;\r
+ $("#welcome").show();\r
+ $("#status").html("Game over");\r
+ $("#start").html("New Game");\r
+ $.ajax({url : "/cgi-bin/qchess.cgi", data : {r : "quit"}, success : function() {console.log("Quit game");}});\r
}\r
- }\r
-}\r
+ });\r
\r
-function resetColour(loc)\r
-{\r
- square = document.getElementById(loc);\r
- if ((+loc[loc.length-1] + +loc[loc.length-2]) % 2 == 0)\r
- square.style.background = "#FFF";\r
- else\r
- square.style.background = "#DDD";\r
+ // bind click event to table cells\r
+ $("#board").on('click', 'td' , function(e)\r
+ {\r
+ if (canClick === false)\r
+ return;\r
+ \r
+ var id = $(this).attr("id"); \r
+ legal = true;\r
+ if (pieceSelected === "")\r
+ {\r
+ if ($(this).legalSelection())\r
+ {\r
+ pieceSelected = id;\r
+ $(this).setSquareColour("blue");\r
+ }\r
+ else\r
+ {\r
+ legal = false;\r
+ alert("Illegal selection " + id);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mover = $("#board").find("#"+pieceSelected);\r
+ if (mover.legalMove($(this)))\r
+ {\r
+ $("#status").html(colourString(otherColour(mover.getColour())) + " SELECT?");\r
+ mover.move($(this));\r
+ pieceSelected = "";\r
+ $("#board td").each(function() {$(this).setSquareColour("default");});\r
+ }\r
+ else\r
+ {\r
+ legal = false;\r
+ alert("Illegal move " + id);\r
+ }\r
+ }\r
\r
-}\r
+ if (legal)\r
+ $.ajax({url : "/cgi-bin/qchess.cgi", data : {x : id[0], y : id[1]}}).done(function(data) {$(this).update(data)});\r
+ });\r
\r
-function validMove(start, piece, end) {\r
- return true;\r
-}\r
-\r
-function doMove(start, end) {\r
- alert("doMove("+start+","+end+")");\r
- s1 = document.getElementById(start);\r
- s2 = document.getElementById(end);\r
- s2.innerHTML = s1.innerHTML;\r
- s1.innerHTML = emptyHTML;\r
+ $.fn.showMoves = function()\r
+ {\r
+ $(this).setSquareColour("green");\r
+ var that = $(this); //Look [DJA]! I used it!\r
+ $("#board td").each(function()\r
+ {\r
+ if (that.legalMove($(this)) === true) // See?\r
+ {\r
+ //alert("Legal move from " + that.attr("id") + " -> " + $(this).attr("id"));\r
+ $(this).setSquareColour("red");\r
+ }\r
+ });\r
+ \r
+ }\r
\r
- resetColour(start);\r
+ // Get colour of occupied square\r
+ // W - white\r
+ // B - black\r
+ // 0 - unoccupied\r
+ $.fn.getColour = function()\r
+ {\r
+ return $(this).html()[4]; // yeah, I know this is horrible, so sue me\r
+ }\r
\r
- if ((+end[end.length-1] + +end[end.length-2]) % 2 == 1)\r
+ // Get type of piece\r
+ $.fn.getType = function()\r
{\r
- s2.innerHTML = s2.innerHTML.replace(/<bold>.*<\/bold>/i, "<bold>?</bold>");\r
+ return $(this).html().match(/<bold>(.*)<\/bold>/)[1]; // again, I know it's horrible, so sue me\r
}\r
- //console.log("Piece Moved");\r
-}\r
\r
-function boardLoad() {\r
- ajaxUpdate("r=force_quit");\r
- \r
+ // Get coords\r
+ $.fn.getX = function() {return Number($(this).attr("id")[0]);}\r
+ $.fn.getY = function() {return Number($(this).attr("id")[1]);}\r
\r
- \r
- for (i = 0; i < 8; i++) {\r
- for (j = 0; j < 8; j++) {\r
- e = ""+i + "" + j;\r
- resetColour(e);\r
- }\r
+ // Check a square is a valid selection\r
+ $.fn.legalSelection = function()\r
+ {\r
+ return ($(this).getColour() == playerColour);\r
}\r
- \r
- //Place pieces on the board\r
- for (i = 0; i < 8; i++) {\r
- black = document.getElementById("1" + i);\r
- white = document.getElementById("6" + i);\r
- //pawns\r
- black.innerHTML = "<!--B--> " + pieceChar["B"]["p"] + " <big> <bold>?</bold> </big> ?";\r
- white.innerHTML = "<!--W--> " + pieceChar["W"]["p"] + " <big> <bold>?</bold> </big> ?";\r
- \r
- black = document.getElementById("0" + i);\r
- white = document.getElementById("7" + i);\r
- piece = "p";\r
- if (i == 0 || i == 7)\r
- piece = "r";\r
- if (i == 1 || i == 6)\r
- piece = "h";\r
- if (i == 2 || i == 5)\r
- piece = "b";\r
- if (i == 3)\r
- piece = "k";\r
- if (i == 4)\r
- piece = "q";\r
- //major pieces\r
- black.innerHTML = "<!--B--> " + pieceChar["B"][piece] + "<big> <bold>?</bold> </big> ?";\r
- white.innerHTML = "<!--W--> " + pieceChar["W"][piece] + "<big> <bold>?</bold> </big> ?";\r
\r
- // empty squares\r
- for (j = 2; j < 6; j++)\r
+ // determine whether a piece can move into another square\r
+ $.fn.legalMove = function(target)\r
+ {\r
+ if (target.getColour() == $(this).getColour())\r
+ return false;\r
+ if (target.getX() == $(this).getX() && target.getY() == $(this).getY())\r
+ return false;\r
+ switch ($(this).getType())\r
{\r
- square = document.getElementById(""+j + i);\r
- square.innerHTML = emptyHTML;\r
- }\r
- }\r
- \r
- setTimeout(function(){ajaxUpdate("r=start");}, 1000);\r
-}\r
+ case pieceChar["W"]['p']:\r
+ if ($(this).getY() == 6 && target.getY() == 4 && $(this).getX() == target.getX() && target.getColour() == '0')\r
+ return true;\r
+ if ($(this).getY() - target.getY() != 1 || Math.abs($(this).getX() - target.getX()) > 1)\r
+ return false;\r
+ return ($(this).getX() == target.getX() || target.getColour() != '0');\r
+\r
+ case pieceChar["B"]['p']:\r
+ if ($(this).getY() == 1 && target.getY() == 3 && $(this).getX() == target.getX())\r
+ return true;\r
+ if ($(this).getY() - target.getY() != -1 || Math.abs($(this).getX() - target.getX()) > 1)\r
+ return false;\r
+ return ($(this).getX() == target.getX() || target.getColour() != '0');\r
\r
-//AJAX Stuff\r
-function ajaxUpdate(queryString) {\r
- var ajaxRequest; // The variable that makes Ajax possible!\r
+ case pieceChar["W"]['h']:\r
+ case pieceChar["B"]['h']:\r
+ return ((Math.abs($(this).getY() - target.getY()) == 2 && Math.abs($(this).getX() - target.getX()) == 1)\r
+ || (Math.abs($(this).getX() - target.getX()) == 2 && Math.abs($(this).getY() - target.getY()) == 1));\r
\r
- try {\r
- // Opera 8.0+, Firefox, Safari\r
- ajaxRequest = new XMLHttpRequest();\r
- } catch (e) {\r
- // Internet Explorer Browsers\r
- try {\r
- ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");\r
- } catch (e) {\r
- try {\r
- ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");\r
- } catch (e) {\r
- // Something went wrong\r
- alert("Your Browser is not Ajax Compatible, Please Upgrade to Google Chrome.");\r
+ case pieceChar["W"]['k']:\r
+ case pieceChar["B"]['k']:\r
+ return (Math.abs($(this).getX() - target.getX()) <= 1 && Math.abs($(this).getY() - target.getY()) <= 1);\r
+ case pieceChar["W"]['b']:\r
+ case pieceChar["B"]['b']:\r
+ //console.log("" + Math.abs($(this).getX() - target.getX()) + " vs " + Math.abs($(this).getY() - target.getY()));\r
+ if (Math.abs($(this).getX() - target.getX()) != Math.abs($(this).getY() - target.getY()))\r
+ return false;\r
+ break;\r
+ case pieceChar["W"]['r']:\r
+ case pieceChar["B"]['r']:\r
+ //console.log("" + Math.abs($(this).getX() - target.getX()) + " vs " + Math.abs($(this).getY() - target.getY()));\r
+ console.log("Rook");\r
+ if (Math.abs($(this).getX() - target.getX()) != 0 && Math.abs($(this).getY() - target.getY()) != 0)\r
+ return false;\r
+ break;\r
+ case pieceChar["W"]['q']:\r
+ case pieceChar["B"]['q']:\r
+ //console.log("" + Math.abs($(this).getX() - target.getX()) + " vs " + Math.abs($(this).getY() - target.getY()));\r
+ if (Math.abs($(this).getX() - target.getX()) != Math.abs($(this).getY() - target.getY()))\r
+ {\r
+ if (Math.abs($(this).getX() - target.getX()) != 0 && Math.abs($(this).getY() - target.getY()) != 0)\r
+ return false;\r
+ }\r
+ break;\r
+ default:\r
return false;\r
- }\r
}\r
+ console.log("scanning");\r
+ var vx = ($(this).getX() == target.getX()) ? 0 : (($(this).getX() < target.getX()) ? 1 : -1);\r
+ var vy = ($(this).getY() == target.getY()) ? 0 : (($(this).getY() < target.getY()) ? 1 : -1);\r
+ var x = $(this).getX() + vx; var y = $(this).getY() + vy;\r
+ while ((x != target.getX() || y != target.getY()) && x >= 0 && y >= 0 && x < 8 && y < 8)\r
+ {\r
+ var c = $("#"+x+""+y).getColour();\r
+ if (c === "W" || c === "B")\r
+ {\r
+ console.log("Blocked at "+x+""+y);\r
+ return false;\r
+ }\r
+ else\r
+ console.log("Scan ok at "+x+""+y);\r
+ x += vx;\r
+ y += vy; \r
+ } \r
+ return true;\r
}\r
- \r
- //alert(queryString);\r
- \r
- // Create a function that will receive data sent from the server\r
- ajaxRequest.onreadystatechange = function () \r
+\r
+ // Move square to another\r
+ $.fn.move = function(dest)\r
{\r
- //alert("RS" + ajaxRequest.readyState);\r
- if (ajaxRequest.readyState == 4) {\r
- console.log("AJAX Response: " + ajaxRequest.responseText);\r
- lines = ajaxRequest.responseText.split("\n");\r
+ dest.html($(this).html());\r
+ $(this).html(emptyHTML);\r
\r
- for (var i = 0; i < lines.length; ++i)\r
- {\r
- tokens = lines[i].split(" ")\r
- x = Number(tokens[0]);\r
+ // Collapse into quantum state if on a black square\r
+ if ((dest.getX() + dest.getY()) % 2 != 0 && (dest.html()[0] == '?' || dest.html()[dest.html().length-1] == '?'))\r
+ {\r
+ oldHTML = dest.html();\r
+ dest.html(oldHTML.replace(/<bold>.*<\/bold>/i, "<bold>?</bold>"));\r
+ }\r
+ }\r
\r
- if (isNaN(tokens[0]) || isNaN(tokens[1]))\r
- continue;\r
+ // Interpret AJAX response\r
+ $.fn.update = function(data)\r
+ {\r
+ console.log("AJAX Response:\n"+data);\r
+ var lines = data.split("\n");\r
+ for (var i = 0; i < lines.length; ++i)\r
+ {\r
+ var tokens = lines[i].split(" ");\r
\r
- var s1 = document.getElementById("" + tokens[1] + "" + tokens[0]);\r
- var s2 = document.getElementById("" + tokens[4] + "" + tokens[3]);\r
- if (tokens[2] == "->" && s1.innerHTML.charAt(4) != '0')\r
+ if (!isNaN(tokens[0]) && !isNaN(tokens[1]))\r
+ {\r
+ s1 = $("#board").find("#"+tokens[0]+tokens[1])\r
+ if (tokens[2] === "->")\r
{\r
- canClick = false;\r
- if ((+tokens[0] + +tokens[1]) % 2 == 0)\r
- s1.style.background = "#DFD";\r
- else\r
- s1.style.background = "#8F8";\r
-\r
- var doThisMove = function(start, end) {doMove(start, end); canClick = true;}(""+tokens[1]+""+tokens[0], ""+tokens[4]+""+tokens[3]);\r
- setTimeout(function() {doThisMove(); canClick = true;}, 500);\r
+ if (s1.html()[4] != '0')\r
+ {\r
+ s2 = $("#board").find("#"+tokens[3]+tokens[4]);\r
+ canClick = false;\r
+ setTimeout((function(x) \r
+ {\r
+ return function() \r
+ {\r
+ s1.move(x);\r
+ $("#board td").each(function() {$(this).setSquareColour("default");});\r
+ x.setSquareColour("blue");\r
+ setTimeout((function(xx) \r
+ {\r
+ return function() \r
+ {\r
+ xx.setSquareColour("default"); canClick = true;\r
+ $("#status").html(colourString(playerColour) + " SELECT?");\r
+ };\r
+ }(x)), 500);\r
+ };\r
+ }(s2)), 500);\r
+ }\r
}\r
- else if (tokens.length == 4 && !isNaN(tokens[0]) && !isNaN(tokens[1]) && !isNaN(tokens[2]) && isNaN(tokens[3]))\r
+ else if (tokens.length === 4 && !isNaN(tokens[2]) && isNaN(tokens[3]))\r
{\r
- html = s1.innerHTML;\r
- c = html.charAt(4);\r
- piece = tokens[3];\r
- if (piece == "knight") //HACK\r
- piece = "h"; \r
- else\r
- piece = ""+piece.charAt(0);\r
+ var t = "h";\r
+ if (tokens[3] != "knight")\r
+ t = tokens[3][0];\r
+ \r
+ var oldHTML = s1.html();\r
+ var c = s1.getColour();\r
if (tokens[2] == "1")\r
- html[html.length-1] = pieceChar[c][piece];\r
-\r
- s1.innerHTML = html.replace(/<bold>.*<\/bold>/i, "<bold>"+pieceChar[c][piece]+"</bold>"); \r
- }\r
- }\r
-\r
- /*\r
- if (ret.charAt(4) == "-" && ret.charAt(5) == ">") {\r
- //Piece has been moved\r
- //console.log("Moving other piece");\r
- lines = ret.split("\n");\r
- //if (lines[3] != "SELECT?") {\r
- if (lines[2] != "SELECT?") {\r
- x1 = lines[2].charAt(0);\r
- y1 = lines[2].charAt(2);\r
- x2 = lines[2].charAt(7);\r
- y2 = lines[2].charAt(9);\r
- console.log("Black Move: " + x1 + "" + y1 + " -> " + x2 + "" + y2);\r
- doMove(y1 + "" + x1, y2 + "" + x2);\r
- }\r
- else {\r
- console.log("Black Unable to move");\r
- }\r
- }\r
- else {\r
- lines = ret.split("\n");\r
- if (lines[1] == "MOVE?") {\r
- //We selected a piece\r
- //console.log("choose where to move our piece");\r
- piece = lines[0].charAt(6);\r
- //console.log("Piece: " + piece);\r
- content = document.getElementById(pieceSelected);\r
- contentHTML = content.innerHTML;\r
- //contentHTML = contentHTML.replace("?", piece);\r
- //"W<br /><small>p</small> <bold>?</bold> <small>?</small></span>";\r
- if (lines[0].charAt(4) == "1") {\r
- //console.log("changing quantum piece");\r
- contentHTML = replaceAt(contentHTML, 44, piece);\r
+ {\r
+ oldHTML = oldHTML.substring(0, oldHTML.length-1)+pieceChar[c][t];\r
}\r
- contentHTML = replaceAt(contentHTML, 28, piece);\r
- //console.log(contentHTML);\r
- //contentHTML = "CHANGED" + contentHTML;\r
- content.innerHTML = contentHTML;\r
+ s1.html(oldHTML.replace(/<bold>.*<\/bold>/i, "<bold>"+pieceChar[c][t]+"</bold>"));\r
+ //console.log(oldHTML + " ==> " + s1.html());\r
+ s1.setSquareColour("green");\r
+ s1.showMoves();\r
+ $("#status").html(colourString(s1.getColour()) + " MOVE?");\r
+ \r
}\r
}\r
- */\r
- //alert(ret);\r
+ else switch (lines[i])\r
+ {\r
+ case "SELECT?":\r
+ pieceSelected = "";\r
+ case "MOVE?":\r
+ case "":\r
+ case "New game.":\r
+ break;\r
+ default:\r
+ alert("Game ends: " + lines[i]);\r
+ gameStarted = false;\r
+ $("#start").html("New Game");\r
+ $("#status").html("Game over");\r
+ //$("#board").html("");\r
+ \r
+ \r
+ break;\r
+ }\r
}\r
}\r
- \r
- //ar = "http://progcomp.ucc.asn.au/cgi-bin/qchess.cgi?" + queryString;\r
- ar = "/../../../cgi-bin/qchess.cgi?" + queryString;\r
- \r
- console.log("AJAX Request: " + ar);\r
- \r
- ajaxRequest.open("GET", ar, true);\r
- ajaxRequest.send();\r
-}\r
\r
+ //Reset the colour of a square\r
+ $.fn.setSquareColour = function(type)\r
+ {\r
+ var colour = "000000";\r
+ switch (type)\r
+ {\r
+ case "blue":\r
+ colour = "5555aa";\r
+ break;\r
+ case "green":\r
+ colour = "55aa55";\r
+ break;\r
+ case "red":\r
+ colour = "aa5555";\r
+ break;\r
+ default:\r
+ colour = "aaaaaa";\r
+ break;\r
+ }\r
+\r
+ id = $(this).attr("id");\r
+ if ((Number(id[0]) + Number(id[1])) % 2 == 0)\r
+ { \r
+ colour = addHexColour(colour, "555555");\r
+ }\r
+ $(this).css("background-color", "#"+colour);\r
+ }\r
+\r
+ // Loads the board\r
+ $.fn.boardLoad = function()\r
+ {\r
+ boardHTML = "";\r
+ for (var y = 0; y < 8; ++y)\r
+ {\r
+ boardHTML += "<tr id=\"y"+y+"\">";\r
+ for (var x = 0; x < 8; ++x)\r
+ {\r
+ boardHTML += "<td id=\""+x+""+y+"\">"+emptyHTML+"</td>";\r
+ }\r
+ boardHTML += "</tr>";\r
+ }\r
+ $(this).html(boardHTML);\r
+\r
+ $(this).find("td").each(function()\r
+ {\r
+ $(this).setSquareColour("default");\r
+ });\r
\r
+ // Add pieces\r
+ for (var x = 0; x < 8; ++x)\r
+ {\r
+ // pawns\r
+ $(this).find("#"+x+"1").html("<!--B--> "+pieceChar["B"]["p"]+"<big> <bold>?</bold> </big> ?");\r
+ $(this).find("#"+x+"6").html("<!--W--> "+pieceChar["W"]["p"]+"<big> <bold>?</bold> </big> ?");\r
+ \r
+ t = "?";\r
+ switch (x)\r
+ {\r
+ case 0:\r
+ case 7:\r
+ t = 'r';\r
+ break;\r
+ case 1:\r
+ case 6:\r
+ t = 'h';\r
+ break;\r
+ case 2:\r
+ case 5:\r
+ t = 'b';\r
+ break;\r
+ case 4:\r
+ t = 'q';\r
+ break;\r
+ }\r
+ if (x == 3)\r
+ continue;\r
+ $(this).find("#"+x+"0").html("<!--B--> "+pieceChar["B"][t]+"<big> <bold>?</bold> </big> ?");\r
+ $(this).find("#"+x+"7").html("<!--W--> "+pieceChar["W"][t]+"<big> <bold>?</bold> </big> ?");\r
+ }\r
+ t = pieceChar["B"]["k"];\r
+ $(this).find("#30").html("<!--B--> "+t+"<big> <bold>"+t+"</bold> </big> "+t);\r
+ t = pieceChar["W"]["k"];\r
+ $(this).find("#37").html("<!--W--> "+t+"<big> <bold>"+t+"</bold> </big> "+t);\r
+ \r
+ }\r
\r
+});\r
\r
\r
+// Add two hex colours\r
+function addHexColour(c1, c2) \r
+{\r
+ var hexStr = (parseInt(c1, 16) + parseInt(c2, 16)).toString(16);\r
+ while (hexStr.length < 6) { hexStr = '0' + hexStr; } // Zero pad.\r
+ return hexStr;\r
+}\r
+\r
+function colourString(c)\r
+{\r
+ return (c == "W") ? "white" : "black";\r
+}\r
\r
-function replaceAt(s, n, t) {\r
- //console.log(s.substring(0, n) + "\n" + t + "\n" + s.substring(n + 1) + "\n");\r
- return (s.substring(0, n) + t + s.substring(n + 1));\r
+function otherColour(c)\r
+{\r
+ return (c == "W") ? "B" : "W";\r
}\r