chessmate 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +0 -0
- data/Gemfile.lock +2 -2
- data/LICENSE +21 -0
- data/README.md +129 -0
- data/lib/chessmate.rb +38 -16
- data/lib/helpers/default.rb +0 -1
- data/lib/helpers/logger.rb +91 -0
- data/lib/helpers/notation_parser.rb +0 -0
- data/lib/pieces/bishop.rb +0 -0
- data/lib/pieces/king.rb +2 -4
- data/lib/pieces/knight.rb +0 -0
- data/lib/pieces/pawn.rb +4 -8
- data/lib/pieces/piece.rb +8 -13
- data/lib/pieces/queen.rb +0 -0
- data/lib/pieces/rook.rb +0 -0
- data/pre-commit.sh +26 -0
- data/spec/chessmate_spec.rb +47 -12
- data/spec/logger_spec.rb +182 -0
- data/spec/notation_parser_spec.rb +0 -0
- data/spec/piece_spec.rb +0 -0
- data/spec/spec_helper.rb +0 -0
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8a0298012d7f8cad83eb00236534883f661bf131b826400de162a952d6a846e
|
4
|
+
data.tar.gz: b3047583dc762d0fa97c555102f59a7289e5dcd913ae76fa71a8b4b937a1b6ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c34f8fc54e8c829e454142f82f4c8b4f788018f32b646de78c39201462e57d849c50792b5cb5d591480fa99aba3fba56a328210ee1bfa5492779eb75bf0efd70
|
7
|
+
data.tar.gz: b865da7aba16232d0fadb70f7156bae86a8bbcf79688ae53644f6209f5bfbd427f246da18d8dc29c34778903551b60cd6dc6e8f1e16ecb2cec9125d2e028edc5
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
9
|
+
level of experience, education, socio-economic status, nationality, personal
|
10
|
+
appearance, race, religion, or sexual identity and orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at tyler.b.porter@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
72
|
+
|
73
|
+
[homepage]: https://www.contributor-covenant.org
|
74
|
+
|
75
|
+
For answers to common questions about this code of conduct, see
|
76
|
+
https://www.contributor-covenant.org/faq
|
data/Gemfile
CHANGED
File without changes
|
data/Gemfile.lock
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Tyler Porter
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<img width="800" height="150" src="https://imgur.com/WFCwf9p.png">
|
3
|
+
</p>
|
4
|
+
<h2 align="center">A dead-simple chess validation gem for Rails</h2>
|
5
|
+
<p align="center">
|
6
|
+
<a href="https://travis-ci.com/pawptart/ChessMate">
|
7
|
+
<img src="https://travis-ci.com/pawptart/ChessMate.svg?branch=master">
|
8
|
+
</a>
|
9
|
+
<a href="https://github.com/pawptart/ChessMate/issues">
|
10
|
+
<img src="https://img.shields.io/github/issues/pawptart/chessmate">
|
11
|
+
</a>
|
12
|
+
<a href="https://rubygems.org/gems/chessmate">
|
13
|
+
<img src="https://img.shields.io/gem/v/chessmate">
|
14
|
+
</a>
|
15
|
+
</p>
|
16
|
+
|
17
|
+
## About
|
18
|
+
ChessMate was built in around 2 months to be as easy to use as possible to quickly and easily bootstrap a chess game in Rails. The original idea came from a bootcamp exercise to build a working chess game, and so the code that was written there has been ported to ChessMate in order to benefit future programmers.
|
19
|
+
|
20
|
+
ChessMate is designed to be a backend tool to validate possible chess moves. Therefore, it is intentionally as agnostic to your frontend as possible to integrate into many different frameworks. Because it's designed to be flexible, it even supports custom game boards and can allow out-of-turn movement!
|
21
|
+
|
22
|
+
Click [here](http://chessmate-demo.herokuapp.com/) to play with a Rails app running ChessMate! (Or check out the source code [here](https://github.com/pawptart/ChessTest).)
|
23
|
+
|
24
|
+
<p align="center">
|
25
|
+
<img src="https://i.imgur.com/vyQjL4Y.png">
|
26
|
+
</p>
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
Simply add ChessMate to your Gemfile:
|
30
|
+
|
31
|
+
```
|
32
|
+
gem 'chessmate'
|
33
|
+
```
|
34
|
+
|
35
|
+
and then you can require it in a model, controller, etc.
|
36
|
+
|
37
|
+
```
|
38
|
+
require 'chessmate'
|
39
|
+
```
|
40
|
+
|
41
|
+
From there, you are free to utilize all the functions and features of ChessMate!
|
42
|
+
|
43
|
+
## Building a new game and playing
|
44
|
+
|
45
|
+
```
|
46
|
+
game = ChessMate.new
|
47
|
+
```
|
48
|
+
|
49
|
+
Moving pieces works based on chess notation: for example, a common first move is `e2` to `e4`. ChessMate accepts these squares as arguments to the `move` method, so you don't need to specify a piece type like in normal chess notation. To make this move in ChessMate:
|
50
|
+
|
51
|
+
```
|
52
|
+
game.move('e2', 'e4')
|
53
|
+
```
|
54
|
+
|
55
|
+
If a move is invalid, `ChessMate.move` will return `false`, and the board and game state will not update. You also do not need to specify for any "special" moves, like castling or _en passant_, as ChessMate can handle this for you.
|
56
|
+
|
57
|
+
Other functions you might call:
|
58
|
+
|
59
|
+
```
|
60
|
+
game.promote?(square) # Check if a square is capable of pawn promotion
|
61
|
+
game.promote!(square, piece) # Promote a promotable pawn, accepts 'rook'/'knight'/'bishop'/'queen'
|
62
|
+
game.in_check? # Determine if either color is currently in check
|
63
|
+
game.checkmate?(color) # Determine if the game is over, accepts 'W'/'B'
|
64
|
+
game.draw?(color) # Same as checkmate, for draw
|
65
|
+
```
|
66
|
+
|
67
|
+
Using these functions, it's quite simple to build a working chess game!
|
68
|
+
|
69
|
+
## Custom games
|
70
|
+
With ChessMate, it's very easy to build your own custom games. Below is a list of all the defaults ChessMate uses to build a game board, but they can be modified and passed into the `ChessMate.new` method as named arguments in any order, and ChessMate will build a game around your custom params.
|
71
|
+
|
72
|
+
For instance, for a custom board, on turn 10, with the white king in check:
|
73
|
+
|
74
|
+
```
|
75
|
+
custom_board = [
|
76
|
+
[nil, nil, nil, nil, 'BK', nil, nil, nil],
|
77
|
+
[nil, nil, nil, nil, 'BQ', nil, nil, nil],
|
78
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
79
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
80
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
81
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
82
|
+
['WP', nil, nil, nil, nil, nil, nil, nil],
|
83
|
+
[nil, nil, nil, nil, 'WK', nil, nil, nil]
|
84
|
+
]
|
85
|
+
turn = 10
|
86
|
+
in_check = { white: true, black: false }
|
87
|
+
|
88
|
+
game = ChessMate.new(board: custom_board, turn: turn, in_check: in_check)
|
89
|
+
```
|
90
|
+
|
91
|
+
ChessMate can build a game with those parameters!
|
92
|
+
|
93
|
+
Here is a list of all the defaults:
|
94
|
+
```
|
95
|
+
board: [
|
96
|
+
%w[BR BN BB BQ BK BB BN BR],
|
97
|
+
%w[BP BP BP BP BP BP BP BP],
|
98
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
99
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
100
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
101
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
102
|
+
%w[WP WP WP WP WP WP WP WP],
|
103
|
+
%w[WR WN WB WQ WK WB WN WR]
|
104
|
+
]
|
105
|
+
|
106
|
+
turn: 1
|
107
|
+
|
108
|
+
promotable: nil
|
109
|
+
|
110
|
+
en_passant: { white: nil, black: nil }
|
111
|
+
|
112
|
+
in_check: { white: false, black: false }
|
113
|
+
|
114
|
+
castling: {
|
115
|
+
white: {
|
116
|
+
kingside: true,
|
117
|
+
queenside: true
|
118
|
+
},
|
119
|
+
black: {
|
120
|
+
kingside: true,
|
121
|
+
queenside: true
|
122
|
+
}
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
ChessMate is open to contributions! If you have a feature request, a bug, or a suggestion, please open an issue! Please note that a review is required and passing TravisCI build before your PR can be merged with master.
|
128
|
+
|
129
|
+
Currently looking to expand ChessMate features by allowing chess notation logging as well as better documentation!
|
data/lib/chessmate.rb
CHANGED
@@ -11,8 +11,16 @@ class ChessMate
|
|
11
11
|
require 'pieces/queen'
|
12
12
|
require 'pieces/king'
|
13
13
|
require 'helpers/default'
|
14
|
+
require 'helpers/logger'
|
14
15
|
|
15
|
-
attr_reader :board,
|
16
|
+
attr_reader :board,
|
17
|
+
:turn,
|
18
|
+
:in_check,
|
19
|
+
:promotable,
|
20
|
+
:en_passant,
|
21
|
+
:castling,
|
22
|
+
:allow_out_of_turn,
|
23
|
+
:move_history
|
16
24
|
|
17
25
|
def initialize(board: nil,
|
18
26
|
turn: nil,
|
@@ -20,10 +28,12 @@ class ChessMate
|
|
20
28
|
en_passant: nil,
|
21
29
|
castling: nil,
|
22
30
|
in_check: nil,
|
23
|
-
allow_out_of_turn: nil
|
31
|
+
allow_out_of_turn: nil,
|
32
|
+
move_history: nil,
|
33
|
+
ignore_logging: false)
|
24
34
|
@board = board || DEFAULT[:board].map(&:dup)
|
25
35
|
@turn = turn || DEFAULT[:turn]
|
26
|
-
@promotable = promotable
|
36
|
+
@promotable = promotable
|
27
37
|
@en_passant = en_passant || DeepDup.deep_dup(DEFAULT[:en_passant])
|
28
38
|
@castling = castling || DeepDup.deep_dup(DEFAULT[:castling])
|
29
39
|
@in_check = in_check || DeepDup.deep_dup(DEFAULT[:in_check])
|
@@ -35,13 +45,13 @@ class ChessMate
|
|
35
45
|
else
|
36
46
|
false
|
37
47
|
end
|
48
|
+
@move_history = move_history || []
|
49
|
+
@ignore_logging = ignore_logging
|
38
50
|
end
|
39
51
|
|
40
52
|
def update(orig, dest = nil)
|
41
|
-
orig_y = orig
|
42
|
-
|
43
|
-
dest_y = dest[0]
|
44
|
-
dest_x = dest[1]
|
53
|
+
orig_y, orig_x = orig
|
54
|
+
dest_y, dest_x = dest
|
45
55
|
piece_type = @board[orig_y][orig_x]
|
46
56
|
piece_color = piece_type[0] == 'W' ? :white : :black
|
47
57
|
opposite_color = piece_type[0] == 'W' ? :black : :white
|
@@ -79,10 +89,16 @@ class ChessMate
|
|
79
89
|
@board[orig_y][new_rook_x_position] = piece_type[0] + 'R'
|
80
90
|
end
|
81
91
|
|
92
|
+
@promotable = dest if piece_type[1] == 'P' && promote?(orig)
|
93
|
+
|
94
|
+
unless @ignore_logging
|
95
|
+
logger = Logger.new(orig, dest, @board)
|
96
|
+
@move_history << logger.log_move
|
97
|
+
end
|
98
|
+
|
82
99
|
@board[orig_y][orig_x] = nil
|
83
100
|
@board[dest_y][dest_x] = piece_type
|
84
101
|
|
85
|
-
@promotable = dest if piece_type[1] == 'P' && promote?(dest)
|
86
102
|
@in_check = in_check?
|
87
103
|
@turn += 1
|
88
104
|
end
|
@@ -117,6 +133,8 @@ class ChessMate
|
|
117
133
|
end
|
118
134
|
|
119
135
|
def move(orig, dest, test = false, test_board = nil)
|
136
|
+
return false if @promotable
|
137
|
+
|
120
138
|
orig_pos = NotationParser.parse_notation(orig)
|
121
139
|
dest_pos = NotationParser.parse_notation(dest)
|
122
140
|
|
@@ -149,7 +167,7 @@ class ChessMate
|
|
149
167
|
false
|
150
168
|
end
|
151
169
|
unless test
|
152
|
-
in_check_after_move = in_check_after_move?(orig_pos, dest_pos)
|
170
|
+
in_check_after_move = in_check_after_move?(orig_pos, dest_pos)
|
153
171
|
update(orig_pos, dest_pos) if valid_move && !test && !in_check_after_move
|
154
172
|
end
|
155
173
|
|
@@ -159,10 +177,8 @@ class ChessMate
|
|
159
177
|
def in_check_after_move?(orig, dest)
|
160
178
|
test_board = @board.map(&:dup)
|
161
179
|
|
162
|
-
orig_y = orig
|
163
|
-
|
164
|
-
dest_y = dest[0]
|
165
|
-
dest_x = dest[1]
|
180
|
+
orig_y, orig_x = orig
|
181
|
+
dest_y, dest_x = dest
|
166
182
|
piece = test_board[orig_y][orig_x]
|
167
183
|
piece_type = test_board[orig_y][orig_x]
|
168
184
|
opposite_color = piece_type[0] == 'W' ? :black : :white
|
@@ -236,8 +252,8 @@ class ChessMate
|
|
236
252
|
def promote?(square)
|
237
253
|
square_y = square[0]
|
238
254
|
square_x = square[1]
|
239
|
-
|
240
|
-
promote_column =
|
255
|
+
piece_color = @board[square_y][square_x][0]
|
256
|
+
promote_column = piece_color.downcase == 'w' ? 1 : 6
|
241
257
|
promote_column == square_y
|
242
258
|
end
|
243
259
|
|
@@ -246,7 +262,7 @@ class ChessMate
|
|
246
262
|
square_x = square[1]
|
247
263
|
|
248
264
|
old_piece = @board[square_y][square_x]
|
249
|
-
return nil if old_piece.nil? ||
|
265
|
+
return nil if old_piece.nil? || @promotable != [square_y, square_x]
|
250
266
|
|
251
267
|
case piece.downcase
|
252
268
|
when 'rook'
|
@@ -262,5 +278,11 @@ class ChessMate
|
|
262
278
|
end
|
263
279
|
|
264
280
|
@board[square_y][square_x] = old_piece[0] + piece_type
|
281
|
+
@promotable = nil
|
282
|
+
|
283
|
+
return if @ignore_logging
|
284
|
+
|
285
|
+
logger = Logger.new(nil, nil, nil, promotion_type: piece_type, history: @move_history)
|
286
|
+
@move_history[-1] += logger.log_promotion
|
265
287
|
end
|
266
288
|
end
|
data/lib/helpers/default.rb
CHANGED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'helpers/notation_parser'
|
4
|
+
require 'chessmate'
|
5
|
+
|
6
|
+
class Logger
|
7
|
+
def initialize(orig, dest, board, en_passant: false, promotion_type: nil, history: nil)
|
8
|
+
@promotion_type = promotion_type
|
9
|
+
@history = history
|
10
|
+
|
11
|
+
return unless orig && dest && board
|
12
|
+
|
13
|
+
@orig = orig
|
14
|
+
@dest = dest
|
15
|
+
@board = board
|
16
|
+
@en_passant = en_passant
|
17
|
+
@orig_y, @orig_x = @orig
|
18
|
+
@dest_y, @dest_x = @dest
|
19
|
+
@piece = @board[@orig_y][@orig_x]
|
20
|
+
@piece_color, @piece_type = @piece.chars
|
21
|
+
end
|
22
|
+
|
23
|
+
def log_move
|
24
|
+
if @piece_type == 'K' && (@orig_x - @dest_x).abs > 1
|
25
|
+
return (@dest_x - @orig_x).positive? ? '0-0' : '0-0-0'
|
26
|
+
end
|
27
|
+
|
28
|
+
origin = encode_origin
|
29
|
+
capture = @board[@dest_y][@dest_x] || @en_passant ? 'x' : ''
|
30
|
+
destination = NotationParser.encode_notation(@dest)
|
31
|
+
|
32
|
+
origin + capture + destination + check_or_mate
|
33
|
+
end
|
34
|
+
|
35
|
+
def log_promotion
|
36
|
+
@promotion_type ? "=(#{@promotion_type})" : ''
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def encode_origin
|
42
|
+
notation_required = [false, false]
|
43
|
+
game = ChessMate.new(board: @board)
|
44
|
+
encoded_dest = NotationParser.encode_notation(@dest)
|
45
|
+
|
46
|
+
@board.each_with_index do |row, y|
|
47
|
+
row.each_with_index do |col, x|
|
48
|
+
next unless @piece == col && [@orig_y, @orig_x] != [y, x]
|
49
|
+
|
50
|
+
encoded_orig = NotationParser.encode_notation([y, x])
|
51
|
+
|
52
|
+
if game.move(encoded_orig, encoded_dest, true)
|
53
|
+
notation_required[0] = true if @orig_y == y || (@orig_y != y && @orig_x != x)
|
54
|
+
notation_required[1] = true if @orig_x == x
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if notation_required.nil? || notation_required.none?(true)
|
60
|
+
if @piece_type == 'P'
|
61
|
+
return NotationParser.encode_notation(@orig)[0] if @board[@dest_y][@dest_x] || @en_passant
|
62
|
+
|
63
|
+
return ''
|
64
|
+
end
|
65
|
+
return @piece_type
|
66
|
+
end
|
67
|
+
ambiguous_encoded = @piece_type
|
68
|
+
encoded_origin_chars = NotationParser.encode_notation(@orig).chars
|
69
|
+
notation_required.each_with_index do |value, i|
|
70
|
+
ambiguous_encoded += encoded_origin_chars[i] if value
|
71
|
+
end
|
72
|
+
ambiguous_encoded
|
73
|
+
end
|
74
|
+
|
75
|
+
def check_or_mate
|
76
|
+
game = ChessMate.new(board: @board, ignore_logging: true)
|
77
|
+
encoded_orig = NotationParser.encode_notation(@orig)
|
78
|
+
encoded_dest = NotationParser.encode_notation(@dest)
|
79
|
+
opposite_color_letter = @piece_color == 'W' ? 'B' : 'W'
|
80
|
+
opposite_color_string = opposite_color_letter == 'W' ? 'white' : 'black'
|
81
|
+
|
82
|
+
game.move(encoded_orig, encoded_dest)
|
83
|
+
checkmate = game.checkmate?(opposite_color_letter)
|
84
|
+
check = game.in_check?[opposite_color_string.to_sym]
|
85
|
+
|
86
|
+
return '#' if checkmate
|
87
|
+
return '+' if check
|
88
|
+
|
89
|
+
''
|
90
|
+
end
|
91
|
+
end
|
File without changes
|
data/lib/pieces/bishop.rb
CHANGED
File without changes
|
data/lib/pieces/king.rb
CHANGED
@@ -16,10 +16,8 @@ class King < Piece
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.valid_castling_move?(orig, dest, board, castling)
|
19
|
-
orig_y = orig
|
20
|
-
|
21
|
-
dest_y = dest[0]
|
22
|
-
dest_x = dest[1]
|
19
|
+
orig_y, orig_x = orig
|
20
|
+
dest_y, dest_x = dest
|
23
21
|
|
24
22
|
return false if orig_y != dest_y || (orig_x - dest_x).abs != 2
|
25
23
|
|
data/lib/pieces/knight.rb
CHANGED
File without changes
|
data/lib/pieces/pawn.rb
CHANGED
@@ -6,10 +6,8 @@ class Pawn < Piece
|
|
6
6
|
def self.move_is_valid?(orig, dest, board, en_passant)
|
7
7
|
return true if en_passant(orig, dest, board, en_passant)
|
8
8
|
|
9
|
-
orig_y = orig
|
10
|
-
|
11
|
-
dest_y = dest[0]
|
12
|
-
dest_x = dest[1]
|
9
|
+
orig_y, orig_x = orig
|
10
|
+
dest_y, dest_x = dest
|
13
11
|
piece_type = board[orig_y][orig_x]
|
14
12
|
piece_color = piece_type[0].downcase
|
15
13
|
|
@@ -36,10 +34,8 @@ class Pawn < Piece
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def self.en_passant(orig, dest, board, en_passant)
|
39
|
-
orig_y = orig
|
40
|
-
|
41
|
-
dest_y = dest[0]
|
42
|
-
dest_x = dest[1]
|
37
|
+
orig_y, orig_x = orig
|
38
|
+
dest_y, dest_x = dest
|
43
39
|
piece_type = board[orig_y][orig_x]
|
44
40
|
opposite_color = piece_type[0].downcase == 'w' ? :black : :white
|
45
41
|
direction = opposite_color == :white ? -1 : 1
|
data/lib/pieces/piece.rb
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
|
3
3
|
class Piece
|
4
4
|
def self.obstructed?(orig, dest, board)
|
5
|
-
orig_y = orig
|
6
|
-
|
7
|
-
dest_y = dest[0]
|
8
|
-
dest_x = dest[1]
|
5
|
+
orig_y, orig_x = orig
|
6
|
+
dest_y, dest_x = dest
|
9
7
|
|
10
8
|
if orig_y == dest_y
|
11
9
|
|
@@ -14,7 +12,8 @@ class Piece
|
|
14
12
|
test_pos = orig_x - (x * direction) - direction
|
15
13
|
return true unless board[orig_y][test_pos].nil?
|
16
14
|
end
|
17
|
-
|
15
|
+
|
16
|
+
false
|
18
17
|
|
19
18
|
elsif orig_x == dest_x
|
20
19
|
|
@@ -24,7 +23,7 @@ class Piece
|
|
24
23
|
return true unless board[test_pos][orig_x].nil?
|
25
24
|
end
|
26
25
|
|
27
|
-
|
26
|
+
false
|
28
27
|
|
29
28
|
elsif (orig_y - dest_y).abs == (orig_x - dest_x).abs
|
30
29
|
|
@@ -37,18 +36,14 @@ class Piece
|
|
37
36
|
return true unless board[test_y_pos][test_x_pos].nil?
|
38
37
|
end
|
39
38
|
|
40
|
-
|
39
|
+
false
|
41
40
|
|
42
|
-
else
|
43
|
-
return nil
|
44
41
|
end
|
45
42
|
end
|
46
43
|
|
47
44
|
def self.capturable?(orig, dest, board)
|
48
|
-
orig_y = orig
|
49
|
-
|
50
|
-
dest_y = dest[0]
|
51
|
-
dest_x = dest[1]
|
45
|
+
orig_y, orig_x = orig
|
46
|
+
dest_y, dest_x = dest
|
52
47
|
orig_piece = board[orig_y][orig_x]
|
53
48
|
dest_piece = board[dest_y][dest_x]
|
54
49
|
|
data/lib/pieces/queen.rb
CHANGED
File without changes
|
data/lib/pieces/rook.rb
CHANGED
File without changes
|
data/pre-commit.sh
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'english'
|
4
|
+
require 'rubocop'
|
5
|
+
|
6
|
+
ADDED_OR_MODIFIED = /A|AM|^M/.freeze
|
7
|
+
|
8
|
+
changed_files = `git status --porcelain`.split(/\n/).
|
9
|
+
select { |file_name_with_status|
|
10
|
+
file_name_with_status =~ ADDED_OR_MODIFIED
|
11
|
+
}.
|
12
|
+
map { |file_name_with_status|
|
13
|
+
file_name_with_status.split(' ')[1]
|
14
|
+
}.
|
15
|
+
select { |file_name|
|
16
|
+
File.extname(file_name) == '.rb'
|
17
|
+
}.join(' ')
|
18
|
+
|
19
|
+
success = system(%(rubocop #{changed_files}))
|
20
|
+
|
21
|
+
STDIN.reopen('/dev/tty')
|
22
|
+
|
23
|
+
if success == false
|
24
|
+
puts "Would you like to continue press 'any key' or 'n/N' to halt?"
|
25
|
+
exit(1) if %w(N n).include?(gets.chomp)
|
26
|
+
end
|
data/spec/chessmate_spec.rb
CHANGED
@@ -59,7 +59,7 @@ describe ChessMate do
|
|
59
59
|
chess = ChessMate.new
|
60
60
|
expect(chess.board).to eql(DEFAULT[:board])
|
61
61
|
expect(chess.turn).to eql(DEFAULT[:turn])
|
62
|
-
expect(chess.promotable).to eql(
|
62
|
+
expect(chess.promotable).to eql(nil)
|
63
63
|
expect(chess.en_passant).to eql(DEFAULT[:en_passant])
|
64
64
|
expect(chess.castling).to eql(DEFAULT[:castling])
|
65
65
|
expect(chess.in_check).to eql(DEFAULT[:in_check])
|
@@ -356,6 +356,21 @@ describe ChessMate do
|
|
356
356
|
)
|
357
357
|
end
|
358
358
|
|
359
|
+
it 'should return false if there is a promotable pawn on the board' do
|
360
|
+
board = [
|
361
|
+
['WP', nil, nil, nil, nil, nil, nil, nil],
|
362
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
363
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
364
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
365
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
366
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
367
|
+
['WP', nil, nil, nil, nil, nil, nil, nil],
|
368
|
+
[nil, nil, nil, nil, nil, nil, nil, nil]
|
369
|
+
]
|
370
|
+
chess = ChessMate.new(board: board, promotable: [0, 0])
|
371
|
+
expect(chess.move('a2', 'a3')).to eql(false)
|
372
|
+
end
|
373
|
+
|
359
374
|
context 'for pawns' do
|
360
375
|
it 'should update the board if pawn move is valid' do
|
361
376
|
@chess.move('c2', 'c3')
|
@@ -1357,27 +1372,27 @@ describe ChessMate do
|
|
1357
1372
|
end
|
1358
1373
|
|
1359
1374
|
describe 'promote? method' do
|
1360
|
-
it 'should return true if white piece is
|
1375
|
+
it 'should return true if white piece is moving to last rank' do
|
1361
1376
|
board = Array.new(8) { Array.new(8, nil) }
|
1362
|
-
board[
|
1377
|
+
board[1][0] = 'WP'
|
1363
1378
|
chess = ChessMate.new(board: board)
|
1364
|
-
expect(chess.promote?([
|
1379
|
+
expect(chess.promote?([1, 0])).to eql(true)
|
1365
1380
|
end
|
1366
1381
|
|
1367
|
-
it 'should return true if black piece is
|
1382
|
+
it 'should return true if black piece is moving to last rank' do
|
1368
1383
|
board = Array.new(8) { Array.new(8, nil) }
|
1369
|
-
board[
|
1384
|
+
board[6][0] = 'BP'
|
1370
1385
|
chess = ChessMate.new(board: board)
|
1371
|
-
expect(chess.promote?([
|
1386
|
+
expect(chess.promote?([6, 0])).to eql(true)
|
1372
1387
|
end
|
1373
1388
|
|
1374
1389
|
it 'should return false otherwise' do
|
1375
1390
|
board = Array.new(8) { Array.new(8, nil) }
|
1376
|
-
board[
|
1377
|
-
board[
|
1391
|
+
board[2][0] = 'WP'
|
1392
|
+
board[5][0] = 'BP'
|
1378
1393
|
chess = ChessMate.new(board: board)
|
1379
|
-
expect(chess.promote?([
|
1380
|
-
expect(chess.promote?([
|
1394
|
+
expect(chess.promote?([2, 0])).to eql(false)
|
1395
|
+
expect(chess.promote?([5, 0])).to eql(false)
|
1381
1396
|
end
|
1382
1397
|
end
|
1383
1398
|
|
@@ -1399,8 +1414,9 @@ describe ChessMate do
|
|
1399
1414
|
context 'should promote to' do
|
1400
1415
|
before :each do
|
1401
1416
|
board = Array.new(8) { Array.new(8, nil) }
|
1402
|
-
board[
|
1417
|
+
board[1][0] = 'WP'
|
1403
1418
|
@chess = ChessMate.new(board: board)
|
1419
|
+
@chess.move('a7', 'a8')
|
1404
1420
|
end
|
1405
1421
|
|
1406
1422
|
it 'queen' do
|
@@ -1423,6 +1439,25 @@ describe ChessMate do
|
|
1423
1439
|
expect(@chess.board[0][0]).to eql('WR')
|
1424
1440
|
end
|
1425
1441
|
end
|
1442
|
+
|
1443
|
+
context 'logging' do
|
1444
|
+
it 'should correctly handle logging promotion' do
|
1445
|
+
board = [
|
1446
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1447
|
+
['WP', nil, nil, nil, nil, nil, nil, nil],
|
1448
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1449
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1450
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1451
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1452
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
1453
|
+
[nil, nil, nil, nil, nil, nil, nil, nil]
|
1454
|
+
]
|
1455
|
+
chess = ChessMate.new(board: board)
|
1456
|
+
chess.move('a7', 'a8')
|
1457
|
+
chess.promote!([0, 0], 'queen')
|
1458
|
+
expect(chess.move_history[-1]).to eql('a8=(Q)')
|
1459
|
+
end
|
1460
|
+
end
|
1426
1461
|
end
|
1427
1462
|
|
1428
1463
|
describe 'en_passant method' do
|
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative '../lib/helpers/logger'
|
5
|
+
require 'chessmate'
|
6
|
+
|
7
|
+
describe 'Logger' do
|
8
|
+
before :each do
|
9
|
+
@normal_moves_board = [
|
10
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
11
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
12
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
13
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
14
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
15
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
16
|
+
['WP', 'WN', 'WB', 'WQ', 'WK', nil, nil, nil],
|
17
|
+
[nil, nil, nil, nil, nil, nil, nil, nil]
|
18
|
+
]
|
19
|
+
|
20
|
+
@capture_moves_board = [
|
21
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
22
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
23
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
24
|
+
[nil, nil, nil, nil, nil, nil, 'WP', 'BP'],
|
25
|
+
['BP', nil, nil, nil, nil, nil, nil, nil],
|
26
|
+
[nil, 'BP', nil, 'BP', nil, nil, nil, nil],
|
27
|
+
['WP', 'WN', 'WB', 'WQ', 'WK', nil, nil, nil],
|
28
|
+
[nil, nil, nil, nil, nil, nil, nil, nil]
|
29
|
+
]
|
30
|
+
|
31
|
+
@ambiguous_moves_board = [
|
32
|
+
[nil, nil, nil, 'BR', nil, nil, nil, 'BR'],
|
33
|
+
['BB', nil, nil, nil, nil, nil, nil, nil],
|
34
|
+
[nil, nil, nil, 'BB', nil, nil, nil, nil],
|
35
|
+
['WR', nil, nil, nil, nil, nil, nil, nil],
|
36
|
+
[nil, nil, nil, nil, 'WQ', nil, nil, 'WQ'],
|
37
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
38
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
39
|
+
['WR', nil, nil, nil, nil, nil, nil, 'WQ']
|
40
|
+
]
|
41
|
+
|
42
|
+
@specialty_moves_board = [
|
43
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
44
|
+
['WP', nil, nil, nil, nil, nil, nil, nil],
|
45
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
46
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
47
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
48
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
49
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
50
|
+
['WR', nil, nil, nil, 'WK', nil, nil, 'WR']
|
51
|
+
]
|
52
|
+
|
53
|
+
@check_board = [
|
54
|
+
[nil, nil, nil, 'BQ', nil, nil, nil, nil],
|
55
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
56
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
57
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
58
|
+
[nil, nil, nil, nil, nil, nil, nil, nil],
|
59
|
+
['BN', nil, nil, nil, nil, nil, nil, nil],
|
60
|
+
[nil, nil, nil, 'WP', nil, 'WP', nil, nil],
|
61
|
+
[nil, nil, nil, 'WR', 'WK', 'WR', nil, nil]
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'pawn moves' do
|
66
|
+
it 'should log normal pawn moves' do
|
67
|
+
logger = Logger.new([6, 0], [5, 0], @normal_moves_board)
|
68
|
+
expect(logger.log_move).to eql('a3')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should log capturing moves' do
|
72
|
+
logger = Logger.new([6, 0], [5, 1], @capture_moves_board)
|
73
|
+
expect(logger.log_move).to eql('axb3')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should log en passant moves' do
|
77
|
+
logger = Logger.new([3, 6], [2, 7], @capture_moves_board, en_passant: true)
|
78
|
+
expect(logger.log_move).to eql('gxh6')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'knight moves' do
|
83
|
+
it 'should log normal knight moves' do
|
84
|
+
logger = Logger.new([6, 1], [4, 0], @normal_moves_board)
|
85
|
+
expect(logger.log_move).to eql('Na4')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should log capturing moves' do
|
89
|
+
logger = Logger.new([6, 1], [4, 0], @capture_moves_board)
|
90
|
+
expect(logger.log_move).to eql('Nxa4')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'bishop moves' do
|
95
|
+
it 'should log normal bishop moves' do
|
96
|
+
logger = Logger.new([6, 2], [5, 1], @normal_moves_board)
|
97
|
+
expect(logger.log_move).to eql('Bb3')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should log capturing moves' do
|
101
|
+
logger = Logger.new([6, 2], [5, 1], @capture_moves_board)
|
102
|
+
expect(logger.log_move).to eql('Bxb3')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'queen moves' do
|
107
|
+
it 'should log normal queen moves' do
|
108
|
+
logger = Logger.new([6, 3], [5, 3], @normal_moves_board)
|
109
|
+
expect(logger.log_move).to eql('Qd3')
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should log capturing moves' do
|
113
|
+
logger = Logger.new([6, 3], [5, 3], @capture_moves_board)
|
114
|
+
expect(logger.log_move).to eql('Qxd3')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'king moves' do
|
119
|
+
it 'should log normal king moves' do
|
120
|
+
logger = Logger.new([6, 4], [5, 4], @normal_moves_board)
|
121
|
+
expect(logger.log_move).to eql('Ke3')
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should log capturing moves' do
|
125
|
+
logger = Logger.new([6, 4], [5, 3], @capture_moves_board)
|
126
|
+
expect(logger.log_move).to eql('Kxd3')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'ambiguous moves' do
|
131
|
+
it 'should add file info to log moves with pieces in same file' do
|
132
|
+
logger = Logger.new([7, 0], [5, 0], @ambiguous_moves_board)
|
133
|
+
expect(logger.log_move).to eql('R1a3')
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should add rank info to log moves with pieces in same rank' do
|
137
|
+
logger = Logger.new([0, 3], [0, 5], @ambiguous_moves_board)
|
138
|
+
expect(logger.log_move).to eql('Rdf8')
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should add file and rank info to log moves with multiple pieces in same file and rank' do
|
142
|
+
logger = Logger.new([4, 7], [7, 4], @ambiguous_moves_board)
|
143
|
+
expect(logger.log_move).to eql('Qh4e1')
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should handle knights/bishops/queens with ability to move to dest square' do
|
147
|
+
logger = Logger.new([2, 3], [0, 1], @ambiguous_moves_board)
|
148
|
+
expect(logger.log_move).to eql('Bdb8')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'specialty moves' do
|
153
|
+
it 'should log kingside castles' do
|
154
|
+
logger = Logger.new([7, 4], [7, 6], @specialty_moves_board)
|
155
|
+
expect(logger.log_move).to eql('0-0')
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should log queenside castles' do
|
159
|
+
logger = Logger.new([7, 4], [7, 2], @specialty_moves_board)
|
160
|
+
expect(logger.log_move).to eql('0-0-0')
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should log pawn promotion' do
|
164
|
+
%w[R N B Q].each do |piece|
|
165
|
+
logger = Logger.new(nil, nil, nil, promotion_type: piece)
|
166
|
+
expect(logger.log_promotion).to eql("=(#{piece})")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'game status indications' do
|
172
|
+
it 'should log check' do
|
173
|
+
logger = Logger.new([5, 0], [6, 2], @check_board)
|
174
|
+
expect(logger.log_move).to eql('Nc2+')
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should log checkmate' do
|
178
|
+
logger = Logger.new([0, 3], [0, 4], @check_board)
|
179
|
+
expect(logger.log_move).to eql('Qe8#')
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
File without changes
|
data/spec/piece_spec.rb
CHANGED
File without changes
|
data/spec/spec_helper.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chessmate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Porter
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.75.1
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.75.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: deep_dup
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,10 +72,14 @@ executables: []
|
|
72
72
|
extensions: []
|
73
73
|
extra_rdoc_files: []
|
74
74
|
files:
|
75
|
+
- CODE_OF_CONDUCT.md
|
75
76
|
- Gemfile
|
76
77
|
- Gemfile.lock
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
77
80
|
- lib/chessmate.rb
|
78
81
|
- lib/helpers/default.rb
|
82
|
+
- lib/helpers/logger.rb
|
79
83
|
- lib/helpers/notation_parser.rb
|
80
84
|
- lib/pieces/bishop.rb
|
81
85
|
- lib/pieces/king.rb
|
@@ -84,7 +88,9 @@ files:
|
|
84
88
|
- lib/pieces/piece.rb
|
85
89
|
- lib/pieces/queen.rb
|
86
90
|
- lib/pieces/rook.rb
|
91
|
+
- pre-commit.sh
|
87
92
|
- spec/chessmate_spec.rb
|
93
|
+
- spec/logger_spec.rb
|
88
94
|
- spec/notation_parser_spec.rb
|
89
95
|
- spec/piece_spec.rb
|
90
96
|
- spec/spec_helper.rb
|
@@ -108,8 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
114
|
- !ruby/object:Gem::Version
|
109
115
|
version: '0'
|
110
116
|
requirements: []
|
111
|
-
|
112
|
-
rubygems_version: 2.7.6.2
|
117
|
+
rubygems_version: 3.0.3
|
113
118
|
signing_key:
|
114
119
|
specification_version: 4
|
115
120
|
summary: Chess for Rails
|