Make SAN case sensitive, add ability to specify from to squares

moves that specify the b column get confused with the symbol for
a bishop. More regex magic required for case insensitivity
This commit is contained in:
Alex Clink 2021-09-12 23:37:31 -04:00
parent d750e9cba0
commit d7623482fd
5 changed files with 68 additions and 25 deletions

View file

@ -33,7 +33,9 @@ end
log = [] of String
fen = LxChess::Fen.parse(options["fen_string"])
game = LxChess::Game.new(board: fen.board)
player_white = LxChess::Player.new
player_black = LxChess::Player.new
game = LxChess::Game.new(board: fen.board, players: [player_white, player_black])
gb = LxChess::TermBoard.new(game.board)
term = LxChess::Terminal.new
@ -74,6 +76,22 @@ loop do
from + to
end.compact.join(" | ")
log.unshift move_string
when /\s*([a-z]\d)\s*([a-z]\d)\s*(?:=\s*)?([RNBQ])?/i
if input
if matches = input.downcase.match(/\s*([a-z]\d)\s*([a-z]\d)\s*(?:=\s*)?([RNBQ])?/i)
from = matches[1]
to = matches[2]
promo = if matches[3]?
matches[3][0]
end
if from && to
gb.clear
san = game.make_move(from, to)
gb.highlight([game.board.index(from), game.board.index(to)])
log.unshift "#{san.to_s}: #{from} => #{to}"
end
end
end
when nil
else
if input
@ -81,10 +99,9 @@ loop do
from, to = game.parse_san(notation)
if from && to
gb.clear
piece = game.board.move(from, to)
game.next_turn
san = game.make_move(from, to)
gb.highlight([from.to_i16, to.to_i16])
log.unshift "#{notation.to_s}: #{game.board.cord(from)} => #{game.board.cord(to)}"
log.unshift "#{san.to_s}: #{game.board.cord(from)} => #{game.board.cord(to)}"
end
end
end

View file

@ -20,11 +20,6 @@ module LxChess
@en_passant_target = @board.index(cord)
end
def next_turn
@turn = (@turn == 0 ? 1 : 0).to_i8
@move_clock += 1
end
def full_moves
(@move_clock / 2).to_i16
end
@ -53,7 +48,8 @@ module LxChess
end
end
def move_to_san(from : Int16, to : Int16, promotion : String? = nil)
# TODO: add check, checkmate, etc.
def move_to_san(from : Int, to : Int, promotion : String? = nil)
raise "No piece at #{@board.cord(from)}" unless piece = @board[from]
en_passant = piece.pawn? && to == @en_passant_target
@ -155,5 +151,22 @@ module LxChess
set
end
end
def make_move(from : String, to : String, promotion : Char? = nil)
make_move(from: @board.index(from), to: @board.index(to), promotion: promotion)
end
def make_move(from : Int, to : Int, promotion : Char? = nil)
san = move_to_san(from, to, promotion)
piece = @board.move(from, to)
next_turn
san
end
def next_turn
@turn += 1
@turn = @turn % @players.size
@move_clock += 1
end
end
end

View file

@ -19,22 +19,22 @@ module LxChess
(\+)?\s* # 8. check
(\#)?\s* # 9. checkmate
(e\.?p\.?)?\s* # 10. en passant
\z}ix
\z}x
@match : Regex::MatchData?
property square : String?,
castles_k : Bool,
castles_q : Bool,
en_passant : Bool,
check : Bool,
checkmate : Bool,
takes : Bool,
piece_abbr : Char?,
origin : String?,
promotion : Char?,
from : String?,
to : String?
property square : String?
property castles_k : Bool
property castles_q : Bool
property en_passant : Bool
property check : Bool
property checkmate : Bool
property takes : Bool
getter piece_abbr : Char?
property origin : String?
property promotion : Char?
property from : String?
property to : String?
def initialize(notation : String)
unless match = notation.match(NOTATION_REGEX)
@ -83,7 +83,7 @@ module LxChess
@from = nil,
@to = nil
)
@piece_abbr = "K" if @castles_q || @castles_k
@piece_abbr = 'K' if @castles_q || @castles_k
validate
end
@ -92,6 +92,12 @@ module LxChess
raise InvalidMove.new("Cannot capture while castling") if castles? && takes?
end
def piece_abbr
if abbr = @piece_abbr
abbr.upcase
end
end
def en_passant?
@en_passant
end
@ -146,7 +152,7 @@ module LxChess
when castles_q?
"O-O-O"
else
@piece_abbr
piece_abbr != 'P' || @takes ? piece_abbr : nil
end
if @en_passant

View file

@ -48,5 +48,9 @@ module LxChess
def fen_symbol
FEN_SYMBOLS[@id]
end
def pawn?
@id & 0b0111 == PAWN
end
end
end

View file

@ -1,4 +1,7 @@
module LxChess
property castle_left = true
property castle_right = true
class Player
end
end