add click-to-move feature
This commit is contained in:
parent
a96e8f1e4f
commit
4339ae2f01
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
$('#cb_board').addClass('cb-live').removeClass('cb-archive');
|
||||||
} else {
|
} else {
|
||||||
$('#cb_pass').attr('disabled', true);
|
$('#cb_board').removeClass('cb-live').addClass('cb-archive');
|
||||||
}
|
|
||||||
$('#cb_resign').attr('disabled', currentGame.status !== PS.PLAYING);
|
|
||||||
$('#cb_board').addClass('cb-live');
|
|
||||||
$('#cb_board').removeClass('cb-archive');
|
|
||||||
} else {
|
|
||||||
$('#cb_undo').attr('disabled', true);
|
|
||||||
$('#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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue