Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crazyhouse drops by click-click #292

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,23 @@
height: 500px;
}

.selected-to-drop {
background-color: rgba(20, 85, 30, 0.5);
}

#pocket {
display: flex;
flex-direction: row;
}

cg-board {
background-color: #bfcfdd;
}
</style>

<script type="module">
import { Chessground } from './dist/chessground.js';
import { setDropMode } from './dist/drop.js';

Chessground(document.getElementById('board-1'), {});
Chessground(document.getElementById('board-2'), {
Expand Down Expand Up @@ -83,6 +93,20 @@
],
},
});
const dropBoard = Chessground(document.getElementById('board-4'), {
draggable: { enabled: true },
selectable: { enabled: true },
});
window.cgState = dropBoard.state;
['white', 'black'].forEach(color => {
['pawn', 'knight', 'bishop'].forEach(role => {
const el = document.getElementById(`drop-${color}-${role}`);
el.addEventListener('mousedown', event => {
event.preventDefault();
dropBoard.dragNewPiece({ role, color }, event, false);
});
});
});
</script>
</head>
<body>
Expand All @@ -98,5 +122,29 @@
board with fixed arrows + labels
<div class="chessground" id="board-3"></div>
</div>
<div>
board with droppable pieces
<div class="chessground" id="board-4"></div>
<div id="pocket">
<div id="drop-white-pawn" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="white pawn"></piece>
</div>
<div id="drop-white-knight" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="white knight"></piece>
</div>
<div id="drop-white-bishop" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="white bishop"></piece>
</div>
<div id="drop-black-pawn" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="black pawn"></piece>
</div>
<div id="drop-black-knight" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="black knight"></piece>
</div>
<div id="drop-black-bishop" class="cg-wrap" style="width: 50px; height: 50px">
<piece style="width: 50px; height: 50px" class="black bishop"></piece>
</div>
</div>
</div>
</body>
</html>
25 changes: 24 additions & 1 deletion src/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,18 @@ export function userMove(state: HeadlessState, orig: cg.Key, dest: cg.Key): bool
return false;
}

export function dropNewPiece(state: HeadlessState, orig: cg.Key, dest: cg.Key, force?: boolean): void {
export function dropNewPiece(state: HeadlessState, orig: cg.Key, dest: cg.Key, force?: boolean): boolean {
const piece = state.pieces.get(orig);
let dropped = false;
if (piece && (canDrop(state, orig, dest) || force)) {
state.pieces.delete(orig);
baseNewPiece(state, piece, dest, force);
callUserFunction(state.movable.events.afterNewPiece, piece.role, dest, {
premove: false,
predrop: false,
});

dropped = true;
} else if (piece && canPredrop(state, orig, dest)) {
setPredrop(state, piece.role, dest);
} else {
Expand All @@ -181,6 +184,18 @@ export function dropNewPiece(state: HeadlessState, orig: cg.Key, dest: cg.Key, f
}
state.pieces.delete(orig);
unselect(state);
return dropped;
}

export function selectNewPieceToDrop(
state: HeadlessState,
piece: cg.Piece,
originTarget: EventTarget | null,
): void {
if (state.selected || state.selectedToDrop) unselect(state);
callUserFunction(state.events.select, 'a0');
(originTarget as HTMLElement).classList.add('selected-to-drop');
state.selectedToDrop = { piece, originTarget };
}

export function selectSquare(state: HeadlessState, key: cg.Key, force?: boolean): void {
Expand All @@ -197,6 +212,10 @@ export function selectSquare(state: HeadlessState, key: cg.Key, force?: boolean)
}
}
}
if (state.selectedToDrop) {
state.pieces.set('a0', state.selectedToDrop.piece);
if (dropNewPiece(state, 'a0', key)) return;
}
if (
(state.selectable.enabled || state.draggable.enabled) &&
(isMovable(state, key) || isPremovable(state, key))
Expand All @@ -217,6 +236,10 @@ export function setSelected(state: HeadlessState, key: cg.Key): void {
}

export function unselect(state: HeadlessState): void {
if (state.selectedToDrop) {
(state.selectedToDrop.originTarget as HTMLElement).classList.remove('selected-to-drop');
state.selectedToDrop = undefined;
}
state.selected = undefined;
state.premovable.dests = undefined;
state.hold.cancel();
Expand Down
17 changes: 16 additions & 1 deletion src/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface DragCurrent {
newPiece?: boolean; // it it a new piece from outside the board
force?: boolean; // can the new piece replace an existing one (editor)
previouslySelected?: cg.Key;
previouslySelectedToDrop?: { piece: cg.Piece; originTarget: EventTarget | null };
originTarget: EventTarget | null;
keyHasChanged: boolean; // whether the drag has left the orig key
}
Expand Down Expand Up @@ -95,6 +96,13 @@ function pieceCloseTo(s: State, pos: cg.NumberPair): boolean {
}

export function dragNewPiece(s: State, piece: cg.Piece, e: cg.MouchEvent, force?: boolean): void {
const previouslySelectedToDrop = s.selectedToDrop;
board.selectNewPieceToDrop(s, piece, e.target);
if (!s.draggable.enabled) {
if (previouslySelectedToDrop?.originTarget === s.selectedToDrop?.originTarget) board.unselect(s);
return;
}

const key: cg.Key = 'a0';
s.pieces.set(key, piece);
s.dom.redraw();
Expand All @@ -112,6 +120,7 @@ export function dragNewPiece(s: State, piece: cg.Piece, e: cg.MouchEvent, force?
newPiece: true,
force: !!force,
keyHasChanged: false,
previouslySelectedToDrop,
};
processDrag(s);
}
Expand Down Expand Up @@ -186,7 +195,13 @@ export function end(s: State, e: cg.MouchEvent): void {
s.pieces.delete(cur.orig);
board.callUserFunction(s.events.change);
}
if ((cur.orig === cur.previouslySelected || cur.keyHasChanged) && (cur.orig === dest || !dest))
if (
(cur.orig === cur.previouslySelected || cur.keyHasChanged) &&
(cur.orig === dest || !dest) &&
(!cur.newPiece ||
e.target !== cur.originTarget ||
(cur.previouslySelectedToDrop && cur.previouslySelectedToDrop.originTarget === e.target))
)
board.unselect(s);
else if (!s.selectable.enabled) board.unselect(s);

Expand Down
5 changes: 5 additions & 0 deletions src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export interface HeadlessState {
check?: cg.Key; // square currently in check "a2"
lastMove?: cg.Key[]; // squares part of the last move ["c3"; "c4"]
selected?: cg.Key; // square currently selected "a1"
selectedToDrop?: {
// piece currently selected to drop
piece: cg.Piece;
originTarget: EventTarget | null;
};
coordinates: boolean; // include coords attributes
ranksPosition: cg.RanksPosition; // position ranks on either side. left | right
autoCastle: boolean; // immediately complete the castle by moving the rook after king move
Expand Down