diff --git a/chess/board.go b/chess/board.go index d790a29..813a945 100644 --- a/chess/board.go +++ b/chess/board.go @@ -731,12 +731,13 @@ func (b *Board) moveBishop(position string, queen bool) error { func (b *Board) moveKnight(position string, fromX int, fromY int) error { var ( - x int - y int - xPrev int - yPrev int - piece *Piece - err error + x int + y int + xPrev int + yPrev int + p *Piece + validPrev []*Square + err error ) if x, y, err = getXY(position); err != nil { @@ -747,73 +748,70 @@ func (b *Board) moveKnight(position string, fromX int, fromY int) error { xPrev = x + 1 yPrev = y - 2 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x + 2 yPrev = y - 1 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x + 2 yPrev = y + 1 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x + 1 yPrev = y + 2 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x - 1 yPrev = y + 2 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x - 2 yPrev = y + 1 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x - 2 yPrev = y - 1 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { - b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece - return nil + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) } xPrev = x - 1 yPrev = y - 2 - piece = b.getPiece(xPrev, yPrev) - if checkMove(piece, xPrev, yPrev) { + p = b.getPiece(xPrev, yPrev) + if checkMove(p, xPrev, yPrev) { + validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev}) + } + + if len(validPrev) > 1 { + return fmt.Errorf("move ambiguous: %d knights can move to %s", len(validPrev), position) + } + + if len(validPrev) == 1 { + xPrev = validPrev[0].X + yPrev = validPrev[0].Y + p = b.getPiece(xPrev, yPrev) + b.tiles[x][y] = p b.tiles[xPrev][yPrev] = nil - b.tiles[x][y] = piece return nil } diff --git a/chess/board_test.go b/chess/board_test.go index 0fe2da8..2af7634 100644 --- a/chess/board_test.go +++ b/chess/board_test.go @@ -189,6 +189,20 @@ func TestBoardMoveKnightInvalid(t *testing.T) { assertMoveError(t, b, "Ne7", "e7 blocked by black pawn") assertMoveError(t, b, "Nd7", "d7 blocked by black pawn") + + // ambiguous moves + + b = chess.NewBoard() + assertParse(t, b, "e4 e5 Nf3 d6 Nc3 d5 Nb5 d4") + assertMoveError(t, b, "Nxd4", "move ambiguous: 2 knights can move to d4") + assertMoveError(t, b, "N4xd4", "no knight found that can move to d4") + // disambiguate via file + assertParse(t, b, "Nfxd4") + + b = chess.NewBoard() + assertParse(t, b, "e4 e5 Nf3 d6 Nc3 d5 Nb5 d4") + // disambiguate via rank + assertParse(t, b, "N3xd4") } func TestBoardMoveKnightCapture(t *testing.T) {