diff --git a/spec/lx_chess/castling_spec.cr b/spec/lx_chess/castling_spec.cr index a3bf963..991f583 100644 --- a/spec/lx_chess/castling_spec.cr +++ b/spec/lx_chess/castling_spec.cr @@ -74,4 +74,20 @@ describe "Castling" do game.make_move(from: "d1", to: "f1") end end + + it "does not allow castling if the king will move through check" do + fen = Fen.parse("5r2/8/8/8/8/8/8/R3K2R w KQkq - 0 1") + game = Game.new(board: fen.board, players: [Player.new, Player.new]) + expect_raises(Game::IllegalMove) do + game.make_move(from: "e1", to: "g1") + end + end + + it "does not allow castling if the king is in check" do + fen = Fen.parse("4r3/8/8/8/8/8/8/R3K2R w KQkq - 0 1") + game = Game.new(board: fen.board, players: [Player.new, Player.new]) + expect_raises(Game::IllegalMove) do + game.make_move(from: "e1", to: "g1") + end + end end diff --git a/src/lx_chess/game.cr b/src/lx_chess/game.cr index e0f3116..66120dd 100644 --- a/src/lx_chess/game.cr +++ b/src/lx_chess/game.cr @@ -287,9 +287,7 @@ module LxChess # Test if the move will expose check tmp_move(from, to) do - if in_check? - raise IllegalMove.new("Cannot move into check") - end + raise IllegalMove.new("Cannot move into check") if in_check? end san = move_to_san(from, to, promotion, next_turn) @@ -300,7 +298,13 @@ module LxChess current_player.no_castling! if dist.abs == 2 + raise IllegalMove.new("Cannot castle out of check") if in_check? + if dist.positive? + tmp_move(from, to - 1) do + raise IllegalMove.new("Cannot castle through check") if in_check? + end + san.castles_k = true rook = @board.find do |p| p && p.color == piece.color && p.rook? && p.index.as(Int16) > piece.index.as(Int16) @@ -309,6 +313,10 @@ module LxChess @board.move(from: rook.index.as(Int16), to: to - 1) end else + tmp_move(from, to + 1) do + raise IllegalMove.new("Cannot castle through check") if in_check? + end + san.castles_q = true rook = @board.find do |p| p && p.color == piece.color && p.rook? && p.index.as(Int16) < piece.index.as(Int16)