Fix capture distinction in notation regex

This commit is contained in:
Alex Clink 2021-09-18 17:08:28 -04:00
parent 1397a01aaf
commit c9448fe368
2 changed files with 100 additions and 24 deletions

View file

@ -0,0 +1,74 @@
require "../spec_helper"
require "../../src/lx_chess/notation"
include LxChess
describe Notation do
describe "#new" do
it "parses castling kingside" do
notation = Notation.new("O-O")
notation.castles_k?.should eq(true)
end
it "parses pawn moves" do
notation = Notation.new("e4")
notation.square.should eq("e4")
end
it "parses pawn moves that specify pawn" do
notation = Notation.new("Pe4")
notation.square.should eq("e4")
notation.piece_abbr.should eq('P')
end
it "parses pawn moves that specify captures" do
notation = Notation.new("Pxe4")
notation.square.should eq("e4")
notation.piece_abbr.should eq('P')
notation.takes.should be_true
end
it "parses weird moves from larger boards" do
notation = Notation.new("Pwxr32")
notation.square.should eq("r32")
notation.piece_abbr.should eq('P')
notation.origin.should eq("w")
notation.takes.should be_true
end
it "parses file disambiguation" do
notation = Notation.new("exd5")
notation.origin.should eq("e")
notation.takes.should be_true
notation.square.should eq("d5")
end
it "parses rank disambiguation" do
notation = Notation.new("4xd5")
notation.origin.should eq("4")
notation.takes.should be_true
notation.square.should eq("d5")
end
it "parses bxe5 as a pawn move" do
notation = Notation.new("bxe5")
notation.origin.should eq("b")
notation.takes.should be_true
notation.square.should eq("e5")
end
it "parses Bxe5 as a bishop move" do
notation = Notation.new("Bxe5")
notation.piece_abbr.should eq('B')
notation.takes.should be_true
notation.square.should eq("e5")
end
it "parses promotions" do
notation = Notation.new("dxe8=Q")
notation.takes.should be_true
notation.square.should eq("e8")
notation.promotion.should eq('Q')
end
end
end

View file

@ -10,18 +10,20 @@ module LxChess
class InvalidMove < Error; end
NOTATION_REGEX = %r{\A\s*
(^[O0]-[O0])?\s* # 1. castles kingside
(^[O0]-[O0]-[O0])?\s* # 2. castles queenside
(^[RNBQKP](?!\d$))?\s* # 3. piece abbreviation
((?:[a-z]|\d|[a-z]\d)(?=.*?[a-z]\d))?\s* # 4. origin square
(x)?\s* # 5. takes
([a-z]\d)?\s* # 6. destination square
(\=\s*[RNBQ])?\s* # 7. promotion
(\+)?\s* # 8. check
(\#)?\s* # 9. checkmate
(e\.?p\.?)?\s* # 10. en passant
\z}x
NOTATION_REGEX = %r{
\A\s*
(?<castle_k> ^[Oo0]-[Oo0] )?\s*
(?<castle_q> ^[Oo0]-[Oo0]-[Oo0] )?\s*
(?<piece_abbr> ^[RNBQKP](?!\d$) )?\s*
(?<origin> (?:[a-wyz]|\d+|[a-z]\d+)(?=\s*x?\s*[a-z]\d+) )?\s*
(?<takes> x )?\s*
(?<dest> [a-z]\d+ )?\s*
(?<promo> \=\s*[RNBQrnbq] )?\s*
(?<check> \+ )?\s*
(?<checkmate> \# )?\s*
(?<en_passent> e\.?p\.? )?\s*
\z
}x
@match : Regex::MatchData?
@ -47,23 +49,23 @@ module LxChess
@square = _square.downcase
end
@castles_k = match[1]? ? true : false
@castles_q = match[2]? ? true : false
@en_passant = match[10]? ? true : false
@check = match[8]? ? true : false
@checkmate = match[9]? ? true : false
@takes = match[5]? ? true : false
@castles_k = match["castle_k"]? ? true : false
@castles_q = match["castle_q"]? ? true : false
@en_passant = match["en_passant"]? ? true : false
@check = match["check"]? ? true : false
@checkmate = match["checkmate"]? ? true : false
@takes = match["takes"]? ? true : false
if _piece_abbr = match[3]?
@piece_abbr = _piece_abbr[0].upcase
match["piece_abbr"]?.try do |abbr|
@piece_abbr = abbr[0].upcase
end
if _origin = match[4]?
@origin = _origin.downcase
match["origin"]?.try do |origin|
@origin = origin.downcase
end
if _promo = match[7]?
@promotion = _promo[-1].upcase
match["promo"]?.try do |promo|
@promotion = promo[-1].upcase
end
@from = nil