chess 0.2.0 → 0.3.2
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 +5 -5
- data/.github/FUNDING.yml +12 -0
- data/.github/workflows/ruby.yml +58 -0
- data/.gitignore +2 -2
- data/.rubocop.yml +51 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +70 -0
- data/README.md +26 -22
- data/Rakefile +5 -4
- data/chess.gemspec +15 -11
- data/docs/Chess.html +157 -0
- data/docs/Chess/BadNotationError.html +237 -0
- data/docs/Chess/Board.html +1759 -0
- data/docs/Chess/CGame.html +2296 -0
- data/docs/Chess/Game.html +1277 -0
- data/docs/Chess/Gnuchess.html +366 -0
- data/docs/Chess/IllegalMoveError.html +137 -0
- data/docs/Chess/InvalidFenFormatError.html +237 -0
- data/docs/Chess/InvalidPgnFormatError.html +217 -0
- data/docs/Chess/Pgn.html +1477 -0
- data/docs/Chess/UTF8Notation.html +270 -0
- data/docs/_index.html +217 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +497 -0
- data/docs/file.README.html +116 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +116 -0
- data/docs/js/app.js +314 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +531 -0
- data/docs/top-level-namespace.html +110 -0
- data/ext/bitboard.c +1 -1
- data/ext/bitboard.h +1 -1
- data/ext/board.c +1 -1
- data/ext/board.h +1 -1
- data/ext/chess.c +2 -2
- data/ext/chess.h +1 -1
- data/ext/common.c +1 -1
- data/ext/common.h +8 -4
- data/ext/extconf.rb +7 -6
- data/ext/game.c +2 -2
- data/ext/game.h +1 -1
- data/ext/special.c +10 -3
- data/ext/special.h +3 -2
- data/lib/chess/exceptions.rb +2 -5
- data/lib/chess/game.rb +55 -77
- data/lib/chess/gnuchess.rb +24 -27
- data/lib/chess/pgn.rb +32 -26
- data/lib/chess/utf8_notation.rb +3 -3
- data/lib/chess/version.rb +1 -1
- data/test/test_big_pgn_collection.rb +3 -4
- data/test/test_checkmate.rb +4 -6
- data/test/test_errors.rb +22 -0
- data/test/test_fifty_rule_move.rb +2 -4
- data/test/test_game.rb +82 -0
- data/test/test_helper.rb +16 -3
- data/test/test_illegal_moves.rb +1 -3
- data/test/test_insufficient_material.rb +6 -7
- data/test/test_load_fen.rb +11 -1
- data/test/test_move_generator.rb +13 -14
- data/test/test_particular_situations.rb +0 -2
- data/test/test_pgn.rb +82 -1
- data/test/test_pgn_collection.rb +2 -2
- data/test/test_stalemate.rb +1 -3
- data/test/test_threefold_repetition.rb +1 -3
- metadata +145 -15
data/lib/chess/gnuchess.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
3
|
module Chess
|
4
|
-
|
5
4
|
# Use Gnuchess to I.A. _(Only a draft)_.
|
6
5
|
#
|
7
6
|
# To use this module, extend a game object with {Chess::Gnuchess}.
|
@@ -12,7 +11,6 @@ module Chess
|
|
12
11
|
# g.gnuchess_move!
|
13
12
|
# puts g
|
14
13
|
module Gnuchess
|
15
|
-
|
16
14
|
# Returns the next move calculated by Gnuchess.
|
17
15
|
# @return [String] Returns the short algebraic chess notation of the move.
|
18
16
|
def gnuchess_move
|
@@ -24,8 +22,9 @@ module Chess
|
|
24
22
|
pipe.puts(m)
|
25
23
|
end
|
26
24
|
pipe.puts('go')
|
27
|
-
while line = pipe.gets
|
25
|
+
while (line = pipe.gets)
|
28
26
|
raise IllegalMoveError if line.include?('Invalid move')
|
27
|
+
|
29
28
|
match = line.match(/My move is : ([a-h][1-8][a-h][1-8][rkbq]?)/)
|
30
29
|
return match[1] if match
|
31
30
|
end
|
@@ -44,16 +43,25 @@ module Chess
|
|
44
43
|
self.move(next_move) if next_move
|
45
44
|
end
|
46
45
|
|
47
|
-
|
46
|
+
class << self
|
47
|
+
private
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
def included(_mod)
|
50
|
+
raise_if_gnuchess_is_not_installed
|
51
|
+
end
|
52
|
+
|
53
|
+
def extended(_mod)
|
54
|
+
raise_if_gnuchess_is_not_installed
|
55
|
+
end
|
52
56
|
|
53
|
-
|
54
|
-
raise_if_gnuchess_is_not_installed
|
57
|
+
# Raise an exception if Gnuchess is not installed
|
58
|
+
def raise_if_gnuchess_is_not_installed
|
59
|
+
raise 'You must install Gnuchess to use the module Chess::Gnuchess!' unless find_executable0('gnuchess')
|
60
|
+
end
|
55
61
|
end
|
56
62
|
|
63
|
+
private
|
64
|
+
|
57
65
|
def gen_pgn(file_to_save, moves = [])
|
58
66
|
done = false
|
59
67
|
pipe = IO.popen('gnuchess', 'r+')
|
@@ -64,20 +72,18 @@ module Chess
|
|
64
72
|
moves.each do |move|
|
65
73
|
pipe.write("#{move}\n")
|
66
74
|
end
|
67
|
-
|
75
|
+
until done
|
68
76
|
pipe.write("go\n")
|
69
|
-
while line = pipe.gets
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
break
|
74
|
-
elsif line =~ / : 1-0 {White mates}/
|
77
|
+
while (line = pipe.gets)
|
78
|
+
break if /My move is : /.match?(line) || / : resign/.match?(line)
|
79
|
+
|
80
|
+
if / : 1-0 {White mates}/.match?(line)
|
75
81
|
done = :white_won
|
76
82
|
break
|
77
|
-
elsif
|
83
|
+
elsif / : 0-1 {Black mates}/.match?(line)
|
78
84
|
done = :black_won
|
79
85
|
break
|
80
|
-
elsif m = line.match(/1\/2-1\/2 {(.*?)}/)
|
86
|
+
elsif (m = line.match(/1\/2-1\/2 {(.*?)}/))
|
81
87
|
case m[1]
|
82
88
|
when 'Stalemate'
|
83
89
|
done = :stalemate
|
@@ -100,14 +106,5 @@ module Chess
|
|
100
106
|
pipe.close
|
101
107
|
end
|
102
108
|
end
|
103
|
-
|
104
|
-
# Raise an exception if Gnuchess is not installed
|
105
|
-
def self.raise_if_gnuchess_is_not_installed
|
106
|
-
unless find_executable0('gnuchess')
|
107
|
-
raise 'You must install Gnuchess to use the module Chess::Gnuchess!'
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
109
|
end
|
112
|
-
|
113
110
|
end
|
data/lib/chess/pgn.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
module Chess
|
2
|
-
|
3
2
|
# Rappresents a game in PGN (Portable Game Notation) format.
|
4
3
|
class Pgn
|
5
|
-
|
6
4
|
# Array that include PGN standard tags.
|
7
|
-
TAGS = %w
|
5
|
+
TAGS = %w[event site date round white black result].freeze
|
8
6
|
|
9
7
|
# The name of the tournament or match event.
|
10
8
|
# @return [String]
|
@@ -16,7 +14,7 @@ module Chess
|
|
16
14
|
attr_accessor :site
|
17
15
|
# The starting date of the game, in YYYY.MM.DD form. ?? is used for unknown values.
|
18
16
|
# @return [String]
|
19
|
-
|
17
|
+
attr_reader :date
|
20
18
|
# The playing round ordinal of the game within the event.
|
21
19
|
# @return [String]
|
22
20
|
attr_accessor :round
|
@@ -42,7 +40,6 @@ module Chess
|
|
42
40
|
def initialize(filename = nil, check_moves: false)
|
43
41
|
self.load(filename, check_moves: check_moves) if filename
|
44
42
|
@date = '??'
|
45
|
-
@round = '1'
|
46
43
|
end
|
47
44
|
|
48
45
|
# Load a PGN from file.
|
@@ -52,21 +49,30 @@ module Chess
|
|
52
49
|
# @raise [InvalidPgnFormatError]
|
53
50
|
# @raise [IllegalMoveError]
|
54
51
|
def load(filename, check_moves: false)
|
55
|
-
|
56
|
-
|
52
|
+
str = File.open(filename, 'r').read
|
53
|
+
load_from_string(str, check_moves: check_moves)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Load a PGN from string.
|
57
|
+
# @param [String] str The PGN string to load.
|
58
|
+
# @param [Boolean] check_moves If true check if the moves are legal.
|
59
|
+
# @return [Pgn] Returns `self`.
|
60
|
+
# @raise [InvalidPgnFormatError]
|
61
|
+
# @raise [IllegalMoveError]
|
62
|
+
def load_from_string(str, check_moves: false)
|
63
|
+
str.gsub!(/\{.*?\}/, '') # remove comments
|
57
64
|
TAGS.each do |t|
|
58
|
-
instance_variable_set("@#{t}",
|
65
|
+
instance_variable_set("@#{t}", str.match(/^\[#{t.capitalize} ".*"\]\s?$/).to_s.strip[t.size + 3..-3])
|
59
66
|
end
|
60
67
|
@result = '1/2-1/2' if @result == '1/2'
|
61
|
-
game_index =
|
62
|
-
raise Chess::InvalidPgnFormatError.new
|
63
|
-
|
64
|
-
|
65
|
-
@moves
|
68
|
+
game_index = str.index(/^1\./)
|
69
|
+
raise Chess::InvalidPgnFormatError.new if game_index.nil?
|
70
|
+
|
71
|
+
game = str[game_index..-1].strip
|
72
|
+
@moves = game.tr("\n", ' ').split(/\d+\./).collect(&:strip)[1..-1].map(&:split).flatten
|
73
|
+
@moves.delete_at(@moves.size - 1) if @moves.last.match?(/(0-1)|(1-0)|(1\/2)|(1\/2-1\/2)|(\*)/)
|
66
74
|
@moves.each do |m|
|
67
|
-
if m !~ MOVE_REGEXP && m !~ SHORT_CASTLING_REGEXP && m !~ LONG_CASTLING_REGEXP
|
68
|
-
raise Chess::InvalidPgnFormatError.new(filename)
|
69
|
-
end
|
75
|
+
raise Chess::InvalidPgnFormatError.new if m !~ MOVE_REGEXP && m !~ SHORT_CASTLING_REGEXP && m !~ LONG_CASTLING_REGEXP
|
70
76
|
end
|
71
77
|
Chess::Game.new(@moves) if check_moves
|
72
78
|
return self
|
@@ -76,13 +82,13 @@ module Chess
|
|
76
82
|
def to_s
|
77
83
|
s = ''
|
78
84
|
TAGS.each do |t|
|
79
|
-
tag = instance_variable_get("@#{t}")
|
85
|
+
tag = instance_variable_defined?("@#{t}") ? instance_variable_get("@#{t}") : ''
|
80
86
|
s << "[#{t.capitalize} \"#{tag}\"]\n"
|
81
87
|
end
|
82
88
|
s << "\n"
|
83
89
|
m = ''
|
84
90
|
@moves.each_with_index do |move, i|
|
85
|
-
m << "#{i/2+1}. " if i
|
91
|
+
m << "#{i / 2 + 1}. " if i.even?
|
86
92
|
m << "#{move} "
|
87
93
|
end
|
88
94
|
m << @result unless @result.nil?
|
@@ -95,17 +101,17 @@ module Chess
|
|
95
101
|
File.open(filename, 'w') { |f| f.write(self.to_s) }
|
96
102
|
end
|
97
103
|
|
98
|
-
# @!visibility private
|
99
|
-
alias
|
104
|
+
# # @!visibility private
|
105
|
+
# alias old_date= date=
|
100
106
|
|
101
107
|
# Set the date tag.
|
102
108
|
def date=(value)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
109
|
+
@date =
|
110
|
+
if value.is_a?(Time)
|
111
|
+
value.strftime('%Y.%m.%d')
|
112
|
+
else
|
113
|
+
value
|
114
|
+
end
|
108
115
|
end
|
109
|
-
|
110
116
|
end
|
111
117
|
end
|
data/lib/chess/utf8_notation.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Chess
|
2
|
+
# rubocop:disable Style/AsciiComments
|
2
3
|
|
3
4
|
# With this module is possible call the method {#to_utf8} on a string. This
|
4
5
|
# method convert the chess piece identifier character into UTF8 chess
|
@@ -12,7 +13,6 @@ module Chess
|
|
12
13
|
# @note To use this utility explicit require is needed: <tt>require
|
13
14
|
# 'chess/utf8_notation'</tt>
|
14
15
|
module UTF8Notation
|
15
|
-
|
16
16
|
# Map a piece identifier character with the corresponding UTF8 chess
|
17
17
|
# character
|
18
18
|
UTF8_MAP = {
|
@@ -28,15 +28,15 @@ module Chess
|
|
28
28
|
'b' => '♝',
|
29
29
|
'q' => '♛',
|
30
30
|
'k' => '♚'
|
31
|
-
}
|
31
|
+
}.freeze
|
32
32
|
|
33
33
|
# Replace the piece identifier characters with UTF8 chess characters.
|
34
34
|
# @return [String]
|
35
35
|
def to_utf8
|
36
36
|
self.gsub(/[PRNBQKprnbqk]/, UTF8_MAP)
|
37
37
|
end
|
38
|
-
|
39
38
|
end
|
39
|
+
# rubocop:enable Style/AsciiComments
|
40
40
|
end
|
41
41
|
|
42
42
|
String.prepend(Chess::UTF8Notation)
|
data/lib/chess/version.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
if ENV['BIG_PGN_COLLECTION'] && File.exist?(TestHelper::BIG_PGN_COLLECTION)
|
6
5
|
puts 'Loading tests for a big PGN collection...'
|
7
6
|
300_000.times do |i|
|
8
|
-
filename =
|
7
|
+
filename = format('%06d.pgn', i + 1)
|
9
8
|
path = File.join(TestHelper::BIG_PGN_COLLECTION, filename)
|
10
9
|
break unless File.exist?(path)
|
10
|
+
|
11
11
|
define_method "test_big_pgn_#{filename}" do
|
12
12
|
pgn = Chess::Pgn.new(path)
|
13
13
|
game = Chess::Game.new(pgn.moves)
|
14
|
-
assert(game.checkmate?) if pgn.moves.last
|
14
|
+
assert(game.checkmate?) if pgn.moves.last.match?(/\#$/)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
19
18
|
end
|
data/test/test_checkmate.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
TestHelper.pgns('checkmate').each do |file|
|
6
5
|
name = File.basename(file, '.pgn')
|
7
6
|
win = file.include?('white') ? 'white' : 'black'
|
@@ -10,13 +9,12 @@ class ChessTest < Minitest::Test
|
|
10
9
|
game = Chess::Game.new(pgn.moves)
|
11
10
|
assert(game.board.checkmate?)
|
12
11
|
if file.include?('white_won')
|
13
|
-
assert_equal(
|
14
|
-
assert_equal(game.active_player
|
12
|
+
assert_equal('1-0', game.result)
|
13
|
+
assert_equal(:black, game.active_player)
|
15
14
|
elsif file.include?('black_won')
|
16
|
-
assert_equal(
|
17
|
-
assert_equal(game.active_player
|
15
|
+
assert_equal('0-1', game.result)
|
16
|
+
assert_equal(:white, game.active_player)
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|
21
|
-
|
22
20
|
end
|
data/test/test_errors.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ChessTest < Minitest::Test
|
4
|
+
def test_bad_notation_error
|
5
|
+
game = Chess::Game.new
|
6
|
+
assert_raises(Chess::BadNotationError) do
|
7
|
+
game << 'gg'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_invalid_pgn_format_error
|
12
|
+
assert_raises(Chess::InvalidPgnFormatError) do
|
13
|
+
Chess::Pgn.new('test/pgn_collection/invalid/0001.pgn')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_invalid_fen_format_error
|
18
|
+
assert_raises(Chess::InvalidFenFormatError) do
|
19
|
+
Chess::Game.load_fen('invalid')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
TestHelper.pgns('fifty_move_rule').each do |file|
|
6
5
|
name = File.basename(file, '.pgn')
|
7
|
-
define_method "
|
6
|
+
define_method "test_fifty_move_rule_#{name}" do
|
8
7
|
pgn = Chess::Pgn.new(file)
|
9
8
|
game = Chess::Game.new(pgn.moves)
|
10
|
-
assert
|
9
|
+
assert game.board.fifty_move_rule?
|
11
10
|
end
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
data/test/test_game.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ChessTest < Minitest::Test
|
4
|
+
def test_moves
|
5
|
+
game = Chess::Game.new
|
6
|
+
game.moves = %w[e4 e5]
|
7
|
+
assert_equal %w[e4 e5], game.moves
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_active_player
|
11
|
+
game = Chess::Game.new
|
12
|
+
game << 'a3'
|
13
|
+
assert_equal :black, game.active_player
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_inactive_player
|
17
|
+
game = Chess::Game.new
|
18
|
+
game.moves = %w[a3 f5]
|
19
|
+
assert_equal :black, game.inactive_player
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_status_white_won_resign
|
23
|
+
game = Chess::Game.new
|
24
|
+
game.resign(:black)
|
25
|
+
assert_equal :white_won_resign, game.status
|
26
|
+
assert game.over?
|
27
|
+
assert '1-0', game.result
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_status_black_won_resign
|
31
|
+
game = Chess::Game.new
|
32
|
+
game << 'e4'
|
33
|
+
game.resign(:white)
|
34
|
+
assert_equal :black_won_resign, game.status
|
35
|
+
assert game.over?
|
36
|
+
assert '0-1', game.result
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_status_insufficient_material
|
40
|
+
pgn = TestHelper.pick_pgn('insufficient_material/0001.pgn')
|
41
|
+
game = Chess::Game.new(pgn.moves)
|
42
|
+
assert_equal :insufficient_material, game.status
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_status_fifty_move_rule
|
46
|
+
pgn = TestHelper.pick_pgn('fifty_move_rule/0001.pgn')
|
47
|
+
game = Chess::Game.new(pgn.moves)
|
48
|
+
game.draw
|
49
|
+
assert_equal :fifty_move_rule, game.status
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_status_threefold_repetition
|
53
|
+
pgn = TestHelper.pick_pgn('threefold_repetition/0001.pgn')
|
54
|
+
game = Chess::Game.new(pgn.moves)
|
55
|
+
game.draw
|
56
|
+
assert_equal :threefold_repetition, game.status
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_pgn
|
60
|
+
pgn = TestHelper.pick_pgn('valid/0001.pgn')
|
61
|
+
game = Chess::Game.new(pgn.moves)
|
62
|
+
expected_pgn = <<~PGN
|
63
|
+
[Event ""]
|
64
|
+
[Site ""]
|
65
|
+
[Date "??"]
|
66
|
+
[Round ""]
|
67
|
+
[White ""]
|
68
|
+
[Black ""]
|
69
|
+
[Result "*"]
|
70
|
+
|
71
|
+
1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Qxd4 Nc6 5. Bb5 Bd7 6. Bxc6 Bxc6 7. Bg5 Nf6
|
72
|
+
8. Bxf6 gxf6 9. Nc3 e6 10. O-O-O Be7 11. Rhe1 Rg8 12. Qe3 Rxg2 13. Rg1 Rg6 14.
|
73
|
+
Nd4 Qb6 15. h4 O-O-O 16. h5 Rg5 17. Nd5 Bxd5 18. exd5 e5 19. Qh3+ Kb8 20. Nf5
|
74
|
+
Bf8 21. Rxg5 fxg5 22. Ne3 Qb4 23. c4 g4 24. Qxg4 Bh6 25. Kb1 Rc8 26. Rc1 Qd2
|
75
|
+
27. Qf5 Bf4 28. Qc2 Qxc2+ 29. Rxc2 Rg8 30. b4 Rg5 31. c5 e4 32. c6 Rxh5 33.
|
76
|
+
Rc4 f5 34. b5 Rg5 35. Rc3 Be5 36. Rc1 Bd4 37. Nc4 Bc5 38. Ne5 dxe5 39. Rxc5
|
77
|
+
Rg6 40. a4 Rd6 41. a5 b6 42. axb6 axb6 43. Rc2 Rxd5 44. Rb2 h5 45. Ka2 h4 46.
|
78
|
+
Ka3 h3 47. Ka4 Rd1 *
|
79
|
+
PGN
|
80
|
+
assert_equal expected_pgn, game.pgn.to_s
|
81
|
+
end
|
82
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,13 +1,26 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter 'lib/chess/gnuchess.rb'
|
4
|
+
end
|
5
|
+
if ENV['CODECOV'] == 'true'
|
6
|
+
require 'codecov'
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
8
|
+
end
|
9
|
+
|
1
10
|
require 'chess'
|
2
11
|
require 'minitest/autorun'
|
12
|
+
require 'byebug'
|
3
13
|
|
4
14
|
module TestHelper
|
5
|
-
|
6
|
-
|
7
|
-
BIG_PGN_COLLECTION = '/Users/pioz/Code/prog/misc/pgn_collection/pgn'
|
15
|
+
PGN_COLLECTION = 'test/pgn_collection'.freeze
|
16
|
+
BIG_PGN_COLLECTION = '/Users/pioz/Code/prog/misc/pgn_collection/pgn'.freeze
|
8
17
|
|
9
18
|
def self.pgns(path, prefix = PGN_COLLECTION)
|
10
19
|
Dir[File.join(prefix, path, '**/*.pgn')]
|
11
20
|
end
|
12
21
|
|
22
|
+
def self.pick_pgn(path, prefix = PGN_COLLECTION)
|
23
|
+
file = File.join(prefix, path)
|
24
|
+
return Chess::Pgn.new(file)
|
25
|
+
end
|
13
26
|
end
|