patternrubyMinor
Chess engine in Ruby
Viewed 0 times
chessengineruby
Problem
I've decided to write a Chess engine in Ruby. The first step (before any move generation, AI, search trees, etc.) is to get a solid board representation so the computer and I can effectively communicate the game state to one another. The board representation I am using here is of the 64-bitstring variety. (I implemented one using 0x88 board rep'n too, but that isn't here. From what I understand, having a several representations on hand in memory will be most useful to solve various number-crunching issues that will appear along the way.)
Please offer any advice on the beginnings of this Chess engine.
```
#!/usr/bin/env ruby
#################################################
=begin
A game of chess can be played in the terminal!
User(s) must know the rules because the program knows none.
Moves must be entered as "initial_square-terminal_square",
where the squares must be given in algebraic chess notation
and any whitespace is ok in that entered string.
The program checks if initial square contains a piece of your color
and if the termnal square does not.
There are no other restrictions on piece movement.
No saving, loading, undoing, etc.
Game runs in an infinite loop, so quit with Ctrl-C.
=end
#################################################
class Integer
# out: String = standard chessboard coordinates (e.g., "D4")
# in: Fixnum = coordinates on the 8x16 board in memory
def to_square
if (0..63).to_a.include?(self)
then
square = String.new
square 0
end
return cells_array
end
end
#################################################
class String
# out: String = standard chessboard coordinates (e.g., "A3", "D4")
# in: Fixnum = virtual cell location (e.g., 0,19,51,... )
def to_cell
# check if in standard form
return nil if self.length!= 2
rank = self[0].upcase
file = self[1]
cell = file.to_i*8 + (rank.ord - 65) - 8
return cell
end
end
#################################################
class Ga
Please offer any advice on the beginnings of this Chess engine.
```
#!/usr/bin/env ruby
#################################################
=begin
A game of chess can be played in the terminal!
User(s) must know the rules because the program knows none.
Moves must be entered as "initial_square-terminal_square",
where the squares must be given in algebraic chess notation
and any whitespace is ok in that entered string.
The program checks if initial square contains a piece of your color
and if the termnal square does not.
There are no other restrictions on piece movement.
No saving, loading, undoing, etc.
Game runs in an infinite loop, so quit with Ctrl-C.
=end
#################################################
class Integer
# out: String = standard chessboard coordinates (e.g., "D4")
# in: Fixnum = coordinates on the 8x16 board in memory
def to_square
if (0..63).to_a.include?(self)
then
square = String.new
square 0
end
return cells_array
end
end
#################################################
class String
# out: String = standard chessboard coordinates (e.g., "A3", "D4")
# in: Fixnum = virtual cell location (e.g., 0,19,51,... )
def to_cell
# check if in standard form
return nil if self.length!= 2
rank = self[0].upcase
file = self[1]
cell = file.to_i*8 + (rank.ord - 65) - 8
return cell
end
end
#################################################
class Ga
Solution
I would separate logic from presentation and I would write unit tests from begin on.
I would split
Advantage:
You can write unit tests:
I made a modified version of
This
Very important: Give a response if there is a problem
So the player can get a response and you have the possibility to test the function in your unittest (make an invalid move and check if the error code is correct).
I would split
display in two methods:build_boardis creating a String or an Array
displaywrites the result ofbuild_board
Advantage:
You can write unit tests:
- Check the result of
build_board
- make a move
- check again the result of
build_board.
I made a modified version of
play:def play
user_input = nil
while true do
# show board
display
# request move
initial_cell, terminal_cell = nil
until ! initial_cell.nil? & !terminal_cell.nil? do
print " enter move : "
# get move in D2-D4 format; break apart into array by "-" and remove any whitespace in each piece
user_input = gets.strip.upcase.delete(' ')
#Check user input
case user_input
# if string entered is something like "A4-C5" or " a4 -C5 " etc
when /[A-H][1-8]-[A-H][1-8]/
user_move = user_input.split("-").map { |cell| cell.strip }
# if initial square contains one of your pieces & terminal square does not
if ((2**user_move[0].to_cell & moversPieces) > 0) & ((2**user_move[1].to_cell & ~moversPieces) > 0)
initial_cell, terminal_cell = user_move[0].to_cell, user_move[1].to_cell
end
when 'SAVE' #store
puts "Store not implemented yet"
next
when 'END' #stop the game
puts "Thanks for playing"
exit
else
puts 'Invalid move. Please use ...' ##Add short description of usage ###
next
end #case user_input
end
case make_move(initial_cell,terminal_cell)
when true
@whitesMove = !@whitesMove
when :empty_field
puts "Start field was empty - please redo"
else
puts "Move not done - please redo"
end
end
endThis
play offers the possibility to add more commands (I prepared END and SAVE).Very important: Give a response if there is a problem
make_move should return a result. trueif it is ok, in other cases provide an error code.So the player can get a response and you have the possibility to test the function in your unittest (make an invalid move and check if the error code is correct).
Code Snippets
def play
user_input = nil
while true do
# show board
display
# request move
initial_cell, terminal_cell = nil
until ! initial_cell.nil? & !terminal_cell.nil? do
print " enter move : "
# get move in D2-D4 format; break apart into array by "-" and remove any whitespace in each piece
user_input = gets.strip.upcase.delete(' ')
#Check user input
case user_input
# if string entered is something like "A4-C5" or " a4 -C5 " etc
when /[A-H][1-8]-[A-H][1-8]/
user_move = user_input.split("-").map { |cell| cell.strip }
# if initial square contains one of your pieces & terminal square does not
if ((2**user_move[0].to_cell & moversPieces) > 0) & ((2**user_move[1].to_cell & ~moversPieces) > 0)
initial_cell, terminal_cell = user_move[0].to_cell, user_move[1].to_cell
end
when 'SAVE' #store
puts "Store not implemented yet"
next
when 'END' #stop the game
puts "Thanks for playing"
exit
else
puts 'Invalid move. Please use ...' ##Add short description of usage ###
next
end #case user_input
end
case make_move(initial_cell,terminal_cell)
when true
@whitesMove = !@whitesMove
when :empty_field
puts "Start field was empty - please redo"
else
puts "Move not done - please redo"
end
end
endContext
StackExchange Code Review Q#10832, answer score: 4
Revisions (0)
No revisions yet.