play.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. var $side = 'w';
  2. var $piece = null;
  3. var $chess = new Chess();
  4. function selectPiece(el) {
  5. el.addClass('selected');
  6. }
  7. function unselectPiece(el) {
  8. el.removeClass('selected');
  9. }
  10. function isSelected(el) {
  11. return el ? el.hasClass('selected') : false;
  12. }
  13. function movePiece(from, to, promotion, rcvd) {
  14. var move = $chess.move({
  15. 'from': from,
  16. 'to': to,
  17. promotion: promotion
  18. });
  19. if (move) {
  20. var tdFrom = $('td.' + from.toUpperCase());
  21. var tdTo = $('td.' + to.toUpperCase());
  22. //highlight moves
  23. if ($('td').hasClass('last-target')){
  24. $('td').removeClass('last-target last-origin');
  25. }
  26. tdFrom.addClass('last-origin');
  27. tdTo.addClass('last-target');
  28. var piece = tdFrom.find('a'); // find out what piece is being moved
  29. var moveSnd = $("#moveSnd")[0]; // sound file variable
  30. unselectPiece(piece.parent());
  31. tdTo.html(piece); // replace td attributes
  32. $piece = null;
  33. // en passant move
  34. if (move.flags === 'e'){
  35. var enpassant = move.to.charAt(0) + move.from.charAt(1);
  36. $('td.' + enpassant.toUpperCase()).html('');
  37. }
  38. //kingside castling
  39. var rook;
  40. if (move.flags === 'k'){
  41. if (move.to === 'g1'){
  42. rook = $('td.H1').find('a');
  43. $('td.F1').html(rook);
  44. }
  45. else if (move.to === 'g8'){
  46. rook = $('td.H8').find('a');
  47. $('td.F8').html(rook);
  48. }
  49. }
  50. //queenside castling
  51. if (move.flags === 'q'){
  52. if (move.to === 'c1'){
  53. rook = $('td.A1').find('a');
  54. $('td.D1').html(rook);
  55. }
  56. else if (move.to === 'c8'){
  57. rook = $('td.A8').find('a');
  58. $('td.D8').html(rook);
  59. }
  60. }
  61. //promotion
  62. if (move.flags === 'np' || move.flags === 'cp'){
  63. var square = $('td.' + move.to.toUpperCase()).find('a');
  64. var option = move.promotion;
  65. var promotion_w = {
  66. 'q': '♕',
  67. 'r': '♖',
  68. 'n': '♘',
  69. 'b': '♗'
  70. };
  71. var promotion_b = {
  72. 'q': '♛',
  73. 'r': '♜',
  74. 'n': '♞',
  75. 'b': '♝'
  76. };
  77. if (square.hasClass('white')){
  78. square.html(promotion_w[option]);
  79. } else {
  80. square.html(promotion_b[option]);
  81. }
  82. }
  83. if ($('#sounds').is(':checked')) {
  84. moveSnd.play();
  85. }
  86. //feedback
  87. var fm = $('.feedback-move');
  88. var fs = $('.feedback-status');
  89. $chess.turn() === 'b' ? fm.text('Black to move.') : fm.text('White to move.');
  90. fm.parent().toggleClass('blackfeedback whitefeedback');
  91. $chess.in_check() ? fs.text(' Check.') : fs.text('');
  92. //game over
  93. if ($chess.game_over()) {
  94. fm.text('');
  95. var result = "";
  96. if ($chess.in_checkmate())
  97. result = $chess.turn() === 'b' ? 'Checkmate. White wins!' : 'Checkmate. Black wins!'
  98. else if ($chess.in_draw())
  99. result = "Draw.";
  100. else if ($chess.in_stalemate())
  101. result = "Stalemate.";
  102. else if ($chess.in_threefold_repetition())
  103. result = "Draw. (Threefold Repetition)";
  104. else if ($chess.insufficient_material())
  105. result = "Draw. (Insufficient Material)";
  106. fs.text(result);
  107. $('.resign').hide();
  108. alert(result);
  109. }
  110. /* Add all moves to the table */
  111. var pgn = $chess.pgn({ max_width: 5, newline_char: ',' });
  112. var moves = pgn.split(',');
  113. var last_move = moves.pop().split('.');
  114. var move_number = last_move[0];
  115. var move_pgn = $.trim(last_move[1]);
  116. if (move_pgn.indexOf(' ') != -1) {
  117. var moves = move_pgn.split(' ');
  118. move_pgn = moves[1];
  119. }
  120. $('#moves tbody tr').append('<td><strong>' + move_number + '</strong>. ' + move_pgn + '</td>');
  121. if (rcvd === undefined) {
  122. $socket.emit('new-move', {
  123. 'token': $token,
  124. 'move': move
  125. });
  126. }
  127. }
  128. }
  129. /* socket.io */
  130. $(document).ready(function () {
  131. $socket.emit('join', {
  132. 'token': $token
  133. });
  134. $socket.on('joined', function (data) {
  135. if (data.color === 'white') {
  136. $side = 'w';
  137. $('.chess_board.black').remove();
  138. } else {
  139. $side = 'b';
  140. $('.chess_board.white').remove();
  141. $('.chess_board.black').show();
  142. }
  143. });
  144. $socket.on('move', function (data) {
  145. movePiece(from=data.move.from, to=data.move.to, promotion=data.move.promotion, rcvd=true);
  146. });
  147. $socket.on('opponent-disconnected', function (data) {
  148. alert("Your opponent has disconnected.");
  149. window.location = '/';
  150. });
  151. $socket.on('opponent-resigned', function (data) {
  152. alert("Your opponent has resigned. You won!");
  153. window.location = '/';
  154. });
  155. $socket.on('full', function (data) {
  156. alert("This game already has two players. You have to create a new one.");
  157. window.location = '/';
  158. });
  159. });
  160. /* gameplay */
  161. $(document).ready(function () {
  162. $('.chess_board a').click(function (e) {
  163. var piece = $(this);
  164. if ((piece.hasClass('white') && $side != 'w') ||
  165. (piece.hasClass('black') && $side != 'b')) {
  166. if ($piece) {
  167. movePiece(
  168. from=$piece.parent().data('id').toLowerCase(),
  169. to=$(this).parent().data('id').toLowerCase(),
  170. promotion=$('#promotion option:selected').val()
  171. )
  172. }
  173. } else {
  174. if ($chess.turn() != $side) {
  175. return false;
  176. }
  177. if ($piece && isSelected($(this).parent())) {
  178. unselectPiece($piece.parent());
  179. $piece = null;
  180. } else {
  181. if ($piece) {
  182. unselectPiece($piece.parent());
  183. $piece = null;
  184. }
  185. $piece = $(this);
  186. selectPiece($piece.parent());
  187. }
  188. }
  189. e.stopImmediatePropagation();
  190. e.preventDefault();
  191. });
  192. $('.chess_board td').click(function (e) {
  193. if ($piece) {
  194. movePiece(
  195. from=$piece.parent().data('id').toLowerCase(),
  196. to=$(this).data('id').toLowerCase(),
  197. promotion=$('#promotion option:selected').val()
  198. )
  199. }
  200. });
  201. $('.resign').click(function (e) {
  202. $socket.emit('resign');
  203. alert('You resigned.');
  204. window.location = '/';
  205. });
  206. });