chess_validator 0.2.18 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 202313773f05394e520671d1b1eeab59d276538e61d964bb9bd21597ce7042d7
4
- data.tar.gz: 752963d28e3592b347f1db3c417e9db721615ddf188052191c92086b3f5fa42e
3
+ metadata.gz: bc464703452ec24fc25c8d122099e52b9788ef81df4d2a3acd2fca332d86c7b2
4
+ data.tar.gz: 11ca33717e5306eaf1538ecb65b55280bfd0c6f5f7b485cd78d540e36d72d726
5
5
  SHA512:
6
- metadata.gz: 0cd85183d720a2465656083e73762239ffae92b3bf76642f295a409018c1f428cccda0f0fa56e36c706a4f98b5c3d62a14865c13294905392b14c397893ecb8b
7
- data.tar.gz: 903adcb0813f761a5eaa293beac38d19091168f4bb3bb5f8f9fd49669471bf209df438301fb6ad49057f6fd6d0b0af54add121891ccfe63a4289c77f55e2ac69
6
+ metadata.gz: 4f4e734ca21f8022cf210effe194057edd9c4302574ce15dc3929858f0426d1992f32c0ab185bf38236ceb6b05fc380a1934589a575eb5278598e96c13826ec5
7
+ data.tar.gz: 2a60f66b946b0e8203c0c79cf8d772b483befbd82b1935ddfa959fe9c424d8056fba1aa5978dfcf6b9d0b7413840b0f85ddc58f22de7a90485b0c79f4e923c62
data/lib/board_logic.rb CHANGED
@@ -3,9 +3,13 @@ require 'piece'
3
3
  module ChessValidator
4
4
  class BoardLogic
5
5
  def self.build_board(fen)
6
+ build_board_from_string(fen.board_string)
7
+ end
8
+
9
+ def self.build_board_from_string(board_string)
6
10
  board = {}
7
11
  square_index = 1
8
- fen.board_string.chars.each do |char|
12
+ board_string.chars.each do |char|
9
13
  if empty_square?(char)
10
14
  square_index += char.to_i
11
15
  elsif char != '/'
@@ -23,7 +27,7 @@ module ChessValidator
23
27
  notation += handle_castle(previous_fen.castling, piece, board)
24
28
  notation += handle_en_passant(piece, move)
25
29
  notation += handle_half_move_clock(previous_fen, piece.piece_type, captured)
26
- notation += piece.color == 'b' ? previous_fen.fullmove.next : previous_fen.fullmove
30
+ notation += piece.color == 'b' ? previous_fen.fullmove&.next.to_s : previous_fen.fullmove.to_s
27
31
  notation
28
32
  end
29
33
 
@@ -38,10 +42,10 @@ module ChessValidator
38
42
  def self.handle_castle(castling, piece, board)
39
43
  return castling if castling == '-'
40
44
  castling.delete!('K') if board[64].nil? || board[64].piece_type != 'R'
41
- castling.delete!('K') if board[61].nil? || board[61].piece_type != 'K'
45
+ castling.delete!('KQ') if board[61].nil? || board[61].piece_type != 'K'
42
46
  castling.delete!('Q') if board[57].nil? || board[57].piece_type != 'R'
43
47
  castling.delete!('k') if board[8].nil? || board[8].piece_type != 'r'
44
- castling.delete!('k') if board[5].nil? || board[5].piece_type != 'k'
48
+ castling.delete!('kq') if board[5].nil? || board[5].piece_type != 'k'
45
49
  castling.delete!('q') if board[1].nil? || board[1].piece_type != 'r'
46
50
  castling.size == 0 ? '-' : castling
47
51
  end
data/lib/engine.rb CHANGED
@@ -32,6 +32,10 @@ module ChessValidator
32
32
  def result(fen_notation)
33
33
  GameLogic.find_game_result(fen_notation)
34
34
  end
35
+
36
+ def defended_pieces(fen_notatioin)
37
+ MoveLogic.defended_pieces_by_square(fen_notation)
38
+ end
35
39
  end
36
40
  end
37
41
  end
data/lib/move_logic.rb CHANGED
@@ -4,19 +4,79 @@ require 'pgn'
4
4
  module ChessValidator
5
5
  class MoveLogic
6
6
  class << self
7
+ MAX_CACHE_SIZE = 1000
8
+
7
9
  def next_moves(fen)
8
- board = BoardLogic.build_board(fen)
10
+ fen_notation = fen.to_s
11
+ return next_moves_for[fen_notation] if next_moves_for[fen_notation]
12
+
13
+ board = get_board(fen.to_s)
9
14
  pieces = []
15
+
10
16
  board.values.each do |piece|
11
17
  if piece.color == fen.active
12
18
  load_move_data(board, piece, fen)
13
19
  pieces << piece if piece.valid_moves.size > 0
14
20
  end
15
21
  end
22
+ next_moves_for[fen_notation] = pieces
16
23
 
17
24
  pieces
18
25
  end
19
26
 
27
+ def boards
28
+ if @boards.nil? || @boards.size > MAX_CACHE_SIZE
29
+ @boards = {}
30
+ end
31
+
32
+ @boards
33
+ end
34
+
35
+ def next_moves_for
36
+ if @next_moves_for.nil? || @next_moves_for.size > MAX_CACHE_SIZE
37
+ @next_moves_for = {}
38
+ end
39
+
40
+ @next_moves_for
41
+ end
42
+
43
+ def occupied_square_sets
44
+ if @occupied_square_sets.nil? || @occupied_square_sets.size > MAX_CACHE_SIZE
45
+ @occupied_square_sets = {}
46
+ end
47
+
48
+ @occupied_square_sets
49
+ end
50
+
51
+ def defended_sets
52
+ if @defended_sets.nil? || @defended_sets.size > MAX_CACHE_SIZE
53
+ @defended_sets = {}
54
+ end
55
+
56
+ @defended_sets
57
+ end
58
+
59
+ def get_board(fen_string)
60
+ return boards[fen_string] if boards[fen_string]
61
+
62
+ board = BoardLogic.build_board_from_string(fen_string.split.first)
63
+ boards[fen_string] = board
64
+ board
65
+ end
66
+
67
+
68
+ def get_occupied_spaces(fen_string)
69
+ return occupied_square_sets[fen_string] if occupied_square_sets[fen_string]
70
+ board = get_board(fen_string)
71
+
72
+ occupied_spaces = []
73
+ board.values.each { |p| occupied_spaces << p.position }
74
+
75
+ occupied_square_sets[fen_string] = occupied_spaces
76
+ occupied_spaces
77
+ end
78
+
79
+
20
80
  def load_move_data(board, piece, fen)
21
81
  moves_for_piece(piece).each do |move|
22
82
  if valid_move?(piece, board, move, fen)
@@ -41,14 +101,13 @@ module ChessValidator
41
101
  end
42
102
 
43
103
  def valid_move?(piece, board, move, fen)
44
- occupied_spaces = []
45
- board.values.each { |p| occupied_spaces << p.position }
46
104
  case piece.piece_type.downcase
47
105
  when 'k'
48
- handle_king(piece, board, move, fen, occupied_spaces)
106
+ handle_king(piece, board, move, fen) && valid_destination?(piece, board, move)
49
107
  when 'p'
50
108
  handle_pawn(piece, board, move, fen)
51
109
  else
110
+ occupied_spaces = get_occupied_spaces(fen.to_s)
52
111
  valid_move_path?(piece, move, occupied_spaces) &&
53
112
  valid_destination?(piece, board, move) &&
54
113
  king_will_be_safe?(piece, board, move)
@@ -112,10 +171,9 @@ module ChessValidator
112
171
  end
113
172
 
114
173
  def make_move(piece, move, fen_notation)
115
- fen = PGN::FEN.new(fen_notation)
116
- board = BoardLogic.build_board(fen)
174
+ board = get_board(fen_notation)
117
175
  new_board = with_next_move(piece, board, move)
118
-
176
+ fen = PGN::FEN.new(fen_notation)
119
177
  BoardLogic.to_fen_notation(new_board, fen, piece, move, board[INDEX_KEY[move]])
120
178
  end
121
179
 
@@ -135,16 +193,16 @@ module ChessValidator
135
193
  end
136
194
 
137
195
  def find_king_and_spaces(board, color)
138
- occupied_spaces = []
139
196
  king = nil
140
- board.values.each do |p|
197
+ occupied_spaces = board.values.map do |p|
141
198
  king = p if p.piece_type.downcase == 'k' && p.color == color
142
- occupied_spaces << p.position
199
+ p.position
143
200
  end
201
+
144
202
  [king, occupied_spaces]
145
203
  end
146
204
 
147
- def handle_king(king, board, move, fen, occupied_spaces)
205
+ def handle_king(king, board, move, fen)
148
206
  if (king.position[0].ord - move[0].ord).abs == 2
149
207
  empty_b_square = true
150
208
  if move[0] == 'c'
@@ -155,6 +213,8 @@ module ChessValidator
155
213
  castle_code = 'k'
156
214
  between = 'f' + move[1]
157
215
  end
216
+ occupied_spaces = get_occupied_spaces(fen.to_s)
217
+
158
218
  (fen.castling.include?(castle_code) && king.color == 'b' || fen.castling.include?(castle_code.upcase) && king.color == 'w') &&
159
219
  king_is_safe?(king.color, board, king.position, occupied_spaces) &&
160
220
  king_is_safe?(king.color, board, between, occupied_spaces) &&
@@ -162,7 +222,7 @@ module ChessValidator
162
222
  board.values.none? { |piece| [between, move].include?(piece.position) } &&
163
223
  empty_b_square
164
224
  else
165
- valid_destination?(king, board, move) && king_will_be_safe?(king, board, move)
225
+ king_will_be_safe?(king, board, move)
166
226
  end
167
227
  end
168
228
 
@@ -271,6 +331,49 @@ module ChessValidator
271
331
  !(move_path & occupied_spaces).empty?
272
332
  end
273
333
 
334
+ def can_defend?(piece, board, position, fen)
335
+ case piece.piece_type.downcase
336
+ when 'k'
337
+ handle_king(piece, board, position, fen)
338
+ when 'p'
339
+ if piece.position[0] != position[0]
340
+ target_piece = find_piece(board, position)
341
+ valid = (target_piece && target_piece.color != piece.color) || position == fen.en_passant
342
+ valid && king_will_be_safe?(piece, board, position)
343
+ end
344
+ else
345
+ occupied_spaces = get_occupied_spaces(fen.to_s)
346
+ valid_move_path?(piece, position, occupied_spaces) && king_will_be_safe?(piece, board, position)
347
+ end
348
+ end
349
+
350
+ def defended_pieces_by_square(fen_notation)
351
+ return defended_sets[fen_notatioin] if defended_sets[fen_notatioin]
352
+
353
+ board = get_board(fen_notation)
354
+
355
+ fen = PGN::FEN.new(fen_notation)
356
+ space_index = {}
357
+
358
+ pieces = board.values.map do |piece|
359
+ space_index[piece.position] = piece.piece_type + piece.color
360
+ piece
361
+ end
362
+
363
+ defended = Hash.new([])
364
+
365
+ pieces.each do |piece|
366
+ moves_for_piece(piece).each do |move|
367
+ if space_index[move] && space_index[move][-1] == piece.color && can_defend?(piece, board, move, fen)
368
+ defended[move] += [piece]
369
+ end
370
+ end
371
+ end
372
+
373
+ defended_sets[fen_notatioin] = defended
374
+ defended
375
+ end
376
+
274
377
  def moves_for_piece(piece)
275
378
  case piece.piece_type.downcase
276
379
  when 'r'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chess_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.18
4
+ version: 0.2.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Ellison
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-16 00:00:00.000000000 Z
11
+ date: 2020-01-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'Documentation: https://github.com/chadellison/chess_validator'
14
14
  email: chad.ellison0123@gmail.com
@@ -27,7 +27,7 @@ homepage: https://rubygems.org/search?utf8=%E2%9C%93&query=chess_validator
27
27
  licenses:
28
28
  - MIT
29
29
  metadata: {}
30
- post_install_message:
30
+ post_install_message:
31
31
  rdoc_options: []
32
32
  require_paths:
33
33
  - lib
@@ -42,8 +42,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
44
  requirements: []
45
- rubygems_version: 3.1.2
46
- signing_key:
45
+ rubygems_version: 3.2.3
46
+ signing_key:
47
47
  specification_version: 4
48
48
  summary: A chess move validator
49
49
  test_files: []