chess 0.1.3 → 0.1.4
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 +4 -4
- data/.gitignore +2 -0
- data/README.md +44 -0
- data/Rakefile +6 -7
- data/chess.gemspec +1 -1
- data/ext/bitboard.c +24 -0
- data/ext/board.c +78 -24
- data/ext/board.h +4 -2
- data/ext/chess.c +216 -196
- data/ext/chess.h +1 -0
- data/ext/common.c +10 -0
- data/ext/game.c +33 -16
- data/ext/special.c +14 -11
- data/ext/special.h +1 -2
- data/lib/chess/exceptions.rb +7 -10
- data/lib/chess/game.rb +66 -50
- data/lib/chess/gnuchess.rb +19 -25
- data/lib/chess/pgn.rb +49 -9
- data/lib/chess/utf8_notation.rb +11 -9
- data/lib/chess/version.rb +1 -1
- data/test/pgn_collection/illegal/0001.pgn +18 -0
- data/test/pgn_collection/illegal/0002.pgn +17 -0
- data/test/pgn_collection/illegal/0003.pgn +13 -0
- data/test/pgn_collection/illegal/0004.pgn +15 -0
- data/test/pgn_collection/illegal/0005.pgn +16 -0
- data/test/pgn_collection/invalid/0001.pgn +20 -0
- data/test/pgn_collection/invalid/0002.pgn +16 -0
- data/test/pgn_collection/invalid/0003.pgn +13 -0
- data/test/pgn_collection/invalid/0004.pgn +15 -0
- data/test/pgn_collection/valid/0001.pgn +6 -7
- data/test/pgn_collection/valid/0002.pgn +8 -9
- data/test/pgn_collection/valid/0005.pgn +7 -8
- data/test/pgn_collection/valid/0009.pgn +14 -15
- data/test/pgn_collection/valid/0010.pgn +6 -7
- data/test/pgn_collection/valid/0011.pgn +5 -6
- data/test/pgn_collection/valid/0012.pgn +0 -1
- data/test/pgn_collection/valid/0013.pgn +5 -6
- data/test/pgn_collection/valid/0014.pgn +6 -7
- data/test/pgn_collection/valid/0020.pgn +6 -7
- data/test/pgn_collection/valid/0021.pgn +15 -16
- data/test/pgn_collection/valid/0971.pgn +22 -14
- data/test/test_big_pgn_collection.rb +12 -5
- data/test/test_helper.rb +1 -1
- data/test/test_illegal_moves.rb +14 -0
- data/test/test_insufficient_material.rb +13 -1
- data/test/test_particular_situations.rb +14 -0
- data/test/test_pgn.rb +24 -0
- data/test/test_pgn_collection.rb +1 -4
- metadata +30 -63
- data/README.rdoc +0 -44
- data/doc/Chess.html +0 -112
- data/doc/Chess/BadNotationError.html +0 -107
- data/doc/Chess/Board.html +0 -700
- data/doc/Chess/CGame.html +0 -1004
- data/doc/Chess/Game.html +0 -684
- data/doc/Chess/Gnuchess.html +0 -215
- data/doc/Chess/IllegalMoveError.html +0 -105
- data/doc/Chess/InvalidFenFormatError.html +0 -105
- data/doc/Chess/InvalidPgnFormatError.html +0 -105
- data/doc/Chess/Pgn.html +0 -309
- data/doc/Chess/UTF8Notation.html +0 -174
- data/doc/README_rdoc.html +0 -143
- data/doc/created.rid +0 -15
- data/doc/css/fonts.css +0 -167
- data/doc/css/rdoc.css +0 -590
- data/doc/fonts/Lato-Light.ttf +0 -0
- data/doc/fonts/Lato-LightItalic.ttf +0 -0
- data/doc/fonts/Lato-Regular.ttf +0 -0
- data/doc/fonts/Lato-RegularItalic.ttf +0 -0
- data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
- data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
- data/doc/images/add.png +0 -0
- data/doc/images/arrow_up.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +0 -160
- data/doc/js/darkfish.js +0 -161
- data/doc/js/jquery.js +0 -4
- data/doc/js/navigation.js +0 -142
- data/doc/js/navigation.js.gz +0 -0
- data/doc/js/search.js +0 -109
- data/doc/js/search_index.js +0 -1
- data/doc/js/search_index.js.gz +0 -0
- data/doc/js/searcher.js +0 -229
- data/doc/js/searcher.js.gz +0 -0
- data/doc/table_of_contents.html +0 -331
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72831c5ff5567709d9ce1e377c98d7867b35b611
|
4
|
+
data.tar.gz: 0af6a358a253414ad636d9fec050eb1dd5ccfbc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf1c0fc216c2e2a76e978b96c4e668eed29d23eef23606280075b58d42a717b27d1fdfe50c1dae6961ffac71d4272ada39c6a3f8a8e2b69d5b16a33c24114abe
|
7
|
+
data.tar.gz: 3544641ba2184d3965574c912472defad0e49020c650ae9f2a342683dddd02b81ced292156c3828d987b6001f5e8993a252c4950bc56bd965de827d5f858e03e
|
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Chess
|
2
|
+
|
3
|
+
A fast Ruby library to play chess with Ruby. This library is quite fast
|
4
|
+
because rappresent the game situations with bitboards. In addition, the move
|
5
|
+
generator is written in C as a Ruby extension.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
* Ruby 1.9 or higher
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
gem install chess
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
require 'chess'
|
18
|
+
g = Chess::Game.new
|
19
|
+
until g.over?
|
20
|
+
begin
|
21
|
+
print "Give me a #{g.active_player} move: "
|
22
|
+
input = gets.chop
|
23
|
+
break if input == 'quit'
|
24
|
+
g << input
|
25
|
+
puts g
|
26
|
+
puts g.moves.last
|
27
|
+
rescue Chess::IllegalMoveError => e
|
28
|
+
puts 'Illegal move!'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
puts g.status
|
32
|
+
|
33
|
+
**Documentation** is available [here](http://pioz.github.com/chess).
|
34
|
+
|
35
|
+
## Questions or problems?
|
36
|
+
|
37
|
+
If you have any issues please add an [issue on
|
38
|
+
GitHub](https://github.com/pioz/chess/issues) or fork the project and send a
|
39
|
+
pull request.
|
40
|
+
|
41
|
+
## Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2017 [Enrico Pilotto (@pioz)](https://github.com/pioz). See
|
44
|
+
[LICENSE](https://github.com/pioz/chess/blob/master/LICENSE) for details.
|
data/Rakefile
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
|
3
|
-
require '
|
4
|
-
Rake::
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
rd.generator = 'darkfish'
|
3
|
+
require 'yard'
|
4
|
+
YARD::Rake::YardocTask.new do |t|
|
5
|
+
t.files = ['lib/**/*.rb', 'ext/*.c']
|
6
|
+
t.options << '-rREADME.md'
|
7
|
+
t.options << '--title=Chess'
|
8
|
+
t.options << '-mmarkdown'
|
10
9
|
end
|
11
10
|
|
12
11
|
require 'rake/testtask'
|
data/chess.gemspec
CHANGED
@@ -24,5 +24,5 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency 'bundler', '~> 1.14'
|
25
25
|
s.add_development_dependency 'rake', '~> 12.0'
|
26
26
|
s.add_development_dependency 'minitest', '~> 5.10'
|
27
|
-
s.add_development_dependency '
|
27
|
+
s.add_development_dependency 'yard', '~> 0.9'
|
28
28
|
end
|
data/ext/bitboard.c
CHANGED
@@ -73,12 +73,15 @@ const bboard AVOID_WRAP[8] =
|
|
73
73
|
};
|
74
74
|
|
75
75
|
// Bitboard getters
|
76
|
+
|
77
|
+
// Given file and rank returns the square (0..63).
|
76
78
|
int
|
77
79
|
square (int file, int rank)
|
78
80
|
{
|
79
81
|
return 8 * rank + file;
|
80
82
|
}
|
81
83
|
|
84
|
+
// Given a bitboard returns the first square (0..63) with a piece.
|
82
85
|
int
|
83
86
|
square2 (bboard b)
|
84
87
|
{
|
@@ -91,6 +94,7 @@ square2 (bboard b)
|
|
91
94
|
return pos;
|
92
95
|
}
|
93
96
|
|
97
|
+
// Returns the array and its size (n) with pieces in the bitboard.
|
94
98
|
void
|
95
99
|
squares (bboard b, int *array, int *n)
|
96
100
|
{
|
@@ -103,29 +107,36 @@ squares (bboard b, int *array, int *n)
|
|
103
107
|
}
|
104
108
|
}
|
105
109
|
|
110
|
+
// Given a square returns the corresponding file.
|
106
111
|
int
|
107
112
|
file (int square)
|
108
113
|
{
|
109
114
|
return square & 7;
|
110
115
|
}
|
111
116
|
|
117
|
+
// Given a square returns the corresponding rank.
|
112
118
|
int rank (int square)
|
113
119
|
{
|
114
120
|
return square >> 3;
|
115
121
|
}
|
116
122
|
|
123
|
+
// Given a bitboard and a square (0..63) returns a bitboard copy with square set
|
124
|
+
// to 1.
|
117
125
|
bboard
|
118
126
|
get (bboard b, int square)
|
119
127
|
{
|
120
128
|
return b & (1ULL << square);
|
121
129
|
}
|
122
130
|
|
131
|
+
// Given a bitboard, a file and a rank returns a bitboard copy with square set
|
132
|
+
// to 1.
|
123
133
|
bboard
|
124
134
|
get2 (bboard b, int file, int rank)
|
125
135
|
{
|
126
136
|
return b & (1ULL << (8 * rank + file));
|
127
137
|
}
|
128
138
|
|
139
|
+
// Print the bitboard.
|
129
140
|
void
|
130
141
|
print_bitboard (bboard b)
|
131
142
|
{
|
@@ -139,24 +150,28 @@ print_bitboard (bboard b)
|
|
139
150
|
|
140
151
|
// Bitboard manipulations
|
141
152
|
|
153
|
+
// Returns true if the bitboard has only one bit equals to 1.
|
142
154
|
bboard
|
143
155
|
has_only_one_one (bboard b)
|
144
156
|
{
|
145
157
|
return b && !(b & (b-1));
|
146
158
|
}
|
147
159
|
|
160
|
+
// Returns true if the bitboard has only bits equals to 1 in the white squares.
|
148
161
|
bboard
|
149
162
|
only_white_squares (bboard b)
|
150
163
|
{
|
151
164
|
return !((b ^ WHITE_SQUARES) & b);
|
152
165
|
}
|
153
166
|
|
167
|
+
// Returns true if the bitboard has only bits equals to 1 in the black squares.
|
154
168
|
bboard
|
155
169
|
only_black_squares (bboard b)
|
156
170
|
{
|
157
171
|
return !((b ^ BLACK_SQUARES) & b);
|
158
172
|
}
|
159
173
|
|
174
|
+
// Returns the horizontally mirrored bitboard.
|
160
175
|
bboard
|
161
176
|
mirror_horizontal (bboard b)
|
162
177
|
{
|
@@ -169,6 +184,7 @@ mirror_horizontal (bboard b)
|
|
169
184
|
return b;
|
170
185
|
}
|
171
186
|
|
187
|
+
// Returns the vertically mirrored bitboard.
|
172
188
|
bboard
|
173
189
|
mirror_vertical (bboard b)
|
174
190
|
{
|
@@ -180,6 +196,7 @@ mirror_vertical (bboard b)
|
|
180
196
|
return b;
|
181
197
|
}
|
182
198
|
|
199
|
+
// Returns the left rotated bitboard.
|
183
200
|
bboard
|
184
201
|
rotate_left (bboard b, int s)
|
185
202
|
{
|
@@ -188,6 +205,7 @@ rotate_left (bboard b, int s)
|
|
188
205
|
return s > 0 ? b << s : b >> -s;
|
189
206
|
}
|
190
207
|
|
208
|
+
// Returns the right rotated bitboard.
|
191
209
|
bboard
|
192
210
|
rotate_right (bboard b, int s)
|
193
211
|
{
|
@@ -196,6 +214,8 @@ rotate_right (bboard b, int s)
|
|
196
214
|
return s > 0 ? b >> s : b << -s;
|
197
215
|
}
|
198
216
|
|
217
|
+
// Given a generator, a propagator and a direction returns the bitboard with
|
218
|
+
// occluded squares setted to 1.
|
199
219
|
bboard
|
200
220
|
occluded_fill (bboard gen, bboard pro, int dir)
|
201
221
|
{
|
@@ -209,12 +229,14 @@ occluded_fill (bboard gen, bboard pro, int dir)
|
|
209
229
|
return gen;
|
210
230
|
}
|
211
231
|
|
232
|
+
// Returns the shifted bitboard.
|
212
233
|
bboard
|
213
234
|
shift_one (bboard b, int dir)
|
214
235
|
{
|
215
236
|
return rotate_left (b, DIR[dir]) & AVOID_WRAP[dir];
|
216
237
|
}
|
217
238
|
|
239
|
+
// Returns the bitboard with sliding attacks.
|
218
240
|
bboard
|
219
241
|
sliding_attacks (bboard slider, bboard propagator, int dir)
|
220
242
|
{
|
@@ -223,6 +245,7 @@ sliding_attacks (bboard slider, bboard propagator, int dir)
|
|
223
245
|
}
|
224
246
|
|
225
247
|
// Pre-calculators
|
248
|
+
|
226
249
|
void
|
227
250
|
precalculate_xray_attack_white_pawn (bboard xray[64])
|
228
251
|
{
|
@@ -281,6 +304,7 @@ precalculate_all_xray ()
|
|
281
304
|
}
|
282
305
|
|
283
306
|
// XRay generators
|
307
|
+
|
284
308
|
bboard
|
285
309
|
xray_white_pawn (bboard occupied_square, int square)
|
286
310
|
{
|
data/ext/board.c
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
#include "board.h"
|
9
9
|
|
10
|
+
// Initialize the board
|
10
11
|
void
|
11
12
|
init_board (Board *board)
|
12
13
|
{
|
@@ -32,6 +33,7 @@ init_board (Board *board)
|
|
32
33
|
set_occupied (board);
|
33
34
|
}
|
34
35
|
|
36
|
+
// Set helpers bitboards (white pieces, black pieces, occupied squares).
|
35
37
|
void
|
36
38
|
set_occupied (Board *board)
|
37
39
|
{
|
@@ -50,6 +52,7 @@ set_occupied (Board *board)
|
|
50
52
|
board->occupied = board->pieces[WHITE] | board->pieces[BLACK];
|
51
53
|
}
|
52
54
|
|
55
|
+
// Board to string.
|
53
56
|
char*
|
54
57
|
print_board (Board *board)
|
55
58
|
{
|
@@ -72,6 +75,7 @@ print_board (Board *board)
|
|
72
75
|
return s;
|
73
76
|
}
|
74
77
|
|
78
|
+
// Given a square returns its color (white is 0, black is 1).
|
75
79
|
int
|
76
80
|
get_color (Board *board, int square)
|
77
81
|
{
|
@@ -85,6 +89,7 @@ get_color (Board *board, int square)
|
|
85
89
|
return -1;
|
86
90
|
}
|
87
91
|
|
92
|
+
// Given a piece returns the piece's bitboard.
|
88
93
|
bboard*
|
89
94
|
get_piece_bitboard (Board *board, char piece)
|
90
95
|
{
|
@@ -107,12 +112,15 @@ get_piece_bitboard (Board *board, char piece)
|
|
107
112
|
}
|
108
113
|
}
|
109
114
|
|
115
|
+
// Given a square (0..63) retuns the piece's bitboard in that square.
|
110
116
|
bboard*
|
111
117
|
get_bitboard (Board *board, int square)
|
112
118
|
{
|
113
119
|
return get_piece_bitboard (board, board->placement[square]);
|
114
120
|
}
|
115
121
|
|
122
|
+
// Returns the bitboard with the xray that start from square. If only_attack use
|
123
|
+
// only pawns attack squares.
|
116
124
|
bboard
|
117
125
|
xray (Board *board, int from, bool only_attack)
|
118
126
|
{
|
@@ -140,7 +148,8 @@ xray (Board *board, int from, bool only_attack)
|
|
140
148
|
}
|
141
149
|
}
|
142
150
|
|
143
|
-
|
151
|
+
|
152
|
+
// Returns the bitboard with all the xray that start from the color pieces.
|
144
153
|
bboard
|
145
154
|
all_xray (Board *board, int color, bool only_attack)
|
146
155
|
{
|
@@ -155,13 +164,15 @@ all_xray (Board *board, int color, bool only_attack)
|
|
155
164
|
return x;
|
156
165
|
}
|
157
166
|
|
158
|
-
//
|
167
|
+
// Returns the bitboard with all the xray that start from the color pieces with
|
168
|
+
// friend squares removed.
|
159
169
|
bboard
|
160
|
-
|
170
|
+
all_xray_without_friends (Board *board, int color, bool only_attack)
|
161
171
|
{
|
162
172
|
return all_xray (board, color, only_attack) & ~board->pieces[color];
|
163
173
|
}
|
164
174
|
|
175
|
+
// Returns a new board with the piece in square position removed.
|
165
176
|
void
|
166
177
|
remove_piece (Board *board, int square, Board *new_board)
|
167
178
|
{
|
@@ -174,7 +185,8 @@ remove_piece (Board *board, int square, Board *new_board)
|
|
174
185
|
}
|
175
186
|
}
|
176
187
|
|
177
|
-
//
|
188
|
+
// Returns the squares of the same pieces of color and its size that can capture
|
189
|
+
// the square. If piece_filter consider only that kind of pieces.
|
178
190
|
int
|
179
191
|
same_pieces_that_can_capture_a_square (Board *board, int color, int square, int *pieces, char piece_filter)
|
180
192
|
{
|
@@ -195,13 +207,15 @@ same_pieces_that_can_capture_a_square (Board *board, int color, int square, int
|
|
195
207
|
return index;
|
196
208
|
}
|
197
209
|
|
210
|
+
// Returns true if square can be captured from color pieces.
|
198
211
|
bool
|
199
212
|
capture (Board *board, int color, int square)
|
200
213
|
{
|
201
|
-
return
|
214
|
+
return all_xray_without_friends (board, color, FALSE) & (1ULL << square) ? TRUE : FALSE;
|
202
215
|
}
|
203
216
|
|
204
|
-
//
|
217
|
+
// Returns true if there is a piece that can capture the square without put its
|
218
|
+
// king in check.
|
205
219
|
bool
|
206
220
|
pieces_can_safe_capture (Board *board, int color, int square)
|
207
221
|
{
|
@@ -209,20 +223,22 @@ pieces_can_safe_capture (Board *board, int color, int square)
|
|
209
223
|
return same_pieces_that_can_capture_a_square (board, color, square, pieces, 0) > 0;
|
210
224
|
}
|
211
225
|
|
226
|
+
// Returns true if the king color is in check.
|
212
227
|
bool
|
213
228
|
king_in_check (Board *board, int color)
|
214
229
|
{
|
215
|
-
return
|
230
|
+
return all_xray_without_friends (board, !color, TRUE) & board->king[color] ? TRUE : FALSE;
|
216
231
|
}
|
217
232
|
|
218
|
-
// Assumes that king is in
|
233
|
+
// Returns true if the king color is in check. Assumes that the king is in
|
234
|
+
// check.
|
219
235
|
bool
|
220
236
|
king_in_checkmate (Board *board, int color)
|
221
237
|
{
|
222
238
|
int king_square = square2 (board->king[color]);
|
223
239
|
bboard king = xray_king (king_square) & ~board->pieces[color];
|
224
240
|
Board board_without_king;
|
225
|
-
remove_piece (board, king_square, &board_without_king); // King
|
241
|
+
remove_piece (board, king_square, &board_without_king); // King can't be auto-shielded xray
|
226
242
|
bboard attackers = all_xray (&board_without_king, !color, TRUE);
|
227
243
|
// If king can move return false
|
228
244
|
if (king & ~attackers)
|
@@ -237,7 +253,8 @@ king_in_checkmate (Board *board, int color)
|
|
237
253
|
if (pieces_can_safe_capture (board, color, attacker))
|
238
254
|
return FALSE;
|
239
255
|
// Test if there is an en passant capture
|
240
|
-
if (
|
256
|
+
if (have_en_passant (board, attacker + 1, board->en_passant) ||
|
257
|
+
have_en_passant (board, attacker - 1, board->en_passant))
|
241
258
|
return FALSE;
|
242
259
|
// Test if attack can be shielded
|
243
260
|
bboard slide = EMPTY_BOARD;
|
@@ -249,7 +266,7 @@ king_in_checkmate (Board *board, int color)
|
|
249
266
|
break;
|
250
267
|
}
|
251
268
|
bboard attack = xray (board, attacker, TRUE) & slide;
|
252
|
-
bboard defend =
|
269
|
+
bboard defend = all_xray_without_friends (board, color, FALSE);
|
253
270
|
bboard shield = attack & defend;
|
254
271
|
if (shield)
|
255
272
|
{
|
@@ -263,6 +280,7 @@ king_in_checkmate (Board *board, int color)
|
|
263
280
|
return TRUE;
|
264
281
|
}
|
265
282
|
|
283
|
+
// Returns true if the color pieces are in stale.
|
266
284
|
bool
|
267
285
|
stalemate (Board *board, int color)
|
268
286
|
{
|
@@ -285,6 +303,7 @@ stalemate (Board *board, int color)
|
|
285
303
|
return TRUE;
|
286
304
|
}
|
287
305
|
|
306
|
+
// Returns true if there are insufficient material to make a checkmate.
|
288
307
|
bool
|
289
308
|
insufficient_material (Board *board)
|
290
309
|
{
|
@@ -310,15 +329,40 @@ insufficient_material (Board *board)
|
|
310
329
|
|| (only_black_squares(board->bishops[WHITE]) && only_black_squares(board->bishops[BLACK])))
|
311
330
|
return TRUE;
|
312
331
|
}
|
332
|
+
// TODO more bishops on same color square
|
313
333
|
return FALSE;
|
314
334
|
}
|
315
335
|
|
336
|
+
// Returns true if on the board there are only the two kings.
|
337
|
+
bool
|
338
|
+
only_kings (Board *board)
|
339
|
+
{
|
340
|
+
return !board->pawns[WHITE] && !board->pawns[BLACK] &&
|
341
|
+
!board->rooks[WHITE] && !board->rooks[BLACK] &&
|
342
|
+
!board->knights[WHITE] && !board->knights[BLACK] &&
|
343
|
+
!board->bishops[WHITE] && !board->bishops[BLACK] &&
|
344
|
+
!board->queens[WHITE] && !board->queens[BLACK];
|
345
|
+
}
|
346
|
+
|
347
|
+
// Returns true if fifty move rule is available.
|
316
348
|
bool
|
317
349
|
fifty_move_rule (Board *board)
|
318
350
|
{
|
319
351
|
return board->halfmove_clock >= 50;
|
320
352
|
}
|
321
353
|
|
354
|
+
// Returns true if the move from-to can not promote the pawn.
|
355
|
+
bool
|
356
|
+
invalid_promotion (Board *board, int from, int to)
|
357
|
+
{
|
358
|
+
if (toupper (board->placement[from]) != 'P')
|
359
|
+
return TRUE;
|
360
|
+
if ((board->active_color ? 0xffffffffffffff00 : 0x00ffffffffffffff) & (1ULL << to))
|
361
|
+
return TRUE;
|
362
|
+
return FALSE;
|
363
|
+
}
|
364
|
+
|
365
|
+
// Returns true if the move from-to is pseudo legal.
|
322
366
|
bool
|
323
367
|
pseudo_legal_move (Board *board, int from, int to)
|
324
368
|
{
|
@@ -336,7 +380,9 @@ pseudo_legal_move (Board *board, int from, int to)
|
|
336
380
|
return x & (1ULL << to) ? TRUE : FALSE;
|
337
381
|
}
|
338
382
|
|
339
|
-
|
383
|
+
// Returns true if the move piece-dis-to is legal. Returns also [from, to]
|
384
|
+
// coordinate (0..63). Pseudo legal move check included.
|
385
|
+
bool
|
340
386
|
get_coord (Board *board, char piece, const char *disambiguating, const char *to_coord, char promote_in, int *from, int *to)
|
341
387
|
{
|
342
388
|
int count = 0;
|
@@ -355,10 +401,10 @@ get_coord (Board *board, char piece, const char *disambiguating, const char *to_
|
|
355
401
|
{
|
356
402
|
file = square_to_file (i);
|
357
403
|
rank = square_to_rank (i);
|
358
|
-
if (!
|
359
|
-
|
360
|
-
|
361
|
-
|
404
|
+
if (!disambiguating
|
405
|
+
|| disambiguating[0] == file
|
406
|
+
|| disambiguating[0] == rank
|
407
|
+
|| (disambiguating[0] == file && disambiguating[1] == rank))
|
362
408
|
{
|
363
409
|
Board new_board;
|
364
410
|
if (try_move (board, i, *to, promote_in, &new_board, 0, 0))
|
@@ -371,14 +417,23 @@ get_coord (Board *board, char piece, const char *disambiguating, const char *to_
|
|
371
417
|
}
|
372
418
|
}
|
373
419
|
if (count != 1)
|
374
|
-
|
420
|
+
{
|
421
|
+
*from = *to = 0;
|
422
|
+
return FALSE;
|
423
|
+
}
|
375
424
|
// For compatibility: if pawn capture a file disambiguating is required
|
376
|
-
|
377
|
-
|
425
|
+
if (piece == 'P' && !disambiguating && square_to_file (*from) != square_to_file (*to))
|
426
|
+
{
|
378
427
|
*from = *to = 0;
|
428
|
+
return FALSE;
|
429
|
+
}
|
430
|
+
return TRUE;
|
379
431
|
}
|
380
432
|
|
381
|
-
//
|
433
|
+
// Returns true if the move from-to can be performed. Returns also the short
|
434
|
+
// algebraic chess notation of the move and the captured piece if occured.
|
435
|
+
// Assume that the move is pseudo legal. Do not consider castling, this is
|
436
|
+
// handled separately.
|
382
437
|
bool
|
383
438
|
try_move (Board *board, int from, int to, char promote_in, Board *new_board, char **move_done, char *capture)
|
384
439
|
{
|
@@ -403,10 +458,7 @@ try_move (Board *board, int from, int to, char promote_in, Board *new_board, cha
|
|
403
458
|
new_board->placement[from] = 0;
|
404
459
|
// Promotion check
|
405
460
|
if (require_a_promotion (new_board))
|
406
|
-
|
407
|
-
if (!promote (new_board, to, promote_in))
|
408
|
-
return FALSE;
|
409
|
-
}
|
461
|
+
promote (new_board, to, promote_in);
|
410
462
|
else
|
411
463
|
promote_in = 0;
|
412
464
|
// Set occupied pieces in new board
|
@@ -420,6 +472,7 @@ try_move (Board *board, int from, int to, char promote_in, Board *new_board, cha
|
|
420
472
|
return TRUE;
|
421
473
|
}
|
422
474
|
|
475
|
+
// Returns the short algebraic chess notation of the move from-to.
|
423
476
|
char*
|
424
477
|
get_notation (Board *board, int from, int to, int capture, int ep, char promotion, int check, int checkmate)
|
425
478
|
{
|
@@ -506,6 +559,7 @@ get_notation (Board *board, int from, int to, int capture, int ep, char promotio
|
|
506
559
|
return notation;
|
507
560
|
}
|
508
561
|
|
562
|
+
// Returns the fen string that rappresent the board.
|
509
563
|
char*
|
510
564
|
to_fen (Board *board)
|
511
565
|
{
|