chess 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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
  {