~ubuntu-branches/ubuntu/trusty/polyglot/trusty

« back to all changes in this revision

Viewing changes to san.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Korff
  • Date: 2005-10-09 21:56:20 UTC
  • Revision ID: james.westby@ubuntu.com-20051009215620-dcuqynujzvmiglpj
Tags: upstream-1.3
ImportĀ upstreamĀ versionĀ 1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
// san.cpp
 
3
 
 
4
// includes
 
5
 
 
6
#include <cctype>
 
7
#include <cstdio>
 
8
#include <cstring>
 
9
 
 
10
#include "attack.h"
 
11
#include "board.h"
 
12
#include "list.h"
 
13
#include "move.h"
 
14
#include "move_gen.h"
 
15
#include "move_legal.h"
 
16
#include "piece.h"
 
17
#include "san.h"
 
18
#include "square.h"
 
19
#include "util.h"
 
20
 
 
21
// constants
 
22
 
 
23
static const bool UseSlowDebug = false;
 
24
 
 
25
enum ambiguity_t {
 
26
   AMBIGUITY_NONE,
 
27
   AMBIGUITY_FILE,
 
28
   AMBIGUITY_RANK,
 
29
   AMBIGUITY_SQUARE
 
30
};
 
31
 
 
32
// functions
 
33
 
 
34
static bool san_to_lan    (const char san[], const board_t * board, char string[], int size);
 
35
static int  move_from_lan (const char string[], const board_t * board);
 
36
 
 
37
static int  ambiguity     (int move, const board_t * board);
 
38
 
 
39
// move_to_san()
 
40
 
 
41
bool move_to_san(int move, const board_t * board, char string[], int size) {
 
42
 
 
43
   int from, to, piece;
 
44
   char tmp_string[256];
 
45
 
 
46
   ASSERT(move_is_ok(move));
 
47
   ASSERT(board_is_ok(board));
 
48
   ASSERT(string!=NULL);
 
49
   ASSERT(size>=8);
 
50
 
 
51
   ASSERT(move_is_legal(move,board));
 
52
 
 
53
   if (size < 8) return false;
 
54
 
 
55
   // init
 
56
 
 
57
   from = move_from(move);
 
58
   to = move_to(move);
 
59
 
 
60
   string[0] = '\0';
 
61
 
 
62
   // castle
 
63
 
 
64
   if (move_is_castle(move,board)) {
 
65
 
 
66
      switch (square_file(to)) {
 
67
      case FileG :
 
68
         strcat(string,"O-O");
 
69
         break;
 
70
      case FileC :
 
71
         strcat(string,"O-O-O");
 
72
         break;
 
73
      default :
 
74
         ASSERT(false);
 
75
         strcat(string,"?");
 
76
         break;
 
77
      }
 
78
 
 
79
      goto check;
 
80
   }
 
81
 
 
82
   // from
 
83
 
 
84
   piece = board->square[from];
 
85
 
 
86
   if (piece_is_pawn(piece)) {
 
87
 
 
88
      // pawn
 
89
 
 
90
      if (move_is_capture(move,board)) {
 
91
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
 
92
         strcat(string,tmp_string);
 
93
      }
 
94
 
 
95
   } else {
 
96
 
 
97
      // piece
 
98
 
 
99
      sprintf(tmp_string,"%c",toupper(piece_to_char(piece)));
 
100
      strcat(string,tmp_string);
 
101
 
 
102
      // ambiguity
 
103
 
 
104
      switch (ambiguity(move,board)) {
 
105
      case AMBIGUITY_NONE :
 
106
         break;
 
107
      case AMBIGUITY_FILE :
 
108
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
 
109
         strcat(string,tmp_string);
 
110
         break;
 
111
      case AMBIGUITY_RANK :
 
112
         sprintf(tmp_string,"%c",rank_to_char(square_rank(from)));
 
113
         strcat(string,tmp_string);
 
114
         break;
 
115
      case AMBIGUITY_SQUARE :
 
116
         if (!square_to_string(from,tmp_string,256)) return false;
 
117
         strcat(string,tmp_string);
 
118
         break;
 
119
      default :
 
120
         ASSERT(false);
 
121
         break;
 
122
      }
 
123
   }
 
124
 
 
125
   // capture
 
126
 
 
127
   if (move_is_capture(move,board)) strcat(string,"x");
 
128
 
 
129
   // to
 
130
 
 
131
   if (!square_to_string(to,tmp_string,256)) return false;
 
132
   strcat(string,tmp_string);
 
133
 
 
134
   // promote
 
135
 
 
136
   if (move_is_promote(move)) {
 
137
      sprintf(tmp_string,"=%c",toupper(piece_to_char(move_promote(move,board))));
 
138
      strcat(string,tmp_string);
 
139
   }
 
140
 
 
141
   // check
 
142
 
 
143
check:
 
144
 
 
145
   if (move_is_mate(move,board)) {
 
146
      strcat(string,"#");
 
147
   } else if (move_is_check(move,board)) {
 
148
      strcat(string,"+");
 
149
   }
 
150
 
 
151
   return true;
 
152
}
 
153
 
 
154
// move_from_san()
 
155
 
 
156
int move_from_san(const char string[], const board_t * board) {
 
157
 
 
158
   char s[256];
 
159
   int move;
 
160
 
 
161
   ASSERT(string!=NULL);
 
162
   ASSERT(board_is_ok(board));
 
163
 
 
164
   san_to_lan(string,board,s,256);
 
165
   move = move_from_lan(s,board);
 
166
 
 
167
   ASSERT(!UseSlowDebug||move==move_from_san_debug(string,board));
 
168
 
 
169
   return move;
 
170
}
 
171
 
 
172
// move_from_san_debug()
 
173
 
 
174
int move_from_san_debug(const char string[], const board_t * board) {
 
175
 
 
176
   list_t list[1];
 
177
   int i, move;
 
178
   char move_string[256];
 
179
 
 
180
   ASSERT(string!=NULL);
 
181
   ASSERT(board_is_ok(board));
 
182
 
 
183
   gen_legal_moves(list,board);
 
184
 
 
185
   for (i = 0; i < list_size(list); i++) {
 
186
      move = list_move(list,i);
 
187
      if (!move_to_san(move,board,move_string,256)) ASSERT(false);
 
188
      if (my_string_equal(move_string,string)) return move;
 
189
   }
 
190
 
 
191
   return MoveNone;
 
192
}
 
193
 
 
194
// san_to_lan()
 
195
 
 
196
static bool san_to_lan(const char san[], const board_t * board, char string[], int size) {
 
197
 
 
198
   int len;
 
199
   int left, right;
 
200
   int c;
 
201
 
 
202
   ASSERT(san!=NULL);
 
203
   ASSERT(board_is_ok(board));
 
204
   ASSERT(string!=NULL);
 
205
   ASSERT(size>=8);
 
206
 
 
207
   // init
 
208
 
 
209
   if (size < 8) return false;
 
210
   strcpy(string,"???????");
 
211
 
 
212
   len = strlen(san);
 
213
 
 
214
   left = 0;
 
215
   right = len;
 
216
 
 
217
   // skip trailing '+' or '#'
 
218
 
 
219
   if (left < right) {
 
220
      c = san[right-1];
 
221
      if (c == '+' || c == '#') right--;
 
222
   }
 
223
 
 
224
   // castling
 
225
 
 
226
   ASSERT(left==0);
 
227
 
 
228
   if (false) {
 
229
 
 
230
   } else if (right == 3 && strncmp(san,"O-O",3) == 0) {
 
231
 
 
232
      if (colour_is_white(board->turn)) {
 
233
         strcpy(string,"Ke1?g1?");
 
234
      } else {
 
235
         strcpy(string,"Ke8?g8?");
 
236
      }
 
237
 
 
238
   } else if (right == 5 && strncmp(san,"O-O-O",5) == 0) {
 
239
 
 
240
      if (colour_is_white(board->turn)) {
 
241
         strcpy(string,"Ke1?c1?");
 
242
      } else {
 
243
         strcpy(string,"Ke8?c8?");
 
244
      }
 
245
 
 
246
   } else {
 
247
 
 
248
      // moved piece
 
249
 
 
250
      if (left < right) {
 
251
 
 
252
         c = san[left];
 
253
 
 
254
         if (char_is_piece(c)) {
 
255
            string[0] = c;
 
256
            left++;
 
257
         }
 
258
      }
 
259
 
 
260
      // promotion
 
261
 
 
262
      if (left < right) {
 
263
 
 
264
         c = toupper(san[right-1]);
 
265
 
 
266
         if (char_is_piece(c)) {
 
267
 
 
268
            string[6] = c;
 
269
            right--;
 
270
 
 
271
            // skip '='
 
272
 
 
273
            if (left < right && san[right-1] == '=') right--;
 
274
         }
 
275
      }
 
276
 
 
277
      // to-square rank
 
278
 
 
279
      if (left < right) {
 
280
 
 
281
         c = san[right-1];
 
282
 
 
283
         if (char_is_rank(c)) {
 
284
            string[5] = c;
 
285
            right--;
 
286
         }
 
287
      }
 
288
 
 
289
      // to-square file
 
290
 
 
291
      if (left < right) {
 
292
 
 
293
         c = san[right-1];
 
294
 
 
295
         if (char_is_file(c)) {
 
296
            string[4] = c;
 
297
            right--;
 
298
         }
 
299
      }
 
300
 
 
301
      // captured piece
 
302
 
 
303
      if (left < right) {
 
304
 
 
305
         c = san[right-1];
 
306
 
 
307
         if (char_is_piece(c)) {
 
308
            string[3] = c;
 
309
            right--;
 
310
         }
 
311
      }
 
312
 
 
313
      // skip middle '-' or 'x'
 
314
 
 
315
      if (left < right) {
 
316
         c = san[right-1];
 
317
         if (c == '-' || c == 'x') right--;
 
318
      }
 
319
 
 
320
      // from-square file
 
321
 
 
322
      if (left < right) {
 
323
 
 
324
         c = san[left];
 
325
 
 
326
         if (char_is_file(c)) {
 
327
            string[1] = c;
 
328
            left++;
 
329
         }
 
330
      }
 
331
 
 
332
      // from-square rank
 
333
 
 
334
      if (left < right) {
 
335
 
 
336
         c = san[left];
 
337
 
 
338
         if (char_is_rank(c)) {
 
339
            string[2] = c;
 
340
            left++;
 
341
         }
 
342
      }
 
343
 
 
344
      if (left != right) return false;
 
345
   }
 
346
 
 
347
   // end
 
348
 
 
349
   return true;
 
350
}
 
351
 
 
352
// move_from_lan()
 
353
 
 
354
static int move_from_lan(const char string[], const board_t * board) {
 
355
 
 
356
   int len;
 
357
   int move;
 
358
   int promote;
 
359
   char s[256];
 
360
   int from, to;
 
361
   int colour;
 
362
   int inc;
 
363
   int piece_char;
 
364
   int n;
 
365
   const uint8 * ptr;
 
366
   int piece;
 
367
 
 
368
   ASSERT(string!=NULL);
 
369
   ASSERT(board_is_ok(board));
 
370
 
 
371
   // init
 
372
 
 
373
   len = strlen(string);
 
374
   if (len != 7) return MoveNone;
 
375
 
 
376
   move = MoveNone;
 
377
   colour = board->turn;
 
378
 
 
379
   // promote
 
380
 
 
381
   promote = 0;
 
382
 
 
383
   switch (string[6]) {
 
384
   case '?': // not a promotion
 
385
      break;
 
386
   case 'N':
 
387
      promote = MovePromoteKnight;
 
388
      break;
 
389
   case 'B':
 
390
      promote = MovePromoteBishop;
 
391
      break;
 
392
   case 'R':
 
393
      promote = MovePromoteRook;
 
394
      break;
 
395
   case 'Q':
 
396
      promote = MovePromoteQueen;
 
397
      break;
 
398
   default:
 
399
      return MoveNone;
 
400
      break;
 
401
   }
 
402
 
 
403
   // to square
 
404
 
 
405
   s[0] = string[4];
 
406
   s[1] = string[5];
 
407
   s[2] = '\0';
 
408
 
 
409
   to = square_from_string(s);
 
410
   if (to == SquareNone) return MoveNone;
 
411
 
 
412
   // known from square?
 
413
 
 
414
   if (string[1] != '?' && string[2] != '?') {
 
415
 
 
416
      // from square
 
417
 
 
418
      s[0] = string[1];
 
419
      s[1] = string[2];
 
420
      s[2] = '\0';
 
421
 
 
422
      from = square_from_string(s);
 
423
      if (from == SquareNone) return MoveNone;
 
424
 
 
425
      // move
 
426
 
 
427
      move = move_make(from,to) | promote;
 
428
 
 
429
      return move;
 
430
   }
 
431
 
 
432
   // pawn non-capture?
 
433
 
 
434
   if (string[0] == '?' && string[1] == '?') {
 
435
 
 
436
      if (board->square[to] != Empty) return MoveNone; // useful?
 
437
 
 
438
      inc = (colour_is_white(colour)) ? +16 : -16;
 
439
 
 
440
      from = to - inc;
 
441
      if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) {
 
442
         from -= inc;
 
443
      }
 
444
 
 
445
      if (board->square[from] != piece_make_pawn(colour)) { // useful?
 
446
         return MoveNone;
 
447
      }
 
448
 
 
449
      // move
 
450
 
 
451
      move = move_make(from,to) | promote;
 
452
 
 
453
      return move;
 
454
   }
 
455
 
 
456
   // pawn capture?
 
457
 
 
458
   piece_char = string[0];
 
459
 
 
460
   if (piece_char == '?' && string[1] != '?') {
 
461
      piece_char = 'P';
 
462
   }
 
463
 
 
464
   // attack loop
 
465
 
 
466
   n = 0;
 
467
 
 
468
   for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {
 
469
 
 
470
      piece = board->square[from];
 
471
 
 
472
      if (toupper(piece_to_char(piece)) == piece_char) {
 
473
         if (piece_attack(board,piece,from,to)) {
 
474
            if (true
 
475
             && (string[1] == '?' || file_to_char(square_file(from)) == string[1])
 
476
             && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) {
 
477
               if (!is_pinned(board,from,to,colour)) {
 
478
                  move = move_make(from,to) | promote;
 
479
                  n++;
 
480
               }
 
481
            }
 
482
         }
 
483
      }
 
484
   }
 
485
 
 
486
   if (n != 1) move = MoveNone;
 
487
 
 
488
   return move;
 
489
}
 
490
 
 
491
// ambiguity()
 
492
 
 
493
static int ambiguity(int move, const board_t * board) {
 
494
 
 
495
   int from, to, piece;
 
496
   list_t list[1];
 
497
   int i, n, m;
 
498
 
 
499
   // init
 
500
 
 
501
   from = move_from(move);
 
502
   to = move_to(move);
 
503
   piece = move_piece(move,board);
 
504
 
 
505
   gen_legal_moves(list,board);
 
506
 
 
507
   // no ambiguity?
 
508
 
 
509
   n = 0;
 
510
 
 
511
   for (i = 0; i < list_size(list); i++) {
 
512
      m = list_move(list,i);
 
513
      if (move_piece(m,board) == piece && move_to(m) == to) {
 
514
         n++;
 
515
      }
 
516
   }
 
517
 
 
518
   if (n == 1) return AMBIGUITY_NONE;
 
519
 
 
520
   // file ambiguity?
 
521
 
 
522
   n = 0;
 
523
 
 
524
   for (i = 0; i < list_size(list); i++) {
 
525
      m = list_move(list,i);
 
526
      if (move_piece(m,board) == piece && move_to(m) == to) {
 
527
         if (square_file(move_from(m)) == square_file(from)) n++;
 
528
      }
 
529
   }
 
530
 
 
531
   if (n == 1) return AMBIGUITY_FILE;
 
532
 
 
533
   // rank ambiguity?
 
534
 
 
535
   n = 0;
 
536
 
 
537
   for (i = 0; i < list_size(list); i++) {
 
538
      m = list_move(list,i);
 
539
      if (move_piece(m,board) == piece && move_to(m) == to) {
 
540
         if (square_rank(move_from(m)) == square_rank(from)) n++;
 
541
      }
 
542
   }
 
543
 
 
544
   if (n == 1) return AMBIGUITY_RANK;
 
545
 
 
546
   // square ambiguity
 
547
 
 
548
   return AMBIGUITY_SQUARE;
 
549
}
 
550
 
 
551
// end of san.cpp
 
552