mirror of
https://github.com/SleepingInsomniac/lx_chess_cr
synced 2025-02-05 20:46:29 +01:00
Add pawn captures, FEN placement, board turns
This commit is contained in:
parent
466075bee9
commit
279a9adaaa
6 changed files with 101 additions and 15 deletions
|
@ -48,7 +48,7 @@ describe LxChess::Game do
|
|||
end
|
||||
end
|
||||
|
||||
it "correctly generates black white pawn moves" do
|
||||
it "correctly generates black pawn moves" do
|
||||
game = LxChess::Game.new
|
||||
game.board["e6"] = LxChess::Piece.from_fen('p')
|
||||
if move_set = game.moves("e6")
|
||||
|
@ -59,6 +59,32 @@ describe LxChess::Game do
|
|||
end
|
||||
end
|
||||
|
||||
it "generates captures for white pawns" do
|
||||
game = LxChess::Game.new
|
||||
game.board["e4"] = LxChess::Piece.from_fen('P')
|
||||
game.board["f5"] = LxChess::Piece.from_fen('p')
|
||||
game.board["d5"] = LxChess::Piece.from_fen('p')
|
||||
if move_set = game.moves("e4")
|
||||
debug_board(game, move_set.moves)
|
||||
move_set.moves.map { |m| game.board.cord(m) }.should eq(%w[e5 d5 f5])
|
||||
else
|
||||
raise "no moves"
|
||||
end
|
||||
end
|
||||
|
||||
it "does not generates captures pawns capturing own pieces" do
|
||||
game = LxChess::Game.new
|
||||
game.board["e4"] = LxChess::Piece.from_fen('P')
|
||||
game.board["f5"] = LxChess::Piece.from_fen('P')
|
||||
game.board["d5"] = LxChess::Piece.from_fen('P')
|
||||
if move_set = game.moves("e4")
|
||||
debug_board(game, move_set.moves)
|
||||
move_set.moves.map { |m| game.board.cord(m) }.should eq(%w[e5])
|
||||
else
|
||||
raise "no moves"
|
||||
end
|
||||
end
|
||||
|
||||
it "correctly generates knight moves" do
|
||||
game = LxChess::Game.new
|
||||
game.board["c3"] = LxChess::Piece.from_fen('N')
|
||||
|
|
|
@ -31,27 +31,44 @@ OptionParser.parse do |parser|
|
|||
end
|
||||
end
|
||||
|
||||
log = [] of String
|
||||
fen = LxChess::Fen.parse(options["fen_string"])
|
||||
game = LxChess::Game.new(board: fen.board)
|
||||
gb = LxChess::TermBoard.new(game.board)
|
||||
term = LxChess::Terminal.new
|
||||
|
||||
loop do
|
||||
term.move 0, 0
|
||||
puts fen.placement
|
||||
puts
|
||||
gb.draw
|
||||
puts
|
||||
print " > "
|
||||
puts
|
||||
if game.turn == 0
|
||||
print " #{game.full_moves + 1}. "
|
||||
else
|
||||
print " #{game.full_moves + 1}. ... "
|
||||
end
|
||||
term.trunc
|
||||
input = gets
|
||||
if input
|
||||
notation = LxChess::Notation.new(input)
|
||||
from, to = game.parse_san(notation)
|
||||
if from && to
|
||||
gb.clear
|
||||
piece = game.board.move(from, to)
|
||||
puts "#{notation.to_s}: #{game.board.cord(from)} => #{game.board.cord(to)}"
|
||||
game.next_turn
|
||||
gb.highlight([from.to_i16, to.to_i16])
|
||||
log.unshift "#{notation.to_s}: #{game.board.cord(from)} => #{game.board.cord(to)}"
|
||||
end
|
||||
end
|
||||
rescue e : LxChess::Notation::InvalidNotation
|
||||
puts e.message
|
||||
rescue e : LxChess::Game::SanError
|
||||
puts e.message
|
||||
rescue e : LxChess::Notation::InvalidNotation | LxChess::Game::SanError
|
||||
if msg = e.message
|
||||
log.unshift msg
|
||||
end
|
||||
ensure
|
||||
puts
|
||||
log.each { |l| puts l }
|
||||
end
|
||||
|
||||
# gb.flip!
|
||||
|
|
|
@ -8,7 +8,7 @@ module LxChess
|
|||
|
||||
property :width, :height, :squares
|
||||
|
||||
def initialize(@width : Int = 8, @height : Int = 8)
|
||||
def initialize(@width : Int16 = 8, @height : Int16 = 8)
|
||||
@squares = Array(Piece | Nil).new(@width * @height) { nil }
|
||||
end
|
||||
|
||||
|
@ -42,6 +42,12 @@ module LxChess
|
|||
self[index(x, y)]
|
||||
end
|
||||
|
||||
# Retrieve a piece relative to an index
|
||||
def from(index : Int, x : Int, y : Int)
|
||||
index = index + x + (y * @width)
|
||||
self[index]
|
||||
end
|
||||
|
||||
# Set a piece an the board at a certain *index*
|
||||
def []=(index : Int, piece : Piece | Nil)
|
||||
piece.index = index.to_i16 if piece
|
||||
|
@ -56,7 +62,7 @@ module LxChess
|
|||
# Convert an *x* and *y* position into an index.
|
||||
# Ex: `4, 4` => `36`
|
||||
def index(x : Int, y : Int)
|
||||
(y * @width) + x
|
||||
((y * @width) + x).to_i16
|
||||
end
|
||||
|
||||
# Convert human *cord* into an index on the board.
|
||||
|
|
|
@ -28,7 +28,7 @@ module LxChess
|
|||
height = ranks.size
|
||||
rank = height - 1
|
||||
|
||||
board = Board.new(width, height)
|
||||
board = Board.new(width.to_i16, height.to_i16)
|
||||
ranks.map { |r| r.chars }.each do |pieces|
|
||||
file = 0
|
||||
|
||||
|
@ -71,5 +71,12 @@ module LxChess
|
|||
@fullmove_counter : Int16
|
||||
)
|
||||
end
|
||||
|
||||
def placement
|
||||
@board.map { |piece| piece ? piece.fen_symbol : nil }
|
||||
.each_slice(@board.width)
|
||||
.map { |row| row.chunks { |r| r.nil? }.map { |chunked, values| chunked ? values.size : values.join }.first }
|
||||
.join('/')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,9 +9,20 @@ module LxChess
|
|||
class SanError < Error; end
|
||||
|
||||
property turn : Int8, board : Board
|
||||
property move_clock : Int16
|
||||
|
||||
def initialize(@board : Board = Board.new, @players = [] of Player)
|
||||
@turn = 0
|
||||
@move_clock = 0
|
||||
end
|
||||
|
||||
def next_turn
|
||||
@turn = (@turn == 0 ? 1 : 0).to_i8
|
||||
@move_clock += 1
|
||||
end
|
||||
|
||||
def full_moves
|
||||
(@move_clock / 2).to_i16
|
||||
end
|
||||
|
||||
# Parse standard algebraic notation
|
||||
|
@ -27,11 +38,12 @@ module LxChess
|
|||
end
|
||||
|
||||
raise SanError.new("Ambiguous SAN") if pieces.size > 1
|
||||
raise SanError.new("Illegal move") if pieces.size == 0
|
||||
piece = pieces.first
|
||||
|
||||
# from, to
|
||||
[piece.as(Piece).index, index]
|
||||
if piece = pieces.first?
|
||||
# from, to
|
||||
[piece.index, index]
|
||||
else
|
||||
raise SanError.new("#{notation.to_s} is an illegal move")
|
||||
end
|
||||
end
|
||||
|
||||
# Generate the psuedo-legal moves for a given *square*
|
||||
|
@ -44,8 +56,12 @@ module LxChess
|
|||
case piece.fen_symbol
|
||||
when 'P' # White pawn
|
||||
set.add_vector(x: 0, y: 1, limit: (@board.rank(index) == 1 ? 2 : 1).to_i16)
|
||||
set.add_vector(x: -1, y: 1, limit: 1) if @board.from(index, x: -1, y: 1)
|
||||
set.add_vector(x: 1, y: 1, limit: 1) if @board.from(index, x: 1, y: 1)
|
||||
when 'p' # Black pawn
|
||||
set.add_vector(x: 0, y: -1, limit: (@board.rank(index) == @board.height - 2 ? 2 : 1).to_i16)
|
||||
set.add_vector(x: -1, y: -1, limit: 1) if @board.from(index, x: -1, y: -1)
|
||||
set.add_vector(x: 1, y: -1, limit: 1) if @board.from(index, x: 1, y: -1)
|
||||
when 'B', 'b' # Bishop
|
||||
set.add_vector(x: -1, y: 1, limit: 8)
|
||||
set.add_vector(x: 1, y: 1, limit: 8)
|
||||
|
|
|
@ -24,6 +24,20 @@ module LxChess
|
|||
end
|
||||
|
||||
def initialize(@io = STDOUT)
|
||||
@x = 0
|
||||
@y = 0
|
||||
end
|
||||
|
||||
# Move cursor to line, column
|
||||
def move(x, y)
|
||||
@x = x
|
||||
@y = y
|
||||
@io.print "\033[#{@x};#{@y}H"
|
||||
end
|
||||
|
||||
# Delete the rest of the line from cursor pos
|
||||
def trunc
|
||||
@io.print "\033[K"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue