cm-chessboard 4.0.2 → 4.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,8 +12,17 @@ export class Position {
12
12
  this.squares = new Array(64).fill(null)
13
13
  this.setFen(fen)
14
14
  }
15
- setFen(fen = FEN_START_POSITION) {
16
- const parts = fen.replace(/^\s*/, "").replace(/\s*$/, "").split(/\/|\s/)
15
+
16
+ setFen(fen = FEN_EMPTY_POSITION) {
17
+ let fenNormalized
18
+ if (fen === "start") {
19
+ fenNormalized = FEN_START_POSITION
20
+ } else if (fen === "empty" || fen === undefined) {
21
+ fenNormalized = FEN_EMPTY_POSITION
22
+ } else {
23
+ fenNormalized = fen
24
+ }
25
+ const parts = fenNormalized.replace(/^\s*/, "").replace(/\s*$/, "").split(/\/|\s/)
17
26
  for (let part = 0; part < 8; part++) {
18
27
  const row = parts[7 - part].replace(/\d/g, (str) => {
19
28
  const numSpaces = parseInt(str)
@@ -37,6 +46,7 @@ export class Position {
37
46
  }
38
47
  }
39
48
  }
49
+
40
50
  getFen() {
41
51
  let parts = new Array(8).fill("")
42
52
  for (let part = 0; part < 8; part++) {
@@ -66,9 +76,9 @@ export class Position {
66
76
  }
67
77
  return parts.join("/")
68
78
  }
69
- getPieces() {
79
+
80
+ getPieces(sortBy = ['k', 'q', 'r', 'b', 'n', 'p']) {
70
81
  const pieces = []
71
- const sortBy = ['k', 'q', 'r', 'b', 'n', 'p']
72
82
  const sort = (a, b) => {
73
83
  return sortBy.indexOf(a.name) - sortBy.indexOf(b.name)
74
84
  }
@@ -82,10 +92,21 @@ export class Position {
82
92
  })
83
93
  }
84
94
  }
85
- pieces.sort(sort)
95
+ if(sortBy) {
96
+ pieces.sort(sort)
97
+ }
86
98
  return pieces
87
99
  }
88
100
 
101
+ movePiece(squareFrom, squareTo) {
102
+ if(!this.squares[Position.squareToIndex(squareFrom)]) {
103
+ console.error("movePiece, no piece on square", squareFrom)
104
+ return
105
+ }
106
+ this.squares[Position.squareToIndex(squareTo)] = this.squares[Position.squareToIndex(squareFrom)]
107
+ this.squares[Position.squareToIndex(squareFrom)] = undefined
108
+ }
109
+
89
110
  setPiece(square, piece) {
90
111
  this.squares[Position.squareToIndex(square)] = piece
91
112
  }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Author and copyright: Stefan Haack (https://shaack.com)
3
+ * Repository: https://github.com/shaack/cm-chessboard
4
+ * License: MIT, see file 'LICENSE'
5
+ */
6
+ import {FEN_EMPTY_POSITION, Position} from "./Position.js"
7
+ import {Svg} from "./View.js"
8
+
9
+ /*
10
+ * Thanks to markosyan for the idea to the PromiseQueue
11
+ * https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5
12
+ */
13
+
14
+ export class PromiseQueue {
15
+
16
+ constructor() {
17
+ this.queue = []
18
+ this.workingOnPromise = false
19
+ this.stop = false
20
+ }
21
+
22
+ async enqueue(promise) {
23
+ return new Promise((resolve, reject) => {
24
+ this.queue.push({
25
+ promise, resolve, reject,
26
+ })
27
+ this.dequeue()
28
+ })
29
+ }
30
+
31
+ dequeue() {
32
+ if (this.workingOnPromise) {
33
+ return
34
+ }
35
+ if (this.stop) {
36
+ this.queue = []
37
+ this.stop = false
38
+ return
39
+ }
40
+ const entry = this.queue.shift()
41
+ if (!entry) {
42
+ return
43
+ }
44
+ try {
45
+ this.workingOnPromise = true
46
+ entry.promise().then((value) => {
47
+ this.workingOnPromise = false
48
+ entry.resolve(value)
49
+ this.dequeue()
50
+ }).catch(err => {
51
+ this.workingOnPromise = false
52
+ entry.reject(err)
53
+ this.dequeue()
54
+ })
55
+ } catch (err) {
56
+ this.workingOnPromise = false
57
+ entry.reject(err)
58
+ this.dequeue()
59
+ }
60
+ return true
61
+ }
62
+
63
+ destroy() {
64
+ console.log("PAQ destroy")
65
+ this.stop = true
66
+ }
67
+
68
+
69
+ }
70
+
71
+
72
+ const CHANGE_TYPE = {
73
+ move: 0,
74
+ appear: 1,
75
+ disappear: 2
76
+ }
77
+
78
+ export class PositionsAnimation {
79
+
80
+ constructor(view, fromPosition, toPosition, duration, callback) {
81
+ this.view = view
82
+ if (fromPosition && toPosition) {
83
+ this.animatedElements = this.createAnimation(fromPosition.squares, toPosition.squares)
84
+ this.duration = duration
85
+ this.callback = callback
86
+ this.frameHandle = requestAnimationFrame(this.animationStep.bind(this))
87
+ } else {
88
+ console.error("fromPosition", fromPosition, "toPosition", toPosition)
89
+ }
90
+ }
91
+
92
+ static seekChanges(fromSquares, toSquares) {
93
+ const appearedList = [], disappearedList = [], changes = []
94
+ for (let i = 0; i < 64; i++) {
95
+ const previousSquare = fromSquares[i]
96
+ const newSquare = toSquares[i]
97
+ if (newSquare !== previousSquare) {
98
+ if (newSquare) {
99
+ appearedList.push({piece: newSquare, index: i})
100
+ }
101
+ if (previousSquare) {
102
+ disappearedList.push({piece: previousSquare, index: i})
103
+ }
104
+ }
105
+ }
106
+ appearedList.forEach((appeared) => {
107
+ let shortestDistance = 8
108
+ let foundMoved = undefined
109
+ disappearedList.forEach((disappeared) => {
110
+ if (appeared.piece === disappeared.piece) {
111
+ const moveDistance = PositionsAnimation.squareDistance(appeared.index, disappeared.index)
112
+ if (moveDistance < shortestDistance) {
113
+ foundMoved = disappeared
114
+ shortestDistance = moveDistance
115
+ }
116
+ }
117
+ })
118
+ if (foundMoved) {
119
+ disappearedList.splice(disappearedList.indexOf(foundMoved), 1) // remove from disappearedList, because it is moved now
120
+ changes.push({
121
+ type: CHANGE_TYPE.move,
122
+ piece: appeared.piece,
123
+ atIndex: foundMoved.index,
124
+ toIndex: appeared.index
125
+ })
126
+ } else {
127
+ changes.push({type: CHANGE_TYPE.appear, piece: appeared.piece, atIndex: appeared.index})
128
+ }
129
+ })
130
+ disappearedList.forEach((disappeared) => {
131
+ changes.push({type: CHANGE_TYPE.disappear, piece: disappeared.piece, atIndex: disappeared.index})
132
+ })
133
+ return changes
134
+ }
135
+
136
+ createAnimation(fromSquares, toSquares) {
137
+ const changes = PositionsAnimation.seekChanges(fromSquares, toSquares)
138
+ // console.log("changes", changes)
139
+ const animatedElements = []
140
+ changes.forEach((change) => {
141
+ const animatedItem = {
142
+ type: change.type
143
+ }
144
+ switch (change.type) {
145
+ case CHANGE_TYPE.move:
146
+ animatedItem.element = this.view.getPieceElement(Position.indexToSquare(change.atIndex))
147
+ animatedItem.element.parentNode.appendChild(animatedItem.element) // move element to top layer
148
+ animatedItem.atPoint = this.view.indexToPoint(change.atIndex)
149
+ animatedItem.toPoint = this.view.indexToPoint(change.toIndex)
150
+ break
151
+ case CHANGE_TYPE.appear:
152
+ animatedItem.element = this.view.drawPiece(Position.indexToSquare(change.atIndex), change.piece)
153
+ animatedItem.element.style.opacity = 0
154
+ break
155
+ case CHANGE_TYPE.disappear:
156
+ animatedItem.element = this.view.getPieceElement(Position.indexToSquare(change.atIndex))
157
+ break
158
+ }
159
+ animatedElements.push(animatedItem)
160
+ })
161
+ return animatedElements
162
+ }
163
+
164
+ animationStep(time) {
165
+ // console.log("animationStep", time)
166
+ if (!this.startTime) {
167
+ this.startTime = time
168
+ }
169
+ const timeDiff = time - this.startTime
170
+ if (timeDiff <= this.duration) {
171
+ this.frameHandle = requestAnimationFrame(this.animationStep.bind(this))
172
+ } else {
173
+ cancelAnimationFrame(this.frameHandle)
174
+ // console.log("ANIMATION FINISHED")
175
+ this.animatedElements.forEach((animatedItem) => {
176
+ if (animatedItem.type === CHANGE_TYPE.disappear) {
177
+ Svg.removeElement(animatedItem.element)
178
+ }
179
+ })
180
+ this.callback()
181
+ return
182
+ }
183
+ const t = Math.min(1, timeDiff / this.duration)
184
+ let progress = t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t // easeInOut
185
+ if (isNaN(progress)) {
186
+ progress = 1
187
+ }
188
+ this.animatedElements.forEach((animatedItem) => {
189
+ // console.log("animatedItem", animatedItem)
190
+ if (animatedItem.element) {
191
+ switch (animatedItem.type) {
192
+ case CHANGE_TYPE.move:
193
+ animatedItem.element.transform.baseVal.removeItem(0)
194
+ const transform = (this.view.svg.createSVGTransform())
195
+ transform.setTranslate(
196
+ animatedItem.atPoint.x + (animatedItem.toPoint.x - animatedItem.atPoint.x) * progress,
197
+ animatedItem.atPoint.y + (animatedItem.toPoint.y - animatedItem.atPoint.y) * progress)
198
+ animatedItem.element.transform.baseVal.appendItem(transform)
199
+ break
200
+ case CHANGE_TYPE.appear:
201
+ animatedItem.element.style.opacity = Math.round(progress * 100) / 100
202
+ break
203
+ case CHANGE_TYPE.disappear:
204
+ animatedItem.element.style.opacity = Math.round((1 - progress) * 100) / 100
205
+ break
206
+ }
207
+ } else {
208
+ console.warn("animatedItem has no element", animatedItem)
209
+ }
210
+ })
211
+ }
212
+
213
+ static squareDistance(index1, index2) {
214
+ const file1 = index1 % 8
215
+ const rank1 = Math.floor(index1 / 8)
216
+ const file2 = index2 % 8
217
+ const rank2 = Math.floor(index2 / 8)
218
+ return Math.max(Math.abs(rank2 - rank1), Math.abs(file2 - file1))
219
+ }
220
+
221
+ }
222
+
223
+ export class PositionAnimationsQueue extends PromiseQueue {
224
+
225
+ constructor(chessboard) {
226
+ super()
227
+ this.chessboard = chessboard
228
+ }
229
+
230
+ async enqueuePositionChange(positionFrom, positionTo, animated) {
231
+ return super.enqueue(() => new Promise((resolve) => {
232
+ let duration = animated ? this.chessboard.props.animationDuration : 0
233
+ if(this.queue.length > 0) {
234
+ duration = duration / (1 + Math.pow(this.queue.length / 5, 2))
235
+ }
236
+ // console.log("duration", duration, animated, "this.chessboard.props.animationDuration", this.chessboard.props.animationDuration)
237
+ new PositionsAnimation(this.chessboard.view,
238
+ positionFrom, positionTo, animated ? duration : 0,
239
+ () => {
240
+ if(this.chessboard.view) { // if destroyed, no view anymore
241
+ this.chessboard.view.redrawPieces(positionTo.squares)
242
+ }
243
+ resolve()
244
+ }
245
+ )
246
+ }))
247
+ }
248
+
249
+ async enqueueTurnBoard(position, color, animated) {
250
+ return super.enqueue(() => new Promise((resolve) => {
251
+ const emptyPosition = new Position(FEN_EMPTY_POSITION)
252
+ let duration = animated ? this.chessboard.props.animationDuration : 0
253
+ if(this.queue.length > 0) {
254
+ duration = duration / (1 + Math.pow(this.queue.length / 5, 2))
255
+ }
256
+ new PositionsAnimation(this.chessboard.view,
257
+ position, emptyPosition, animated ? duration : 0,
258
+ () => {
259
+ this.chessboard.state.orientation = color
260
+ this.chessboard.view.redraw()
261
+ this.chessboard.view.redrawPieces(emptyPosition.squares)
262
+ new PositionsAnimation(this.chessboard.view,
263
+ emptyPosition, position, animated ? duration : 0,
264
+ () => {
265
+ this.chessboard.view.redrawPieces(position.squares)
266
+ resolve()
267
+ }
268
+ )
269
+ }
270
+ )
271
+ }))
272
+ }
273
+
274
+ }
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import {Position} from "./Position.js"
7
7
 
8
- export class ChessboardState {
8
+ export class State {
9
9
 
10
10
  constructor() {
11
11
  this.position = new Position()
@@ -16,21 +16,28 @@ export class ChessboardState {
16
16
  this.inputEnabled = false
17
17
  this.squareSelectEnabled = false
18
18
  }
19
- /*
20
- getPieces() {
21
- return this.position.getPieces()
22
- }
23
19
 
24
- setPiece(square, piece) {
25
- this.position.setPiece(square, piece)
20
+ setPosition(fen, animated = false) {
21
+ this.position = new Position(fen, animated)
26
22
  }
27
- */
28
- setPosition(fen) {
29
- this.position.setFen(fen)
23
+
24
+ movePiece(fromSquare, toSquare, animated = false) {
25
+ const position = this._position.clone()
26
+ position.animated = animated
27
+ const piece = position.getPiece(fromSquare)
28
+ if(!piece) {
29
+ console.error("no piece on", fromSquare)
30
+ }
31
+ position.setPiece(fromSquare, undefined)
32
+ position.setPiece(toSquare, piece)
33
+ this._position = position
30
34
  }
31
35
 
32
- getPosition() {
33
- return this.position.getFen()
36
+ setPiece(square, piece, animated = false) {
37
+ const position = this._position.clone()
38
+ position.animated = animated
39
+ position.setPiece(square, piece)
40
+ this._position = position
34
41
  }
35
42
 
36
43
  addMarker(square, type) {
@@ -4,9 +4,8 @@
4
4
  * License: MIT, see file 'LICENSE'
5
5
  */
6
6
 
7
- import {ChessboardMoveInput} from "./ChessboardMoveInput.js"
8
- import {COLOR, INPUT_EVENT_TYPE, BORDER_TYPE} from "./Chessboard.js"
9
- import {ChessboardPiecesAnimation} from "./ChessboardPiecesAnimation.js"
7
+ import {MoveInput} from "./MoveInput.js"
8
+ import {COLOR, INPUT_EVENT_TYPE, BORDER_TYPE} from "../Chessboard.js"
10
9
  import {Position} from "./Position.js"
11
10
 
12
11
  export const piecesTranslations = {
@@ -48,13 +47,13 @@ export function renderPieceTitle(lang, name, color = undefined) {
48
47
  return title
49
48
  }
50
49
 
51
- export class ChessboardView {
50
+ export class View {
52
51
 
53
52
  constructor(chessboard) {
54
- this.animationRunning = false
55
- this.currentAnimation = undefined
53
+ // this.animationRunning = false
54
+ // this.currentAnimation = undefined
56
55
  this.chessboard = chessboard
57
- this.moveInput = new ChessboardMoveInput(this,
56
+ this.moveInput = new MoveInput(this,
58
57
  this.moveStartCallback.bind(this),
59
58
  this.moveDoneCallback.bind(this),
60
59
  this.moveCanceledCallback.bind(this)
@@ -104,11 +103,11 @@ export class ChessboardView {
104
103
  }
105
104
  this.chessboard.context.removeEventListener("mousedown", this.pointerDownListener)
106
105
  this.chessboard.context.removeEventListener("touchstart", this.pointerDownListener)
107
- Svg.removeElement(this.svg)
108
106
  this.animationQueue = []
109
107
  if (this.currentAnimation) {
110
108
  cancelAnimationFrame(this.currentAnimation.frameHandle)
111
109
  }
110
+ Svg.removeElement(this.svg)
112
111
  }
113
112
 
114
113
  // Sprite //
@@ -172,6 +171,7 @@ export class ChessboardView {
172
171
  this.context.clientHeight !== this.height) {
173
172
  this.updateMetrics()
174
173
  this.redraw()
174
+ this.redrawPieces()
175
175
  }
176
176
  this.svg.setAttribute("width", "100%") // safari bugfix
177
177
  this.svg.setAttribute("height", "100%")
@@ -182,7 +182,6 @@ export class ChessboardView {
182
182
  this.drawCoordinates()
183
183
  this.drawMarkers()
184
184
  this.visualizeInputState()
185
- this.drawPieces(this.chessboard.state.position.squares)
186
185
  }
187
186
 
188
187
  // Board //
@@ -276,7 +275,7 @@ export class ChessboardView {
276
275
 
277
276
  // Pieces //
278
277
 
279
- drawPieces(squares = this.chessboard.state.position.squares) {
278
+ redrawPieces(squares = this.chessboard.state.position.squares) {
280
279
  const childNodes = Array.from(this.piecesGroup.childNodes)
281
280
  for (let i = 0; i < 64; i++) {
282
281
  const pieceName = squares[i]
@@ -314,7 +313,7 @@ export class ChessboardView {
314
313
  }
315
314
 
316
315
  setPieceVisibility(square, visible = true) {
317
- const piece = this.getPiece(square)
316
+ const piece = this.getPieceElement(square)
318
317
  if (visible) {
319
318
  piece.setAttribute("visibility", "visible")
320
319
  } else {
@@ -322,11 +321,15 @@ export class ChessboardView {
322
321
  }
323
322
  }
324
323
 
325
- getPiece(square) {
324
+ getPieceElement(square) {
326
325
  if(square.length < 2) {
327
326
  throw new Error("980e03")
328
327
  }
329
- return this.piecesGroup.querySelector(`g[data-square='${square}']`)
328
+ const piece = this.piecesGroup.querySelector(`g[data-square='${square}']`)
329
+ if(!piece) {
330
+ console.error("no piece found on", square)
331
+ }
332
+ return piece
330
333
  }
331
334
 
332
335
  // Markers //
@@ -358,38 +361,6 @@ export class ChessboardView {
358
361
  return markerGroup
359
362
  }
360
363
 
361
- // animation queue //
362
-
363
- animatePieces(fromSquares, toSquares, callback) {
364
- this.animationQueue.push({fromSquares: fromSquares, toSquares: toSquares, callback: callback})
365
- if (!this.animationRunning) {
366
- this.nextPieceAnimationInQueue()
367
- }
368
- }
369
-
370
- nextPieceAnimationInQueue() {
371
- const nextAnimation = this.animationQueue.shift()
372
- if (nextAnimation !== undefined) {
373
- this.animationRunning = true
374
- this.currentAnimation = new ChessboardPiecesAnimation(this, nextAnimation.fromSquares, nextAnimation.toSquares, this.chessboard.props.animationDuration / (this.animationQueue.length + 1), () => {
375
- if (!this.moveInput.draggablePiece) {
376
- this.drawPieces(nextAnimation.toSquares)
377
- this.animationRunning = false
378
- this.nextPieceAnimationInQueue()
379
- if (nextAnimation.callback) {
380
- nextAnimation.callback()
381
- }
382
- } else {
383
- this.animationRunning = false
384
- this.nextPieceAnimationInQueue()
385
- if (nextAnimation.callback) {
386
- nextAnimation.callback()
387
- }
388
- }
389
- })
390
- }
391
- }
392
-
393
364
  // enable and disable move input //
394
365
 
395
366
  enableMoveInput(eventHandler, color = undefined) {
@@ -3,9 +3,9 @@
3
3
  * Repository: https://github.com/shaack/cm-chessboard
4
4
  * License: MIT, see file 'LICENSE'
5
5
  */
6
- import {ChessboardView, renderPieceTitle} from "./ChessboardView.js"
7
- import {COLOR, INPUT_EVENT_TYPE} from "./Chessboard.js"
8
- import {piecesTranslations} from "./ChessboardView.js"
6
+ import {View, renderPieceTitle} from "./View.js"
7
+ import {COLOR, INPUT_EVENT_TYPE} from "../Chessboard.js"
8
+ import {piecesTranslations} from "./View.js"
9
9
 
10
10
  const hlTranslations = {
11
11
  de: {
@@ -32,7 +32,7 @@ const hlTranslations = {
32
32
  }
33
33
  }
34
34
 
35
- export class ChessboardViewAccessible extends ChessboardView {
35
+ export class ViewAccessible extends View {
36
36
 
37
37
  constructor(chessboard, callbackAfterCreation) {
38
38
  super(chessboard, callbackAfterCreation)
@@ -103,8 +103,8 @@ export class ChessboardViewAccessible extends ChessboardView {
103
103
  }
104
104
  }
105
105
 
106
- drawPieces(squares = this.chessboard.state.position.squares) {
107
- super.drawPieces(squares)
106
+ redrawPieces(squares = this.chessboard.state.position.squares) {
107
+ super.redrawPieces(squares)
108
108
  setTimeout(() => {
109
109
  if(this.chessboard.props.accessibility.boardAsTable) {
110
110
  this.redrawBoardAsTable()
@@ -5,32 +5,29 @@
5
5
  */
6
6
 
7
7
  import {describe, it, assert} from "../node_modules/teevi/src/teevi.js"
8
- import {ChessboardPiecesAnimation} from "../src/cm-chessboard/ChessboardPiecesAnimation.js"
9
- import {ChessboardState} from "../src/cm-chessboard/ChessboardState.js"
10
- import {ViewMock} from "./mocks/ViewMock.js"
11
-
12
- const cfa = new ChessboardPiecesAnimation(new ViewMock())
8
+ import {State} from "../src/cm-chessboard/core/State.js"
9
+ import {PositionsAnimation} from "../src/cm-chessboard/core/PositionAnimationsQueue.js"
13
10
 
14
11
  describe("TestPiecesAnimation", () => {
15
12
  it("should calculate square distances", () => {
16
- assert.equals(cfa.squareDistance(0, 0), 0)
17
- assert.equals(cfa.squareDistance(0, 1), 1)
18
- assert.equals(cfa.squareDistance(0, 7), 7)
19
- assert.equals(cfa.squareDistance(0, 8), 1)
20
- assert.equals(cfa.squareDistance(10, 20), 2)
21
- assert.equals(cfa.squareDistance(0, 63), 7)
22
- assert.equals(cfa.squareDistance(8, 24), 2)
23
- assert.equals(cfa.squareDistance(14, 24), 6)
13
+ assert.equals(PositionsAnimation.squareDistance(0, 0), 0)
14
+ assert.equals(PositionsAnimation.squareDistance(0, 1), 1)
15
+ assert.equals(PositionsAnimation.squareDistance(0, 7), 7)
16
+ assert.equals(PositionsAnimation.squareDistance(0, 8), 1)
17
+ assert.equals(PositionsAnimation.squareDistance(10, 20), 2)
18
+ assert.equals(PositionsAnimation.squareDistance(0, 63), 7)
19
+ assert.equals(PositionsAnimation.squareDistance(8, 24), 2)
20
+ assert.equals(PositionsAnimation.squareDistance(14, 24), 6)
24
21
  })
25
22
 
26
23
  it("should seek changes", () => {
27
- const state1 = new ChessboardState()
24
+ const state1 = new State()
28
25
  state1.setPosition("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")
29
- const state2 = new ChessboardState()
26
+ const state2 = new State()
30
27
  state2.setPosition("rn2k1r1/ppp1pp1p/3p2p1/5bn1/P7/2N2B2/1PPPPP2/2BNK1RR")
31
28
  const previousBoard1 = state1.position.squares
32
29
  const newBoard1 = state2.position.squares
33
- const changes = cfa.seekChanges(previousBoard1, newBoard1)
30
+ const changes = PositionsAnimation.seekChanges(previousBoard1, newBoard1)
34
31
 
35
32
  assert.equals(changes[0].type,0 )
36
33
  assert.equals(changes[0].piece, "wn")
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import {describe, it, assert} from "../node_modules/teevi/src/teevi.js"
8
- import {Position} from "../src/cm-chessboard/Position.js"
8
+ import {Position} from "../src/cm-chessboard/core/Position.js"
9
9
 
10
10
  describe("TestPosition", () => {
11
11
  it("should convert square to index", () => {