Module: ChessData::Moves
- Defined in:
- lib/chess_data/moves.rb
Overview
Moves is a collection of regular expressions and methods to recognise how moves are written in PGN files, and to make the moves on a given board.
As the moves are obtained from PGN files, they are assumed to be correct.
Defined Under Namespace
Classes: KingsideCastles, PawnCapture, PieceMove, PromotionPawnCapture, PromotionPawnMove, QueensideCastles, SimplePawnMove
Constant Summary collapse
- Square =
:nodoc: Regular expressions to match each of the move types.
/[a-h][1-8]/- Piece =
/[KQRBN]/- MatchKingsideCastles =
/^O-O\+?\Z/- MatchQueensideCastles =
/^O-O-O\+?\Z/- MatchPieceMove =
/^(#{Piece})([a-h]?|[1-8]?)x?(#{Square})\+?\Z/- MatchPawnCapture =
/^([a-h])x(#{Square})\+?\Z/- MatchPromotionPawnMove =
/^([a-h][18])=([QqRrBbNn])\+?\Z/- MatchSimplePawnMove =
/^(#{Square})\+?\Z/- MatchPromotionPawnCapture =
/^([a-h])x([a-h][18])=([QqRrBbNn])\+?\Z/- LegalMove =
Combined regular expression, to match a legal move.
/#{MatchKingsideCastles}|#{MatchQueensideCastles}|#{MatchPieceMove}|#{MatchPawnCapture}|#{MatchPromotionPawnMove}|#{MatchSimplePawnMove}|#{MatchPromotionPawnCapture}/
Class Method Summary collapse
- .bishop_can_reach(board, start, finish) ⇒ Object
-
.can_reach(board, piece, start, finish) ⇒ Object
Return true if given piece can move from start square to finish on given board.
- .king_can_reach(start, finish) ⇒ Object
-
.king_left_in_check(board, piece, start, finish) ⇒ Object
Return true if moving the giving piece from start to finish will leave the moving side’s king in check.
- .knight_can_reach(start, finish) ⇒ Object
-
.new_move(string) ⇒ Object
Returns an instance of the appropriate move type.
- .queen_can_reach(board, start, finish) ⇒ Object
- .rook_can_reach(board, start, finish) ⇒ Object
-
.step_h(start, finish) ⇒ Object
Return size of horizontal gap between start and finish.
-
.step_v(start, finish) ⇒ Object
Return size of vertical gap between start and finish.
Class Method Details
.bishop_can_reach(board, start, finish) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/chess_data/moves.rb', line 106 def Moves.bishop_can_reach board, start,finish return false unless Moves.step_h(start,finish) == Moves.step_v(start, finish) start_col, start_row = Board.square_to_coords start end_col, end_row = Board.square_to_coords finish dirn_h = (end_row - start_row) / (end_row - start_row).abs dirn_v = (end_col - start_col) / (end_col - start_col).abs 1.upto(Moves.step_h(start,finish)-1) do |i| square = Board.coords_to_square(start_col+(i*dirn_v), start_row+(i*dirn_h)) unless board[square] == nil return false end end return true end |
.can_reach(board, piece, start, finish) ⇒ Object
Return true if given piece can move from start square to finish on given board.
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/chess_data/moves.rb', line 48 def Moves.can_reach board, piece, start, finish start = start.upcase finish = finish.upcase case piece when "K", "k" then Moves.king_can_reach start, finish when "Q", "q" then Moves.queen_can_reach board, start, finish when "R", "r" then Moves.rook_can_reach board, start, finish when "B", "b" then Moves.bishop_can_reach board, start,finish when "N", "n" then Moves.knight_can_reach start, finish end end |
.king_can_reach(start, finish) ⇒ Object
76 77 78 |
# File 'lib/chess_data/moves.rb', line 76 def Moves.king_can_reach start, finish Moves.step_h(start, finish) <= 1 && Moves.step_v(start, finish) <= 1 end |
.king_left_in_check(board, piece, start, finish) ⇒ Object
Return true if moving the giving piece from start to finish will leave the moving side’s king in check.
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/chess_data/moves.rb', line 64 def Moves.king_left_in_check board, piece, start, finish test_board = board.clone test_board[start] = nil test_board[finish] = piece if board.to_move == "w" test_board.white_king_in_check? else test_board.black_king_in_check? end end |
.knight_can_reach(start, finish) ⇒ Object
122 123 124 125 126 |
# File 'lib/chess_data/moves.rb', line 122 def Moves.knight_can_reach start, finish h = Moves.step_h start, finish v = Moves.step_v start, finish return (h == 2 && v == 1) || (h == 1 && v == 2) end |
.new_move(string) ⇒ Object
Returns an instance of the appropriate move type.
- string
-
a move read from a PGN file.
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/chess_data/moves.rb', line 34 def Moves.new_move string case string when MatchKingsideCastles then KingsideCastles.new when MatchQueensideCastles then QueensideCastles.new when MatchPieceMove then PieceMove.new string when MatchPawnCapture then PawnCapture.new string when MatchPromotionPawnMove then PromotionPawnMove.new string when MatchSimplePawnMove then SimplePawnMove.new string when MatchPromotionPawnCapture then PromotionPawnCapture.new string else raise InvalidMoveError.new("Invalid move: #{string}") end end |
.queen_can_reach(board, start, finish) ⇒ Object
80 81 82 83 |
# File 'lib/chess_data/moves.rb', line 80 def Moves.queen_can_reach board, start,finish Moves.rook_can_reach(board, start, finish) || Moves.bishop_can_reach(board, start, finish) end |
.rook_can_reach(board, start, finish) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/chess_data/moves.rb', line 85 def Moves.rook_can_reach board, start, finish start_col, start_row = Board.square_to_coords start end_col, end_row = Board.square_to_coords finish if start_col == end_col # moving along column row_1 = [start_row, end_row].min + 1 row_2 = [start_row, end_row].max - 1 row_1.upto(row_2) do |row| return false unless board[Board.coords_to_square(start_col, row)] == nil end elsif start_row == end_row # moving along row col_1 = [start_col, end_col].min + 1 col_2 = [start_col, end_col].max - 1 col_1.upto(col_2) do |col| return false unless board[Board.coords_to_square(col, start_row)] == nil end else return false end return true end |
.step_h(start, finish) ⇒ Object
Return size of horizontal gap between start and finish
129 130 131 |
# File 'lib/chess_data/moves.rb', line 129 def Moves.step_h start, finish (start.bytes[0] - finish.bytes[0]).abs end |
.step_v(start, finish) ⇒ Object
Return size of vertical gap between start and finish
134 135 136 |
# File 'lib/chess_data/moves.rb', line 134 def Moves.step_v start, finish (start.bytes[1] - finish.bytes[1]).abs end |