Fix ambiguous knight capture

This commit is contained in:
ekzyis 2024-09-26 02:27:51 +02:00
parent 8f70fcb552
commit a9a4216d4e
2 changed files with 63 additions and 11 deletions

View File

@ -285,7 +285,20 @@ func (b *Board) Move(move string) error {
} }
if captureFrom != -1 { if captureFrom != -1 {
move = strings.Split(move, "x")[1] parts := strings.Split(move, "x")
piece := parts[0]
position := parts[1]
if strings.ToLower(piece) == piece {
// pawn capture move like exd4
move = position
} else {
// piece capture move like Nbxd4
// remove the capture column from the piece
move = piece[:1] + position
}
} else {
// even if captureFrom is not set, it might still be a capture move just unambiguous like Nxe4
move = strings.Replace(move, "x", "", 1)
} }
// TODO: parse promotions // TODO: parse promotions
@ -318,7 +331,7 @@ func (b *Board) Move(move string) error {
case "b": case "b":
return b.moveBishop(targetPosition, false) return b.moveBishop(targetPosition, false)
case "n": case "n":
return b.moveKnight(targetPosition) return b.moveKnight(targetPosition, captureFrom)
case "q": case "q":
return b.moveQueen(targetPosition) return b.moveQueen(targetPosition)
case "k": case "k":
@ -640,7 +653,7 @@ func (b *Board) moveBishop(position string, queen bool) error {
return fmt.Errorf("no bishop found that can move to %s", position) return fmt.Errorf("no bishop found that can move to %s", position)
} }
func (b *Board) moveKnight(position string) error { func (b *Board) moveKnight(position string, captureFrom int) error {
var ( var (
x int x int
y int y int
@ -654,10 +667,17 @@ func (b *Board) moveKnight(position string) error {
return err return err
} }
checkMove := func(p *Piece, xPrev int) bool {
// capture condition fulfilled if capture
capture := captureFrom == -1 || xPrev == captureFrom
found := p != nil && p.Name == Knight && p.Color == b.turn
return capture && found
}
xPrev = x + 1 xPrev = x + 1
yPrev = y - 2 yPrev = y - 2
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -666,7 +686,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x + 2 xPrev = x + 2
yPrev = y - 1 yPrev = y - 1
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -675,7 +695,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x + 2 xPrev = x + 2
yPrev = y + 1 yPrev = y + 1
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -684,7 +704,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x + 1 xPrev = x + 1
yPrev = y + 2 yPrev = y + 2
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -693,7 +713,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x - 1 xPrev = x - 1
yPrev = y + 2 yPrev = y + 2
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -702,7 +722,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x - 2 xPrev = x - 2
yPrev = y + 1 yPrev = y + 1
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -711,7 +731,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x - 2 xPrev = x - 2
yPrev = y - 1 yPrev = y - 1
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil
@ -720,7 +740,7 @@ func (b *Board) moveKnight(position string) error {
xPrev = x - 1 xPrev = x - 1
yPrev = y - 2 yPrev = y - 2
piece = b.getPiece(xPrev, yPrev) piece = b.getPiece(xPrev, yPrev)
if piece != nil && piece.Name == Knight && piece.Color == b.turn { if checkMove(piece, xPrev) {
b.tiles[xPrev][yPrev] = nil b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece b.tiles[x][y] = piece
return nil return nil

View File

@ -173,6 +173,38 @@ func TestBoardMoveKnightCapture(t *testing.T) {
assertNoPiece(t, b, "g8") assertNoPiece(t, b, "g8")
assertNoPiece(t, b, "e2") assertNoPiece(t, b, "e2")
assertNoPiece(t, b, "d2") assertNoPiece(t, b, "d2")
// test ambiguous capture
b = chess.NewBoard()
b.Parse("e4 e5 Nf3 d6 Nc3 d5 Nb5 d4 Nbxd4")
assertPiece(t, b, "e4", chess.Pawn, chess.Light)
assertPiece(t, b, "e5", chess.Pawn, chess.Dark)
assertPiece(t, b, "d4", chess.Knight, chess.Light)
assertPiece(t, b, "f3", chess.Knight, chess.Light)
assertNoPiece(t, b, "g1")
assertNoPiece(t, b, "b1")
assertNoPiece(t, b, "c3")
assertNoPiece(t, b, "d6")
assertNoPiece(t, b, "d5")
assertNoPiece(t, b, "b5")
b = chess.NewBoard()
b.Parse("e4 e5 Nf3 d6 Nc3 d5 Nb5 d4 Nfxd4")
assertPiece(t, b, "e4", chess.Pawn, chess.Light)
assertPiece(t, b, "e5", chess.Pawn, chess.Dark)
assertPiece(t, b, "d4", chess.Knight, chess.Light)
assertPiece(t, b, "b5", chess.Knight, chess.Light)
assertNoPiece(t, b, "g1")
assertNoPiece(t, b, "b1")
assertNoPiece(t, b, "c3")
assertNoPiece(t, b, "d6")
assertNoPiece(t, b, "d5")
assertNoPiece(t, b, "f3")
} }
func TestBoardMoveBishop(t *testing.T) { func TestBoardMoveBishop(t *testing.T) {