- #include "chess.h" 
- #include "data.h" 
- /* last modified 02/24/14 */ 
- /* 
-  ******************************************************************************* 
-  *                                                                             * 
-  *   InputMove() is responsible for converting a move from a text string to    * 
-  *   the internal move format.  It allows the so-called "reduced algebraic     * 
-  *   move format" which makes the origin square optional unless required for   * 
-  *   clarity.  It also accepts as little as required to remove ambiguity from  * 
-  *   the move, by using GenerateMoves() to produce a set of legal moves that   * 
-  *   the text can be applied against to eliminate those moves not intended.    * 
-  *   Hopefully, only one move will remain after the elimination and legality   * 
-  *   checks.                                                                   * 
-  *                                                                             * 
-  ******************************************************************************* 
-  */ 
- int InputMove(TREE * RESTRICT tree, int ply, int wtm, int silent, 
-     int ponder_list, char *text) { 
-   unsigned moves[220], *mv, *mvp, *goodmove = 0; 
-   int piece = -1, capture, promote, give_check; 
-   int ffile, frank, tfile, trank; 
-   int current, i, nleft; 
-   char *goodchar, *tc; 
-   char movetext[128]; 
-   static const char pieces[15] = 
-       { ' ', ' ', 'P', 'p', 'N', 'n', 'B', 'b', 'R', 'r', 
-     'Q', 'q', 'K', 'k', '\0' 
-   }; 
-   static const char pro_pieces[15] = 
-       { ' ', ' ', 'P', 'p', 'N', 'n', 'B', 'b', 'R', 'r', 'Q', 'q', 
-     'K', 'k', '\0' 
-   }; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  First, we need to strip off the special characters for  * 
-  *  check, mate, bad move, good move, and such that might   * 
-  *  come from a PGN input file.                             * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     *tc = 0; 
-     *tc = 0; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Check for full coordinate input (f1e1) and handle that  * 
-  *  if needed.                                              * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     return 0; 
-   if ((text[0] >= 'a') && (text[0] <= 'h') && (text[1] >= '1') 
-       && (text[1] <= '8') && (text[2] >= 'a') && (text[2] <= 'h') 
-       && (text[3] >= '1') && (text[3] <= '8')) 
-     return InputMoveICS(tree, ply, wtm, silent, ponder_list, text); 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Initialize move structure.  If we discover a parsing    * 
-  *  error, this will cause us to return a move of "0" to    * 
-  *  indicate some sort of error was detected.               * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   tree->status[MAXPLY] = tree->status[ply]; 
-   moves[0] = 0; 
-   piece = 0; 
-   capture = 0; 
-   promote = 0; 
-   give_check = 0; 
-   frank = -1; 
-   ffile = -1; 
-   trank = -1; 
-   tfile = -1; 
-   goodchar  = strchr(- movetext , '#');
-   if (goodchar) 
-     *goodchar = 0; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  First we look for castling moves which are a special    * 
-  *  case with an unusual syntax compared to normal moves.   * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     piece = king; 
-     if (wtm) { 
-       ffile = 4; 
-       frank = 0; 
-       tfile = 6; 
-       trank = 0; 
-     } else { 
-       ffile = 4; 
-       frank = 7; 
-       tfile = 6; 
-       trank = 7; 
-     } 
-   } else if (!strcmp(- movetext , "o-o-o") || !strcmp(- movetext , "o-o-o+")
 
-       || !strcmp(- movetext , "O-O-O") || !strcmp(- movetext , "O-O-O+")
 
-       || !strcmp(- movetext , "0-0-0") || !strcmp(- movetext , "0-0-0+")) {
 
-     piece = king; 
-     if (wtm) { 
-       ffile = 4; 
-       frank = 0; 
-       tfile = 2; 
-       trank = 0; 
-     } else { 
-       ffile = 4; 
-       frank = 7; 
-       tfile = 2; 
-       trank = 7; 
-     } 
-   } else { 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  OK, it is not a castling move.  Check for two "b"       * 
-  *  characters which might be a piece (bishop) and a file   * 
-  *  (b-file).  The first "b" should be "B" but we allow     * 
-  *  this to make typing input simpler.                      * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     if ((movetext[0] == 'b') && (movetext[1] == 'b')) 
-       movetext[0] = 'B'; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Check to see if there is a "+" character which means    * 
-  *  that this move is a check.  We can use this to later    * 
-  *  eliminate all non-checking moves as possibilities.      * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-       give_check = 1; 
-     } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  If this is a promotion, indicated by an "=" in the      * 
-  *  text, we can pick up the promote-to piece and save it   * 
-  *  to use later when eliminating moves.                    * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-       goodchar  = strchr(- movetext , '=');
-       goodchar++; 
-       promote  = (strchr(- pro_pieces , *- goodchar ) --  pro_pieces ) >> 1;
-     } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Now for a kludge.  ChessBase (and others) can't follow  * 
-  *  the PGN standard of bxc8=Q for promotion, and instead   * 
-  *  will produce "bxc8Q" omitting the PGN-standard "="      * 
-  *  character.  We handle that here so that we can read     * 
-  *  their non-standard moves.                               * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     else { 
-       char *- prom  = strchr(- pro_pieces ,-  movetext [strlen(- movetext ) - 1]);
 
-   
-       if (prom) { 
-         promote = (prom - pro_pieces) >> 1; 
-         movetext [strlen(- movetext ) - 1] = 0;
-       } 
-     } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Next we extract the last rank/file designators from the * 
-  *  text, since the destination is required for all valid   * 
-  *  non-castling moves.  Note that we might not have both a * 
-  *  rank and file but we must have at least one.            * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     current  = strlen(- movetext ) - 1;
-     trank = movetext[current] - '1'; 
-     if ((trank >= 0) && (trank <= 7)) 
-       movetext[current] = 0; 
-     else 
-       trank = -1; 
-     current  = strlen(- movetext ) - 1;
-     tfile = movetext[current] - 'a'; 
-     if ((tfile >= 0) && (tfile <= 7)) 
-       movetext[current] = 0; 
-     else 
-       tfile = -1; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  The first character is the moving piece, unless it is a * 
-  *  pawn.  In this case, the moving piece is omitted and we * 
-  *  know what it has to be.                                 * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-       if (strchr("  PpNnBBRrQqKk", *- movetext )) {
 
-         piece  = (strchr(- pieces ,-  movetext [0]) --  pieces ) >> 1;
-         for (- i  = 0;-  i  < (int) strlen(- movetext );-  i ++)
 
-           movetext[i] = movetext[i + 1]; 
-       } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  It is also possible that this move is a capture, which  * 
-  *  is indicated by a "x" between either the source and     * 
-  *  destination squares, or between the moving piece and    * 
-  *  the destination.                                        * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-       if ((strlen(- movetext )) && (- movetext [strlen(- movetext ) - 1] == 'x')) {
 
-         capture = 1; 
-         movetext [strlen(- movetext ) - 1] = 0;
-       } else 
-         capture = 0; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  It is possible to have no source square, but we could   * 
-  *  have a complete algebraic square designation, or just   * 
-  *  rank or file, needed to disambiguate the move.          * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-         ffile = movetext[0] - 'a'; 
-         if ((ffile < 0) || (ffile > 7)) { 
-           ffile = -1; 
-           frank = movetext[0] - '1'; 
-           if ((frank < 0) || (frank > 7)) 
-             piece = -1; 
-         } else { 
-             frank = movetext[1] - '1'; 
-             if ((frank < 0) || (frank > 7)) 
-               piece = -1; 
-           } 
-         } 
-       } 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Now for the easy part.  We first generate all moves if  * 
-  *  not pondering, or else use a pre-computed list of moves * 
-  *  (if pondering) since the board position is not correct  * 
-  *  for move input analysis.  We then loop through the list * 
-  *  of moves, using the information we extracted previously * 
-  *  , and eliminate all moves that are (a) the wrong piece  * 
-  *  type;  (b) wrong source or destination square;          * 
-  *  (c) wrong promotion type;  (d) should be a capture,     * 
-  *  check or promotion but is not, or vice-versa.           * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (!piece) 
-     piece = 1; 
-   if (!ponder_list) { 
-     mvp = GenerateCaptures(tree, MAXPLY, wtm, moves); 
-     mvp = GenerateNoncaptures(tree, MAXPLY, wtm, mvp); 
-   } else { 
-     for (i = 0; i < num_ponder_moves; i++) 
-       moves[i] = ponder_moves[i]; 
-     mvp = moves + num_ponder_moves; 
-   } 
-   for (mv = &moves[0]; mv < mvp; mv++) { 
-     if (piece && (Piece(*mv) != piece)) 
-       *mv = 0; 
-     if ((ffile >= 0) && (File(From(*mv)) != ffile)) 
-       *mv = 0; 
-     if (capture && (!Captured(*mv))) 
-       *mv = 0; 
-     if (promote && (Promote(*mv) != promote)) 
-       *mv = 0; 
-     if ((frank >= 0) && (Rank(From(*mv)) != frank)) 
-       *mv = 0; 
-     if ((tfile >= 0) && (File(To(*mv)) != tfile)) 
-       *mv = 0; 
-     if ((trank >= 0) && (Rank(To(*mv)) != trank)) 
-       *mv = 0; 
-     if (!ponder_list && *mv) { 
-       MakeMove(tree, MAXPLY, wtm, *mv); 
-       if (Check(wtm) || (give_check && !Check(Flip(wtm)))) { 
-         UnmakeMove(tree, MAXPLY, wtm, *mv); 
-         *mv = 0; 
-       } else 
-         UnmakeMove(tree, MAXPLY, wtm, *mv); 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Once we have completed eliminating incorrect moves, we  * 
-  *  hope to have exactly one move left.  If none or left,   * 
-  *  the entered move is illegal.  If more than one is left, * 
-  *  the move entered is ambiguous.  If appropriate, we      * 
-  *  output some sort of diagnostic message and then return. * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   nleft = 0; 
-   for (mv = &moves[0]; mv < mvp; mv++) { 
-     if (*mv) { 
-       nleft++; 
-       goodmove = mv; 
-     } 
-   } 
-   if (nleft == 1) 
-     return *goodmove; 
-   if (!silent) { 
-     if (nleft == 0) 
-       Print(4095, "Illegal move: %s\n", text); 
-     else if (piece < 0) 
-       Print(4095, "Illegal move (unrecognizable): %s\n", text); 
-     else 
-       Print(4095, "Illegal move (ambiguous): %s\n", text); 
-   } 
-   return 0; 
- } 
-   
- /* last modified 02/24/14 */ 
- /* 
-  ******************************************************************************* 
-  *                                                                             * 
-  *   InputMoveICS() is responsible for converting a move from the ics format   * 
-  *   [from][to][promote] to the program's internal format.                     * 
-  *                                                                             * 
-  ******************************************************************************* 
-  */ 
- int InputMoveICS(TREE * RESTRICT tree, int ply, int wtm, int silent, 
-     int ponder_list, char *text) { 
-   unsigned moves[220], *mv, *mvp, *goodmove = 0; 
-   int piece = -1, promote; 
-   int ffile, frank, tfile, trank; 
-   int i, nleft; 
-   char movetext[128]; 
-   static const char pieces[15] = 
-       { ' ', ' ', 'P', 'p', 'N', 'n', 'B', 'b', 'R', 'r', 
-     'Q', 'q', 'K', 'k', '\0' 
-   }; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Initialize move structure.  If we discover a parsing    * 
-  *  error, this will cause us to return a move of "0" to    * 
-  *  indicate some sort of error was detected.               * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     return 0; 
-   tree->status[MAXPLY] = tree->status[ply]; 
-   moves[0] = 0; 
-   promote = 0; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  First we look for castling moves which are a special    * 
-  *  case with an unusual syntax compared to normal moves.   * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-       || !strcmp(- movetext , "0-0")) {
 
-     piece = king; 
-     if (wtm) { 
-       ffile = 4; 
-       frank = 0; 
-       tfile = 6; 
-       trank = 0; 
-     } else { 
-       ffile = 4; 
-       frank = 7; 
-       tfile = 6; 
-       trank = 7; 
-     } 
-   } else if (!strcmp(- movetext , "o-o-o") || !strcmp(- movetext , "O-O-O")
 
-       || !strcmp(- movetext , "0-0-0")) {
 
-     piece = king; 
-     if (wtm) { 
-       ffile = 4; 
-       frank = 0; 
-       tfile = 2; 
-       trank = 0; 
-     } else { 
-       ffile = 4; 
-       frank = 7; 
-       tfile = 2; 
-       trank = 7; 
-     } 
-   } else { 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Next we extract both rank/file designators from the     * 
-  *  text, since the destination is required for all valid   * 
-  *  non-castling moves.                                     * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     ffile = movetext[0] - 'a'; 
-     frank = movetext[1] - '1'; 
-     tfile = movetext[2] - 'a'; 
-     trank = movetext[3] - '1'; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  If this is a promotion, indicated by an "=" in the      * 
-  *  text, we can pick up the promote-to piece and save it   * 
-  *  to use later when eliminating moves.                    * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     if (movetext[4] == '=') 
-       promote  = (strchr(- pieces ,-  movetext [5]) --  pieces ) >> 1;
-     else if ((movetext[4] != 0) && (movetext[4] != ' ')) 
-       promote  = (strchr(- pieces ,-  movetext [4]) --  pieces ) >> 1;
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Now for the easy part.  We first generate all moves if  * 
-  *  not pondering, or else use a pre-computed list of moves * 
-  *  (if pondering) since the board position is not correct  * 
-  *  for move input analysis.  We then loop through the list * 
-  *  of moves, using the information we extracted previously * 
-  *  and eliminate all moves that are (a) the wrong piece    * 
-  *  type;  (b) wrong source or destination square;          * 
-  *  (c) wrong promotion type;  (d) should be a capture,     * 
-  *  check or promotion but is not or vice-versa.            * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (!ponder_list) { 
-     mvp = GenerateCaptures(tree, MAXPLY, wtm, moves); 
-     mvp = GenerateNoncaptures(tree, MAXPLY, wtm, mvp); 
-   } else { 
-     for (i = 0; i < num_ponder_moves; i++) 
-       moves[i] = ponder_moves[i]; 
-     mvp = moves + num_ponder_moves; 
-   } 
-   for (mv = &moves[0]; mv < mvp; mv++) { 
-     if (Promote(*mv) != promote) 
-       *mv = 0; 
-     if (Rank(From(*mv)) != frank) 
-       *mv = 0; 
-     if (File(From(*mv)) != ffile) 
-       *mv = 0; 
-     if (Rank(To(*mv)) != trank) 
-       *mv = 0; 
-     if (File(To(*mv)) != tfile) 
-       *mv = 0; 
-     if (!ponder_list && *mv) { 
-       MakeMove(tree, MAXPLY, wtm, *mv); 
-       if (Check(wtm)) { 
-         UnmakeMove(tree, MAXPLY, wtm, *mv); 
-         *mv = 0; 
-       } else 
-         UnmakeMove(tree, MAXPLY, wtm, *mv); 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Once we have completed eliminating incorrect moves, we  * 
-  *  hope to have exactly one move left.  If none or left,   * 
-  *  the entered move is illegal.  If more than one is left, * 
-  *  the move entered is ambiguous.  If appropriate, we      * 
-  *  output some sort of diagnostic message and then return. * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   nleft = 0; 
-   for (mv = &moves[0]; mv < mvp; mv++) { 
-     if (*mv) { 
-       nleft++; 
-       goodmove = mv; 
-     } 
-   } 
-   if (nleft == 1) 
-     return *goodmove; 
-   if (!silent) { 
-     if (nleft == 0) 
-       Print(4095, "Illegal move: %s\n", text); 
-     else if (piece < 0) 
-       Print(4095, "Illegal move (unrecognizable): %s\n", text); 
-     else 
-       Print(4095, "Illegal move (ambiguous): %s\n", text); 
-   } 
-   return 0; 
- } 
-