Fix fen placement string, disambiguate moves from san

This commit is contained in:
Alex Clink 2021-09-12 00:01:54 -04:00
parent 279a9adaaa
commit 39010fcdf2
4 changed files with 47 additions and 8 deletions

View file

@ -39,7 +39,9 @@ term = LxChess::Terminal.new
loop do loop do
term.move 0, 0 term.move 0, 0
puts fen.placement print fen.placement
term.trunc
puts
puts puts
gb.draw gb.draw
puts puts
@ -68,7 +70,10 @@ rescue e : LxChess::Notation::InvalidNotation | LxChess::Game::SanError
end end
ensure ensure
puts puts
log.each { |l| puts l } log.each { |l| print l; term.trunc; puts }
until log.size < 8
log.pop
end
end end
# gb.flip! # gb.flip!

View file

@ -68,7 +68,7 @@ module LxChess
# Convert human *cord* into an index on the board. # Convert human *cord* into an index on the board.
# Ex: `A1` => `0` # Ex: `A1` => `0`
def index(cord : String) def index(cord : String)
x = LETTERS.index(cord[0]) || 0 x = LETTERS.index(cord[0].downcase) || 0
y = cord[1].to_i - 1 y = cord[1].to_i - 1
index(x, y) index(x, y)
end end
@ -102,11 +102,16 @@ module LxChess
index + (@width - dist_left) - 1 index + (@width - dist_left) - 1
end end
def rank(index) def rank(index : Int16)
rank, _ = index.divmod(@width) rank, _ = index.divmod(@width)
rank rank
end end
def file(index : Int16)
_, file = index.divmod(@width)
file
end
def move(from : (String | Int), to : (String | Int)) def move(from : (String | Int), to : (String | Int))
piece = self[from.to_i16] piece = self[from.to_i16]
self[from.to_i16] = nil self[from.to_i16] = nil

View file

@ -73,10 +73,10 @@ module LxChess
end end
def placement def placement
@board.map { |piece| piece ? piece.fen_symbol : nil } rows = @board.map { |piece| piece ? piece.fen_symbol : nil }
.each_slice(@board.width) .each_slice(@board.width)
.map { |row| row.chunks { |r| r.nil? }.map { |chunked, values| chunked ? values.size : values.join }.first } .map { |row| row.chunks { |r| r.nil? }.map { |chunked, values| chunked ? values.size : values.join }.join }
.join('/') .to_a.reverse.join('/')
end end
end end
end end

View file

@ -37,7 +37,10 @@ module LxChess
end end
end end
raise SanError.new("Ambiguous SAN") if pieces.size > 1 if pieces.size > 1
pieces = disambiguate_candidates(notation, pieces)
end
raise SanError.new("#{notation.to_s} is ambiguous") if pieces.size > 1
if piece = pieces.first? if piece = pieces.first?
# from, to # from, to
[piece.index, index] [piece.index, index]
@ -46,6 +49,32 @@ module LxChess
end end
end end
# Attempt to reduce ambiguities in candidate moves
def disambiguate_candidates(notation : Notation, pieces : Array(Piece | Nil))
return pieces unless origin = notation.origin
case origin
when /[a-z]\d/
piece = @board[origin]
pieces.select { |c| c == piece }
when /[a-z]/
file = Board::LETTERS.index(origin[0].downcase) || 0
pieces.select do |c|
next unless c
next unless index = c.index
@board.file(index) == file
end
when /\d/
rank = origin.to_i16
pieces.select do |c|
next unless c
next unless index = c.index
@board.rank(index) == rank
end
else
pieces
end
end
# Generate the psuedo-legal moves for a given *square* # Generate the psuedo-legal moves for a given *square*
# TODO: add en passant, add boundaries, remove illegal moves # TODO: add en passant, add boundaries, remove illegal moves
def moves(square : (String | Int)) def moves(square : (String | Int))