chessboardjs
chessboardjs copied to clipboard
Temporarily duplicated pieces due to racing updates to currentPosition.
Consider the "Play Random Computer" example from https://www.chessboardjs.com/examples#5001
First, the following bug can be easily reproduced locally by exaggerating the effect with the following changes:
- reduce the makeRandomMove delay to 1 (
window.setTimeout(makeRandomMove, 1
) - increase the move speed to 1000 (in the board config, set
moveSpeed: 1000
)
As a result of the above, you'll see duplicated pieces (for the duration of the animation) whenever the computer makes a move.
This happens because of these racing currentPosition
reads/writes:
- The player makes a move (drops the piece) which calls onDrop and schedules the "snap" animation to run after config.snapSpeed (30ms by default). That is, after 30ms, Chessboard will
drawPositionInstant()
withcurrentPosition
. UsuallycurrentPosition
is whatever was on the board when the player dropped the piece and everything is correct in that case. - However, in the example above (or whenever one attempts to implement a computer opponent), when the player drops a piece,
onDrop
is called which: calculates the new move (can be faster than 30ms), callsboard.position()
(potentially queued with setTimeout), and starts an animation for the computer move. Note thatboard.position()
updates thecurrentPosition
immediately.
As a result, if board.position()
is called in the 30ms snapSpeed
time window after player's move, the player gets to see two versions of the piece moved by the computer:
- one because of the animation moving the piece (this is expected)
- one because when snap animation finishes, it sees the new position that happens only after the computer move but the snap animation callback intended to only draw the position that happened after the player's move (i.e. before the computer gets to move their piece).
I attached a screenshot. I played 1.d4 and the computer from your example replied 2...,g4 and now the black g-pawn is duplicated: one is on g4 and the other one is moving from g2 to g4).
As mentioned at the start of this post, you can easily reproduce it locally by changing makeRandomMove delay to 1 and config.moveSpeed to 1000 in your example at https://www.chessboardjs.com/examples#5001
One workaround is to set config.snapSpeed to 0 and disallowing dragging pieces while computer move is being animated.
I have the same problem
I added delay whenever the computer makes a move, it is fix duplicated pieces.