From 7aa65f4ec0547bbc385c9fce7571425ce71d3d1b Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 26 Sep 2024 10:21:09 +0200 Subject: [PATCH] Add kingside castle --- chess/board.go | 55 +++++++++++++++++++++++++++++++++++++++++++-- chess/board_test.go | 20 +++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/chess/board.go b/chess/board.go index fd497c5..82e8275 100644 --- a/chess/board.go +++ b/chess/board.go @@ -278,6 +278,7 @@ func (b *Board) Move(move string) error { fromX int fromY int promotion string + castle = false collisionPiece *Piece err error ) @@ -291,6 +292,14 @@ func (b *Board) Move(move string) error { return err } + if move == "O-O" { + castle = true + if b.turn == Dark { + to = "g8" + fromY = 0 + } + } + // TODO: parse ambiguous captures for all pieces // TODO: parse checkmates e.g. e5# // TODO: parse O-O as kingside castle and O-O-O as queenside castle @@ -316,7 +325,7 @@ func (b *Board) Move(move string) error { case "q": return b.moveQueen(to) case "k": - return b.moveKing(to) + return b.moveKing(to, castle) default: return fmt.Errorf("invalid move %s: %v", move, err) } @@ -356,6 +365,10 @@ func parseMove(move string) (string, int, int, string, error) { from string ) + if move == "O-O" { + return "K", 5, 7, "g1", nil + } + if strings.Contains(move, "x") { return parseCaptureMove(move) } @@ -1113,7 +1126,7 @@ func (b *Board) moveQueen(position string) error { return fmt.Errorf("no queen found that can move to %s", position) } -func (b *Board) moveKing(position string) error { +func (b *Board) moveKing(position string, castle bool) error { var ( x int y int @@ -1127,6 +1140,44 @@ func (b *Board) moveKing(position string) error { return err } + if castle { + // TODO: check if castle is allowed + + y := 7 + if b.turn == Dark { + y = 0 + } + + if (b.turn == Light && position == "g1") || (b.turn == Dark && position == "g8") { + // kingside castle + + king := b.getPiece(4, y) + if king == nil || king.Color != b.turn || king.Name != King { + return fmt.Errorf("invalid castle move") + } + + if b.getPiece(5, y) != nil { + return fmt.Errorf("invalid castle move") + } + + if b.getPiece(6, y) != nil { + return fmt.Errorf("invalid castle move") + } + + rook := b.getPiece(7, y) + if rook == nil || rook.Color != b.turn || rook.Name != Rook { + return fmt.Errorf("invalid castle move") + } + + b.tiles[6][y] = king + b.tiles[4][y] = nil + b.tiles[5][y] = rook + b.tiles[7][y] = nil + + return nil + } + } + // ^ xPrev = x + 0 yPrev = y - 1 diff --git a/chess/board_test.go b/chess/board_test.go index 88d821e..b06a3d4 100644 --- a/chess/board_test.go +++ b/chess/board_test.go @@ -482,6 +482,26 @@ func TestBoardPin(t *testing.T) { assertMoveError(t, b, "Ne4", "invalid move Ne4: king is in check") } +func TestBoardCastle(t *testing.T) { + t.Parallel() + + b := chess.NewBoard() + + assertParse(t, b, "e4 e5 Nf3 Nf6 Be2 Be7 O-O") + + assertPiece(t, b, "f1", chess.Rook, chess.Light) + assertPiece(t, b, "g1", chess.King, chess.Light) + assertNoPiece(t, b, "h1") + assertNoPiece(t, b, "e1") + + assertParse(t, b, "O-O") + + assertPiece(t, b, "f8", chess.Rook, chess.Dark) + assertPiece(t, b, "g8", chess.King, chess.Dark) + assertNoPiece(t, b, "h8") + assertNoPiece(t, b, "e8") +} + func assertParse(t *testing.T, b *chess.Board, moves string) { assert.NoError(t, b.Parse(moves)) }