// move.cpp
 
 
 
#include "common.h"
 
 
 
 
 
// handy macros
 
#define IS_VALID(li,co) (((li) >= 0) && ((li) < 8) && ((co) >= 0) && ((co) < 8))
 
#define IS_FREE(li,co) (IS_VALID ((li), (co)) && (move->slots[(li)][(co)].part == PART_NONE))
 
#define CAN_PLAY(li,co) (IS_VALID ((li), (co)) && ((move->slots[(li)][(co)].part == PART_NONE) || (move->slots[(li)][(co)].color != boardslot->color)))
 
 
 
 
 
// prototypes of local functions
 
static void AddPossibleMove (boardmove_t **possiblemoves, int *possiblemove_count, int color, int part, int source_line, int source_column, int target_line, int target_column, int promotion_type, bool has_captured, bool is_enpassant);
 
 
 
 
 
void Move_SetSlot (boardmove_t *move, int line, int column, int color, int part_type)
 
{
 
   // this function populates a board's slot at the given line,column coordinates with the
 
   // given part of the given color
 
 
 
   move->slots[line][column].flags = 0; // reset flags
 
   move->slots[line][column].color = color; // set part color
 
   move->slots[line][column].part = part_type; // set part type
 
 
 
   return; // finished, board slot is set
 
}
 
 
 
 
 
bool Move_IsKingThreatenedAtLocation (boardmove_t *move, int color, int at_line, int at_column, int *threat_line, int *threat_column)
 
{
 
   // this function returns TRUE if the specified color is safe at the specified location.
 
   // In case it is not, it returns FALSE and sets the threat's line and column parameters.
 
   // Note the use of the threat_line and threat_column output parameters as iterator
 
   // variables.
 
 
 
   boardslot_t *boardslot;
 
   int movement_direction;
 
   int line;
 
   int column;
 
   int index_line;
 
   int index_column;
 
 
 
   // cycle through all the board
 
   for (line = 0; line < 8; line++)
 
      for (column = 0; column < 8; column++)
 
      {
 
         boardslot = &move->slots[line][column]; // quick access to grid slot
 
 
 
         if ((boardslot->part == PART_NONE) || (boardslot->color == color))
 
            continue; // if this location is empty or ours, it doesn't threaten us
 
 
 
         // update new possible threat position
 
         *threat_line = line;
 
         *threat_column = column;
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// PAWN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // is it a pawn ? (note: pawns can only threaten kings normally, never "en passant")
 
         if (boardslot->part == PART_PAWN)
 
         {
 
            // figure out movement direction
 
            if (boardslot->color == COLOR_WHITE)
 
               movement_direction = 1;
 
            else
 
               movement_direction = -1;
 
 
 
            // see if pawn can take our piece on either of its sides
 
            if ((column > 0) && (line + movement_direction == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us, it can take our piece on its left
 
            else if ((column < 7) && (line + movement_direction == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us, it can take our piece on its right
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// ROOK //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a rook ?
 
         else if (boardslot->part == PART_ROOK)
 
         {
 
            // is rook in the same column as our king ?
 
            if (column == at_column)
 
            {
 
               // is our king above ?
 
               if (at_line > line)
 
               {
 
                  // see if rook can threaten our king by moving upwards
 
                  for (index_line = line + 1; index_line < 8; index_line++)
 
                     if (index_line == at_line)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be below
 
               else
 
               {
 
                  // see if rook can threaten our king by moving downwards
 
                  for (index_line = line - 1; index_line >= 0; index_line--)
 
                     if (index_line == at_line)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
 
 
            // else is rook in the same line as our king ?
 
            else if (line == at_line)
 
            {
 
               // is our king on the right ?
 
               if (at_column > column)
 
               {
 
                  // see if rook can threaten our king by moving right
 
                  for (index_column = column + 1; index_column < 8; index_column++)
 
                     if (index_column == at_column)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be on the left
 
               else
 
               {
 
                  // see if rook can threaten our king by moving left
 
                  for (index_column = column - 1; index_column >= 0; index_column--)
 
                     if (index_column == at_column)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// KNIGHT /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a knight ?
 
         else if (boardslot->part == PART_KNIGHT)
 
         {
 
            if ((column > 0) && (line < 6) && (line + 2 == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us on its NNW move
 
            else if ((column < 7) && (line < 6) && (line + 2 == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us on its NNE move
 
            else if ((column < 6) && (line < 7) && (line + 1 == at_line) && (column + 2 == at_column))
 
               return (true); // this part threatens us on its ENE move
 
            else if ((column < 6) && (line > 0) && (line - 1 == at_line) && (column + 2 == at_column))
 
               return (true); // this part threatens us on its ESE move
 
            else if ((column > 0) && (line > 1) && (line - 2 == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us on its SSW move
 
            else if ((column < 7) && (line > 1) && (line - 2 == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us on its SSE move
 
            else if ((column > 1) && (line < 7) && (line + 1 == at_line) && (column - 2 == at_column))
 
               return (true); // this part threatens us on its WNW move
 
            else if ((column > 1) && (line > 0) && (line - 1 == at_line) && (column - 2 == at_column))
 
               return (true); // this part threatens us on its WSW move
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// BISHOP /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a bishop ?
 
         else if (boardslot->part == PART_BISHOP)
 
         {
 
            // is bishop in the same SWNE diagonal as our king ?
 
            if (line - at_line == column - at_column)
 
            {
 
               // is our king NE ?
 
               if (at_line > line)
 
               {
 
                  // see how far bishop can move NE
 
                  for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be SW
 
               else
 
               {
 
                  // see how far bishop can move SW
 
                  for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
 
 
            // else is bishop in the same SENW diagonal as our king ?
 
            else if (line - at_line == -(column - at_column))
 
            {
 
               // is our king NW ?
 
               if (at_line > line)
 
               {
 
                  // see how far bishop can move NW
 
                  for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be SE
 
               else
 
               {
 
                  // see how far bishop can move SE
 
                  for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// QUEEN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a queen ?
 
         else if (boardslot->part == PART_QUEEN)
 
         {
 
            // is queen in the same column as our king ?
 
            if (column == at_column)
 
            {
 
               // is our king above ?
 
               if (at_line > line)
 
               {
 
                  // see if queen can threaten our king by moving upwards
 
                  for (index_line = line + 1; index_line < 8; index_line++)
 
                     if (index_line == at_line)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be below
 
               else
 
               {
 
                  // see if queen can threaten our king by moving downwards
 
                  for (index_line = line - 1; index_line >= 0; index_line--)
 
                     if (index_line == at_line)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
 
 
            // else is queen in the same line as our king ?
 
            else if (line == at_line)
 
            {
 
               // is our king on the right ?
 
               if (at_column > column)
 
               {
 
                  // see if queen can threaten our king by moving right
 
                  for (index_column = column + 1; index_column < 8; index_column++)
 
                     if (index_column == at_column)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be on the left
 
               else
 
               {
 
                  // see if queen can threaten our king by moving left
 
                  for (index_column = column - 1; index_column >= 0; index_column--)
 
                     if (index_column == at_column)
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
 
 
            // else is queen in the same SWNE diagonal as our king ?
 
            else if (line - at_line == column - at_column)
 
            {
 
               // is our king NE ?
 
               if (at_line > line)
 
               {
 
                  // see how far queen can move NE
 
                  for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be SW
 
               else
 
               {
 
                  // see how far queen can move SW
 
                  for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
 
 
            // else is queen in the same SENW diagonal as our king ?
 
            else if (line - at_line == -(column - at_column))
 
            {
 
               // is our king NW ?
 
               if (at_line > line)
 
               {
 
                  // see how far queen can move NW
 
                  for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
 
 
               // else our king must be SE
 
               else
 
               {
 
                  // see how far queen can move SE
 
                  for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
                     if ((index_line == at_line) && (index_column == at_column))
 
                        return (true); // this part threatens us
 
                     else if (!IS_FREE (index_line, index_column))
 
                        break; // if part can no longer move this way, stop searching
 
               }
 
            }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// KING //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a king ?
 
         else if (boardslot->part == PART_KING)
 
         {
 
            if ((line < 7) && (column < 7) && (line + 1 == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us on its NE move
 
            else if ((line > 0) && (column < 7) && (line - 1 == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us on its SE move
 
            else if ((line < 7) && (column > 0) && (line + 1 == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us on its NW move
 
            else if ((line > 0) && (column > 0) && (line - 1 == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us on its SW move
 
            else if ((line < 7) && (line + 1 == at_line) && (column == at_column))
 
               return (true); // this part threatens us on an upwards move
 
            else if ((line > 0) && (line - 1 == at_line) && (column == at_column))
 
               return (true); // this part threatens us on a downwards move
 
            else if ((column < 7) && (line == at_line) && (column + 1 == at_column))
 
               return (true); // this part threatens us on a right move
 
            else if ((column > 0) && (line == at_line) && (column - 1 == at_column))
 
               return (true); // this part threatens us on a left move
 
         }
 
      }
 
 
 
   return (false); // this king looks safe at this location
 
}
 
 
 
 
 
bool Move_IsCheck (boardmove_t *move, int color)
 
{
 
   // this function returns TRUE if the king of the specified color is under check
 
 
 
   boardslot_t *boardslot;
 
   int line;
 
   int column;
 
   int threat_line;
 
   int threat_column;
 
 
 
   // cycle through all the grid again and see if the king we want is in check
 
   for (line = 0; line < 8; line++)
 
      for (column = 0; column < 8; column++)
 
      {
 
         boardslot = &move->slots[line][column]; // quick access to grid slot
 
 
 
         if ((boardslot->color != color) || (boardslot->part != PART_KING))
 
            continue; // if this slot is not our king, skip it
 
 
 
         // is this king currently threatened ?
 
         if (Move_IsKingThreatenedAtLocation (move, color, line, column, &threat_line, &threat_column))
 
            return (true); // yes, it is
 
         else
 
            return (false); // no, this king is safe
 
      }
 
 
 
   // code should never reach here (it would mean that no king is on the board)
 
 
 
   return (false); // no king of such color found on board, no check possible, return FALSE
 
}
 
 
 
 
 
bool Move_IsStaleMate (boardmove_t *move, int color)
 
{
 
   // this function returns TRUE if the specified color is stalemate (no valid move possible)
 
 
 
   boardslot_t *boardslot;
 
   int movement_direction;
 
   int line;
 
   int column;
 
   int index_line;
 
   int index_column;
 
 
 
   // cycle through all the board and find our parts
 
   for (line = 0; line < 8; line++)
 
      for (column = 0; column < 8; column++)
 
      {
 
         boardslot = &move->slots[line][column]; // quick access to grid slot
 
 
 
         if ((boardslot->part == PART_NONE) || (boardslot->color != color))
 
            continue; // if this location is empty or not ours, we aren't interested in it
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// PAWN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // is it a pawn ?
 
         if (boardslot->part == PART_PAWN)
 
         {
 
            // figure out movement direction
 
            if (boardslot->color == COLOR_WHITE)
 
               movement_direction = 1;
 
            else
 
               movement_direction = -1;
 
 
 
            // see if pawn can move forward
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (move->slots[line + movement_direction][column].part == PART_NONE) // target slot free
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column, color))
 
               return (false); // this move is possible
 
 
 
            // see if pawn can take a piece on its left
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (column > 0) // has room
 
                && (move->slots[line + movement_direction][column - 1].color != color) // target slot NOT our color
 
                && (move->slots[line + movement_direction][column - 1].part != PART_NONE) // target slot occupied
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column - 1, color))
 
               return (false); // this move is possible
 
 
 
            // see if pawn can take a piece on its right
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (column < 7) // has room
 
                && (move->slots[line + movement_direction][column + 1].color != color) // target slot NOT our color
 
                && (move->slots[line + movement_direction][column + 1].part != PART_NONE) // target slot occupied
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column + 1, color))
 
               return (false); // this move is possible
 
 
 
            // if previous move was a pawn rush, see if pawn can take "en passant"
 
            if ((move->part == PART_PAWN) // last move was a pawn
 
                  && (move->target[1] == move->source[1]) // pawn moved in column
 
                  && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
                  && (move->target[0] == line) // pawn is in line with us
 
                  && (move->target[1] - column == -1) // pawn is left to us
 
                  && !Move_IsColorInCheckAfterTestMoveEP (move, line, column, line + movement_direction, column - 1, move->target[0], move->target[1], color))
 
               return (false); // this move is possible
 
            else if ((move->part == PART_PAWN) // last move was a pawn
 
                  && (move->target[1] == move->source[1]) // pawn moved in column
 
                  && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
                  && (move->target[0] == line) // pawn is in line with us
 
                  && (move->target[1] - column == 1) // pawn is right to us
 
                  && !Move_IsColorInCheckAfterTestMoveEP (move, line, column, line + movement_direction, column + 1, move->target[0], move->target[1], color))
 
               return (false); // this move is possible
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// ROOK //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a rook ?
 
         else if (boardslot->part == PART_ROOK)
 
         {
 
            // see if rook can move upwards
 
            for (index_line = line + 1; index_line < 8; index_line++)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if rook can move downwards
 
            for (index_line = line - 1; index_line >= 0; index_line--)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if rook can move right
 
            for (index_column = column + 1; index_column < 8; index_column++)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if rook can move left
 
            for (index_column = column - 1; index_column >= 0; index_column--)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
                  return (false); // this move is possible
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// KNIGHT /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a knight ?
 
         else if (boardslot->part == PART_KNIGHT)
 
         {
 
            // see if knight can move in either of his allowed directions NNW
 
            if (CAN_PLAY (line + 2, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 2, column - 1, color))
 
               return (false); // knight can move NNW, we are not stalemate
 
            else if (CAN_PLAY (line + 2, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 2, column + 1, color))
 
               return (false); // knight can move NNE, we are not stalemate
 
            else if (CAN_PLAY (line + 1, column + 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column + 2, color))
 
               return (false); // knight can move ENE, we are not stalemate
 
            else if (CAN_PLAY (line - 1, column + 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column + 2, color))
 
               return (false); // knight can move ESE, we are not stalemate
 
            else if (CAN_PLAY (line - 2, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 2, column - 1, color))
 
               return (false); // knight can move SSW, we are not stalemate
 
            else if (CAN_PLAY (line - 2, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 2, column + 1, color))
 
               return (false); // knight can move SSE, we are not stalemate
 
            else if (CAN_PLAY (line + 1, column - 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column - 2, color))
 
               return (false); // knight can move WNW, we are not stalemate
 
            else if (CAN_PLAY (line - 1, column - 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column - 2, color))
 
               return (false); // knight can move WSW, we are not stalemate
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// BISHOP /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a bishop ?
 
         else if (boardslot->part == PART_BISHOP)
 
         {
 
            // see if bishop can move NE
 
            for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if bishop can move SE
 
            for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if bishop can move NW
 
            for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if bishop can move SW
 
            for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// QUEEN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a queen ?
 
         else if (boardslot->part == PART_QUEEN)
 
         {
 
            // see if queen can move upwards
 
            for (index_line = line + 1; index_line < 8; index_line++)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move downwards
 
            for (index_line = line - 1; index_line >= 0; index_line--)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move right
 
            for (index_column = column + 1; index_column < 8; index_column++)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move left
 
            for (index_column = column - 1; index_column >= 0; index_column--)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move NE
 
            for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move SE
 
            for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move NW
 
            for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
 
 
            // see if queen can move SW
 
            for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
                  return (false); // this move is possible
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// KING //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a king ?
 
         else if (boardslot->part == PART_KING)
 
         {
 
            // see if king can move in either of his allowed directions
 
            if (CAN_PLAY (line + 1, column) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column, color))
 
               return (false); // king can move up, we are not stalemate
 
            else if (CAN_PLAY (line - 1, column) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column, color))
 
               return (false); // king can move down, we are not stalemate
 
            else if (CAN_PLAY (line, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line, column + 1, color))
 
               return (false); // king can move right, we are not stalemate
 
            else if (CAN_PLAY (line, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line, column - 1, color))
 
               return (false); // king can move left, we are not stalemate
 
            else if (CAN_PLAY (line + 1, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column + 1, color))
 
               return (false); // king can move NE, we are not stalemate
 
            else if (CAN_PLAY (line - 1, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column + 1, color))
 
               return (false); // king can move SE, we are not stalemate
 
            else if (CAN_PLAY (line + 1, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column - 1, color))
 
               return (false); // king can move NW, we are not stalemate
 
            else if (CAN_PLAY (line - 1, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column - 1, color))
 
               return (false); // king can move SW, we are not stalemate
 
         }
 
      }
 
 
 
   return (true); // found no legal move, we are indeed stalemate
 
}
 
 
 
 
 
bool Move_IsMoveValid (boardmove_t *move, int from_line, int from_column, int to_line, int to_column)
 
{
 
   // this function returns TRUE if the specified move is valid, FALSE otherwise
 
 
 
   // FIXME: doesn't support castling testing so far! (even though it shouldn't be necessary)
 
 
 
   boardslot_t *boardslot;
 
   int movement_direction;
 
   int index_line;
 
   int index_column;
 
 
 
   boardslot = &move->slots[from_line][from_column]; // quick access to grid slot
 
 
 
   // consistency check
 
   if (!IS_VALID (from_line, from_column) || !IS_VALID (to_line, to_column))
 
      return (false); // if movement is out of bounds, it's obviously invalid
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ////////////////////////////////////////// PAWN //////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // is it a pawn ?
 
   if (boardslot->part == PART_PAWN)
 
   {
 
      // figure out movement direction
 
      if (boardslot->color == COLOR_WHITE)
 
         movement_direction = 1;
 
      else
 
         movement_direction = -1;
 
 
 
      // quick checks
 
      if (abs (to_line - from_line) > 2)
 
         return (false); // pawns cannot make moves longer than 2 rows
 
      else if (abs (to_column - from_column) > 1)
 
         return (false); // pawns cannot make moves aside more than 1 column
 
 
 
      // do we want pawn to rush forward
 
      // OR do we want pawn to move forward
 
      // OR do we want pawn to take a piece on its left
 
      // OR do we want pawn to take a piece on its right ?
 
      if ((((from_line == 1) || (from_line == 6)) // pawn on its initial slot
 
           && (from_line + 2 * movement_direction == to_line) && (from_column == to_column) // target position is the position we want
 
           && (move->slots[from_line + movement_direction][to_column].part == PART_NONE) // intermediate slot free
 
           && (move->slots[to_line][to_column].part == PART_NONE)) // target slot free
 
          || ((((movement_direction == 1) && (from_line < 7)) || ((movement_direction == -1) && (from_line > 0))) // has room
 
              && (from_line + movement_direction == to_line) && (from_column == to_column) // target position is the position we want
 
              && (move->slots[to_line][to_column].part == PART_NONE)) // target slot free
 
          || ((((movement_direction == 1) && (from_line < 7)) || ((movement_direction == -1) && (from_line > 0)))
 
              && (from_column > 0) // has room
 
              && (from_line + movement_direction == to_line) && (from_column - 1 == to_column) // target position is the position we want
 
              && (move->slots[to_line][to_column].color != boardslot->color) // target slot NOT our color
 
              && (move->slots[to_line][to_column].part != PART_NONE)) // target slot occupied
 
          || ((((movement_direction == 1) && (from_line < 7)) || ((movement_direction == -1) && (from_line > 0)))
 
              && (from_column < 7) // has room
 
              && (from_line + movement_direction == to_line) && (from_column + 1 == to_column) // target position is the position we want
 
              && (move->slots[to_line][to_column].color != boardslot->color) // target slot NOT our color
 
              && (move->slots[to_line][to_column].part != PART_NONE))) // target slot occupied
 
      {
 
         if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
            return (true); // this move is possible
 
 
 
         return (false); // else this pawn can't move in the claimed way (his king would be in check)
 
      }
 
 
 
      // if previous move was a pawn rush, see if pawn can take "en passant"
 
      if (IS_VALID (move->target[0], move->target[1]) // last move is valid
 
            && (move->part == PART_PAWN) // last move was a pawn
 
            && (move->target[1] == move->source[1]) // pawn moved in column
 
            && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
            && (move->target[0] == from_line) // pawn is in line with us
 
            && (move->target[1] - from_column == -1) // pawn is left to us
 
            && (from_line + movement_direction == to_line) && (from_column - 1 == to_column) // target position is the position we want
 
            && !Move_IsColorInCheckAfterTestMoveEP (move, from_line, from_column, to_line, to_column, move->target[0], move->target[1], boardslot->color))
 
         return (true); // this move is possible
 
      else if (IS_VALID (move->target[0], move->target[1]) // last move is valid
 
               && (move->part == PART_PAWN) // last move was a pawn
 
               && (move->target[1] == move->source[1]) // pawn moved in column
 
               && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
               && (move->target[0] == from_line) // pawn is in line with us
 
               && (move->target[1] - from_column == 1) // pawn is right to us
 
               && (from_line + movement_direction == to_line) && (from_column + 1 == to_column) // target position is the position we want
 
               && !Move_IsColorInCheckAfterTestMoveEP (move, from_line, from_column, to_line, to_column, move->target[0], move->target[1], boardslot->color))
 
         return (true); // this move is possible
 
 
 
      return (false); // this pawn can't move in the claimed way
 
   }
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ////////////////////////////////////////// ROOK //////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // else is it a rook ?
 
   else if (boardslot->part == PART_ROOK)
 
   {
 
      // quick checks
 
      if ((to_column != from_column) && (to_line != from_line))
 
         return (false); // rooks can only move horizontally or vertically
 
 
 
      // do we want the rook to move upwards ?
 
      if (to_line > from_line)
 
      {
 
         // see if rook can move upwards
 
         for (index_line = from_line + 1; index_line < 8; index_line++)
 
            if (!CAN_PLAY (index_line, to_column))
 
               return (false); // if rook can no longer move this way, stop searching
 
            else if (index_line == to_line)
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this rook can't move in the claimed way (its king would be in check)
 
            }
 
            else if (move->slots[index_line][to_column].part != PART_NONE)
 
               return (false); // rook can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want the rook to move downwards ?
 
      else if (to_line < from_line)
 
      {
 
         // see if rook can move downwards
 
         for (index_line = from_line - 1; index_line >= 0; index_line--)
 
            if (!CAN_PLAY (index_line, to_column))
 
               return (false); // if rook can no longer move this way, stop searching
 
            else if (index_line == to_line)
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this rook can't move in the claimed way (its king would be in check)
 
            }
 
            else if (move->slots[index_line][to_column].part != PART_NONE)
 
               return (false); // rook can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want the rook to move right ?
 
      else if (to_column > from_column)
 
      {
 
         // see if rook can move right
 
         for (index_column = from_column + 1; index_column < 8; index_column++)
 
            if (!CAN_PLAY (to_line, index_column))
 
               return (false); // if rook can no longer move this way, stop searching
 
            else if (index_column == to_column)
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this rook can't move in the claimed way (its king would be in check)
 
            }
 
            else if (move->slots[to_line][index_column].part != PART_NONE)
 
               return (false); // rook can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want the rook to move left ?
 
      else if (to_column < from_column)
 
      {
 
         // see if rook can move left
 
         for (index_column = from_column - 1; index_column >= 0; index_column--)
 
            if (!CAN_PLAY (to_line, index_column))
 
               return (false); // if rook can no longer move this way, stop searching
 
            else if (index_column == to_column)
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this rook can't move in the claimed way (its king would be in check)
 
            }
 
            else if (move->slots[to_line][index_column].part != PART_NONE)
 
               return (false); // rook can take a part there BUT it's not the location we want
 
      }
 
 
 
      return (false); // this rook can't move in the claimed way
 
   }
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////// KNIGHT /////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // else is it a knight ?
 
   else if (boardslot->part == PART_KNIGHT)
 
   {
 
      // do we want to move that knight in one of the allowed directions ?
 
      if (((from_line + 2 == to_line) && (from_column - 1 == to_column)) // NNW
 
          || ((from_line + 2 == to_line) && (from_column + 1 == to_column)) // NNE
 
          || ((from_line + 1 == to_line) && (from_column + 2 == to_column)) // ENE
 
          || ((from_line - 1 == to_line) && (from_column + 2 == to_column)) // ESE
 
          || ((from_line - 2 == to_line) && (from_column - 1 == to_column)) // SSW
 
          || ((from_line - 2 == to_line) && (from_column + 1 == to_column)) // SSE
 
          || ((from_line + 1 == to_line) && (from_column - 2 == to_column)) // WNW
 
          || ((from_line - 1 == to_line) && (from_column - 2 == to_column))) // WSW
 
      {
 
         if (!CAN_PLAY (to_line, to_column))
 
            return (false); // if knight can't move there (out of board, or some of our parts there), return false
 
         else if (Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
            return (false); // if knight would leave his king in check there, return false
 
 
 
         return (true); // else this move is safe
 
      }
 
 
 
      return (false); // this knight can't move in the claimed way
 
   }
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////// BISHOP /////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // else is it a bishop ?
 
   else if (boardslot->part == PART_BISHOP)
 
   {
 
      // quick checks
 
      if (abs (to_column - from_column) != abs (to_line - from_line))
 
         return (false); // bishops can only move diagonally
 
 
 
      // do we want to move the bishop NE ?
 
      if ((to_line > from_line) && (to_column > from_column))
 
      {
 
         // see if bishop can move NE
 
         for (index_line = from_line + 1, index_column = from_column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if bishop can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this bishop can't move in the claimed way (his king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // bishop can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the bishop SE ?
 
      else if ((to_line < from_line) && (to_column > from_column))
 
      {
 
         // see if bishop can move SE
 
         for (index_line = from_line - 1, index_column = from_column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if bishop can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this bishop can't move in the claimed way (his king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // bishop can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the bishop NW ?
 
      else if ((to_line > from_line) && (to_column < from_column))
 
      {
 
         // see if bishop can move NW
 
         for (index_line = from_line + 1, index_column = from_column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if bishop can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this bishop can't move in the claimed way (his king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // bishop can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the bishop SW ?
 
      else if ((to_line < from_line) && (to_column < from_column))
 
      {
 
         // see if bishop can move SW
 
         for (index_line = from_line - 1, index_column = from_column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if bishop can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this bishop can't move in the claimed way (his king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // bishop can take a part there BUT it's not the location we want
 
      }
 
 
 
      return (false); // this bishop can't move in the claimed way
 
   }
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////// QUEEN //////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // else is it a queen ?
 
   else if (boardslot->part == PART_QUEEN)
 
   {
 
      // quick checks
 
      if ((to_column != from_column) && (to_line != from_line)
 
          && (abs (to_column - from_column) != abs (to_line - from_line)))
 
         return (false); // queens can only move horizontally, vertically or diagonally
 
 
 
      // do we want to move that queen vertically ?
 
      if (from_column == to_column)
 
      {
 
         // do we want to move her upwards ?
 
         if (to_line > from_line)
 
         {
 
            // see if queen can move upwards
 
            for (index_line = from_line + 1; index_line < 8; index_line++)
 
               if (!CAN_PLAY (index_line, to_column))
 
                  return (false); // if queen can no longer move this way, stop searching
 
               else if (index_line == to_line)
 
               {
 
                  if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                     return (true); // this move is possible
 
 
 
                  return (false); // else this queen can't move in the claimed way (her king would be in check)
 
               }
 
               else if (move->slots[index_line][to_column].part != PART_NONE)
 
                  return (false); // queen can take a part there BUT it's not the location we want
 
         }
 
 
 
         // else do we want to move her downwards ?
 
         else if (to_line < from_line)
 
         {
 
            // see if queen can move downwards
 
            for (index_line = from_line - 1; index_line >= 0; index_line--)
 
               if (!CAN_PLAY (index_line, to_column))
 
                  return (false); // if queen can no longer move this way, stop searching
 
               else if (index_line == to_line)
 
               {
 
                  if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                     return (true); // this move is possible
 
 
 
                  return (false); // else this queen can't move in the claimed way (her king would be in check)
 
               }
 
               else if (move->slots[index_line][to_column].part != PART_NONE)
 
                  return (false); // queen can take a part there BUT it's not the location we want
 
         }
 
 
 
         return (false); // this queen can't move in the claimed way
 
      }
 
 
 
      // else do we want to move that queen horizontally ?
 
      else if (from_line == to_line)
 
      {
 
         // do we want this queen to move right ?
 
         if (to_column > from_column)
 
         {
 
            // see if queen can move right
 
            for (index_column = from_column + 1; index_column < 8; index_column++)
 
               if (!CAN_PLAY (to_line, index_column))
 
                  return (false); // if queen can no longer move this way, stop searching
 
               else if (index_column == to_column)
 
               {
 
                  if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                     return (true); // this move is possible
 
 
 
                  return (false); // else this queen can't move in the claimed way (her king would be in check)
 
               }
 
               else if (move->slots[to_line][index_column].part != PART_NONE)
 
                  return (false); // queen can take a part there BUT it's not the location we want
 
         }
 
 
 
         // else do we want this queen to move left ?
 
         else if (to_column < from_column)
 
         {
 
            // see if queen can move left
 
            for (index_column = from_column - 1; index_column >= 0; index_column--)
 
               if (!CAN_PLAY (to_line, index_column))
 
                  return (false); // if queen can no longer move this way, stop searching
 
               else if (index_column == to_column)
 
               {
 
                  if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
                     return (true); // this move is possible
 
 
 
                  return (false); // else this queen can't move in the claimed way (her king would be in check)
 
               }
 
               else if (move->slots[to_line][index_column].part != PART_NONE)
 
                  return (false); // queen can take a part there BUT it's not the location we want
 
         }
 
 
 
         return (false); // this queen can't move in the claimed way
 
      }
 
 
 
      // else do we want to move the queen NE ?
 
      else if ((to_line > from_line) && (to_column > from_column))
 
      {
 
         // see if queen can move NE
 
         for (index_line = from_line + 1, index_column = from_column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if queen can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this queen can't move in the claimed way (her king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // queen can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the queen SE ?
 
      else if ((to_line < from_line) && (to_column > from_column))
 
      {
 
         // see if queen can move SE
 
         for (index_line = from_line - 1, index_column = from_column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if queen can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this queen can't move in the claimed way (her king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // queen can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the queen NW ?
 
      else if ((to_line > from_line) && (to_column < from_column))
 
      {
 
         // see if queen can move NW
 
         for (index_line = from_line + 1, index_column = from_column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if queen can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this queen can't move in the claimed way (her king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // queen can take a part there BUT it's not the location we want
 
      }
 
 
 
      // else do we want to move the queen SW ?
 
      else if ((to_line < from_line) && (to_column < from_column))
 
      {
 
         // see if queen can move SW
 
         for (index_line = from_line - 1, index_column = from_column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
            if (!CAN_PLAY (index_line, index_column))
 
               return (false); // if queen can no longer move this way, stop searching
 
            else if ((index_line == to_line) && (index_column == to_column))
 
            {
 
               if (!Move_IsColorInCheckAfterTestMove (move, from_line, from_column, index_line, index_column, boardslot->color))
 
                  return (true); // this move is possible
 
 
 
               return (false); // else this queen can't move in the claimed way (her king would be in check)
 
            }
 
            else if (move->slots[index_line][index_column].part != PART_NONE)
 
               return (false); // queen can take a part there BUT it's not the location we want
 
      }
 
 
 
      return (false); // this queen can't move in the claimed way
 
   }
 
 
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   ////////////////////////////////////////// KING //////////////////////////////////////////
 
   //////////////////////////////////////////////////////////////////////////////////////////
 
   // else is it a king ?
 
   else if (boardslot->part == PART_KING)
 
   {
 
      // do we want to move that king in one of the allowed directions ?
 
      if (((from_line + 1 == to_line) && (from_column == to_column)) // up
 
          || ((from_line - 1 == to_line) && (from_column == to_column)) // down
 
          || ((from_line == to_line) && (from_column + 1 == to_column)) // right
 
          || ((from_line == to_line) && (from_column - 1 == to_column)) // left
 
          || ((from_line + 1 == to_line) && (from_column + 1 == to_column)) // NE
 
          || ((from_line - 1 == to_line) && (from_column + 1 == to_column)) // SE
 
          || ((from_line + 1 == to_line) && (from_column - 1 == to_column)) // NW
 
          || ((from_line - 1 == to_line) && (from_column - 1 == to_column))) // SW
 
      {
 
         if (!CAN_PLAY (to_line, to_column))
 
            return (false); // if king can't move there, return false
 
         else if (Move_IsColorInCheckAfterTestMove (move, from_line, from_column, to_line, to_column, boardslot->color))
 
            return (false); // if king would be in check there, return false
 
 
 
         return (true); // else this move is safe
 
      }
 
 
 
      return (false); // if not, this king can't move in the claimed way
 
   }
 
 
 
   return (false); // this move is not possible, else we'd have returned earlier
 
}
 
 
 
 
 
bool Move_FindRandomMove (boardmove_t *move, int color, boardmove_t *random_move)
 
{
 
   // this function returns TRUE if it can find a random move (most of the time blunderous)
 
   // and sets its coordinates in the given output parameters
 
 
 
   boardslot_t *boardslot;
 
   int movement_direction;
 
   int line;
 
   int column;
 
   int index_line;
 
   int index_column;
 
   boardmove_t *possiblemoves; // mallocated
 
   int possiblemove_count;
 
   int move_index;
 
 
 
   // assume no possible move until told otherwise
 
   possiblemoves = NULL;
 
   possiblemove_count = 0;
 
 
 
   // cycle through all the board and find our parts
 
   for (line = 0; line < 8; line++)
 
      for (column = 0; column < 8; column++)
 
      {
 
         boardslot = &move->slots[line][column]; // quick access to grid slot
 
 
 
         if ((boardslot->part == PART_NONE) || (boardslot->color != color))
 
            continue; // if this location is empty or not ours, we aren't interested in it
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// PAWN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // is it a pawn ?
 
         if (boardslot->part == PART_PAWN)
 
         {
 
            // figure out movement direction
 
            if (boardslot->color == COLOR_WHITE)
 
               movement_direction = 1;
 
            else
 
               movement_direction = -1;
 
 
 
            // see if pawn can move forward
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (move->slots[line + movement_direction][column].part == PART_NONE) // target slot free
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column, color))
 
            {
 
               if (((movement_direction == 1) && (line + movement_direction == 7))
 
                   || ((movement_direction == -1) && (line + movement_direction == 0)))
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column, PART_QUEEN, false, false); // save promotional move
 
               else
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column, PART_NONE, false, false); // save possible move
 
            }
 
 
 
            // see if pawn can take a piece on its left
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (column > 0) // has room
 
                && (move->slots[line + movement_direction][column - 1].color != color) // target slot NOT our color
 
                && (move->slots[line + movement_direction][column - 1].part != PART_NONE) // target slot occupied
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column - 1, PART_NONE, true, false); // save possible move
 
 
 
            // see if pawn can take a piece on its right
 
            if ((((movement_direction == 1) && (line < 7)) || ((movement_direction == -1) && (line > 0)))
 
                && (column < 7) // has room
 
                && (move->slots[line + movement_direction][column + 1].color != color) // target slot NOT our color
 
                && (move->slots[line + movement_direction][column + 1].part != PART_NONE) // target slot occupied
 
                && !Move_IsColorInCheckAfterTestMove (move, line, column, line + movement_direction, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column + 1, PART_NONE, true, false); // save possible move
 
 
 
            // if previous move was a pawn rush, see if pawn can take "en passant"
 
            if ((move->part == PART_PAWN) // last move was a pawn
 
                && (move->target[1] == move->source[1]) // pawn moved in column
 
                && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
                && (move->target[0] == line) // pawn is in line with us
 
                && (move->target[1] - column == -1) // pawn is left to us
 
                && !Move_IsColorInCheckAfterTestMoveEP (move, line, column, line + movement_direction, column - 1, move->target[0], move->target[1], color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column - 1, PART_NONE, true, true); // save possible move
 
            if ((move->part == PART_PAWN) // last move was a pawn
 
                && (move->target[1] == move->source[1]) // pawn moved in column
 
                && (abs (move->target[0] - move->source[0]) == 2) // pawn rushed
 
                && (move->target[0] == line) // pawn is in line with us
 
                && (move->target[1] - column == 1) // pawn is right to us
 
                && !Move_IsColorInCheckAfterTestMoveEP (move, line, column, line + movement_direction, column + 1, move->target[0], move->target[1], color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_PAWN, line, column, line + movement_direction, column + 1, PART_NONE, true, true); // save possible move
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// ROOK //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a rook ?
 
         else if (boardslot->part == PART_ROOK)
 
         {
 
            // see if rook can move upwards
 
            for (index_line = line + 1; index_line < 8; index_line++)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_ROOK, line, column, index_line, column, PART_NONE, (move->slots[index_line][column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if rook can move downwards
 
            for (index_line = line - 1; index_line >= 0; index_line--)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_ROOK, line, column, index_line, column, PART_NONE, (move->slots[index_line][column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if rook can move right
 
            for (index_column = column + 1; index_column < 8; index_column++)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_ROOK, line, column, line, index_column, PART_NONE, (move->slots[line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if rook can move left
 
            for (index_column = column - 1; index_column >= 0; index_column--)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_ROOK, line, column, line, index_column, PART_NONE, (move->slots[line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// KNIGHT /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a knight ?
 
         else if (boardslot->part == PART_KNIGHT)
 
         {
 
            // see if knight can move NNW
 
            if (CAN_PLAY (line + 2, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 2, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line + 2, column - 1, PART_NONE, (move->slots[line + 2][column - 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move NNE
 
            if (CAN_PLAY (line + 2, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 2, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line + 2, column + 1, PART_NONE, (move->slots[line + 2][column + 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move ENE
 
            if (CAN_PLAY (line + 1, column + 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column + 2, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line + 1, column + 2, PART_NONE, (move->slots[line + 1][column + 2].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move ESE
 
            if (CAN_PLAY (line - 1, column + 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column + 2, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line - 1, column + 2, PART_NONE, (move->slots[line - 1][column + 2].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move SSW
 
            if (CAN_PLAY (line - 2, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 2, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line - 2, column - 1, PART_NONE, (move->slots[line - 2][column - 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move SSE
 
            if (CAN_PLAY (line - 2, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 2, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line - 2, column + 1, PART_NONE, (move->slots[line - 2][column + 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move WNW
 
            if (CAN_PLAY (line + 1, column - 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column - 2, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line + 1, column - 2, PART_NONE, (move->slots[line + 1][column - 2].part != PART_NONE), false); // save possible move
 
 
 
            // see if knight can move WSW
 
            if (CAN_PLAY (line - 1, column - 2) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column - 2, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KNIGHT, line, column, line - 1, column - 2, PART_NONE, (move->slots[line - 1][column - 2].part != PART_NONE), false); // save possible move
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// BISHOP /////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a bishop ?
 
         else if (boardslot->part == PART_BISHOP)
 
         {
 
            // see if bishop can move NE
 
            for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_BISHOP, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if bishop can move SE
 
            for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_BISHOP, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if bishop can move NW
 
            for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_BISHOP, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if bishop can move SW
 
            for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_BISHOP, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ///////////////////////////////////////// QUEEN //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a queen ?
 
         else if (boardslot->part == PART_QUEEN)
 
         {
 
            // see if queen can move upwards
 
            for (index_line = line + 1; index_line < 8; index_line++)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, column, PART_NONE, (move->slots[index_line][column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move downwards
 
            for (index_line = line - 1; index_line >= 0; index_line--)
 
               if (!CAN_PLAY (index_line, column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, column, PART_NONE, (move->slots[index_line][column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move right
 
            for (index_column = column + 1; index_column < 8; index_column++)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, line, index_column, PART_NONE, (move->slots[line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move left
 
            for (index_column = column - 1; index_column >= 0; index_column--)
 
               if (!CAN_PLAY (line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, line, index_column, PART_NONE, (move->slots[line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move NE
 
            for (index_line = line + 1, index_column = column + 1; (index_line < 8) && (index_column < 8); index_line++, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move SE
 
            for (index_line = line - 1, index_column = column + 1; (index_line >= 0) && (index_column < 8); index_line--, index_column++)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move NW
 
            for (index_line = line + 1, index_column = column - 1; (index_line < 8) && (index_column >= 0); index_line++, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
 
 
            // see if queen can move SW
 
            for (index_line = line - 1, index_column = column - 1; (index_line >= 0) && (index_column >= 0); index_line--, index_column--)
 
               if (!CAN_PLAY (index_line, index_column))
 
                  break; // if part can no longer move this way, stop searching
 
               else if (!Move_IsColorInCheckAfterTestMove (move, line, column, index_line, index_column, color))
 
               {
 
                  AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_QUEEN, line, column, index_line, index_column, PART_NONE, (move->slots[index_line][index_column].part != PART_NONE), false); // save possible move
 
                  if (move->slots[index_line][index_column].part != PART_NONE)
 
                     break; // this move is possible, but no further moves are possible in the same direction
 
               }
 
         }
 
 
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         ////////////////////////////////////////// KING //////////////////////////////////////////
 
         //////////////////////////////////////////////////////////////////////////////////////////
 
         // else is it a king ?
 
         else if (boardslot->part == PART_KING)
 
         {
 
            // see if king can move up
 
            if (CAN_PLAY (line + 1, column) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line + 1, column, PART_NONE, (move->slots[line + 1][column].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move down
 
            if (CAN_PLAY (line - 1, column) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line - 1, column, PART_NONE, (move->slots[line - 1][column].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move right
 
            if (CAN_PLAY (line, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line, column + 1, PART_NONE, (move->slots[line][column + 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move left
 
            if (CAN_PLAY (line, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line, column - 1, PART_NONE, (move->slots[line][column - 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move NE
 
            if (CAN_PLAY (line + 1, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line + 1, column + 1, PART_NONE, (move->slots[line + 1][column + 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move SE
 
            if (CAN_PLAY (line - 1, column + 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column + 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line - 1, column + 1, PART_NONE, (move->slots[line - 1][column + 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move NW
 
            if (CAN_PLAY (line + 1, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line + 1, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line + 1, column - 1, PART_NONE, (move->slots[line + 1][column - 1].part != PART_NONE), false); // save possible move
 
 
 
            // see if king can move SW
 
            if (CAN_PLAY (line - 1, column - 1) && !Move_IsColorInCheckAfterTestMove (move, line, column, line - 1, column - 1, color))
 
               AddPossibleMove (&possiblemoves, &possiblemove_count, boardslot->color, PART_KING, line, column, line - 1, column - 1, PART_NONE, (move->slots[line - 1][column - 1].part != PART_NONE), false); // save possible move
 
         }
 
      }
 
 
 
   // now that all the table has been parsed, see if we have some possible moves
 
 
 
   if (possiblemove_count == 0)
 
      return (false); // if none, return FALSE (it means that we are stalemate, but there's a faster function to check that)
 
 
 
   move_index = rand () % possiblemove_count; // select a possible move at random
 
   memcpy (random_move, &possiblemoves[move_index], sizeof (boardmove_t)); // copy it into destination variable
 
 
 
   SAFE_free ((void **) &possiblemoves); // free the possible moves array, we no longer need them
 
   return (true); // we did find some possible moves
 
}
 
 
 
 
 
int Move_CountPartsByColorAndType (boardmove_t *move, int color, int part_type)
 
{
 
   // this function returns the amount of parts of the specified color and type left on board
 
 
 
   int line;
 
   int column;
 
   int count;
 
 
 
   count = 0; // assume none so far
 
 
 
   // cycle through all the board...
 
   for (line = 0; line < 8; line++)
 
      for (column = 0; column < 8; column++)
 
         if ((move->slots[line][column].color == color) && (move->slots[line][column].part == part_type))
 
            count++; // sum up all the parts of the same colour and type we find
 
 
 
   return (count); // and return their quantity
 
}
 
 
 
 
 
bool Move_IsColorInCheckAfterTestMove (boardmove_t *move, int source_line, int source_column, int target_line, int target_column, int color)
 
{
 
   // helper function to play a test move on a temporary board (which must have been previously allocated)
 
 
 
   static boardmove_t temp_move; // declare this static so as not to allocate/free it continuously
 
 
 
   memcpy (temp_move.slots, move->slots, sizeof (move->slots)); // have a copy of the table, then make the move
 
   memcpy (&temp_move.slots[target_line][target_column], &temp_move.slots[source_line][source_column], sizeof (boardslot_t));
 
   memset (&temp_move.slots[source_line][source_column], 0, sizeof (boardslot_t)); // erase the source slot
 
 
 
   return (Move_IsCheck (&temp_move, color)); // return whether the final board has the given color in check
 
}
 
 
 
 
 
bool Move_IsColorInCheckAfterTestMoveEP (boardmove_t *move, int source_line, int source_column, int target_line, int target_column, int clear_line, int clear_column, int color)
 
{
 
   // helper function to play a test move on a temporary board (which must have been previously allocated)
 
   // En Passant version -- cleans the specified target before testing
 
 
 
   static boardmove_t temp_move; // declare this static so as not to allocate/free it continuously
 
 
 
   memcpy (temp_move.slots, move->slots, sizeof (move->slots)); // have a copy of the table, then make the move
 
   memcpy (&temp_move.slots[target_line][target_column], &temp_move.slots[source_line][source_column], sizeof (boardslot_t));
 
   memset (&temp_move.slots[source_line][source_column], 0, sizeof (boardslot_t)); // erase the source slot
 
 
 
   memset (&temp_move.slots[clear_line][clear_column], 0, sizeof (boardslot_t)); // erase the "en passant" target
 
 
 
   return (Move_IsCheck (&temp_move, color)); // return whether the final board has the given color in check
 
}
 
 
 
 
 
void Move_DescribeInFEN (boardmove_t *move)
 
{
 
   // convert a board and its part placements into a Forsyth Edwards notation, writing in the fen_string buffer
 
 
 
   boardslot_t *slot;
 
   int line;
 
   int column;
 
   int free_slots;
 
   int length;
 
 
 
   // first reset the string
 
   move->fen_string[0] = 0;
 
 
 
   ////////////////////////////////////////////////////////
 
   // first part of the FEN notation is the parts placement
 
 
 
   // cycle through each column, line after line, starting up left and going downwards right
 
   for (line = 7; line >= 0; line--)
 
   {
 
      free_slots = 0; // no free slot in that line yet
 
 
 
      for (column = 0; column < 8; column++)
 
      {
 
         slot = &move->slots[line][column]; // quick access to current slot
 
 
 
         if (slot->part == PART_ROOK)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"r" : (slot->color == COLOR_WHITE ? L"R": L"?")));
 
         }
 
         else if (slot->part == PART_KNIGHT)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"n" : (slot->color == COLOR_WHITE ? L"N": L"?")));
 
         }
 
         else if (slot->part == PART_BISHOP)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"b" : (slot->color == COLOR_WHITE ? L"B": L"?")));
 
         }
 
         else if (slot->part == PART_QUEEN)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"q" : (slot->color == COLOR_WHITE ? L"Q": L"?")));
 
         }
 
         else if (slot->part == PART_KING)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"k" : (slot->color == COLOR_WHITE ? L"K": L"?")));
 
         }
 
         else if (slot->part == PART_PAWN)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), (slot->color == COLOR_BLACK ? L"p" : (slot->color == COLOR_WHITE ? L"P": L"?")));
 
         }
 
         else
 
            free_slots++; // we found one free slot more
 
 
 
         // are we at the end of a line ?
 
         if (column == 7)
 
         {
 
            // if there are free slots to mention, do it
 
            if (free_slots > 0)
 
            {
 
               length = wcslen (move->fen_string); // append the free slots count
 
               swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", free_slots);
 
               free_slots = 0; // reset the free slots count
 
            }
 
            if (line > 0)
 
               wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"/"); // at the end of each line, drop a slash (except on the last line)
 
         }
 
      }
 
   }
 
 
 
   //////////////////////////////////////////////////////
 
   // second part of the FEN notation is the side on move
 
 
 
   // deduce the side to move according to last move's color
 
   if (move->color == COLOR_WHITE)
 
      wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L" b"); // black to move
 
   else
 
      wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L" w"); // white to move (this also catches the beginning of a game)
 
 
 
   ///////////////////////////////////////////////////////////////
 
   // third part of the FEN notation is the castling possibilities
 
 
 
   wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L" ");
 
   if (!(move->sides[COLOR_BLACK].longcastle_allowed | move->sides[COLOR_WHITE].longcastle_allowed | move->sides[COLOR_BLACK].shortcastle_allowed | move->sides[COLOR_WHITE].shortcastle_allowed))
 
      wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"-"); // neither side can castle
 
   else
 
   {
 
      if (move->sides[COLOR_WHITE].shortcastle_allowed)
 
         wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"K"); // white can castle kingside
 
      if (move->sides[COLOR_WHITE].longcastle_allowed)
 
         wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"Q"); // white can castle queenside
 
      if (move->sides[COLOR_BLACK].shortcastle_allowed)
 
         wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"k"); // black can castle kingside
 
      if (move->sides[COLOR_BLACK].longcastle_allowed)
 
         wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"q"); // black can castle queenside
 
   }
 
 
 
   ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   // fourth part of the FEN notation is the optional position for a pawn that can be taken en passant
 
 
 
   wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L" "); // spacer
 
 
 
   if ((move->part == PART_PAWN) // last move was a pawn
 
       && (move->target[1] == move->source[1]) // pawn moved in column
 
       && (abs (move->target[0] - move->source[0]) == 2)) // pawn rushed
 
   {
 
      // column
 
      if (move->source[1] == 0) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"a");
 
      else if (move->source[1] == 1) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"b");
 
      else if (move->source[1] == 2) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"c");
 
      else if (move->source[1] == 3) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"d");
 
      else if (move->source[1] == 4) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"e");
 
      else if (move->source[1] == 5) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"f");
 
      else if (move->source[1] == 6) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"g");
 
      else if (move->source[1] == 7) wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"h");
 
      else wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"?");
 
 
 
      // line (it's the line the pawn would be on if it had made a "normal" move)
 
      length = wcslen (move->fen_string);
 
      swprintf_s (&move->fen_string[length], WCHAR_SIZEOF (move->fen_string) - length, L"%d", 1 + (move->target[0] + move->source[0]) / 2);
 
   }
 
   else
 
      wcscat_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), L"-"); // last move was not a pawn rush
 
 
 
   return; // finished
 
}
 
 
 
 
 
bool Move_SetupFromFEN (boardmove_t *move, wchar_t *fen_string)
 
{
 
   // this function sets up the given board according to the Forsyth-Edwards description fen_string makes of it
 
 
 
   // FIXME : load fen, then load PGN, then back arrow.
 
 
 
   int char_index;
 
   int length;
 
   int current_line;
 
   int current_column;
 
   int enpassant_line;
 
   int enpassant_column;
 
 
 
   // reset the chess grid
 
   memset (&move->slots, 0, sizeof (move->slots));
 
 
 
   // reset the taken pieces for both sides
 
   SAFE_free ((void **) &move->sides[COLOR_WHITE].takenparts); // release memory space
 
   move->sides[COLOR_WHITE].takenpart_count = 0;
 
   SAFE_free ((void **) &move->sides[COLOR_BLACK].takenparts); // release memory space
 
   move->sides[COLOR_BLACK].takenpart_count = 0;
 
 
 
   // reset the moves array comments and the moves array itself
 
   SAFE_free ((void **) &move->comment);
 
 
 
   // DISallow both sides to castle, until told otherwise
 
   move->sides[COLOR_WHITE].shortcastle_allowed = false;
 
   move->sides[COLOR_WHITE].longcastle_allowed = false;
 
   move->sides[COLOR_BLACK].shortcastle_allowed = false;
 
   move->sides[COLOR_BLACK].longcastle_allowed = false;
 
 
 
   // get the length of the FEN string
 
   length = wcslen (fen_string);
 
 
 
   // now parse the board from top left to bottom right, placing parts on the fly
 
   current_line = 7;
 
   current_column = 0;
 
   for (char_index = 0; char_index < length; char_index++)
 
   {
 
      // is it a number ?
 
      if (iswdigit (fen_string[char_index]))
 
      {
 
         current_column += _wtoi (&fen_string[char_index]); // skip as many columns as needed
 
         if (current_column > 8)
 
            return (false); // consistency check: something's wrong with this notation, return FALSE
 
      }
 
 
 
      // else is it a line skip ?
 
      else if (fen_string[char_index] == L'/')
 
      {
 
         // were we reading the last line ?
 
         if (current_line == 0)
 
         {
 
            char_index++; // skip this character
 
            break; // stop reading parts placement
 
         }
 
 
 
         current_line--; // proceed to next line, decrescending
 
         current_column = 0; // and begin at the first column on that line
 
      }
 
 
 
      // else is it a blank space ? meaning parts have been read
 
      else if (fen_string[char_index] == L' ')
 
         break; // stop reading parts placement
 
 
 
      // else it's a part. Check first if the current line/column is valid
 
      else if (IS_VALID (current_line, current_column))
 
      {
 
         if (fen_string[char_index] == L'r')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_ROOK); // black rook
 
         else if (fen_string[char_index] == L'R')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_ROOK); // white rook
 
         else if (fen_string[char_index] == L'n')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_KNIGHT); // black knight
 
         else if (fen_string[char_index] == L'N')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_KNIGHT); // white knight
 
         else if (fen_string[char_index] == L'b')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_BISHOP); // black bishop
 
         else if (fen_string[char_index] == L'B')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_BISHOP); // white bishop
 
         else if (fen_string[char_index] == L'q')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_QUEEN); // black queen
 
         else if (fen_string[char_index] == L'Q')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_QUEEN); // white queen
 
         else if (fen_string[char_index] == L'k')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_KING); // black king
 
         else if (fen_string[char_index] == L'K')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_KING); // white king
 
         else if (fen_string[char_index] == L'p')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_PAWN); // black pawn
 
         else if (fen_string[char_index] == L'P')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_PAWN); // white pawn
 
 
 
         current_column++; // proceed to next column
 
      }
 
      else
 
         return (false); // invalid position, something's wrong with this notation, return FALSE
 
   }
 
 
 
   // a space has been reached: next thing to read is the side on move
 
   char_index++;
 
   if (char_index >= length)
 
      return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
   if (towlower (fen_string[char_index]) == L'w')
 
      move->color = COLOR_BLACK; // white to move
 
   else if (towlower (fen_string[char_index]) == L'b')
 
      move->color = COLOR_WHITE; // black to move
 
   else
 
      return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
   // there should be a space after this
 
   char_index++;
 
   if ((char_index >= length) || (fen_string[char_index] != L' '))
 
      return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
   // a space has been reached: next thing to read is the castling possibilities
 
   char_index++;
 
   if (char_index >= length)
 
      return (false); // consistency check: something's wrong with this notation, return FALSE
 
   for (; char_index < length; char_index++)
 
   {
 
      if (fen_string[char_index] == L'k')
 
         move->sides[COLOR_BLACK].shortcastle_allowed = true; // short castling allowed for black
 
      else if (fen_string[char_index] == L'K')
 
         move->sides[COLOR_WHITE].shortcastle_allowed = true; // short castling allowed for white
 
      else if (fen_string[char_index] == L'q')
 
         move->sides[COLOR_BLACK].longcastle_allowed = true; // long castling allowed for black
 
      else if (fen_string[char_index] == L'Q')
 
         move->sides[COLOR_WHITE].longcastle_allowed = true; // long castling allowed for white
 
      else if (fen_string[char_index] == L'-')
 
         continue; // no side can castle (explicitly)
 
      else if (fen_string[char_index] == L' ')
 
         break; // if blank space, stop reading castling possibilities
 
   }
 
 
 
   // is there a free space after this ?
 
   if (char_index < length)
 
   {
 
      char_index++; // if so, skip it
 
 
 
      // is there enough room for an en passant position AND is it specified ?
 
      if ((char_index + 2 <= length) && (fen_string[char_index] != L'-'))
 
      {
 
         // read column
 
         if (towlower (fen_string[char_index]) == L'a') enpassant_column = 0;
 
         else if (towlower (fen_string[char_index]) == L'b') enpassant_column = 1;
 
         else if (towlower (fen_string[char_index]) == L'c') enpassant_column = 2;
 
         else if (towlower (fen_string[char_index]) == L'd') enpassant_column = 3;
 
         else if (towlower (fen_string[char_index]) == L'e') enpassant_column = 4;
 
         else if (towlower (fen_string[char_index]) == L'f') enpassant_column = 5;
 
         else if (towlower (fen_string[char_index]) == L'g') enpassant_column = 6;
 
         else if (towlower (fen_string[char_index]) == L'h') enpassant_column = 7;
 
         else return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
         // read line
 
         enpassant_line = _wtoi (&fen_string[char_index + 1]) - 1;
 
         if ((enpassant_line != 2) && (enpassant_line != 5))
 
            return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
         // setup move data
 
         move->part = PART_PAWN;
 
         if (enpassant_line == 2)
 
         {
 
            move->source[0] = 1; // rush from line 1 to line 3
 
            move->target[0] = 3;
 
            move->color = COLOR_WHITE;
 
         }
 
         else
 
         {
 
            move->source[0] = 6; // rush from line 6 to line 4
 
            move->target[0] = 4;
 
            move->color = COLOR_BLACK;
 
         }
 
         move->source[1] = enpassant_column;
 
         move->target[1] = enpassant_column;
 
      }
 
   }
 
 
 
   // table was setup correctly, save FEN string in move structure
 
   wcscpy_s (move->fen_string, WCHAR_SIZEOF (move->fen_string), fen_string);
 
   return (true); // and return TRUE
 
}
 
 
 
 
 
bool Move_SetupFromStyle12 (boardmove_t *move, wchar_t *positions, int move_color, int pawnrush_column,
 
                            bool can_white_castle_short, bool can_white_castle_long, bool can_black_castle_short, bool can_black_castle_long, wchar_t *pretty_movestring)
 
{
 
   // this function sets up the given board according to the Style12 ICC/FICS description style12_string makes of it
 
 
 
   int pos_index;
 
   int current_line;
 
   int current_column;
 
 
 
   // reset the chess grid
 
   memset (&move->slots, 0, sizeof (move->slots));
 
 
 
   // now parse the line from left to right, placing parts on the fly
 
   for (current_line = 0; current_line < 8; current_line++)
 
      for (current_column = 0; current_column < 8; current_column++)
 
      {
 
         pos_index = (7 - current_line) * 8 + current_column; // compute position in line
 
 
 
         if (positions[pos_index] == L'r')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_ROOK); // black rook
 
         else if (positions[pos_index] == L'R')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_ROOK); // white rook
 
         else if (positions[pos_index] == L'n')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_KNIGHT); // black knight
 
         else if (positions[pos_index] == L'N')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_KNIGHT); // white knight
 
         else if (positions[pos_index] == L'b')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_BISHOP); // black bishop
 
         else if (positions[pos_index] == L'B')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_BISHOP); // white bishop
 
         else if (positions[pos_index] == L'q')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_QUEEN); // black queen
 
         else if (positions[pos_index] == L'Q')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_QUEEN); // white queen
 
         else if (positions[pos_index] == L'k')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_KING); // black king
 
         else if (positions[pos_index] == L'K')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_KING); // white king
 
         else if (positions[pos_index] == L'p')
 
            Move_SetSlot (move, current_line, current_column, COLOR_BLACK, PART_PAWN); // black pawn
 
         else if (positions[pos_index] == L'P')
 
            Move_SetSlot (move, current_line, current_column, COLOR_WHITE, PART_PAWN); // white pawn
 
      }
 
 
 
   // save move color
 
   move->color = move_color;
 
 
 
   // allow or disallow both sides to castle, as told
 
   move->sides[COLOR_WHITE].shortcastle_allowed = can_white_castle_short;
 
   move->sides[COLOR_WHITE].longcastle_allowed = can_white_castle_long;
 
   move->sides[COLOR_BLACK].shortcastle_allowed = can_black_castle_short;
 
   move->sides[COLOR_BLACK].longcastle_allowed = can_black_castle_long;
 
 
 
   // is the last move a pawn rush ?
 
   if (pawnrush_column != -1)
 
   {
 
      if ((pawnrush_column < 0) || (pawnrush_column > 7))
 
         return (false); // consistency check: something's wrong with this notation, return FALSE
 
 
 
      move->part = PART_PAWN;
 
      if (move->color == COLOR_WHITE)
 
      {
 
         move->source[0] = 1; // rush from line 1 to line 3
 
         move->target[0] = 3;
 
      }
 
      else
 
      {
 
         move->source[0] = 6; // rush from line 6 to line 4
 
         move->target[0] = 4;
 
      }
 
      move->source[1] = pawnrush_column;
 
      move->target[1] = pawnrush_column;
 
   }
 
 
 
   // finally, save the FEN string with which we initialized this board
 
   Move_DescribeInFEN (move);
 
   return (true); // finished, no error encountered
 
}
 
 
 
 
 
static void AddPossibleMove (boardmove_t **possiblemoves, int *possiblemove_count, int color, int part, int source_line, int source_column, int target_line, int target_column, int promotion_type, bool has_captured, bool is_enpassant)
 
{
 
   // helper function that resizes the given possiblemoves array and adds a possible move to it
 
 
 
   // TODO: raise or clear the is_check and is_stalemate move flags in the returned move.
 
   // Not crucial as this function is only called by Board_FindRandomMove(), the result is then
 
   // translated in SAN and then fed to the chess engine to order a blunderous move. The move
 
   // is then played normally using Board_AppendMove() using source and target locations, and this
 
   // call does evaluate the actual move and set the flags correctly in the final moves array.
 
 
 
   *possiblemoves = (boardmove_t *) SAFE_realloc (*possiblemoves, *possiblemove_count, (*possiblemove_count) + 1, sizeof (boardmove_t), true);
 
   (*possiblemoves)[*possiblemove_count].color = color;
 
   (*possiblemoves)[*possiblemove_count].part = part;
 
   (*possiblemoves)[*possiblemove_count].source[0] = source_line;
 
   (*possiblemoves)[*possiblemove_count].source[1] = source_column;
 
   (*possiblemoves)[*possiblemove_count].target[0] = target_line;
 
   (*possiblemoves)[*possiblemove_count].target[1] = target_column;
 
   (*possiblemoves)[*possiblemove_count].promotion_type = promotion_type;
 
   (*possiblemoves)[*possiblemove_count].has_captured = has_captured;
 
   (*possiblemoves)[*possiblemove_count].is_enpassant = is_enpassant;
 
   (*possiblemove_count)++; // possible moves array holds now one move more
 
 
 
   return; // finished
 
}