Fix ambiguous rook moves

This commit is contained in:
ekzyis 2024-09-26 06:48:07 +02:00
parent e6f9c529f8
commit bab667d0ed
3 changed files with 54 additions and 33 deletions

View File

@ -553,12 +553,13 @@ func (b *Board) movePawn(position string, fromX int, fromY int) error {
func (b *Board) moveRook(position string, queen bool, 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 {
@ -567,21 +568,20 @@ func (b *Board) moveRook(position string, queen bool, fromX int, fromY int) erro
checkRookMove := b.validateMove(Rook, fromX, fromY)
checkQueenMove := b.validateMove(Queen, fromX, fromY)
checkMove := func(p *Piece, xPrev int, yPrev int) bool {
return (!queen && checkRookMove(p, xPrev, yPrev)) || (queen && checkQueenMove(p, xPrev, yPrev))
}
xPrev = x
yPrev = y
for xPrev >= 0 && xPrev < 8 && yPrev >= 0 && yPrev < 8 {
xPrev++
piece = b.getPiece(xPrev, yPrev)
if piece != nil {
if (!queen && checkRookMove(piece, xPrev, yPrev)) || (queen && checkQueenMove(piece, xPrev, yPrev)) {
b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece
return nil
} else {
// direction blocked by other piece
break
p = b.getPiece(xPrev, yPrev)
if p != nil {
if checkMove(p, xPrev, yPrev) {
validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev})
}
break
}
}
@ -589,12 +589,10 @@ func (b *Board) moveRook(position string, queen bool, fromX int, fromY int) erro
yPrev = y
for xPrev >= 0 && xPrev < 8 && yPrev >= 0 && yPrev < 8 {
yPrev--
piece = b.getPiece(xPrev, yPrev)
if piece != nil {
if (!queen && checkRookMove(piece, xPrev, yPrev)) || (queen && checkQueenMove(piece, xPrev, yPrev)) {
b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece
return nil
p = b.getPiece(xPrev, yPrev)
if p != nil {
if checkMove(p, xPrev, yPrev) {
validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev})
} else {
break
}
@ -605,12 +603,10 @@ func (b *Board) moveRook(position string, queen bool, fromX int, fromY int) erro
yPrev = y
for xPrev >= 0 && xPrev < 8 && yPrev >= 0 && yPrev < 8 {
xPrev--
piece = b.getPiece(xPrev, yPrev)
if piece != nil {
if (!queen && checkRookMove(piece, xPrev, yPrev)) || (queen && checkQueenMove(piece, xPrev, yPrev)) {
b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece
return nil
p = b.getPiece(xPrev, yPrev)
if p != nil {
if checkMove(p, xPrev, yPrev) {
validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev})
} else {
break
}
@ -621,18 +617,29 @@ func (b *Board) moveRook(position string, queen bool, fromX int, fromY int) erro
yPrev = y
for xPrev >= 0 && xPrev < 8 && yPrev >= 0 && yPrev < 8 {
yPrev++
piece = b.getPiece(xPrev, yPrev)
if piece != nil {
if (!queen && checkRookMove(piece, xPrev, yPrev)) || (queen && checkQueenMove(piece, xPrev, yPrev)) {
b.tiles[xPrev][yPrev] = nil
b.tiles[x][y] = piece
return nil
p = b.getPiece(xPrev, yPrev)
if p != nil {
if checkMove(p, xPrev, yPrev) {
validPrev = append(validPrev, &Square{X: xPrev, Y: yPrev})
} else {
break
}
}
}
if len(validPrev) > 1 {
return fmt.Errorf("move ambiguous: %d rooks 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
return nil
}
return fmt.Errorf("no rook found that can move to %s", position)
}

View File

@ -332,6 +332,14 @@ func TestBoardMoveRookInvalid(t *testing.T) {
// path blocked by pawn at d3
assertMoveError(t, b, "Rh3", "no rook found that can move to h3")
// ambiguous moves
b = chess.NewBoard()
assertParse(t, b, "a4 e6 h4 e5 Ra3 e4")
assertMoveError(t, b, "Rh3", "move ambiguous: 2 rooks can move to h3")
assertParse(t, b, "Rhh3")
}
func TestBoardMoveQueen(t *testing.T) {

6
chess/square.go Normal file
View File

@ -0,0 +1,6 @@
package chess
type Square struct {
X int
Y int
}