add click-to-move feature

This commit is contained in:
Jesse D. McDonald 2020-03-22 12:58:29 -05:00
parent a96e8f1e4f
commit 4339ae2f01
3 changed files with 109 additions and 46 deletions

View File

@ -240,6 +240,11 @@ button:disabled .silhouette {
user-select: none; user-select: none;
} }
.cb-piece.cb-selected {
filter: drop-shadow(0 0 5px blue);
-webkit-filter: drop-shadow(0 0 5px blue);
}
#cb_board .cb-piece.ui-draggable { #cb_board .cb-piece.ui-draggable {
cursor: grab; cursor: grab;
} }

View File

@ -339,6 +339,14 @@ class Game {
return JSON.parse(JSON.stringify(this._redo)); return JSON.parse(JSON.stringify(this._redo));
} }
canCapture(side, from) {
if (from === PHANTOM) {
return true;
} else {
return this._board.getPiece(otherSide(side), from) === EMPTY;
}
}
legalMoves(side, from, canCapture) { legalMoves(side, from, canCapture) {
const board = this._board; const board = this._board;
const type = board.getPiece(side, from); const type = board.getPiece(side, from);
@ -347,6 +355,10 @@ class Game {
return []; return [];
} }
if (canCapture === undefined) {
canCapture = this.canCapture(side, from);
}
if (from === PHANTOM) { if (from === PHANTOM) {
/* this is valid because board.getPiece(side, PHANTOM) !== EMPTY */ /* this is valid because board.getPiece(side, PHANTOM) !== EMPTY */
from = board.phantom.from; from = board.phantom.from;

View File

@ -57,31 +57,76 @@ $(function (){
} }
} }
function pieceStartDrag(ev, ui) { function squareClickDestination(ev, ui) {
const dragged = $(this); let selected = $('#cb_board .cb-selected');
const side = dragged.data('side'); if (selected.length !== 1) {
const type = dragged.data('type'); renderBoard();
const from = dragged.data('location'); return;
const board = currentGame.board; }
const where = (from === PS.PHANTOM) ? board.phantom.from : from;
const canCapture = (from === PS.PHANTOM) || let from = selected.data('location');
board.getPiece(PS.Util.otherSide(side), where) === PS.EMPTY; let to = this.id.replace(/^cb_/, '');
const legals = currentGame.legalMoves(side, from, canCapture); selected.appendTo('#cb_hidden');
try {
const meta = { timestamp: new Date(Gun.state()).getTime() };
currentGame.move(from, to, meta);
} catch (err) {
debug('unable to move', err);
}
$('#cb_board').data('last_state', currentGame.moves);
setCurrentBoard(currentGame);
putState();
}
function pieceStartMove(piece, event) {
const side = piece.data('side');
const type = piece.data('type');
const from = piece.data('location');
const legals = currentGame.legalMoves(side, from);
for (const there of legals) { for (const there of legals) {
cbSquare(there).addClass('cb-legal').droppable('enable'); const square = cbSquare(there);
square.addClass('cb-legal')
if (event === 'drag') {
square.droppable('enable');
} else if (event === 'click') {
square.on('click.destination', squareClickDestination);
}
} }
} }
function pieceClickUnselect(ev, ui) {
renderBoard();
}
function pieceClickSelect(ev, ui) {
const clicked = $(this);
clicked.addClass('cb-selected');
$('#cb_board .cb-piece').off('click.select');
clicked.on('click.unselect', pieceClickUnselect);
pieceStartMove(clicked, 'click');
}
function pieceStartDrag(ev, ui) {
$('#cb_board .cb-selected').removeClass('cb-selected');
$('#cb_board .cb-square').off('click.destination');
pieceStartMove($(this), 'drag');
}
function pieceStopDrag(ev, ui) { function pieceStopDrag(ev, ui) {
$('#cb_board .cb-legal').removeClass('cb-legal').droppable('disable'); renderBoard();
} }
function placePiece(where, side, type, suffix) { function placePiece(where, side, type, suffix) {
const code = pieceCode(side, type); const code = pieceCode(side, type);
const piece_id = 'cb_piece_' + code + '_' + suffix; const piece_id = 'cb_piece_' + code + '_' + suffix;
const piece = $($('#' + piece_id)[0] || $('#cb_piece_' + code + ' img').clone()); const piece = $($('#' + piece_id)[0] || $('#cb_piece_' + code + ' img').clone());
piece.attr('style', '');
piece.attr('id', piece_id); piece.attr('id', piece_id);
piece.removeClass('cb-selected');
piece.removeAttr('style');
piece.off('click.select');
piece.off('click.unselect');
piece.data({ side: side, type: type, location: where }); piece.data({ side: side, type: type, location: where });
piece.appendTo(cbSquare(where)); piece.appendTo(cbSquare(where));
piece.draggable({ piece.draggable({
@ -96,8 +141,11 @@ $(function (){
} }
function renderBoard() { function renderBoard() {
$('#cb_board .cb-piece .ui-draggable').draggable('destroy'); $('#cb_board .cb-piece').off('click.select');
$('#cb_board .cb-piece').attr('style', '').appendTo('#cb_hidden'); $('#cb_board .cb-piece').off('click.unselect');
$('#cb_board .cb-square').off('click.destination');
$('#cb_board .cb-piece.cb-selected').removeClass('cb-selected');
$('#cb_board .cb-piece').removeAttr('style').appendTo('#cb_hidden');
$('#cb_board .cb-start').removeClass('cb-start'); $('#cb_board .cb-start').removeClass('cb-start');
$('#cb_board .cb-end').removeClass('cb-end'); $('#cb_board .cb-end').removeClass('cb-end');
$('#cb_board .cb-legal').removeClass('cb-legal'); $('#cb_board .cb-legal').removeClass('cb-legal');
@ -122,17 +170,6 @@ $(function (){
} }
} }
let clss = game.player === PS.LIGHT ? '.cb-lt-piece' : '.cb-dk-piece';
if (board.phantom) {
let where = board.phantom.from;
placePiece(PS.PHANTOM, board.phantom.side, board.phantom.type, 'ph');
cbSquare(PS.PHANTOM).appendTo(cbSquare(where));
$('#cb_phantom .ui-draggable-disabled').filter(clss).draggable('enable');
} else if (game.status === PS.PLAYING) {
$('#cb_board .ui-draggable-disabled').filter(clss).draggable('enable');
}
const lastMove = game.lastMove; const lastMove = game.lastMove;
if (lastMove) { if (lastMove) {
if (lastMove.from) { if (lastMove.from) {
@ -144,6 +181,26 @@ $(function (){
} }
} }
const liveView = !game.canRedo;
const playing = game.status === PS.PLAYING;
/* only enable selection / drag-and-drop in the live view */
if (liveView && playing) {
const phantom = board.phantom;
if (phantom) {
const piece = placePiece(PS.PHANTOM, phantom.side, phantom.type, 'ph');
cbSquare(PS.PHANTOM).appendTo(cbSquare(phantom.from));
piece.draggable('enable');
piece.addClass('cb-selected');
pieceStartMove(piece, 'click');
} else if (game.status === PS.PLAYING) {
const clss = game.player === PS.LIGHT ? '.cb-lt-piece' : '.cb-dk-piece';
const pieces = $('#cb_board ' + clss)
pieces.on('click.select', pieceClickSelect);
pieces.draggable('enable');
}
}
let msg = ''; let msg = '';
let winner = game.winner; let winner = game.winner;
if (winner) { if (winner) {
@ -151,7 +208,7 @@ $(function (){
msg += (lastMove.side === PS.LIGHT ? 'Light' : 'Dark') + ' player resigned. '; msg += (lastMove.side === PS.LIGHT ? 'Light' : 'Dark') + ' player resigned. ';
} }
msg += (winner === PS.LIGHT ? 'Light' : 'Dark') + ' player won!'; msg += (winner === PS.LIGHT ? 'Light' : 'Dark') + ' player won!';
} else if (game.status === PS.PLAYING) { } else if (playing) {
msg += (game.player === PS.LIGHT ? 'Light' : 'Dark') + ' player\'s turn.'; msg += (game.player === PS.LIGHT ? 'Light' : 'Dark') + ' player\'s turn.';
} else { } else {
msg += 'Game ended in a draw.'; msg += 'Game ended in a draw.';
@ -167,25 +224,14 @@ $(function (){
$('#cb_nav_next_turn').attr('disabled', !game.canRedo); $('#cb_nav_next_turn').attr('disabled', !game.canRedo);
$('#cb_nav_last').attr('disabled', !game.canRedo); $('#cb_nav_last').attr('disabled', !game.canRedo);
if (!game.canRedo) { $('#cb_undo').attr('disabled', !liveView || !currentGame.canUndo);
$('#cb_undo').attr('disabled', !currentGame.canUndo); $('#cb_redo').attr('disabled', !liveView || !currentGame.canRedo);
$('#cb_redo').attr('disabled', !currentGame.canRedo); $('#cb_resign').attr('disabled', !liveView || !playing);
if (currentGame.status === PS.PLAYING) {
$('#cb_pass').attr('disabled', currentGame.board.phantom ? true : false); if (liveView) {
} else { $('#cb_board').addClass('cb-live').removeClass('cb-archive');
$('#cb_pass').attr('disabled', true);
}
$('#cb_resign').attr('disabled', currentGame.status !== PS.PLAYING);
$('#cb_board').addClass('cb-live');
$('#cb_board').removeClass('cb-archive');
} else { } else {
$('#cb_undo').attr('disabled', true); $('#cb_board').removeClass('cb-live').addClass('cb-archive');
$('#cb_redo').attr('disabled', true);
$('#cb_pass').attr('disabled', true);
$('#cb_resign').attr('disabled', true);
$('#cb_board .ui-draggable').draggable('disable');
$('#cb_board').removeClass('cb-live');
$('#cb_board').addClass('cb-archive');
} }
} }
@ -714,7 +760,7 @@ $(function (){
} else if (move.resign) { } else if (move.resign) {
game.resign(); game.resign();
} else { } else {
throw { message: "unknown move", move: move }; throw { message: 'unknown move', move: move };
} }
} }