mirror of
https://github.com/SleepingInsomniac/lx_chess_cr
synced 2024-11-16 19:49:34 +01:00
Add promotion and promotion checks for pawns
This commit is contained in:
parent
f96c207066
commit
3502140bdb
4 changed files with 54 additions and 3 deletions
32
spec/lx_chess/game/make_move_spec.cr
Normal file
32
spec/lx_chess/game/make_move_spec.cr
Normal file
|
@ -0,0 +1,32 @@
|
|||
require "../../spec_helper"
|
||||
require "../../../src/lx_chess/board"
|
||||
require "../../../src/lx_chess/piece"
|
||||
require "../../../src/lx_chess/move_set"
|
||||
require "../../../src/lx_chess/game"
|
||||
|
||||
include LxChess
|
||||
|
||||
describe Game do
|
||||
describe "#make_move" do
|
||||
context "when a move will promote" do
|
||||
it "raises an exception when promotion is not specified" do
|
||||
game = Game.new
|
||||
game.board["e7"] = Piece.from_fen('P')
|
||||
expect_raises(Game::IllegalMove) do
|
||||
game.make_move("e7", "e8")
|
||||
end
|
||||
end
|
||||
|
||||
it "raises an exception when promotion is not specified" do
|
||||
game = Game.new
|
||||
game.board["e7"] = Piece.from_fen('P')
|
||||
game.make_move("e7", "e8", 'Q')
|
||||
piece = game.board["e8"]
|
||||
from = game.board["e7"]
|
||||
from.should be_nil
|
||||
raise "e8 is empty" unless piece
|
||||
piece.fen_symbol.should eq('Q')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -126,7 +126,7 @@ module LxChess
|
|||
end
|
||||
|
||||
# TODO: checkmate
|
||||
def move_to_san(from : Int, to : Int, promotion : String? = nil, turn = @turn)
|
||||
def move_to_san(from : Int, to : Int, promotion : Char? = nil, turn = @turn)
|
||||
raise "No piece at #{@board.cord(from)}" unless piece = @board[from]
|
||||
en_passant = piece.pawn? && to == @en_passant_target
|
||||
|
||||
|
@ -355,6 +355,7 @@ module LxChess
|
|||
if piece.pawn?
|
||||
distance = from - to
|
||||
if distance.abs == @board.width * 2
|
||||
# Double pawn push, set en passant target
|
||||
@en_passant_target = distance > 0 ? to + @board.width : to - @board.width
|
||||
else
|
||||
if to == @en_passant_target
|
||||
|
@ -368,6 +369,22 @@ module LxChess
|
|||
@en_passant_target = nil
|
||||
end
|
||||
|
||||
# Promotion
|
||||
if piece.pawn?
|
||||
rank = @board.rank(to)
|
||||
if rank == 0 || rank == @board.height - 1
|
||||
if promotion
|
||||
raise IllegalMove.new("Cannot promote to #{promotion}") unless "RNBQ".chars.includes?(promotion.upcase)
|
||||
promotion = piece.white? ? promotion.upcase : promotion.downcase
|
||||
@board[from] = Piece.from_fen(promotion)
|
||||
else
|
||||
raise IllegalMove.new("Pawns must promote on the last rank")
|
||||
end
|
||||
elsif promotion
|
||||
raise IllegalMove.new("Cannot promote on #{@board.cord(to)}")
|
||||
end
|
||||
end
|
||||
|
||||
@board.move(from, to)
|
||||
next_turn!
|
||||
@pgn.history << san
|
||||
|
@ -408,6 +425,7 @@ module LxChess
|
|||
|
||||
# Get the next turn index
|
||||
def next_turn
|
||||
return 0.to_i8 if @players.size == 0
|
||||
(@turn + 1) % @players.size
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ module LxChess
|
|||
KNIGHT = 5
|
||||
|
||||
def self.from_fen(fen : Char)
|
||||
raise "#{fen} is not a valid FEN symbol" unless FEN_SYMBOLS.chars.includes?(fen)
|
||||
id = FEN_SYMBOLS.index(fen).as(Int32).to_i8
|
||||
Piece.new(id)
|
||||
end
|
||||
|
|
|
@ -71,7 +71,7 @@ module LxChess
|
|||
end
|
||||
if from && to
|
||||
@gb.clear
|
||||
san = @game.make_move(from, to)
|
||||
san = @game.make_move(from, to, promo)
|
||||
@gb.highlight([@game.board.index(from), @game.board.index(to)])
|
||||
@log.unshift "#{san.to_s}: #{from} => #{to}"
|
||||
end
|
||||
|
@ -84,7 +84,7 @@ module LxChess
|
|||
from, to = @game.parse_san(notation)
|
||||
if from && to
|
||||
@gb.clear
|
||||
san = @game.make_move(from, to)
|
||||
san = @game.make_move(from, to, notation.promotion)
|
||||
@gb.highlight([from.to_i16, to.to_i16])
|
||||
@log.unshift "#{san.to_s}: #{@game.board.cord(from)} => #{@game.board.cord(to)}"
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue