/**
Main module
@module Main
**/
/**
Main methods
This is not actually a class, but a necessary convention to get YUIdoc to document standalone items.
@class Main
*/
var board;
var promotionCoor;
var selectedPiece;
var game_id = 0;
var drawOffer = "none";
var userId;
var timerId;
var topClock = 0;
var bottomClock = 0;
/**
* Recursively calls ajax request to check for the start of the game
* @method reqGame
* @return {Object} ajax result
*/
function reqGame() {
return $.ajax({
url: "server.php?action=requestGame",
datatype: 'json'
}).then(function (result) {
if(result.data.game_id != null) {
board.setBoard(result.data);
board.drawPieces();
displayDrawOffer(result.data.draw_offer)
game_id = result.data.game_id;
setClock(result.data.white_clock, result.data.black_clock);
$('#pre-post-game').hide();
if(board.side != result.data.side_to_move) {
reqMove(result.data.game_id).done();
} else {
$('#buttons').fadeIn("fast");
}
$('#bottom-clock').show();
$('#top-clock').show();
return;
} else {
return reqGame();
}
});
}
/**
* Recursively calls ajax request to check for an opponent move
* @method reqGame
* @param {Number} game_id the id of the game
* @return {Object} ajax result
*/
function reqMove(game_id) {
return $.ajax({
url:"server.php?action=requestMove&game_id=" + game_id,
datatype: 'json',
}).then(function(result){
if(result.data.game_state != "in progress") {
finishGame(result.data.game_state, result.data.game_finished);
return;
}
if(board.side == result.data.side_to_move) {
if(result.data.draw_offer == "none") {
$('#buttons').fadeIn("fast");
}
setClock(result.data.white_clock, result.data.black_clock);
board.setBoard(result.data);
board.drawPieces();
displayDrawOffer(result.data.draw_offer);
requestHistory(game_id).then(function(res){
updateHistoryTable(res);
});
return;
} else {
return reqMove(game_id).done();
}
});
}
/**
* Sends ajax request to submit a move
* @method submitMove
* @param {Number} game_id the id of the game
* @param {String} fen Forsyth–Edwards notation of the current state of the chess game
* @param {String} move notation representation of the move
* @param {String} castling valid values are 'long', 'short' or 'none'
* @param {String} enpassant the notation coordinates of the pawn which can be taken en passant
* @param {Number} draw_moves number of moves to finish a game under 50 moves rule
* @param {String} wlc white long castling right, valid values 'true' and 'false'
* @param {String} wsc white short castling right, valid values 'true' and 'false'
* @param {String} blc black short castling right, valid values 'true' and 'false'
* @param {String} bsc black short castling right, valid values 'true' and 'false'
* @param {String} result the result of the game in case the game has finished, valid values are 'white', 'black or 'draw'
* @param {String} gameFinished the reason to finish the game
*/
function submitMove(game_id, fen, move, castling, enpassant, draw_moves, wlc, wsc, blc, bsc, result, gameFinished) {
$('#opponent-draw-offer').hide();
$('#cancel-a-draw').hide();
$('#offer-a-draw').show();
$('#buttons').fadeOut("fast");
return $.ajax({
url:"server.php?action=submitMove",
data: {
game_id :game_id,
fen :fen,
move :move,
castling :castling,
enpassant :enpassant,
draw_moves :draw_moves,
wlc :wlc,
wsc :wsc,
blc :blc,
bsc :bsc,
draw_offer :drawOffer,
result :result,
game_finished :gameFinished
}
}).then(function(res){
updateHistoryTable(res);
reqMove(game_id);
});
}
/**
* ajax request to retrieve game history
* @method requestHistory
* @param {Number} game_id the id of the game
* @return {Object} ajax result
*/
function requestHistory(game_id) {
return $.ajax({
url:"server.php?action=requestHistory&game_id="+game_id,
datatype: 'json',
}).promise();
}
/**
* ajax request to submit the result of the game
* @method submitResult
* @param {String} result the result of the game, valid values are 'black', 'white' or 'draw'
* @param {String} game_finished the reason to finish the game
* @return {Object} ajax result
*/
function submitResult(result, game_finished) {
return $.ajax({
url:"server.php?action=finishGame&game_id="+game_id+"&result="+result+"&game_finished="+game_finished,
datatype: 'json',
}).promise();
}
/**
* ajax request to connect to the server
* @method connect
* @return {Object} ajax result
*/
function connect() {
return $.ajax({
url:"server.php?action=connect",
datatype: 'json',
}).promise();
}
/**
* ajax request to stop the search for the game
* @method stopSearch
* @return {Object} ajax result
*/
function stopSearch() {
return $.ajax({
url:"server.php?action=stopSearch",
datatype: 'json'
}).promise();
}
/**
* renders the chess board in case of initial window load or window resize events
* @method render
*/
function render(){
var c = $('#chess-board');
c.attr('width', $(c).parent().width());
c.attr('height', $(c).parent().height());
var c2 = $('#chess-pieces');
c2.attr('width', $(c2).parent().width());
c2.attr('height', $(c2).parent().height());
var c3 = $('#legal-moves');
c3.attr('width', $(c3).parent().width());
c3.attr('height', $(c3).parent().height());
var c4 = $('#field-highlight');
c4.attr('width', $(c4).parent().width());
c4.attr('height', $(c4).parent().height());
var c5 = $('#promote-pawn');
c5.attr('width', $(c4).parent().width());
c5.attr('height', $(c4).parent().height());
board.drawBoard();
board.drawPieces();
}
/**
* document.load event
* @method load
*/
$(function() {
$(window).resize(render);
$('#field-highlight').mousemove(mousemove);
$('#field-highlight').mouseleave(mouseleave);
$('#field-highlight').click(click);
$('#promote-pawn').hide();
$('#promote-pawn').click(clickPromote);
$('#cancel-search').hide();
$('#play-again').hide();
$('#bottom-clock').hide();
$('#top-clock').hide();
$('#white-to-promote').hide();
$('#black-to-promote').hide();
$('#opponent-draw-offer').hide();
$('#buttons').hide();
$('#start-search-button').click(requestGame);
$('#cancel-search-button').click(cancelGame);
$('#play-again-button').click(playAgain);
$('#offer-a-draw').click(offerDrawClick);
$('#cancel-a-draw').click(cancelDrawClick);
$('#accept-a-draw').click(acceptDrawClick);
$('#resign').click(resignClick);
connect().done(function(res){
userId = res.data.user_id;
});
board = new Board();
render();
});
/**
* hides #play-again div, shows #cancel-search and requests for the game
* @method requestGame
*/
function requestGame() {
$('#play-again').hide();
$('#start-search').fadeOut('slow').promise().done(function(){
$('#cancel-search').fadeIn('slow');
});
reqGame().done();
}
/**
* hides #cancel-search div, shows #start-search and sends stop search request to the server
* @method cancelGame
*/
function cancelGame() {
$('#play-again').hide();
$('#cancel-search').fadeOut('slow').promise().done(function(){
$('#start-search').fadeIn('slow');
});
stopSearch().then(function(){});
}
/**
* hides #start-search div, shows #cancel-search and requests for the game
* @method playAgain
*/
function playAgain() {
$('#start-search').hide();
$('#play-again').fadeOut('slow').promise().done(function(){
$('#cancel-search').fadeIn('slow');
});
reqGame().done();
}
/**
* updates history table
* @param {Object} res data to be colected from the requestHistory ajax request
* @method updateHistoryTable
*/
function updateHistoryTable(res){
$("#target-to-update tr").remove();
for(var i = 0; i < res.data.length; i++) {
if((i)%2==0) {
if(i != res.data.length - 1) continue;
else {
var w = res.data[i].move;
$('#target-to-update tbody').append('<tr><td>'+((i/2)+1)+'</td><td>'+w+'</td><td></td></tr>');
break;
}
}
var w = res.data[i-1].move;
var b = res.data[i].move;
$('#target-to-update tbody').append('<tr><td>'+((i+1)/2)+'</td><td>'+w+'</td><td>'+b+'</td></tr>');
}
var h = 99999;
$('#table').slimScroll({ scrollTo : h });
}
/**
* display draw offer menu
* @param {String} offer offer side, valid values are 'white', 'black' or 'none'
* @method displayDrawOffer
*/
function displayDrawOffer(offer) {
$('#cancel-a-draw').fadeOut('fast').promise().done(function(){
$('#offer-a-draw').fadeIn('fast').css("display","inline-block");
});
if(offer == "none") {
$('#opponent-draw-offer').hide();
drawOffer = "none";
return;
}
if(offer != board.side) {
$('#buttons').fadeOut("fast");
$('#cancel-a-draw').fadeOut('fast');
$('#offer-a-draw').fadeOut('fast');
$('#opponent-draw-offer').fadeIn('fast');
}
}
/**
* displays the game result and prompts user to start new game
* @param {String} result result of the game, valid values are 'white', 'black' or 'draw'
* @param {String} message the reason to finish the game
* @method finishGame
*/
function finishGame(result, message) {
if(result == "white") {
$('#game-summary').html(message);
$('#game-result').html("1 - 0");
}
if(result == "black") {
$('#game-summary').html(message);
$('#game-result').html("0 - 1");
}
if(result == "draw") {
$('#game-summary').html(message);
$('#game-result').html("½ - ½");
}
$('#play-again').show();
$('#cancel-search').hide();
$('#pre-post-game').fadeIn();
$('#bottom-clock').hide();
$('#top-clock').hide();
clearInterval(timerId);
}
/**
* sets a clock
* @param {Number} wc white side clock
* @param {Number} bc black side clock
* @method setClock
*/
function setClock(wc,bc){
if(board.side == "white") {
topClock = bc;
bottomClock = wc;
} else {
topClock = wc;
bottomClock = bc;
}
clearInterval(timerId);
timerId = setInterval(function() {
if(board.sideToMove == board.side) {
bottomClock--;
} else {
topClock--;
}
if(bottomClock <= 0) {
if(board.side == "white") {
submitResult("black", "White lost on time");
finishGame("black", "White lost on time");
clearInterval(timerId);
} else {
submitResult("white", "Black lost on time");
finishGame("white", "Black lost on time");
clearInterval(timerId);
}
}
if(topClock <= 0) {
if(board.side == "white") {
submitResult("white", "Black lost on time");
finishGame("white", "Black lost on time");
clearInterval(timerId);
} else {
submitResult("black", "White lost on time");
finishGame("black", "White lost on time");
clearInterval(timerId);
}
}
$("#top-clock").text(unixTimeStampToTimerString(topClock));
$("#bottom-clock").text(unixTimeStampToTimerString(bottomClock));
},1000)
}