chess 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +186 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/Rakefile +4 -4
- data/chess.gemspec +9 -8
- data/ext/extconf.rb +6 -6
- data/lib/chess/exceptions.rb +2 -5
- data/lib/chess/game.rb +46 -54
- data/lib/chess/gnuchess.rb +60 -59
- data/lib/chess/pgn.rb +25 -17
- data/lib/chess/utf8_notation.rb +1 -4
- data/lib/chess/version.rb +1 -1
- data/test/test_big_pgn_collection.rb +2 -3
- data/test/test_checkmate.rb +0 -2
- data/test/test_fifty_rule_move.rb +0 -2
- data/test/test_helper.rb +2 -4
- data/test/test_illegal_moves.rb +1 -3
- data/test/test_insufficient_material.rb +2 -3
- data/test/test_load_fen.rb +0 -2
- data/test/test_move_generator.rb +12 -14
- data/test/test_particular_situations.rb +0 -2
- data/test/test_pgn.rb +47 -1
- data/test/test_stalemate.rb +0 -2
- data/test/test_threefold_repetition.rb +0 -2
- metadata +39 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4cc1db854c4be0ade586baddccf252d377a4429e4ec9663ca893c02678c97113
|
4
|
+
data.tar.gz: '0494c3fea2208b2d4c47c705678b6595d11578b5da6296ef8136af79b4ae95fe'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7e2971e83ee9aa24caccbd23825df3bfc959c47ab8d68db5ae48af24fcc78044854a1339091c7c54a9f536707fe16ca512adb886c835f5ec32a9891a286623b
|
7
|
+
data.tar.gz: 8008eb2294ec8b9860dd03e02fd7207cfd37b4292f6d16b5ba1a24e047bdb42e62b5a05e6ac21f126899a8a4299c45bf42310c1e2001277dcf76d86a6a2547ea
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require: rubocop-performance
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- bin/*
|
6
|
+
- db/migrate/*
|
7
|
+
- db/schema.rb
|
8
|
+
- db/seeds.rb
|
9
|
+
- lib/*/Gemfile
|
10
|
+
- lib/*/Rakefile
|
11
|
+
- lib/*/bin/*
|
12
|
+
- lib/*/*.gemspec
|
13
|
+
- node_modules/**/*
|
14
|
+
- spec/**/*
|
15
|
+
- tmp/**/*
|
16
|
+
|
17
|
+
Gemspec/RequiredRubyVersion:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Layout/AlignHash:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Layout/AlignParameters:
|
24
|
+
EnforcedStyle: with_fixed_indentation
|
25
|
+
|
26
|
+
Layout/EmptyLinesAroundBlockBody:
|
27
|
+
EnforcedStyle: no_empty_lines
|
28
|
+
|
29
|
+
Layout/EmptyLinesAroundClassBody:
|
30
|
+
EnforcedStyle: no_empty_lines
|
31
|
+
|
32
|
+
Layout/IndentationConsistency:
|
33
|
+
EnforcedStyle: rails
|
34
|
+
|
35
|
+
Layout/IndentFirstArrayElement:
|
36
|
+
EnforcedStyle: consistent
|
37
|
+
|
38
|
+
Layout/IndentFirstHashElement:
|
39
|
+
EnforcedStyle: consistent
|
40
|
+
|
41
|
+
Layout/MultilineMethodCallIndentation:
|
42
|
+
EnforcedStyle: indented
|
43
|
+
|
44
|
+
Layout/MultilineOperationIndentation:
|
45
|
+
EnforcedStyle: indented
|
46
|
+
|
47
|
+
Metrics/AbcSize:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Metrics/BlockLength:
|
51
|
+
Max: 100
|
52
|
+
|
53
|
+
Metrics/BlockNesting:
|
54
|
+
Max: 4
|
55
|
+
|
56
|
+
Metrics/ClassLength:
|
57
|
+
Max: 1000
|
58
|
+
|
59
|
+
Metrics/CyclomaticComplexity:
|
60
|
+
Max: 15
|
61
|
+
|
62
|
+
Metrics/LineLength:
|
63
|
+
Enabled: false
|
64
|
+
Max: 120
|
65
|
+
|
66
|
+
Metrics/MethodLength:
|
67
|
+
Max: 100
|
68
|
+
|
69
|
+
Metrics/ModuleLength:
|
70
|
+
Max: 1000
|
71
|
+
|
72
|
+
Metrics/ParameterLists:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
Metrics/PerceivedComplexity:
|
76
|
+
Max: 20
|
77
|
+
|
78
|
+
Performance/Casecmp:
|
79
|
+
Enabled: false
|
80
|
+
|
81
|
+
Rails:
|
82
|
+
Enabled: true
|
83
|
+
|
84
|
+
Rails/HasAndBelongsToMany:
|
85
|
+
Enabled: false
|
86
|
+
|
87
|
+
Rails/HasManyOrHasOneDependent:
|
88
|
+
Enabled: false
|
89
|
+
|
90
|
+
Rails/InverseOf:
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
Rails/OutputSafety:
|
94
|
+
Enabled: false
|
95
|
+
|
96
|
+
Rails/SafeNavigation:
|
97
|
+
ConvertTry: true
|
98
|
+
|
99
|
+
Rails/SkipsModelValidations:
|
100
|
+
Enabled: false
|
101
|
+
|
102
|
+
Rails/UnknownEnv:
|
103
|
+
Environments:
|
104
|
+
- development
|
105
|
+
- test
|
106
|
+
- simulation
|
107
|
+
- staging
|
108
|
+
- production
|
109
|
+
|
110
|
+
Style/AsciiComments:
|
111
|
+
Enabled: false
|
112
|
+
|
113
|
+
Style/BlockDelimiters:
|
114
|
+
Enabled: false
|
115
|
+
|
116
|
+
Style/BracesAroundHashParameters:
|
117
|
+
Enabled: false
|
118
|
+
|
119
|
+
Style/ClassAndModuleChildren:
|
120
|
+
Enabled: false
|
121
|
+
|
122
|
+
Style/ClassVars:
|
123
|
+
Enabled: false
|
124
|
+
|
125
|
+
Style/ConditionalAssignment:
|
126
|
+
Enabled: false
|
127
|
+
|
128
|
+
Style/Documentation:
|
129
|
+
Enabled: false
|
130
|
+
|
131
|
+
Style/EmptyMethod:
|
132
|
+
EnforcedStyle: expanded
|
133
|
+
|
134
|
+
Style/FormatStringToken:
|
135
|
+
EnforcedStyle: template
|
136
|
+
|
137
|
+
Style/FrozenStringLiteralComment:
|
138
|
+
Enabled: false
|
139
|
+
|
140
|
+
Style/GlobalVars:
|
141
|
+
Enabled: false
|
142
|
+
|
143
|
+
Style/GuardClause:
|
144
|
+
Enabled: false
|
145
|
+
|
146
|
+
Style/IfUnlessModifier:
|
147
|
+
Enabled: false
|
148
|
+
|
149
|
+
Style/Lambda:
|
150
|
+
EnforcedStyle: literal
|
151
|
+
|
152
|
+
Style/MethodDefParentheses:
|
153
|
+
Enabled: false
|
154
|
+
|
155
|
+
Style/NegatedIf:
|
156
|
+
Enabled: false
|
157
|
+
|
158
|
+
Style/Next:
|
159
|
+
Enabled: false
|
160
|
+
|
161
|
+
Style/NumericPredicate:
|
162
|
+
Enabled: false
|
163
|
+
|
164
|
+
Style/RaiseArgs:
|
165
|
+
EnforcedStyle: compact
|
166
|
+
|
167
|
+
Style/RedundantReturn:
|
168
|
+
Enabled: false
|
169
|
+
|
170
|
+
Style/RedundantSelf:
|
171
|
+
Enabled: false
|
172
|
+
|
173
|
+
Style/RegexpLiteral:
|
174
|
+
AllowInnerSlashes: true
|
175
|
+
|
176
|
+
Style/RescueModifier:
|
177
|
+
Enabled: false
|
178
|
+
|
179
|
+
Style/SafeNavigation:
|
180
|
+
Enabled: true
|
181
|
+
|
182
|
+
Style/SingleLineMethods:
|
183
|
+
Enabled: false
|
184
|
+
|
185
|
+
Style/SymbolArray:
|
186
|
+
Enabled: false
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -2,10 +2,10 @@ require 'bundler/gem_tasks'
|
|
2
2
|
|
3
3
|
require 'yard'
|
4
4
|
YARD::Rake::YardocTask.new do |t|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
t.files = ['lib/**/*.rb', 'ext/*.c']
|
6
|
+
t.options << '-rREADME.md'
|
7
|
+
t.options << '--title=Chess'
|
8
|
+
t.options << '-mmarkdown'
|
9
9
|
end
|
10
10
|
|
11
11
|
require 'rake/testtask'
|
data/chess.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
$:.push File.expand_path('../lib', __FILE__)
|
1
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
3
2
|
require 'chess/version'
|
4
3
|
|
5
4
|
Gem::Specification.new do |s|
|
@@ -8,21 +7,23 @@ Gem::Specification.new do |s|
|
|
8
7
|
s.authors = ['Enrico Pilotto']
|
9
8
|
s.email = ['epilotto@gmx.com']
|
10
9
|
s.homepage = 'https://github.com/pioz/chess'
|
11
|
-
s.summary =
|
12
|
-
s.description =
|
10
|
+
s.summary = 'A fast chess library to play chess with Ruby.'
|
11
|
+
s.description = 'A fast chess library that use bitboards to play chess with Ruby.'
|
13
12
|
s.license = 'LGPLv3'
|
14
13
|
|
15
14
|
s.rubyforge_project = 'chess'
|
16
15
|
|
17
16
|
s.files = `git ls-files`.split("\n")
|
18
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
20
19
|
s.extensions = ['ext/extconf.rb']
|
21
20
|
s.require_paths = ['lib']
|
22
21
|
|
23
22
|
s.required_ruby_version = '>= 1.9'
|
24
|
-
s.add_development_dependency 'bundler', '~>
|
25
|
-
s.add_development_dependency '
|
26
|
-
s.add_development_dependency '
|
23
|
+
s.add_development_dependency 'bundler', '~> 2'
|
24
|
+
s.add_development_dependency 'minitest', '~> 5'
|
25
|
+
s.add_development_dependency 'rake', '~> 12'
|
26
|
+
s.add_development_dependency 'rubocop', '~> 0.71'
|
27
|
+
s.add_development_dependency 'rubocop-performance', '~> 1'
|
27
28
|
s.add_development_dependency 'yard', '~> 0.9'
|
28
29
|
end
|
data/ext/extconf.rb
CHANGED
@@ -10,8 +10,8 @@ INCLUDE_DIRS = [
|
|
10
10
|
# Then search /usr/local for people that installed from source
|
11
11
|
'/usr/local/include',
|
12
12
|
# Finally fall back to /usr
|
13
|
-
'/usr/include'
|
14
|
-
]
|
13
|
+
'/usr/include'
|
14
|
+
].freeze
|
15
15
|
|
16
16
|
LIB_DIRS = [
|
17
17
|
# Check the ruby install locations
|
@@ -21,10 +21,10 @@ LIB_DIRS = [
|
|
21
21
|
# Then search /usr/local for people that installed from source
|
22
22
|
'/usr/local/lib',
|
23
23
|
# Finally fall back to /usr
|
24
|
-
'/usr/lib'
|
25
|
-
]
|
24
|
+
'/usr/lib'
|
25
|
+
].freeze
|
26
26
|
|
27
|
-
#dir_config('chess', INCLUDE_DIRS, LIB_DIRS)
|
28
|
-
$CFLAGS <<
|
27
|
+
# dir_config('chess', INCLUDE_DIRS, LIB_DIRS)
|
28
|
+
$CFLAGS << ' -std=c99'
|
29
29
|
|
30
30
|
create_makefile('chess/chess')
|
data/lib/chess/exceptions.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Chess
|
2
|
-
|
3
2
|
# This exception will be raised when an invalid short algebraic chess notation
|
4
3
|
# string is passed to the {Game#move} function.
|
5
4
|
class BadNotationError < StandardError
|
@@ -11,9 +10,8 @@ module Chess
|
|
11
10
|
|
12
11
|
# This exception will be raised when a malformed PGN file is loaded.
|
13
12
|
class InvalidPgnFormatError < StandardError
|
14
|
-
|
15
|
-
|
16
|
-
super("Invalid PGN file '#{filename}'")
|
13
|
+
def initialize
|
14
|
+
super('Invalid PGN format')
|
17
15
|
end
|
18
16
|
end
|
19
17
|
|
@@ -24,5 +22,4 @@ module Chess
|
|
24
22
|
super("Invalid FEN string '#{fen_string}'")
|
25
23
|
end
|
26
24
|
end
|
27
|
-
|
28
25
|
end
|
data/lib/chess/game.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '../../ext/chess')
|
2
2
|
|
3
3
|
module Chess
|
4
|
-
|
5
4
|
# This class rappresents a chess game.
|
6
5
|
class Game < CGame
|
7
|
-
|
8
6
|
# @param [Array<String>] moves If an array of moves is provided, the moves will be performed.
|
9
7
|
# @raise [IllegalMoveError]
|
10
8
|
# @raise [BadNotationError]
|
@@ -41,7 +39,7 @@ module Chess
|
|
41
39
|
# @raise [InvalidFenFormatError]
|
42
40
|
# @note This game do not have history before the FEN placement.
|
43
41
|
def self.load_fen(fen)
|
44
|
-
if
|
42
|
+
if /^((?:[PRNBQKprnbqk1-8]{1,8}\/){7}[RNBQKPrnbqkp1-8]{1,8})\s(w|b)\s(K?Q?k?q?|-)\s([a-h][1-8]|-)\s(\d+)\s(\d+)$/.match?(fen)
|
45
43
|
game = Chess::Game.new
|
46
44
|
game.set_fen!(fen)
|
47
45
|
return game
|
@@ -52,8 +50,8 @@ module Chess
|
|
52
50
|
|
53
51
|
# Make a move.
|
54
52
|
# @note This add a new {Board} in the {Game}.
|
55
|
-
# @param [String]
|
56
|
-
# the move. `
|
53
|
+
# @param [String] notation Represents the short algebraic chess notation string of
|
54
|
+
# the move. `notation` can be also _from_square_ plus _to_square_ _('e2e4', ...,
|
57
55
|
# 'b1c3')_ (coordinate chess notation).
|
58
56
|
# @return [String] Returns a string that represents the short algebraic
|
59
57
|
# chess notation of the move.
|
@@ -61,24 +59,22 @@ module Chess
|
|
61
59
|
# @raise {IllegalMoveError} if the move is illegal.
|
62
60
|
# @raise {BadNotationError} if the short algebraic chess notation is
|
63
61
|
# malformed.
|
64
|
-
def move(
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
raise IllegalMoveError.new("Illegal move '#{m}'")
|
77
|
-
end
|
62
|
+
def move(notation)
|
63
|
+
expand = expand_move(notation)
|
64
|
+
if expand[:from]
|
65
|
+
move2(expand[:from], expand[:to], expand[:promotion])
|
66
|
+
else
|
67
|
+
super(expand[:name], expand[:dis], expand[:to], expand[:promotion])
|
68
|
+
end
|
69
|
+
rescue IllegalMoveError
|
70
|
+
if ENV['DEBUG']
|
71
|
+
raise IllegalMoveError.new("Illegal move '#{notation}'\nStatus: #{self.status}\nPlayer turn #{self.active_player}\n#{self}")
|
72
|
+
else
|
73
|
+
raise IllegalMoveError.new("Illegal move '#{notation}'")
|
78
74
|
end
|
79
75
|
end
|
80
|
-
alias
|
81
|
-
alias
|
76
|
+
alias move= move
|
77
|
+
alias << move
|
82
78
|
|
83
79
|
# Make the array of moves.
|
84
80
|
# @param [Array<String>] moves The array of moves to performe.
|
@@ -160,41 +156,37 @@ module Chess
|
|
160
156
|
|
161
157
|
private
|
162
158
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
159
|
+
# Expand the short algebraic chess notation string `notation` in a hash like this:
|
160
|
+
#
|
161
|
+
# Ngxe2 ==> { name: 'N', dis: 'g', from: nil, to: 'e2', promotion: nil }
|
162
|
+
def expand_move(notation)
|
163
|
+
if (match = notation.match(Chess::MOVE_REGEXP))
|
164
|
+
expand = {
|
165
|
+
name: match[1] || 'P', # Piece name [RNBQK]
|
166
|
+
dis: match[2], # Disambiguating move
|
167
|
+
to: match[3], # Move to
|
168
|
+
promotion: match[4] # Promote with
|
169
|
+
}
|
170
|
+
expand[:from] = match[2] if match[2] && match[2].size == 2
|
171
|
+
return expand
|
172
|
+
elsif SHORT_CASTLING_REGEXP.match?(notation)
|
173
|
+
if self.board.active_color # black king short castling
|
174
|
+
return { name: 'K', dis: nil, from: 'e8', to: 'g8', promotion: nil }
|
175
|
+
else # white king short castling
|
176
|
+
return { name: 'K', dis: nil, from: 'e1', to: 'g1', promotion: nil }
|
177
|
+
end
|
178
|
+
elsif LONG_CASTLING_REGEXP.match?(notation)
|
179
|
+
if self.board.active_color # black king long castling
|
180
|
+
return { name: 'K', dis: nil, from: 'e8', to: 'c8', promotion: nil }
|
181
|
+
else # white king long castling
|
182
|
+
return { name: 'K', dis: nil, from: 'e1', to: 'c1', promotion: nil }
|
183
|
+
end
|
187
184
|
end
|
185
|
+
raise BadNotationError.new(notation)
|
188
186
|
end
|
189
|
-
raise BadNotationError.new(m)
|
190
|
-
end
|
191
|
-
|
192
187
|
end
|
193
188
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
SHORT_CASTLING_REGEXP = /^([0O])-([0O])([\+#])?$/
|
198
|
-
LONG_CASTLING_REGEXP = /^([0O])-([0O])-([0O])([\+#])?$/
|
199
|
-
|
189
|
+
MOVE_REGEXP = /^([RNBQK])?([a-h]|[1-8]|[a-h][1-8])?(?:x)?([a-h][1-8])(?:=?([RrNnBbQq]))?(?:ep)?(?:\+|\#)?$/.freeze
|
190
|
+
SHORT_CASTLING_REGEXP = /^([0O])-([0O])([\+#])?$/.freeze
|
191
|
+
LONG_CASTLING_REGEXP = /^([0O])-([0O])-([0O])([\+#])?$/.freeze
|
200
192
|
end
|
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,70 +43,72 @@ 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
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
def extended(_mod)
|
54
|
+
raise_if_gnuchess_is_not_installed
|
55
|
+
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
pipe.write("force\n")
|
63
|
-
pipe.write("name chess.rb\n")
|
64
|
-
moves.each do |move|
|
65
|
-
pipe.write("#{move}\n")
|
57
|
+
# Raise an exception if Gnuchess is not installed
|
58
|
+
def raise_if_gnuchess_is_not_installed
|
59
|
+
unless find_executable0('gnuchess')
|
60
|
+
raise 'You must install Gnuchess to use the module Chess::Gnuchess!'
|
61
|
+
end
|
66
62
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
done = :
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def gen_pgn(file_to_save, moves = [])
|
68
|
+
done = false
|
69
|
+
pipe = IO.popen('gnuchess', 'r+')
|
70
|
+
begin
|
71
|
+
pipe.write("depth 1\n")
|
72
|
+
pipe.write("force\n")
|
73
|
+
pipe.write("name chess.rb\n")
|
74
|
+
moves.each do |move|
|
75
|
+
pipe.write("#{move}\n")
|
76
|
+
end
|
77
|
+
until done
|
78
|
+
pipe.write("go\n")
|
79
|
+
while (line = pipe.gets)
|
80
|
+
if /My move is : /.match?(line)
|
81
|
+
break
|
82
|
+
elsif / : resign/.match?(line)
|
83
|
+
break
|
84
|
+
elsif / : 1-0 {White mates}/.match?(line)
|
85
|
+
done = :white_won
|
86
|
+
break
|
87
|
+
elsif / : 0-1 {Black mates}/.match?(line)
|
88
|
+
done = :black_won
|
89
|
+
break
|
90
|
+
elsif (m = line.match(/1\/2-1\/2 {(.*?)}/))
|
91
|
+
case m[1]
|
92
|
+
when 'Stalemate'
|
93
|
+
done = :stalemate
|
94
|
+
when 'Draw by repetition'
|
95
|
+
done = :repetition
|
96
|
+
when 'Draw by fifty-move rule'
|
97
|
+
done = :fifty_move_rule
|
98
|
+
when 'Draw by insufficient material'
|
99
|
+
done = :insufficient_material
|
100
|
+
end
|
101
|
+
break
|
90
102
|
end
|
91
|
-
break
|
92
103
|
end
|
93
104
|
end
|
105
|
+
dir = File.dirname(file_to_save)
|
106
|
+
name = File.basename(file_to_save)
|
107
|
+
pipe.write("pgnsave #{File.join(dir, done.to_s, name)}\n")
|
108
|
+
ensure
|
109
|
+
pipe.write("quit\n")
|
110
|
+
pipe.close
|
94
111
|
end
|
95
|
-
dir = File.dirname(file_to_save)
|
96
|
-
name = File.basename(file_to_save)
|
97
|
-
pipe.write("pgnsave #{File.join(dir, done.to_s, name)}\n")
|
98
|
-
ensure
|
99
|
-
pipe.write("quit\n")
|
100
|
-
pipe.close
|
101
112
|
end
|
102
|
-
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
113
|
end
|
112
|
-
|
113
114
|
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
|
@@ -52,20 +50,31 @@ module Chess
|
|
52
50
|
# @raise [InvalidPgnFormatError]
|
53
51
|
# @raise [IllegalMoveError]
|
54
52
|
def load(filename, check_moves: false)
|
55
|
-
|
56
|
-
|
53
|
+
str = File.open(filename, 'r').read
|
54
|
+
load_from_string(str, check_moves: check_moves)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Load a PGN from string.
|
58
|
+
# @param [String] str The PGN string to load.
|
59
|
+
# @param [Boolean] check_moves If true check if the moves are legal.
|
60
|
+
# @return [Pgn] Returns `self`.
|
61
|
+
# @raise [InvalidPgnFormatError]
|
62
|
+
# @raise [IllegalMoveError]
|
63
|
+
def load_from_string(str, check_moves: false)
|
64
|
+
str.gsub!(/\{.*?\}/, '') # remove comments
|
57
65
|
TAGS.each do |t|
|
58
|
-
instance_variable_set("@#{t}",
|
66
|
+
instance_variable_set("@#{t}", str.match(/^\[#{t.capitalize} ".*"\]\s?$/).to_s.strip[t.size + 3..-3])
|
59
67
|
end
|
60
68
|
@result = '1/2-1/2' if @result == '1/2'
|
61
|
-
game_index =
|
62
|
-
raise Chess::InvalidPgnFormatError.new
|
63
|
-
|
64
|
-
|
65
|
-
@moves
|
69
|
+
game_index = str.index(/^1\./)
|
70
|
+
raise Chess::InvalidPgnFormatError.new if game_index.nil?
|
71
|
+
|
72
|
+
game = str[game_index..-1].strip
|
73
|
+
@moves = game.tr("\n", ' ').split(/\d+\./).collect(&:strip)[1..-1].collect { |t| t.split(' ') }.flatten
|
74
|
+
@moves.delete_at(@moves.size - 1) if @moves.last =~ /(0-1)|(1-0)|(1\/2)|(1\/2-1\/2)|(\*)/
|
66
75
|
@moves.each do |m|
|
67
76
|
if m !~ MOVE_REGEXP && m !~ SHORT_CASTLING_REGEXP && m !~ LONG_CASTLING_REGEXP
|
68
|
-
raise Chess::InvalidPgnFormatError.new
|
77
|
+
raise Chess::InvalidPgnFormatError.new
|
69
78
|
end
|
70
79
|
end
|
71
80
|
Chess::Game.new(@moves) if check_moves
|
@@ -82,7 +91,7 @@ module Chess
|
|
82
91
|
s << "\n"
|
83
92
|
m = ''
|
84
93
|
@moves.each_with_index do |move, i|
|
85
|
-
m << "#{i/2+1}. " if i
|
94
|
+
m << "#{i / 2 + 1}. " if i.even?
|
86
95
|
m << "#{move} "
|
87
96
|
end
|
88
97
|
m << @result unless @result.nil?
|
@@ -95,8 +104,8 @@ module Chess
|
|
95
104
|
File.open(filename, 'w') { |f| f.write(self.to_s) }
|
96
105
|
end
|
97
106
|
|
98
|
-
# @!visibility private
|
99
|
-
alias
|
107
|
+
# # @!visibility private
|
108
|
+
# alias old_date= date=
|
100
109
|
|
101
110
|
# Set the date tag.
|
102
111
|
def date=(value)
|
@@ -106,6 +115,5 @@ module Chess
|
|
106
115
|
@date = value
|
107
116
|
end
|
108
117
|
end
|
109
|
-
|
110
118
|
end
|
111
119
|
end
|
data/lib/chess/utf8_notation.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Chess
|
2
|
-
|
3
2
|
# With this module is possible call the method {#to_utf8} on a string. This
|
4
3
|
# method convert the chess piece identifier character into UTF8 chess
|
5
4
|
# character.
|
@@ -12,7 +11,6 @@ module Chess
|
|
12
11
|
# @note To use this utility explicit require is needed: <tt>require
|
13
12
|
# 'chess/utf8_notation'</tt>
|
14
13
|
module UTF8Notation
|
15
|
-
|
16
14
|
# Map a piece identifier character with the corresponding UTF8 chess
|
17
15
|
# character
|
18
16
|
UTF8_MAP = {
|
@@ -28,14 +26,13 @@ module Chess
|
|
28
26
|
'b' => '♝',
|
29
27
|
'q' => '♛',
|
30
28
|
'k' => '♚'
|
31
|
-
}
|
29
|
+
}.freeze
|
32
30
|
|
33
31
|
# Replace the piece identifier characters with UTF8 chess characters.
|
34
32
|
# @return [String]
|
35
33
|
def to_utf8
|
36
34
|
self.gsub(/[PRNBQKprnbqk]/, UTF8_MAP)
|
37
35
|
end
|
38
|
-
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
data/lib/chess/version.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
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)
|
@@ -15,5 +15,4 @@ class ChessTest < Minitest::Test
|
|
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'
|
@@ -18,5 +17,4 @@ class ChessTest < Minitest::Test
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|
21
|
-
|
22
20
|
end
|
@@ -1,7 +1,6 @@
|
|
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
6
|
define_method "test_fifty_rule_move_#{name}" do
|
@@ -10,5 +9,4 @@ class ChessTest < Minitest::Test
|
|
10
9
|
assert(game.board.fifty_rule_move?)
|
11
10
|
end
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
data/test/test_helper.rb
CHANGED
@@ -2,12 +2,10 @@ require 'chess'
|
|
2
2
|
require 'minitest/autorun'
|
3
3
|
|
4
4
|
module TestHelper
|
5
|
-
|
6
|
-
|
7
|
-
BIG_PGN_COLLECTION = '/Users/pioz/Code/prog/misc/pgn_collection/pgn'
|
5
|
+
PGN_COLLECTION = 'test/pgn_collection'.freeze
|
6
|
+
BIG_PGN_COLLECTION = '/Users/pioz/Code/prog/misc/pgn_collection/pgn'.freeze
|
8
7
|
|
9
8
|
def self.pgns(path, prefix = PGN_COLLECTION)
|
10
9
|
Dir[File.join(prefix, path, '**/*.pgn')]
|
11
10
|
end
|
12
|
-
|
13
11
|
end
|
data/test/test_illegal_moves.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
def test_illegal_moves
|
6
5
|
game = Chess::Game.new
|
7
|
-
%w
|
6
|
+
%w[Qf6 Rd4 Nc3=Q].each do |move|
|
8
7
|
assert_raises(Chess::IllegalMoveError) do
|
9
8
|
game << move
|
10
9
|
end
|
11
10
|
end
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
@@ -7,12 +7,12 @@ class ChessTest < Minitest::Test
|
|
7
7
|
'8/2k5/8/3b4/B7/8/2K5/8 w - - 0 1',
|
8
8
|
'8/2k5/8/8/4B3/8/2K5/8 w - - 0 1',
|
9
9
|
'8/2k5/8/5b2/8/8/2K5/8 w - - 0 1'
|
10
|
-
]
|
10
|
+
].freeze
|
11
11
|
|
12
12
|
ONLY_KINGS_FENS = [
|
13
13
|
'8/2k5/8/8/8/8/2K5/8 w - - 0 1',
|
14
14
|
'8/4k3/8/8/1K6/8/8/8 w - - 0 1'
|
15
|
-
]
|
15
|
+
].freeze
|
16
16
|
|
17
17
|
FENS.each_with_index do |fen, i|
|
18
18
|
define_method("test_insufficient_material_by_fen_#{i}") do
|
@@ -37,5 +37,4 @@ class ChessTest < Minitest::Test
|
|
37
37
|
assert(game.board.insufficient_material?)
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
data/test/test_load_fen.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
def test_fen_in_progress
|
6
5
|
g = Chess::Game.load_fen('rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2')
|
7
6
|
assert_equal 'P', g.board['e4']
|
@@ -49,5 +48,4 @@ class ChessTest < Minitest::Test
|
|
49
48
|
g.move('Qh8')
|
50
49
|
assert_equal '2b1kbnQ/rpq1pp1p/2n3p1/8/8/2P5/PP3PPP/RN2KBNR b KQ - 0 9', g.board.to_fen
|
51
50
|
end
|
52
|
-
|
53
51
|
end
|
data/test/test_move_generator.rb
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
GENS = {
|
6
|
-
'r2qk3/8/2n5/8/8/8/p2B4/4K2R w K - 0 1' => {'e1' => ['Kd1', 'Ke2', 'Kf2', 'Kf1', 'O-O']},
|
7
|
-
'r2qk3/8/2n5/8/8/8/p2B4/4K2R w - - 0 1' => {'e1' => [
|
8
|
-
'r2qk3/8/2n5/2b5/8/8/p2B4/4K2R w K - 0 1' => {'e1' => [
|
9
|
-
'r2qk3/8/2n5/2b5/8/8/p2B4/4K2R b K - 0 1' => {'a2' => ['a1=Q']},
|
10
|
-
'r2qk3/8/2n1n3/2b5/8/8/p2B4/4K2R b K - 0 1' => {'e6' => [
|
11
|
-
'r2qk3/8/2n5/2b2pP1/8/8/3B4/4K2R w K f6 0 1' => {'g5' => [
|
12
|
-
'1B1k4/r3q3/2n1n3/2b2pP1/8/1n6/3B4/4K2R b K - 0 1' => {'c6' => [
|
13
|
-
'1B1k4/r3q3/2n1n3/2b2pP1/8/8/2nB4/3K3R b - - 0 1' => {'c6' => [
|
14
|
-
'1B1k4/r3q3/2n1n2P/2b5/5p2/3p1RP1/3B4/3K4 w - - 0 1' => {'f3' => [
|
15
|
-
'k7/1Q6/2P5/8/8/8/8/3K4 b - - 0 1' => {'a8' => []},
|
16
|
-
'k7/6P1/8/8/8/3r4/3Q4/3K4 w - - 0 1' => {'d2' => ['Qxd3']}
|
17
|
-
}
|
5
|
+
'r2qk3/8/2n5/8/8/8/p2B4/4K2R w K - 0 1' => { 'e1' => ['Kd1', 'Ke2', 'Kf2', 'Kf1', 'O-O'] },
|
6
|
+
'r2qk3/8/2n5/8/8/8/p2B4/4K2R w - - 0 1' => { 'e1' => %w[Kd1 Ke2 Kf2 Kf1] },
|
7
|
+
'r2qk3/8/2n5/2b5/8/8/p2B4/4K2R w K - 0 1' => { 'e1' => %w[Kd1 Ke2 Kf1] },
|
8
|
+
'r2qk3/8/2n5/2b5/8/8/p2B4/4K2R b K - 0 1' => { 'a2' => ['a1=Q'] },
|
9
|
+
'r2qk3/8/2n1n3/2b5/8/8/p2B4/4K2R b K - 0 1' => { 'e6' => %w[Nf8 Ng7 Ng5 Nf4 Ned4 Nc7] },
|
10
|
+
'r2qk3/8/2n5/2b2pP1/8/8/3B4/4K2R w K f6 0 1' => { 'g5' => %w[gxf6ep g6] },
|
11
|
+
'1B1k4/r3q3/2n1n3/2b2pP1/8/1n6/3B4/4K2R b K - 0 1' => { 'c6' => %w[Nxb8 Ne5 Ncd4 Nb4 Nca5] },
|
12
|
+
'1B1k4/r3q3/2n1n3/2b2pP1/8/8/2nB4/3K3R b - - 0 1' => { 'c6' => %w[Nxb8 Ne5 Nc6d4 N6b4 Na5] },
|
13
|
+
'1B1k4/r3q3/2n1n2P/2b5/5p2/3p1RP1/3B4/3K4 w - - 0 1' => { 'f3' => %w[Rxd3 Re3 Rxf4 Rf2 Rf1] },
|
14
|
+
'k7/1Q6/2P5/8/8/8/8/3K4 b - - 0 1' => { 'a8' => [] },
|
15
|
+
'k7/6P1/8/8/8/3r4/3Q4/3K4 w - - 0 1' => { 'd2' => ['Qxd3'] }
|
16
|
+
}.freeze
|
18
17
|
|
19
18
|
GENS.each do |fen, generators|
|
20
19
|
define_method("test_move_generator_#{fen}") do
|
@@ -25,5 +24,4 @@ class ChessTest < Minitest::Test
|
|
25
24
|
end
|
26
25
|
end
|
27
26
|
end
|
28
|
-
|
29
27
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
def test_cant_castling
|
6
5
|
game = Chess::Game.load_fen('2r1k2r/pR2p2p/2pn2Nb/P2p1p2/8/1P2P3/2PP4/2BQK3 b k - 1 3')
|
7
6
|
assert_raises(Chess::IllegalMoveError) do
|
@@ -10,5 +9,4 @@ class ChessTest < Minitest::Test
|
|
10
9
|
game = Chess::Game.load_fen('2r1k2r/pR2p2p/2pn3b/P2p1p2/8/1P2P3/2PP4/2BQK3 b k - 1 3')
|
11
10
|
game << 'O-O'
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
data/test/test_pgn.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
TestHelper.pgns('invalid').each do |file|
|
6
5
|
name = File.basename(file, '.pgn')
|
7
6
|
define_method "test_invalid_pgn_#{name}" do
|
@@ -21,4 +20,51 @@ class ChessTest < Minitest::Test
|
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
23
|
+
def test_load_from_string
|
24
|
+
pgn_string = <<~PGN
|
25
|
+
[Event "70th ch-ITA"]
|
26
|
+
[Site "Siena ITA"]
|
27
|
+
[Round "10"]
|
28
|
+
[Date "2010.12.3"]
|
29
|
+
[White "Caruana, Fabiano"]
|
30
|
+
[Black "Godena, Michele"]
|
31
|
+
[Result "1-0"]
|
32
|
+
1.d4 d5 2.c4 dxc4 3.e4 e5 4.Nf3 Bb4+ 5.Nc3 exd4 6.Nxd4 Ne7 7.Bf4 Bxc3+ 8.bxc3 Ng6 9.Bg3 Qe7 10.Bxc4 Qxe4+ 11.Qe2 Qxe2+ 12.Bxe2 Na6 13.Rb1 O-O 14.O-O Re8 15.Rfe1 Nc5 16.Bxc7 Bd7 17.Bf3 Rxe1+ 18.Rxe1 Rc8 19.Bg3 b6 20.h4 Ne6 21.h5 Ne7 22.Be5 Nc6 23.Nxc6 Bxc6 24.Bg4 Re8 25.Bg3 g6 26.h6 f5 27.Bd1 f4 28.Bh4 Kf8 29.Re5 g5 30.Bh5 Rc8 31.Bxg5 Nxg5 32.Rxg5 Bd7 33.Rg7 Rc5 34.Bf3 Bf5 35.Rxa7 Rxc3 36.Bd5 Bg6 37.Ra4 Rc1+ 38.Kh2 Rc5 39.Rxf4+ Ke7 40.Bf3 Ra5 41.Rb4 b5 42.Bd5 Kf6 43.f4 Bf5 44.Bc6 Bd3 45.Rd4 Ra3 46.Bd5 Bb1 47.Rd1 Bd3 48.Bb3 Bc4 49.Bc2 Ke7 50.Bf5 Rxa2 51.Rd7+ Kf8 52.Rxh7 Bd5 53.Rd7 1-0
|
33
|
+
PGN
|
34
|
+
pgn = Chess::Pgn.new
|
35
|
+
pgn.load_from_string(pgn_string, check_moves: true)
|
36
|
+
assert_equal '70th ch-ITA', pgn.event
|
37
|
+
assert_equal 'Siena ITA', pgn.site
|
38
|
+
assert_equal '10', pgn.round
|
39
|
+
assert_equal '2010.12.3', pgn.date
|
40
|
+
assert_equal 'Caruana, Fabiano', pgn.white
|
41
|
+
assert_equal 'Godena, Michele', pgn.black
|
42
|
+
assert_equal 'Godena, Michele', pgn.black
|
43
|
+
assert_equal '1-0', pgn.result
|
44
|
+
assert_equal 'Rd7', pgn.moves.last
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_load_from_string_without_tags
|
48
|
+
pgn_string = <<~PGN
|
49
|
+
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 {This opening is called the Ruy Lopez.}
|
50
|
+
4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. c3 O-O 9. h3 Nb8 10. d4 Nbd7
|
51
|
+
11. c4 c6 12. cxb5 axb5 13. Nc3 Bb7 14. Bg5 b4 15. Nb1 h6 16. Bh4 c5 17. dxe5
|
52
|
+
Nxe4 18. Bxe7 Qxe7 19. exd6 Qf6 20. Nbd2 Nxd6 21. Nc4 Nxc4 22. Bxc4 Nb6
|
53
|
+
23. Ne5 Rae8 24. Bxf7+ Rxf7 25. Nxf7 Rxe1+ 26. Qxe1 Kxf7 27. Qe3 Qg5 28. Qxg5
|
54
|
+
hxg5 29. b3 Ke6 30. a3 Kd6 31. axb4 cxb4 32. Ra5 Nd5 33. f3 Bc8 34. Kf2 Bf5
|
55
|
+
35. Ra7 g6 36. Ra6+ Kc5 37. Ke1 Nf4 38. g3 Nxh3 39. Kd2 Kb5 40. Rd6 Kc5 41. Ra6
|
56
|
+
Nf2 42. g4 Bd3 43. Re6 1/2-1/2
|
57
|
+
PGN
|
58
|
+
pgn = Chess::Pgn.new
|
59
|
+
pgn.load_from_string(pgn_string, check_moves: true)
|
60
|
+
assert_nil pgn.event
|
61
|
+
assert_nil pgn.site
|
62
|
+
assert_nil pgn.round
|
63
|
+
assert_nil pgn.date
|
64
|
+
assert_nil pgn.white
|
65
|
+
assert_nil pgn.black
|
66
|
+
assert_nil pgn.black
|
67
|
+
assert_nil pgn.result
|
68
|
+
assert_equal 'Re6', pgn.moves.last
|
69
|
+
end
|
24
70
|
end
|
data/test/test_stalemate.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
TestHelper.pgns('stalemate').each do |file|
|
6
5
|
name = File.basename(file, '.pgn')
|
7
6
|
define_method "test_stalemate_#{name}" do
|
@@ -11,5 +10,4 @@ class ChessTest < Minitest::Test
|
|
11
10
|
assert_equal(game.result, '1/2-1/2')
|
12
11
|
end
|
13
12
|
end
|
14
|
-
|
15
13
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ChessTest < Minitest::Test
|
4
|
-
|
5
4
|
TestHelper.pgns('threefold_repetition').each do |file|
|
6
5
|
name = File.basename(file, '.pgn')
|
7
6
|
define_method "test_threefold_repetition_#{name}" do
|
@@ -10,5 +9,4 @@ class ChessTest < Minitest::Test
|
|
10
9
|
assert(game.threefold_repetition?)
|
11
10
|
end
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Enrico Pilotto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,42 +16,70 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '12
|
47
|
+
version: '12'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '12
|
54
|
+
version: '12'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.71'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.71'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-performance
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
44
72
|
requirements:
|
45
73
|
- - "~>"
|
46
74
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
75
|
+
version: '1'
|
48
76
|
type: :development
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
82
|
+
version: '1'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: yard
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +103,7 @@ extensions:
|
|
75
103
|
extra_rdoc_files: []
|
76
104
|
files:
|
77
105
|
- ".gitignore"
|
106
|
+
- ".rubocop.yml"
|
78
107
|
- Gemfile
|
79
108
|
- LICENSE
|
80
109
|
- README.md
|
@@ -1340,8 +1369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1340
1369
|
- !ruby/object:Gem::Version
|
1341
1370
|
version: '0'
|
1342
1371
|
requirements: []
|
1343
|
-
|
1344
|
-
rubygems_version: 2.6.13
|
1372
|
+
rubygems_version: 3.0.2
|
1345
1373
|
signing_key:
|
1346
1374
|
specification_version: 4
|
1347
1375
|
summary: A fast chess library to play chess with Ruby.
|