shogiground
Version:
lishogi.org shogi ui
399 lines • 14.8 kB
JavaScript
import { callUserFunction, opposite, pieceNameOf, samePiece } from './util.js';
import { addToHand, removeFromHand } from './hands.js';
export function toggleOrientation(state) {
state.orientation = opposite(state.orientation);
state.animation.current =
state.draggable.current =
state.promotion.current =
state.hovered =
state.selected =
state.selectedPiece =
undefined;
}
export function reset(state) {
unselect(state);
unsetPremove(state);
unsetPredrop(state);
cancelPromotion(state);
state.animation.current = state.draggable.current = state.hovered = undefined;
}
export function setPieces(state, pieces) {
for (const [key, piece] of pieces) {
if (piece)
state.pieces.set(key, piece);
else
state.pieces.delete(key);
}
}
export function setChecks(state, checksValue) {
if (Array.isArray(checksValue)) {
state.checks = checksValue;
}
else {
if (checksValue === true)
checksValue = state.turnColor;
if (checksValue) {
const checks = [];
for (const [k, p] of state.pieces) {
if (state.highlight.checkRoles.includes(p.role) && p.color === checksValue)
checks.push(k);
}
state.checks = checks;
}
else
state.checks = undefined;
}
}
function setPremove(state, orig, dest, prom) {
unsetPredrop(state);
state.premovable.current = { orig, dest, prom };
callUserFunction(state.premovable.events.set, orig, dest, prom);
}
export function unsetPremove(state) {
if (state.premovable.current) {
state.premovable.current = undefined;
callUserFunction(state.premovable.events.unset);
}
}
function setPredrop(state, piece, key, prom) {
unsetPremove(state);
state.predroppable.current = { piece, key, prom };
callUserFunction(state.predroppable.events.set, piece, key, prom);
}
export function unsetPredrop(state) {
if (state.predroppable.current) {
state.predroppable.current = undefined;
callUserFunction(state.predroppable.events.unset);
}
}
export function baseMove(state, orig, dest, prom) {
const origPiece = state.pieces.get(orig), destPiece = state.pieces.get(dest);
if (orig === dest || !origPiece)
return false;
const captured = destPiece && destPiece.color !== origPiece.color ? destPiece : undefined, promPiece = prom && promotePiece(state, origPiece);
if (dest === state.selected || orig === state.selected)
unselect(state);
state.pieces.set(dest, promPiece || origPiece);
state.pieces.delete(orig);
state.lastDests = [orig, dest];
state.lastPiece = undefined;
state.checks = undefined;
callUserFunction(state.events.move, orig, dest, prom, captured);
callUserFunction(state.events.change);
return captured || true;
}
export function baseDrop(state, piece, key, prom) {
var _a;
const pieceCount = ((_a = state.hands.handMap.get(piece.color)) === null || _a === void 0 ? void 0 : _a.get(piece.role)) || 0;
if (!pieceCount && !state.droppable.spare)
return false;
const promPiece = prom && promotePiece(state, piece);
if (key === state.selected ||
(!state.droppable.spare &&
pieceCount === 1 &&
state.selectedPiece &&
samePiece(state.selectedPiece, piece)))
unselect(state);
state.pieces.set(key, promPiece || piece);
state.lastDests = [key];
state.lastPiece = piece;
state.checks = undefined;
if (!state.droppable.spare)
removeFromHand(state, piece);
callUserFunction(state.events.drop, piece, key, prom);
callUserFunction(state.events.change);
return true;
}
function baseUserMove(state, orig, dest, prom) {
const result = baseMove(state, orig, dest, prom);
if (result) {
state.movable.dests = undefined;
state.droppable.dests = undefined;
state.turnColor = opposite(state.turnColor);
state.animation.current = undefined;
}
return result;
}
function baseUserDrop(state, piece, key, prom) {
const result = baseDrop(state, piece, key, prom);
if (result) {
state.movable.dests = undefined;
state.droppable.dests = undefined;
state.turnColor = opposite(state.turnColor);
state.animation.current = undefined;
}
return result;
}
export function userDrop(state, piece, key, prom) {
const realProm = prom || state.promotion.forceDropPromotion(piece, key);
if (canDrop(state, piece, key)) {
const result = baseUserDrop(state, piece, key, realProm);
if (result) {
unselect(state);
callUserFunction(state.droppable.events.after, piece, key, realProm, { premade: false });
return true;
}
}
else if (canPredrop(state, piece, key)) {
setPredrop(state, piece, key, realProm);
unselect(state);
return true;
}
unselect(state);
return false;
}
export function userMove(state, orig, dest, prom) {
const realProm = prom || state.promotion.forceMovePromotion(orig, dest);
if (canMove(state, orig, dest)) {
const result = baseUserMove(state, orig, dest, realProm);
if (result) {
unselect(state);
const metadata = { premade: false };
if (result !== true)
metadata.captured = result;
callUserFunction(state.movable.events.after, orig, dest, realProm, metadata);
return true;
}
}
else if (canPremove(state, orig, dest)) {
setPremove(state, orig, dest, realProm);
unselect(state);
return true;
}
unselect(state);
return false;
}
export function basePromotionDialog(state, piece, key) {
const promotedPiece = promotePiece(state, piece);
if (state.viewOnly || state.promotion.current || !promotedPiece)
return false;
state.promotion.current = { piece, promotedPiece, key, dragged: !!state.draggable.current };
state.hovered = key;
return true;
}
export function promotionDialogDrop(state, piece, key) {
if (canDropPromote(state, piece, key) &&
(canDrop(state, piece, key) || canPredrop(state, piece, key))) {
if (basePromotionDialog(state, piece, key)) {
callUserFunction(state.promotion.events.initiated);
return true;
}
}
return false;
}
export function promotionDialogMove(state, orig, dest) {
if (canMovePromote(state, orig, dest) &&
(canMove(state, orig, dest) || canPremove(state, orig, dest))) {
const piece = state.pieces.get(orig);
if (piece && basePromotionDialog(state, piece, dest)) {
callUserFunction(state.promotion.events.initiated);
return true;
}
}
return false;
}
function promotePiece(s, piece) {
const promRole = s.promotion.promotesTo(piece.role);
return promRole !== undefined ? { color: piece.color, role: promRole } : undefined;
}
export function deletePiece(state, key) {
if (state.pieces.delete(key))
callUserFunction(state.events.change);
}
export function selectSquare(state, key, prom, force) {
callUserFunction(state.events.select, key);
// unselect if selecting selected key, keep selected for drag
if (!state.draggable.enabled && state.selected === key) {
callUserFunction(state.events.unselect, key);
unselect(state);
return;
}
// try moving/dropping
if (state.selectable.enabled ||
force ||
(state.selectable.forceSpares && state.selectedPiece && state.droppable.spare)) {
if (state.selectedPiece && userDrop(state, state.selectedPiece, key, prom))
return;
else if (state.selected && userMove(state, state.selected, key, prom))
return;
}
if ((state.selectable.enabled || state.draggable.enabled || force) &&
(isMovable(state, key) || isPremovable(state, key))) {
setSelected(state, key);
}
}
export function selectPiece(state, piece, spare, force, api) {
callUserFunction(state.events.pieceSelect, piece);
if (state.selectable.addSparesToHand && state.droppable.spare && state.selectedPiece) {
addToHand(state, { role: state.selectedPiece.role, color: piece.color });
callUserFunction(state.events.change);
unselect(state);
}
else if (!api &&
!state.draggable.enabled &&
state.selectedPiece &&
samePiece(state.selectedPiece, piece)) {
callUserFunction(state.events.pieceUnselect, piece);
unselect(state);
}
else if ((state.selectable.enabled || state.draggable.enabled || force) &&
(isDroppable(state, piece, !!spare) || isPredroppable(state, piece))) {
setSelectedPiece(state, piece);
state.droppable.spare = !!spare;
}
else {
unselect(state);
}
}
export function setSelected(state, key) {
unselect(state);
state.selected = key;
setPreDests(state);
}
export function setSelectedPiece(state, piece) {
unselect(state);
state.selectedPiece = piece;
setPreDests(state);
}
export function setPreDests(state) {
state.premovable.dests = state.predroppable.dests = undefined;
if (state.selected && isPremovable(state, state.selected) && state.premovable.generate)
state.premovable.dests = state.premovable.generate(state.selected, state.pieces);
else if (state.selectedPiece &&
isPredroppable(state, state.selectedPiece) &&
state.predroppable.generate)
state.predroppable.dests = state.predroppable.generate(state.selectedPiece, state.pieces);
}
export function unselect(state) {
state.selected =
state.selectedPiece =
state.premovable.dests =
state.predroppable.dests =
state.promotion.current =
undefined;
state.droppable.spare = false;
}
function isMovable(state, orig) {
const piece = state.pieces.get(orig);
return (!!piece &&
(state.activeColor === 'both' ||
(state.activeColor === piece.color && state.turnColor === piece.color)));
}
function isDroppable(state, piece, spare) {
var _a;
return ((spare || !!((_a = state.hands.handMap.get(piece.color)) === null || _a === void 0 ? void 0 : _a.get(piece.role))) &&
(state.activeColor === 'both' ||
(state.activeColor === piece.color && state.turnColor === piece.color)));
}
export function canMove(state, orig, dest) {
var _a, _b;
return (orig !== dest &&
isMovable(state, orig) &&
(state.movable.free || !!((_b = (_a = state.movable.dests) === null || _a === void 0 ? void 0 : _a.get(orig)) === null || _b === void 0 ? void 0 : _b.includes(dest))));
}
export function canDrop(state, piece, dest) {
var _a, _b;
return (isDroppable(state, piece, state.droppable.spare) &&
(state.droppable.free ||
state.droppable.spare ||
!!((_b = (_a = state.droppable.dests) === null || _a === void 0 ? void 0 : _a.get(pieceNameOf(piece))) === null || _b === void 0 ? void 0 : _b.includes(dest))));
}
function canMovePromote(state, orig, dest) {
const piece = state.pieces.get(orig);
return !!piece && state.promotion.movePromotionDialog(orig, dest);
}
function canDropPromote(state, piece, key) {
return !state.droppable.spare && state.promotion.dropPromotionDialog(piece, key);
}
function isPremovable(state, orig) {
const piece = state.pieces.get(orig);
return (!!piece &&
state.premovable.enabled &&
state.activeColor === piece.color &&
state.turnColor !== piece.color);
}
function isPredroppable(state, piece) {
var _a;
return (!!((_a = state.hands.handMap.get(piece.color)) === null || _a === void 0 ? void 0 : _a.get(piece.role)) &&
state.predroppable.enabled &&
state.activeColor === piece.color &&
state.turnColor !== piece.color);
}
export function canPremove(state, orig, dest) {
return (orig !== dest &&
isPremovable(state, orig) &&
!!state.premovable.generate &&
state.premovable.generate(orig, state.pieces).includes(dest));
}
export function canPredrop(state, piece, dest) {
const destPiece = state.pieces.get(dest);
return (isPredroppable(state, piece) &&
(!destPiece || destPiece.color !== state.activeColor) &&
!!state.predroppable.generate &&
state.predroppable.generate(piece, state.pieces).includes(dest));
}
export function isDraggable(state, piece) {
return (state.draggable.enabled &&
(state.activeColor === 'both' ||
(state.activeColor === piece.color &&
(state.turnColor === piece.color || state.premovable.enabled))));
}
export function playPremove(state) {
const move = state.premovable.current;
if (!move)
return false;
const orig = move.orig, dest = move.dest, prom = move.prom;
let success = false;
if (canMove(state, orig, dest)) {
const result = baseUserMove(state, orig, dest, prom);
if (result) {
const metadata = { premade: true };
if (result !== true)
metadata.captured = result;
callUserFunction(state.movable.events.after, orig, dest, prom, metadata);
success = true;
}
}
unsetPremove(state);
return success;
}
export function playPredrop(state) {
const drop = state.predroppable.current;
if (!drop)
return false;
const piece = drop.piece, key = drop.key, prom = drop.prom;
let success = false;
if (canDrop(state, piece, key)) {
if (baseUserDrop(state, piece, key, prom)) {
callUserFunction(state.droppable.events.after, piece, key, prom, { premade: true });
success = true;
}
}
unsetPredrop(state);
return success;
}
export function cancelMoveOrDrop(state) {
unsetPremove(state);
unsetPredrop(state);
unselect(state);
}
export function cancelPromotion(state) {
if (!state.promotion.current)
return;
unselect(state);
state.promotion.current = undefined;
state.hovered = undefined;
callUserFunction(state.promotion.events.cancel);
}
export function stop(state) {
state.activeColor =
state.movable.dests =
state.droppable.dests =
state.draggable.current =
state.animation.current =
state.promotion.current =
state.hovered =
undefined;
cancelMoveOrDrop(state);
}
//# sourceMappingURL=board.js.map