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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +44 -0
  4. data/Rakefile +6 -7
  5. data/chess.gemspec +1 -1
  6. data/ext/bitboard.c +24 -0
  7. data/ext/board.c +78 -24
  8. data/ext/board.h +4 -2
  9. data/ext/chess.c +216 -196
  10. data/ext/chess.h +1 -0
  11. data/ext/common.c +10 -0
  12. data/ext/game.c +33 -16
  13. data/ext/special.c +14 -11
  14. data/ext/special.h +1 -2
  15. data/lib/chess/exceptions.rb +7 -10
  16. data/lib/chess/game.rb +66 -50
  17. data/lib/chess/gnuchess.rb +19 -25
  18. data/lib/chess/pgn.rb +49 -9
  19. data/lib/chess/utf8_notation.rb +11 -9
  20. data/lib/chess/version.rb +1 -1
  21. data/test/pgn_collection/illegal/0001.pgn +18 -0
  22. data/test/pgn_collection/illegal/0002.pgn +17 -0
  23. data/test/pgn_collection/illegal/0003.pgn +13 -0
  24. data/test/pgn_collection/illegal/0004.pgn +15 -0
  25. data/test/pgn_collection/illegal/0005.pgn +16 -0
  26. data/test/pgn_collection/invalid/0001.pgn +20 -0
  27. data/test/pgn_collection/invalid/0002.pgn +16 -0
  28. data/test/pgn_collection/invalid/0003.pgn +13 -0
  29. data/test/pgn_collection/invalid/0004.pgn +15 -0
  30. data/test/pgn_collection/valid/0001.pgn +6 -7
  31. data/test/pgn_collection/valid/0002.pgn +8 -9
  32. data/test/pgn_collection/valid/0005.pgn +7 -8
  33. data/test/pgn_collection/valid/0009.pgn +14 -15
  34. data/test/pgn_collection/valid/0010.pgn +6 -7
  35. data/test/pgn_collection/valid/0011.pgn +5 -6
  36. data/test/pgn_collection/valid/0012.pgn +0 -1
  37. data/test/pgn_collection/valid/0013.pgn +5 -6
  38. data/test/pgn_collection/valid/0014.pgn +6 -7
  39. data/test/pgn_collection/valid/0020.pgn +6 -7
  40. data/test/pgn_collection/valid/0021.pgn +15 -16
  41. data/test/pgn_collection/valid/0971.pgn +22 -14
  42. data/test/test_big_pgn_collection.rb +12 -5
  43. data/test/test_helper.rb +1 -1
  44. data/test/test_illegal_moves.rb +14 -0
  45. data/test/test_insufficient_material.rb +13 -1
  46. data/test/test_particular_situations.rb +14 -0
  47. data/test/test_pgn.rb +24 -0
  48. data/test/test_pgn_collection.rb +1 -4
  49. metadata +30 -63
  50. data/README.rdoc +0 -44
  51. data/doc/Chess.html +0 -112
  52. data/doc/Chess/BadNotationError.html +0 -107
  53. data/doc/Chess/Board.html +0 -700
  54. data/doc/Chess/CGame.html +0 -1004
  55. data/doc/Chess/Game.html +0 -684
  56. data/doc/Chess/Gnuchess.html +0 -215
  57. data/doc/Chess/IllegalMoveError.html +0 -105
  58. data/doc/Chess/InvalidFenFormatError.html +0 -105
  59. data/doc/Chess/InvalidPgnFormatError.html +0 -105
  60. data/doc/Chess/Pgn.html +0 -309
  61. data/doc/Chess/UTF8Notation.html +0 -174
  62. data/doc/README_rdoc.html +0 -143
  63. data/doc/created.rid +0 -15
  64. data/doc/css/fonts.css +0 -167
  65. data/doc/css/rdoc.css +0 -590
  66. data/doc/fonts/Lato-Light.ttf +0 -0
  67. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  68. data/doc/fonts/Lato-Regular.ttf +0 -0
  69. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  70. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  71. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  72. data/doc/images/add.png +0 -0
  73. data/doc/images/arrow_up.png +0 -0
  74. data/doc/images/brick.png +0 -0
  75. data/doc/images/brick_link.png +0 -0
  76. data/doc/images/bug.png +0 -0
  77. data/doc/images/bullet_black.png +0 -0
  78. data/doc/images/bullet_toggle_minus.png +0 -0
  79. data/doc/images/bullet_toggle_plus.png +0 -0
  80. data/doc/images/date.png +0 -0
  81. data/doc/images/delete.png +0 -0
  82. data/doc/images/find.png +0 -0
  83. data/doc/images/loadingAnimation.gif +0 -0
  84. data/doc/images/macFFBgHack.png +0 -0
  85. data/doc/images/package.png +0 -0
  86. data/doc/images/page_green.png +0 -0
  87. data/doc/images/page_white_text.png +0 -0
  88. data/doc/images/page_white_width.png +0 -0
  89. data/doc/images/plugin.png +0 -0
  90. data/doc/images/ruby.png +0 -0
  91. data/doc/images/tag_blue.png +0 -0
  92. data/doc/images/tag_green.png +0 -0
  93. data/doc/images/transparent.png +0 -0
  94. data/doc/images/wrench.png +0 -0
  95. data/doc/images/wrench_orange.png +0 -0
  96. data/doc/images/zoom.png +0 -0
  97. data/doc/index.html +0 -160
  98. data/doc/js/darkfish.js +0 -161
  99. data/doc/js/jquery.js +0 -4
  100. data/doc/js/navigation.js +0 -142
  101. data/doc/js/navigation.js.gz +0 -0
  102. data/doc/js/search.js +0 -109
  103. data/doc/js/search_index.js +0 -1
  104. data/doc/js/search_index.js.gz +0 -0
  105. data/doc/js/searcher.js +0 -229
  106. data/doc/js/searcher.js.gz +0 -0
  107. data/doc/table_of_contents.html +0 -331
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b1b122a9e2e4ddaf1384bb4436f27d657c0691fd
4
- data.tar.gz: 806cded3d3289d7766774e898315634698bd94e4
3
+ metadata.gz: 72831c5ff5567709d9ce1e377c98d7867b35b611
4
+ data.tar.gz: 0af6a358a253414ad636d9fec050eb1dd5ccfbc9
5
5
  SHA512:
6
- metadata.gz: 8613eb5ba2e25085ac2988f8184e4ad2b961e26846c1bc62aade2a7d1bc28162a904c921ce3b6d46f52a03a4b9fc5cc12cc7d01edc0fb75ab11eb68c7ef9aa48
7
- data.tar.gz: 0e57bca085a33d11f4ebc0690cfa04da76472cb432b2b96a35d01c27c65e035794f154c8c317a3632e239c0622827a52410f938f036def5ff6a0096adaf792b7
6
+ metadata.gz: cf1c0fc216c2e2a76e978b96c4e668eed29d23eef23606280075b58d42a717b27d1fdfe50c1dae6961ffac71d4272ada39c6a3f8a8e2b69d5b16a33c24114abe
7
+ data.tar.gz: 3544641ba2184d3965574c912472defad0e49020c650ae9f2a342683dddd02b81ced292156c3828d987b6001f5e8993a252c4950bc56bd965de827d5f858e03e
data/.gitignore CHANGED
@@ -1,5 +1,7 @@
1
1
  *.gem
2
2
  .bundle
3
+ .yardoc/
4
+ doc/
3
5
  ext/chess
4
6
  ext/Makefile
5
7
  ext/*.bundle
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 'rdoc/task'
4
- Rake::RDocTask.new do |rd|
5
- rd.title = 'Chess'
6
- rd.main = 'README.rdoc'
7
- rd.rdoc_dir = 'doc'
8
- rd.rdoc_files.include('README.rdoc', 'lib/**/*.rb', 'ext/*.c')
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 'rdoc', '~> 5.1'
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
- // All xray of color pieces
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
- // All xray of color pieces with friends square removed
167
+ // Returns the bitboard with all the xray that start from the color pieces with
168
+ // friend squares removed.
159
169
  bboard
160
- all_xray_friend (Board *board, int color, bool only_attack)
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
- // return the squares of pieces as piece that can capture in to
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 all_xray_friend (board, color, FALSE) & (1ULL << square) ? TRUE : FALSE;
214
+ return all_xray_without_friends (board, color, FALSE) & (1ULL << square) ? TRUE : FALSE;
202
215
  }
203
216
 
204
- // If there is a piece that can capture the to square without put its king in check return true
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 all_xray_friend (board, !color, TRUE) & board->king[color] ? TRUE : FALSE;
230
+ return all_xray_without_friends (board, !color, TRUE) & board->king[color] ? TRUE : FALSE;
216
231
  }
217
232
 
218
- // Assumes that king is in check
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 cant be auto-shielded xray
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 (have_en_passant2 (board, attacker))
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 = all_xray_friend (board, color, FALSE);
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
- void
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 (!strcmp (disambiguating, "")
359
- || disambiguating[0] == file
360
- || disambiguating[0] == rank
361
- || (disambiguating[0] == file && disambiguating[1] == rank))
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
- *from = *to = 0;
420
+ {
421
+ *from = *to = 0;
422
+ return FALSE;
423
+ }
375
424
  // For compatibility: if pawn capture a file disambiguating is required
376
- else if (piece == 'P' && !strcmp (disambiguating, ""))
377
- if (square_to_file (*from) != square_to_file (*to))
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
- // This function do not consider castling, this is handled separately.
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
  {