mirror of
https://github.com/SleepingInsomniac/lx_chess_cr
synced 2024-11-16 19:49:34 +01:00
Add tests for check
This commit is contained in:
parent
01625b0c9b
commit
d9ca848bc3
3 changed files with 91 additions and 9 deletions
|
@ -69,7 +69,7 @@ describe "Castling" do
|
|||
game.make_move(from: "e1", to: "d1")
|
||||
fen.update(game)
|
||||
fen.to_s.should eq("8/8/8/8/8/8/8/R2K3R b kq - 1 1")
|
||||
game.next_turn
|
||||
game.next_turn!
|
||||
expect_raises(Game::IllegalMove) do
|
||||
game.make_move(from: "d1", to: "f1")
|
||||
end
|
||||
|
|
|
@ -6,6 +6,24 @@ require "../../src/lx_chess/game"
|
|||
require "../../src/lx_chess/term_board"
|
||||
|
||||
describe LxChess::Game do
|
||||
describe "#find_king" do
|
||||
it "finds the black king" do
|
||||
game = LxChess::Game.new
|
||||
place(game.board, { "e1" => 'K', "e8" => 'k' })
|
||||
black_king = game.find_king(1)
|
||||
black_king.should_not be(nil)
|
||||
black_king.try { |k| k.fen_symbol.should eq('k') }
|
||||
end
|
||||
|
||||
it "finds the white king" do
|
||||
game = LxChess::Game.new
|
||||
place(game.board, { "e1" => 'K', "e8" => 'k' })
|
||||
white_king = game.find_king(0)
|
||||
white_king.should_not be(nil)
|
||||
white_king.try { |k| k.fen_symbol.should eq('K') }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#moves" do
|
||||
it "correctly generates white pawn moves from the initial rank" do
|
||||
game = LxChess::Game.new
|
||||
|
|
|
@ -52,6 +52,13 @@ module LxChess
|
|||
end
|
||||
end
|
||||
|
||||
def find_king(turn = @turn)
|
||||
@board.find do |piece|
|
||||
next unless piece
|
||||
piece.king? && (turn == 0 ? piece.white? : piece.black?)
|
||||
end
|
||||
end
|
||||
|
||||
# Parse SAN from a string
|
||||
def parse_san(notation : String)
|
||||
parse_san(Notation.new(notation))
|
||||
|
@ -97,11 +104,15 @@ module LxChess
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: add check, checkmate, etc.
|
||||
def move_to_san(from : Int, to : Int, promotion : String? = nil)
|
||||
# TODO: checkmate
|
||||
def move_to_san(from : Int, to : Int, promotion : String? = nil, turn = @turn)
|
||||
raise "No piece at #{@board.cord(from)}" unless piece = @board[from]
|
||||
en_passant = piece.pawn? && to == @en_passant_target
|
||||
|
||||
check = tmp_move(from, to) do
|
||||
in_check?(turn)
|
||||
end
|
||||
|
||||
Notation.new(
|
||||
square: @board.cord(to),
|
||||
promotion: promotion,
|
||||
|
@ -109,7 +120,8 @@ module LxChess
|
|||
from: @board.cord(from),
|
||||
to: @board.cord(to),
|
||||
takes: en_passant || !@board[to].nil?,
|
||||
en_passant: en_passant
|
||||
en_passant: en_passant,
|
||||
check: check
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -227,6 +239,19 @@ module LxChess
|
|||
@board[index - 1].nil? && @board[index - 2].nil?
|
||||
end
|
||||
|
||||
# Temporarily make a move
|
||||
def tmp_move(from : Int16, to : Int16)
|
||||
from_piece = @board[from]
|
||||
to_piece = @board[to]
|
||||
@board[from] = nil
|
||||
@board[to] = from_piece
|
||||
return_val = yield
|
||||
ensure
|
||||
@board[from] = from_piece
|
||||
@board[to] = to_piece
|
||||
return_val
|
||||
end
|
||||
|
||||
def make_move(from : String, to : String, promotion : Char? = nil)
|
||||
make_move(from: @board.index(from), to: @board.index(to), promotion: promotion)
|
||||
end
|
||||
|
@ -239,7 +264,15 @@ module LxChess
|
|||
raise IllegalMove.new("#{@board.cord(from)} has no moves")
|
||||
end
|
||||
|
||||
san = move_to_san(from, to, promotion)
|
||||
# Test if the move will expose check
|
||||
tmp_move(from, to) do
|
||||
if in_check?
|
||||
raise IllegalMove.new("Cannot move into check")
|
||||
end
|
||||
end
|
||||
|
||||
san = move_to_san(from, to, promotion, next_turn)
|
||||
|
||||
# Castling
|
||||
if piece.king?
|
||||
dist = to - from
|
||||
|
@ -315,15 +348,46 @@ module LxChess
|
|||
end
|
||||
|
||||
@board.move(from, to)
|
||||
next_turn
|
||||
next_turn!
|
||||
@pgn.history << san
|
||||
san
|
||||
end
|
||||
|
||||
def next_turn
|
||||
@turn += 1
|
||||
@turn = @turn % @players.size
|
||||
def in_check?(turn = @turn)
|
||||
if king = find_king(turn)
|
||||
opponent_pieces = @board.select do |square|
|
||||
square.try do |piece|
|
||||
piece.color != king.color
|
||||
end
|
||||
end
|
||||
|
||||
in_check = false
|
||||
moves = opponent_pieces.each do |piece|
|
||||
piece.try do |piece|
|
||||
moves(piece.index).try do |move_set|
|
||||
if move_set.moves.includes?(king.index)
|
||||
in_check = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
in_check
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Increment the turn index
|
||||
def next_turn!
|
||||
@turn = next_turn
|
||||
@move_clock += 1
|
||||
end
|
||||
|
||||
# Get the next turn index
|
||||
def next_turn
|
||||
(@turn + 1) % @players.size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue