/*int tile_occupied(struct board *brd, unsigned row, unsigned col)
{
//  return brd->tiles[row][col];
  return ((unsigned char*)brd->tiles)[(row<<3)+col];
}*/
#define tile_occupied(brd, row, col)  (((unsigned char*)(((struct board*)brd)->tiles))[(row<<3)+col])

#define piece_in_tile(brd, row, col) tile_occupied(brd, row, col)

/*unsigned char *ptr_to_tile(struct board *brd, unsigned row, unsigned col)
{
  return &((unsigned char*)brd->tiles)[(row<<3)+col];
}*/
#define ptr_to_tile(brd, row, col) (((unsigned char*)(((struct board*)brd)->tiles))+(row<<3)+col)


struct coord *legal_moves(struct board *brd, struct coord pc_coords, unsigned char *count, struct coord *king_pos);
int move_in_list(struct coord *list, unsigned char count, unsigned char row, unsigned char col);
void outofmemory(void);

/*uint16_t move_bitmap_rook[] =
{
  0x0080,
  0x0080,
  0x0080,

  0x0080,
  0x0080,
  0x0080,
  0x0080,

  0xFF7F, // current position
  0x0080,
  0x0080,
  0x0080,

  0x0080,
  0x0080,
  0x0080,
  0x0080
};

uint16_t move_bitmap_bishop[] =
{
  0x4001,
  0x2002,
  0x1004,

  0x0808,
  0x0410,
  0x0220,
  0x0140,

  0x0000, // current position
  0x0140,
  0x0220,
  0x0410,

  0x0808,
  0x1004,
  0x2002,
  0x4001
};

uint16_t move_bitmap_queen[] =
{
  0x4081,
  0x2082,
  0x1084,

  0x0888,
  0x0490,
  0x02A0,
  0x01C0,

  0xFF7F, // current position
  0x01C0,
  0x02A0,
  0x0490,

  0x0888,
  0x1084,
  0x2082,
  0x4081
};


uint16_t move_bitmap_knight[] =
{
  0x0000,
  0x0000,
  0x0000,

  0x0000,
  0x0000,
  0x0140,
  0x0220,

  0x0000, // current position
  0x0220,
  0x0140,
  0x0000,

  0x0000,
  0x0000,
  0x0000,
  0x0000
};

void royal_move_bitmap(struct coord pc_coords, unsigned char royal_value, uint8_t *map)
{
  unsigned n;
  uint16_t *move_bitmap;

  if(royal_value == PC_ROOK)
    move_bitmap = move_bitmap_rook;
  else if(royal_value == PC_BISHOP)
    move_bitmap = move_bitmap_bishop;
  else if(royal_value == PC_KNIGHT)
    move_bitmap = move_bitmap_knight;
  else if(royal_value == PC_QUEEN)
    move_bitmap = move_bitmap_queen;

  move_bitmap += 7 - pc_coords.row;

  for(n=0;n<8;n++)
  {
    map[n] = move_bitmap[n] >> pc_coords.col;
  }
}

void map_enemy_pieces(struct board *brd, uint8_t *map, unsigned char piece_value)
{
  unsigned row, col;
  unsigned char piece;

  memset(map, 0, 8);

  for(row=0;row<8;row++,map++)
    for(col=0;col<8;col++)
    {
      if((piece = piece_in_tile(brd, row, col))
         && piece_value == (piece & 0xF))
        *map |= 1;
      *map <<= 1;
    }
}

int position_in_move_bitmap(struct coord pc_coords, uint8_t *map)
{
  uint8_t mask = 0x80 >> pc_coords.col;

  return map[pc_coords.row] & mask;
}

void list_moves_in_bitmap(struct coord *moves, unsigned char *count, uint8_t *map)
{
  unsigned char row, col;

  for(row=0;row<8;row++,map++)
    for(col=0;col<8;col++)
    {
      if((*map >> col) & 1)
      {
        moves->row = row;
        moves->col = col;
        count++;
        moves++;
      }
    }
}*/

int king_threatened(struct board *brd, struct coord *king_pos, struct coord pc_coords)
{
  unsigned char side = piece_in_tile(brd, pc_coords.row, pc_coords.col) & PC_BLACK;
  unsigned char piece;
  unsigned char royal;
  struct coord *moves;
  struct coord *movptr;
  unsigned char move_count;
  unsigned char pawn_row;
  unsigned char retval;
  struct board temp;
  unsigned char *tile_ptr;
  unsigned row, col;

  for(row=king_pos->row-1;row<=king_pos->row+1;row++)
  {
    if(row < 8) for(col=king_pos->col-1;col<=king_pos->col+1;col++)
    {
      if(col < 8) if(((piece_in_tile(brd, row, col) ^ side) & 0xF) == (PC_KING | PC_BLACK))
        return 1;
    }
  }

  if(side) pawn_row = king_pos->row + 1;
  else pawn_row = king_pos->row - 1;

  if(pawn_row < 8)
  {
    if(king_pos->col)
    {
      piece = piece_in_tile(brd, pawn_row, king_pos->col - 1);
      if(piece && (piece & 0x7) < PC_ROOK)
        if((piece & PC_BLACK) ^ side)
        {
          return 1;
        }
    }
    if(king_pos->col < 7)
    {
      piece = piece_in_tile(brd, pawn_row, king_pos->col + 1);
      if(piece && (piece & 0x7) < PC_ROOK)
        if((piece & PC_BLACK) ^ side)
        {
          return 1;
        }
    }
  }


  temp = *brd;
  tile_ptr = ptr_to_tile(&temp, king_pos->row, king_pos->col);

  for(retval=0,royal=PC_ROOK;!retval && royal<PC_KING;royal++)
  {
    *tile_ptr = royal | side;
    moves = legal_moves(&temp, *king_pos, &move_count, 0);
    if(!moves)
      outofmemory();
    if(move_count)
    {
      movptr = moves;
      while(move_count--)
      {
        piece = piece_in_tile(&temp, movptr->row, movptr->col);
        if((piece & 0x7) == royal && ((piece & PC_BLACK) ^ side))
          retval = 1;
        movptr++;
      }
      free(moves);
    }
  }

  return retval;
}

void ascend_piece(struct board *brd, struct coord pc_coords, unsigned char new_rank)
{
  unsigned char *piece = ptr_to_tile(brd, pc_coords.row, pc_coords.col);
  *piece &= ~0x07;
  *piece |= new_rank;
}

void unset_enpass_bits(struct board *brd)
{
  unsigned char n;
  unsigned char *ptr = (void*)&brd->tiles[0][0];

  for(n=0;n<8*8;n++)
    ptr[n] &= ~PC_PAWN_ENPASS;
}

// returns 1 if the piece must be ascended
int move_piece(struct board *brd, struct coord pc_coords, struct coord new_coords)
{
  unsigned char *piece = ptr_to_tile(brd, pc_coords.row, pc_coords.col);
  unsigned char en_passant_set = 0;
  unsigned char capture = piece_in_tile(brd, new_coords.row, new_coords.col);

  if((*piece & 0x7) == PC_PAWN_UNMOVED)
  {
    *piece = PC_PAWN_MOVED | (*piece & PC_BLACK);
    if(abs(pc_coords.row - new_coords.row) == 2)
    {
      *piece |= PC_PAWN_ENPASS;
      en_passant_set = 1;
    }
  }
  else if((*piece & 0x7) == PC_PAWN_MOVED)
  {
    if(pc_coords.col != new_coords.col && !capture)
    {
      // en passant
      *ptr_to_tile(brd, ((*piece & PC_BLACK) ? new_coords.row-1 : new_coords.row+1), new_coords.col) = 0;
    }
  }
  else if((*piece & 0x07) == PC_KING)
  {
    // castle
    if(abs(pc_coords.col - new_coords.col) == 2)
    {
      if(pc_coords.col > new_coords.col)
      {
        *ptr_to_tile(brd, pc_coords.row, 3) = piece_in_tile(brd, pc_coords.row, 0) | PC_MOVED;
        *ptr_to_tile(brd, pc_coords.row, 0) = 0;
      }
      else
      {
        *ptr_to_tile(brd, pc_coords.row, 5) = piece_in_tile(brd, pc_coords.row, 7) | PC_MOVED;
        *ptr_to_tile(brd, pc_coords.row, 7) = 0;
      }
    }
  }

  *ptr_to_tile(brd, new_coords.row, new_coords.col) = (*piece | PC_MOVED);
  *piece = 0;
  piece = ptr_to_tile(brd, new_coords.row, new_coords.col);

  if(!en_passant_set)
  {
    unset_enpass_bits(brd);
  }

  if(brd == &board)
  {
    if(capture || (*piece & 0x7) == PC_PAWN_MOVED)
      game_status.moves_pawn_capture = 0;
    else
      game_status.moves_pawn_capture++;
  }

  if((*piece & 0x7) == PC_PAWN_MOVED)
  {
    if(!new_coords.row || new_coords.row == 7)
      return 1;
  }

  return 0;
}

struct coord find_king(struct board *brd, unsigned char side)
{
  unsigned char ndl;
//  unsigned char row, col;
  unsigned n;
  struct coord retval;
  unsigned char *ptr;

  if(side)
    ndl = PC_KING | PC_BLACK;
  else
    ndl = PC_KING;

/*  for(row=0;row<8;row++)
    for(col=0;col<8;col++)
      if((brd->tiles[row][col] & 0xF) == ndl)
      {
        retval.row = row;
        retval.col = col;
        return retval;
      }*/

  ptr = (void*)brd->tiles;
  for(n=0;n<sizeof(brd->tiles);n++)
    if((ptr[n] & 0xF) == ndl)
    {
      retval.row = n>>3;
      retval.col = n&7;
      return retval;;
    }

#ifdef DEBUG
  if(n == sizeof(brd->tiles))
  {
    printf("Error: No king %u found!\n", side);
    print_last_pos();
  }
#endif
  memset(&retval, -1, sizeof(retval));
  return retval;
}


/*void piece_count(struct board *brd, unsigned char side,
                 unsigned char *queen_count, unsigned char *rook_count,
                 unsigned char *bishop_count, unsigned char *knight_count,
                 unsigned char *pawn_count)*/
void piece_count(struct board *brd, unsigned char side,
                 struct piece_count *piece_count)
{
//  unsigned char row, col;
  unsigned char queen, rook, knight, bishop, pawn1, pawn2;
  unsigned char piece;
  unsigned char *ptr;
  unsigned char n;

  if(side)
  {
    queen = PC_QUEEN | PC_BLACK;
    rook = PC_ROOK | PC_BLACK;
    knight = PC_KNIGHT | PC_BLACK;
    bishop = PC_BISHOP | PC_BLACK;
    pawn1 = PC_PAWN_UNMOVED | PC_BLACK;
    pawn2 = PC_PAWN_MOVED | PC_BLACK;
  }
  else
  {
    queen = PC_QUEEN;;
    rook = PC_ROOK;
    knight = PC_KNIGHT;
    bishop = PC_BISHOP;
    pawn1 = PC_PAWN_UNMOVED;
    pawn2 = PC_PAWN_MOVED;
  }

//  *queen_count = *rook_count = *bishop_count = *knight_count = *pawn_count = 0;
  memset(piece_count, 0, sizeof(struct piece_count));
//  *piece_count = (struct piece_count){ 0 };

/*  for(row=0;row<8;row++)
    for(col=0;col<8;col++)
    {
      piece = brd->tiles[row][col] & 0xF;
      if(piece == pawn1 || piece == pawn2) ++*pawn_count;
      else if(piece == rook) ++*rook_count;
      else if(piece == knight) ++*knight_count;
      else if(piece == bishop) ++*bishop_count;
      else if(piece == queen) ++*queen_count;
    }*/

  for(ptr=&brd->tiles[0][0],n=0;n<8*8;n++)
  {
    piece = ptr[n] & 0xF;
    if(piece == pawn1 || piece == pawn2) ++piece_count->pawn_count;
    else if(piece == rook) ++piece_count->rook_count;
    else if(piece == knight) ++piece_count->knight_count;
    else if(piece == bishop) ++piece_count->bishop_count;
    else if(piece == queen) ++piece_count->queen_count;
  }
}

void add_move_to_list(struct board *brd, struct coord pc_coords, struct coord *king_pos,
                      struct coord *retval, unsigned char *count, unsigned char col, unsigned char row)
{
  struct board temp;

  retval[*count].col = col;
  retval[*count].row = row;

  if(king_pos)
  {
    temp = *brd;
    move_piece(&temp, pc_coords, retval[*count]);
    if(king_threatened(&temp, king_pos, retval[*count]))
      return;
  }

  ++*count;
}

int move_in_list(struct coord *list, unsigned char count, unsigned char row, unsigned char col)
{
  while(count--)
  {
    if(list[count].row == row && list[count].col == col)
      return 1;
  }

  return 0;
}

void legal_moves_rook(struct board *brd, struct coord pc_coords, unsigned char *count,
                      struct coord *king_pos, struct coord *retval)
{
  unsigned char newrow, newcol, loop_end;
  unsigned char side = piece_in_tile(brd, pc_coords.row, pc_coords.col) & PC_BLACK;

  for(loop_end=0,newcol=pc_coords.col+1;!loop_end && newcol<8;newcol++)
    if(!(loop_end = tile_occupied(brd, pc_coords.row, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, pc_coords.row);

  for(loop_end=0,newcol=pc_coords.col;!loop_end && newcol--;)
    if(!(loop_end = tile_occupied(brd, pc_coords.row, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, pc_coords.row);

  for(loop_end=0,newrow=pc_coords.row+1;!loop_end && newrow<8;newrow++)
    if(!(loop_end = tile_occupied(brd, newrow, pc_coords.col))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col, newrow);

  for(loop_end=0,newrow=pc_coords.row;!loop_end && newrow--;)
    if(!(loop_end = tile_occupied(brd, newrow, pc_coords.col))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col, newrow);
}

void legal_moves_bishop(struct board *brd, struct coord pc_coords, unsigned char *count,
                      struct coord *king_pos, struct coord *retval)
{
  unsigned char newrow, newcol, loop_end;
  unsigned char side = piece_in_tile(brd, pc_coords.row, pc_coords.col) & PC_BLACK;

  for(loop_end=0,newcol=pc_coords.col+1,newrow=pc_coords.row+1;!loop_end && newcol<8 && newrow<8;newrow++,newcol++)
    if(!(loop_end = tile_occupied(brd, newrow, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

  for(loop_end=0,newcol=pc_coords.col,newrow=pc_coords.row;!loop_end && newcol-- && newrow--;)
    if(!(loop_end = tile_occupied(brd, newrow, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

  for(loop_end=0,newcol=pc_coords.col+1,newrow=pc_coords.row;!loop_end && newcol<8 && newrow--;newcol++)
    if(!(loop_end = tile_occupied(brd, newrow, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

  for(loop_end=0,newcol=pc_coords.col,newrow=pc_coords.row+1;!loop_end && newcol-- && newrow<8;newrow++)
    if(!(loop_end = tile_occupied(brd, newrow, newcol))
       || ((loop_end & PC_BLACK)
           ^ (side)))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);
}

int king_in_adjacent_tile(struct board *brd, struct coord pc_coords, unsigned char side)
{
  struct coord king_coords = find_king(brd, !side);

  if(abs(king_coords.row - pc_coords.row) <= 1 && abs(king_coords.col - pc_coords.col) <= 1)
    return 1;
  return 0;
}

void legal_moves_king(struct board *brd, struct coord pc_coords, unsigned char *count,
                      struct coord *retval)
{
  signed char newrow, newcol;
  struct coord new_coords;
  unsigned char castle_left_white[] = { PC_ROOK, 0, 0, 0, PC_KING };
  unsigned char castle_right_white[] = { PC_KING, 0, 0, PC_ROOK };
  unsigned char castle_left_black[] = { PC_ROOK | PC_BLACK, 0, 0, 0, PC_KING | PC_BLACK };
  unsigned char castle_right_black[] = { PC_KING | PC_BLACK, 0, 0, PC_ROOK | PC_BLACK };
  unsigned char piece;
  unsigned char side = piece_in_tile(brd, pc_coords.row, pc_coords.col) & PC_BLACK;


  for(newrow=pc_coords.row-1;newrow<=pc_coords.row+1;newrow++)
  {
    if((unsigned char)newrow < 8)
      for(newcol=pc_coords.col-1;newcol<=pc_coords.col+1;newcol++)
        if((unsigned char)newcol < 8)
        {
          if(newrow == pc_coords.row && newcol == pc_coords.col)
            continue;
          if(!(piece = tile_occupied(brd, newrow, newcol))
             || (piece && ((piece & PC_BLACK) ^ (side))))
            {
              new_coords.col = newcol;
              new_coords.row = newrow;
              if(!king_in_adjacent_tile(brd, new_coords, side))
                add_move_to_list(brd, pc_coords, &new_coords, retval, count, newcol, newrow);
            }
        }
  }

  // castling not allowed if the king is in check
  if(king_threatened(brd, &pc_coords, pc_coords))
    return;

  // castling not allowed if the king has already moved
  if((piece = piece_in_tile(brd, pc_coords.row, pc_coords.col)) & PC_MOVED)
    return;

  new_coords.row = pc_coords.row;
  if((side)
     ? !memcmp(brd->tiles[0], castle_left_black, 5)
     : !memcmp(brd->tiles[7], castle_left_white, 5))
  {
    new_coords.col = pc_coords.col-1;
    if(!king_threatened(brd, &new_coords, pc_coords))
    {
      new_coords.col--;
      add_move_to_list(brd, pc_coords, &new_coords, retval, count, new_coords.col, new_coords.row);
    }
  }

  if((side)
     ? !memcmp(&brd->tiles[0][4], castle_right_black, 4)
     : !memcmp(&brd->tiles[7][4], castle_right_white, 4))
  {
    new_coords.col = pc_coords.col+1;
    if(!king_threatened(brd, &new_coords, pc_coords))
    {
      new_coords.col++;
      add_move_to_list(brd, pc_coords, &new_coords, retval, count, new_coords.col, new_coords.row);
    }
  }
}

void legal_moves_knight(struct board *brd, struct coord pc_coords, unsigned char *count,
                        struct coord *king_pos, struct coord *retval)
{
  signed char newrow, newcol;
  unsigned char piece;
  unsigned char side = piece_in_tile(brd, pc_coords.row, pc_coords.col) & PC_BLACK;

  newrow = pc_coords.row - 1;
  if(newrow >= 0)
  {
    newcol = pc_coords.col - 2;
    if(newcol >= 0
       && (!(piece = tile_occupied(brd, newrow, newcol))
           || ((piece & PC_BLACK)
               ^ (side))))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

    newcol += 4;
    if(newcol < 8
       && (!(piece = tile_occupied(brd, newrow, newcol))
           || ((piece & PC_BLACK)
               ^ (side))))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

    newrow--;
    if(newrow >= 0)
    {
      newcol = pc_coords.col - 1;
      if(newcol >= 0
         && (!(piece = tile_occupied(brd, newrow, newcol))
             || ((piece & PC_BLACK)
                 ^ (side))))
        add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

      newcol += 2;
      if(newcol < 8
         && (!(piece = tile_occupied(brd, newrow, newcol))
             || ((piece & PC_BLACK)
                 ^ (side))))
        add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);
    }
  }

  newrow = pc_coords.row + 1;
  if(newrow < 8)
  {
    newcol = pc_coords.col - 2;
        if(newcol >= 0
       && (!(piece = tile_occupied(brd, newrow, newcol))
           || ((piece & PC_BLACK)
               ^ (side))))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

    newcol += 4;
    if(newcol < 8
       && (!(piece = tile_occupied(brd, newrow, newcol))
           || ((piece & PC_BLACK)
               ^ (side))))
      add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

    newrow++;
    if(newrow < 8)
    {
      newcol = pc_coords.col - 1;
      if(newcol >= 0
         && (!(piece = tile_occupied(brd, newrow, newcol))
             || ((piece & PC_BLACK)
                 ^ (side))))
        add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);

      newcol += 2;
      if(newcol < 8
         && (!(piece = tile_occupied(brd, newrow, newcol))
             || ((piece & PC_BLACK)
                 ^ (side))))
        add_move_to_list(brd, pc_coords, king_pos, retval, count, newcol, newrow);
    }
  }
}

struct coord *legal_moves(struct board *brd, struct coord pc_coords, unsigned char *count, struct coord *king_pos)
{
  unsigned char newrow;
  struct coord *retval;
  unsigned char *piece = ptr_to_tile(brd, pc_coords.row, pc_coords.col);
  unsigned char piece2;
  void *ptr;

  *count = 0;

  switch((*piece & 0x7))
  {
    case PC_PAWN_UNMOVED: case PC_PAWN_MOVED:
      retval = calloc(4, sizeof(struct coord));
      if(!retval) return 0;

      if((*piece & 0x7) == PC_PAWN_MOVED)
        goto pawn;

      newrow = pc_coords.row + (*piece & PC_BLACK ? 2 : -2);

      if(!tile_occupied(brd, (newrow + (*piece & PC_BLACK ? -1 : 1)), pc_coords.col)
         && !tile_occupied(brd, newrow, pc_coords.col))
      {
        add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col, newrow);
      }

      pawn:
      newrow = pc_coords.row + (*piece & PC_BLACK ? 1 : -1);

      if(!tile_occupied(brd, newrow, pc_coords.col))
      {
        add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col, newrow);
      }

      if(pc_coords.col &&
          (((piece2 = tile_occupied(brd, newrow, pc_coords.col - 1))
           && (piece2 & PC_BLACK) ^ (*piece & PC_BLACK))
          || ((piece2 = tile_occupied(brd, pc_coords.row, pc_coords.col - 1))
              && (piece2 & PC_BLACK) ^ (*piece & PC_BLACK) && (piece2 & PC_PAWN_ENPASS))))
      {
        add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col - 1, newrow);
      }

      if(pc_coords.col < 7 &&
          (((piece2 = tile_occupied(brd, newrow, pc_coords.col + 1))
           && (piece2 & PC_BLACK) ^ (*piece & PC_BLACK))
          || ((piece2 = tile_occupied(brd, pc_coords.row, pc_coords.col + 1))
              && (piece2 & PC_BLACK) ^ (*piece & PC_BLACK) && (piece2 & PC_PAWN_ENPASS))))
      {
        add_move_to_list(brd, pc_coords, king_pos, retval, count, pc_coords.col + 1, newrow);
      }
      break;
    case PC_ROOK:
      retval = calloc(7+7, sizeof(struct coord));
      if(!retval) return 0;
      legal_moves_rook(brd, pc_coords, count, king_pos, retval);
      break;
    case PC_KNIGHT:
      retval = calloc(8, sizeof(struct coord));
      if(!retval) return 0;
      legal_moves_knight(brd, pc_coords, count, king_pos, retval);
      break;
    case PC_BISHOP:
      retval = calloc(7+6, sizeof(struct coord));
      if(!retval) return 0;
      legal_moves_bishop(brd, pc_coords, count, king_pos, retval);
      break;
    case PC_QUEEN:
      retval = calloc(7+7+7+6, sizeof(struct coord));
      if(!retval) return 0;
      legal_moves_rook(brd, pc_coords, count, king_pos, retval);
      legal_moves_bishop(brd, pc_coords, count, king_pos, retval);
      break;
    case PC_KING:
      retval = calloc(8, sizeof(struct coord));
      if(!retval) return 0;
      legal_moves_king(brd, pc_coords, count, retval);
      break;
  }
  if(!*count)
    free(retval);
  else
  {
    ptr = realloc(retval, *count*sizeof(struct coord));
    if(ptr)
      retval = ptr;
  }

  return retval;
}
