Add forgotten files 1.4.70b
[polyglot.git] / fen.c
diff --git a/fen.c b/fen.c
index be3ec17..cfab964 100644 (file)
--- a/fen.c
+++ b/fen.c
-\r
-// fen.c\r
-\r
-// includes\r
-\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "fen.h"\r
-#include "option.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-// const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1";\r
-const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";\r
-\r
-// variables\r
-\r
-static const bool Strict = FALSE;\r
-\r
-// macros\r
-\r
-#define skip_white_space() \\r
-        c=string[pos];\\r
-        if (c != ' ' && c!='\t') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); \\r
-        while(c==' ' || c=='\t') c=string[++pos];\r
-\r
-\r
-// functions\r
-\r
-// board_from_fen()\r
-\r
-bool board_from_fen(board_t * board, const char string[]) {\r
-\r
-   int pos;\r
-   int file, rank, sq;\r
-   int c;\r
-   int i, len;\r
-   int piece;\r
-   int king_pos[ColourNb];\r
-\r
-   ASSERT(board!=NULL);\r
-   ASSERT(string!=NULL);\r
-\r
-   board_clear(board);\r
-\r
-   king_pos[White] = SquareNone;\r
-   king_pos[Black] = SquareNone;\r
-\r
-   pos = 0;\r
-   c = string[pos];\r
-\r
-   // piece placement\r
-\r
-   for (rank = 7; rank >= 0; rank--) {\r
-\r
-      for (file = 0; file < 8;) {\r
-\r
-         sq = square_make(file,rank);\r
-\r
-         if (c >= '1' && c <= '8') { // empty square(s)\r
-\r
-            len = c - '0';\r
-            if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-\r
-            for (i = 0; i < len; i++) {\r
-               board->square[sq++] = Empty;\r
-               file++;\r
-            }\r
-\r
-         } else { // piece\r
-\r
-            piece = piece_from_char(c);\r
-            if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-\r
-            if (piece_is_king(piece)) king_pos[piece_colour(piece)] = sq;\r
-\r
-            board->square[sq++] = piece;\r
-            file++;\r
-         }\r
-\r
-         c = string[++pos];\r
-      }\r
-\r
-      if (rank > 0) {\r
-         if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-         c = string[++pos];\r
-     }\r
-   }\r
-\r
-   // active colour\r
-\r
-   skip_white_space();\r
-\r
-   switch (c) {\r
-   case 'w':\r
-      board->turn = White;\r
-      break;\r
-   case 'b':\r
-      board->turn = Black;\r
-      break;\r
-   default:\r
-      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-      break;\r
-   }\r
-\r
-   c = string[++pos];\r
-\r
-   // castling\r
-\r
-   skip_white_space();\r
-\r
-   board->castle[White][SideH] = SquareNone;\r
-   board->castle[White][SideA] = SquareNone;\r
-   board->castle[Black][SideH] = SquareNone;\r
-   board->castle[Black][SideA] = SquareNone;\r
-\r
-   if (c == '-') { // no castling rights\r
-\r
-      c = string[++pos];\r
-\r
-   } else {\r
-\r
-      // TODO: filter out illegal rights\r
-\r
-      do {\r
-\r
-         if (FALSE) {\r
-\r
-         } else if (c == 'K') {\r
-\r
-            for (sq = H1; sq > king_pos[White]; sq--) {\r
-               if (board->square[sq] == WhiteRook256) {\r
-                  board->castle[White][SideH] = sq;\r
-                  break;\r
-               }\r
-            }\r
-\r
-         } else if (c == 'Q') {\r
-\r
-            for (sq = A1; sq < king_pos[White]; sq++) {\r
-               if (board->square[sq] == WhiteRook256) {\r
-                  board->castle[White][SideA] = sq;\r
-                  break;\r
-               }\r
-            }\r
-\r
-         } else if (c == 'k') {\r
-\r
-            for (sq = H8; sq > king_pos[Black]; sq--) {\r
-               if (board->square[sq] == BlackRook256) {\r
-                  board->castle[Black][SideH] = sq;\r
-                  break;\r
-               }\r
-            }\r
-\r
-         } else if (c == 'q') {\r
-\r
-            for (sq = A8; sq < king_pos[Black]; sq++) {\r
-               if (board->square[sq] == BlackRook256) {\r
-                  board->castle[Black][SideA] = sq;\r
-                  break;\r
-               }\r
-            }\r
-\r
-         } else if (c >= 'A' && c <= 'H') {\r
-\r
-            // white castling right\r
-\r
-            sq = square_make(file_from_char(tolower(c)),Rank1);\r
-\r
-            if (sq > king_pos[White]) { // h side\r
-               board->castle[White][SideH] = sq;\r
-            } else { // a side\r
-               board->castle[White][SideA] = sq;\r
-            }\r
-\r
-         } else if (c >= 'a' && c <= 'h') {\r
-\r
-            // black castling right\r
-\r
-            sq = square_make(file_from_char(tolower(c)),Rank8);\r
-\r
-            if (sq > king_pos[Black]) { // h side\r
-               board->castle[Black][SideH] = sq;\r
-            } else { // a side\r
-               board->castle[Black][SideA] = sq;\r
-            }\r
-\r
-         } else {\r
-\r
-            my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-         }\r
-\r
-         c = string[++pos];\r
-\r
-      } while (c != ' ');\r
-   }\r
-\r
-   // en-passant\r
-\r
-   skip_white_space();\r
-\r
-   if (c == '-') { // no en-passant\r
-\r
-      sq = SquareNone;\r
-      c = string[++pos];\r
-\r
-   } else {\r
-\r
-      if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-      file = file_from_char(c);\r
-      c = string[++pos];\r
-\r
-      if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-      rank = rank_from_char(c);\r
-      c = string[++pos];\r
-\r
-      sq = square_make(file,rank);\r
-   }\r
-\r
-   board->ep_square = sq;\r
-\r
-   // halfmove clock\r
-\r
-   board->ply_nb = 0;\r
-   board->move_nb = 0; // HACK, in case of broken syntax\r
-\r
-   if (c != ' ') {\r
-      if (!Strict) goto update;\r
-      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-   }\r
-   c = string[++pos];\r
-\r
-   if (!isdigit(c)) {\r
-      if (!Strict) goto update;\r
-      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-   }\r
-\r
-   board->ply_nb = atoi(&string[pos]);\r
-   do c = string[++pos]; while (isdigit(c));\r
-\r
-   // fullmove number\r
-\r
-   board->move_nb = 0;\r
-\r
-   if (c != ' ') {\r
-      if (!Strict) goto update;\r
-      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-   }\r
-   c = string[++pos];\r
-\r
-   if (!isdigit(c)) {\r
-      if (!Strict) goto update;\r
-      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-   }\r
-\r
-   board->move_nb = atoi(&string[pos]) - 1;\r
-   do c = string[++pos]; while (isdigit(c));\r
-\r
-   // board update\r
-\r
-update:\r
-   board_init_list(board);\r
-\r
-   return TRUE;\r
-}\r
-\r
-// board_to_fen()\r
-\r
-bool board_to_fen(const board_t * board, char string[], int size) {\r
-\r
-   int pos;\r
-   int file, rank;\r
-   int sq, piece;\r
-   int c;\r
-   int len;\r
-   int old_pos;\r
-\r
-   ASSERT(board_is_ok(board));\r
-   ASSERT(string!=NULL);\r
-   ASSERT(size>=92);\r
-\r
-   // init\r
-\r
-   if (size < 92) return FALSE;\r
-\r
-   pos = 0;\r
-\r
-   // piece placement\r
-\r
-   for (rank = 7; rank >= 0; rank--) {\r
-\r
-      for (file = 0; file < 8;) {\r
-\r
-         sq = square_make(file,rank);\r
-         piece = board->square[sq];\r
-         ASSERT(piece==Empty||piece_is_ok(piece));\r
-\r
-         if (piece == Empty) {\r
-\r
-            len = 0;\r
-            for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) {\r
-               len++;\r
-            }\r
-\r
-            ASSERT(len>=1&&len<=8);\r
-            c = '0' + len;\r
-\r
-         } else {\r
-\r
-            c = piece_to_char(piece);\r
-            file++;\r
-         }\r
-\r
-         string[pos++] = c;\r
-      }\r
-\r
-      string[pos++] = '/';\r
-   }\r
-\r
-   string[pos-1] = ' '; // HACK: remove the last '/'\r
-\r
-   // active colour\r
-\r
-   string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b';\r
-   string[pos++] = ' ';\r
-\r
-   // castling\r
-\r
-   old_pos = pos;\r
-\r
-   if (option_get_bool("Chess960")) {\r
-\r
-      // FEN-960\r
-\r
-      if (board->castle[White][SideH] != SquareNone) {\r
-         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH])));\r
-      }\r
-\r
-      if (board->castle[White][SideA] != SquareNone) {\r
-         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA])));\r
-      }\r
-\r
-      if (board->castle[Black][SideH] != SquareNone) {\r
-         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH])));\r
-      }\r
-\r
-      if (board->castle[Black][SideA] != SquareNone) {\r
-         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA])));\r
-      }\r
-\r
-   } else {\r
-\r
-      // FEN\r
-\r
-      if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K';\r
-      if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q';\r
-      if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k';\r
-      if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q';\r
-   }\r
-\r
-   if (pos == old_pos) string[pos++] = '-';\r
-\r
-   string[pos++] = ' ';\r
-\r
-   // en-passant\r
-\r
-   if (board->ep_square == SquareNone) {\r
-      string[pos++] = '-';\r
-   } else {\r
-      if (!square_to_string(board->ep_square,&string[pos],3)) return FALSE;\r
-      pos += 2;\r
-   }\r
-\r
-   string[pos++] = ' ';\r
-\r
-   // halfmove clock and fullmove number\r
-\r
-   sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1);\r
-\r
-   return TRUE;\r
-}\r
-\r
-// end of fen.cpp\r
-\r
+
+// fen.c
+
+// includes
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "board.h"
+#include "colour.h"
+#include "fen.h"
+#include "option.h"
+#include "piece.h"
+#include "square.h"
+#include "util.h"
+
+// "constants"
+
+// const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1";
+const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
+
+// variables
+
+static const bool Strict = FALSE;
+
+// macros
+
+#define skip_white_space() \
+        c=string[pos];\
+        if (c != ' ' && c!='\t') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); \
+        while(c==' ' || c=='\t') c=string[++pos];
+
+
+// functions
+
+// board_from_fen()
+
+bool board_from_fen(board_t * board, const char string[]) {
+
+   int pos;
+   int file, rank, sq;
+   int c;
+   int i, len;
+   int piece;
+   int king_pos[ColourNb];
+
+   ASSERT(board!=NULL);
+   ASSERT(string!=NULL);
+
+   board_clear(board);
+
+   king_pos[White] = SquareNone;
+   king_pos[Black] = SquareNone;
+
+   pos = 0;
+   c = string[pos];
+
+   // piece placement
+
+   for (rank = 7; rank >= 0; rank--) {
+
+      for (file = 0; file < 8;) {
+
+         sq = square_make(file,rank);
+
+         if (c >= '1' && c <= '8') { // empty square(s)
+
+            len = c - '0';
+            if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+
+            for (i = 0; i < len; i++) {
+               board->square[sq++] = Empty;
+               file++;
+            }
+
+         } else { // piece
+
+            piece = piece_from_char(c);
+            if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+
+            if (piece_is_king(piece)) king_pos[piece_colour(piece)] = sq;
+
+            board->square[sq++] = piece;
+            file++;
+         }
+
+         c = string[++pos];
+      }
+
+      if (rank > 0) {
+         if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+         c = string[++pos];
+     }
+   }
+
+   // active colour
+
+   skip_white_space();
+
+   switch (c) {
+   case 'w':
+      board->turn = White;
+      break;
+   case 'b':
+      board->turn = Black;
+      break;
+   default:
+      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+      break;
+   }
+
+   c = string[++pos];
+
+   // castling
+
+   skip_white_space();
+
+   board->castle[White][SideH] = SquareNone;
+   board->castle[White][SideA] = SquareNone;
+   board->castle[Black][SideH] = SquareNone;
+   board->castle[Black][SideA] = SquareNone;
+
+   if (c == '-') { // no castling rights
+
+      c = string[++pos];
+
+   } else {
+
+      // TODO: filter out illegal rights
+
+      do {
+
+         if (FALSE) {
+
+         } else if (c == 'K') {
+
+            for (sq = H1; sq > king_pos[White]; sq--) {
+               if (board->square[sq] == WhiteRook256) {
+                  board->castle[White][SideH] = sq;
+                  break;
+               }
+            }
+
+         } else if (c == 'Q') {
+
+            for (sq = A1; sq < king_pos[White]; sq++) {
+               if (board->square[sq] == WhiteRook256) {
+                  board->castle[White][SideA] = sq;
+                  break;
+               }
+            }
+
+         } else if (c == 'k') {
+
+            for (sq = H8; sq > king_pos[Black]; sq--) {
+               if (board->square[sq] == BlackRook256) {
+                  board->castle[Black][SideH] = sq;
+                  break;
+               }
+            }
+
+         } else if (c == 'q') {
+
+            for (sq = A8; sq < king_pos[Black]; sq++) {
+               if (board->square[sq] == BlackRook256) {
+                  board->castle[Black][SideA] = sq;
+                  break;
+               }
+            }
+
+         } else if (c >= 'A' && c <= 'H') {
+
+            // white castling right
+
+            sq = square_make(file_from_char(tolower(c)),Rank1);
+
+            if (sq > king_pos[White]) { // h side
+               board->castle[White][SideH] = sq;
+            } else { // a side
+               board->castle[White][SideA] = sq;
+            }
+
+         } else if (c >= 'a' && c <= 'h') {
+
+            // black castling right
+
+            sq = square_make(file_from_char(tolower(c)),Rank8);
+
+            if (sq > king_pos[Black]) { // h side
+               board->castle[Black][SideH] = sq;
+            } else { // a side
+               board->castle[Black][SideA] = sq;
+            }
+
+         } else {
+
+            my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+         }
+
+         c = string[++pos];
+
+      } while (c != ' ');
+   }
+
+   // en-passant
+
+   skip_white_space();
+
+   if (c == '-') { // no en-passant
+
+      sq = SquareNone;
+      c = string[++pos];
+
+   } else {
+
+      if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+      file = file_from_char(c);
+      c = string[++pos];
+
+      if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+      rank = rank_from_char(c);
+      c = string[++pos];
+
+      sq = square_make(file,rank);
+   }
+
+   board->ep_square = sq;
+
+   // halfmove clock
+
+   board->ply_nb = 0;
+   board->move_nb = 0; // HACK, in case of broken syntax
+
+   if (c != ' ') {
+      if (!Strict) goto update;
+      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+   }
+   c = string[++pos];
+
+   if (!isdigit(c)) {
+      if (!Strict) goto update;
+      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+   }
+
+   board->ply_nb = atoi(&string[pos]);
+   do c = string[++pos]; while (isdigit(c));
+
+   // fullmove number
+
+   board->move_nb = 0;
+
+   if (c != ' ') {
+      if (!Strict) goto update;
+      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+   }
+   c = string[++pos];
+
+   if (!isdigit(c)) {
+      if (!Strict) goto update;
+      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
+   }
+
+   board->move_nb = atoi(&string[pos]) - 1;
+   do c = string[++pos]; while (isdigit(c));
+
+   // board update
+
+update:
+   board_init_list(board);
+
+   return TRUE;
+}
+
+// board_to_fen()
+
+bool board_to_fen(const board_t * board, char string[], int size) {
+
+   int pos;
+   int file, rank;
+   int sq, piece;
+   int c;
+   int len;
+   int old_pos;
+
+   ASSERT(board_is_ok(board));
+   ASSERT(string!=NULL);
+   ASSERT(size>=92);
+
+   // init
+
+   if (size < 92) return FALSE;
+
+   pos = 0;
+
+   // piece placement
+
+   for (rank = 7; rank >= 0; rank--) {
+
+      for (file = 0; file < 8;) {
+
+         sq = square_make(file,rank);
+         piece = board->square[sq];
+         ASSERT(piece==Empty||piece_is_ok(piece));
+
+         if (piece == Empty) {
+
+            len = 0;
+            for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) {
+               len++;
+            }
+
+            ASSERT(len>=1&&len<=8);
+            c = '0' + len;
+
+         } else {
+
+            c = piece_to_char(piece);
+            file++;
+         }
+
+         string[pos++] = c;
+      }
+
+      string[pos++] = '/';
+   }
+
+   string[pos-1] = ' '; // HACK: remove the last '/'
+
+   // active colour
+
+   string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b';
+   string[pos++] = ' ';
+
+   // castling
+
+   old_pos = pos;
+
+   if (option_get_bool(Option,"Chess960")) {
+
+      // FEN-960
+
+      if (board->castle[White][SideH] != SquareNone) {
+         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH])));
+      }
+
+      if (board->castle[White][SideA] != SquareNone) {
+         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA])));
+      }
+
+      if (board->castle[Black][SideH] != SquareNone) {
+         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH])));
+      }
+
+      if (board->castle[Black][SideA] != SquareNone) {
+         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA])));
+      }
+
+   } else {
+
+      // FEN
+
+      if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K';
+      if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q';
+      if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k';
+      if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q';
+   }
+
+   if (pos == old_pos) string[pos++] = '-';
+
+   string[pos++] = ' ';
+
+   // en-passant
+
+   if (board->ep_square == SquareNone) {
+      string[pos++] = '-';
+   } else {
+      if (!square_to_string(board->ep_square,&string[pos],3)) return FALSE;
+      pos += 2;
+   }
+
+   string[pos++] = ' ';
+
+   // halfmove clock and fullmove number
+
+   sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1);
+
+   return TRUE;
+}
+
+// end of fen.cpp
+