// File: /workspace/github_cpp_makefile_star2_O1/ATOMIC-LICHESS[P]ATOMKRAFT/position.cpp
// Function: Position::move_is_legal(Move, unsigned long) const
bool Position::move_is_legal(const Move m, Bitboard pinned) const {
  assert(is_ok());
  assert(pinned == pinned_pieces(sideToMove));
  NEW // don't test that since it might be a tested tt
  //NEW assert(color_of_piece_on(move_from(m)) != COLOR_NONE);

  Color us = sideToMove;
  Color them = opposite_color(sideToMove);
  Square from = move_from(m);
  Square to = move_to(m);
  Piece pc = piece_on(from);

  // Use a slower but simpler function for uncommon cases
  if (move_is_special(m))
      return move_is_legal(m);

  // If the from square is not occupied by a piece belonging to the side to
  // move, the move is obviously not legal.
  if (color_of_piece(pc) != us)
      return false;

  // The destination square cannot be occupied by a friendly piece
  if (color_of_piece_on(to) == us)
      return false;

  // Handle the special case of a pawn move
  if (type_of_piece(pc) == PAWN)
  {
      // Move direction must be compatible with pawn color
      int direction = to - from;
      if ((us == WHITE) != (direction > 0))
          return false;

      // We have already handled promotion moves, so destination
      // cannot be on the 8/1th rank.
      OLD if (square_rank(to) == RANK_8 || square_rank(to) == RANK_1) return false;
      
      STARTNEW
      // capture moves of pawns to the relative 8th rank are no longer special
      if ((square_rank(to) == RANK_8 || square_rank(to) == RANK_1) && color_of_piece_on(to) != them)
    	  return false;
      ENDNEW

      // Proceed according to the square delta between the origin and
      // destination squares.
      switch (direction)
      {
      case DELTA_NW:
      case DELTA_NE:
      case DELTA_SW:
      case DELTA_SE:
      // Capture. The destination square must be occupied by an enemy
      // piece (en passant captures was handled earlier).
          if (color_of_piece_on(to) != them)
              return false;
          break;

      case DELTA_N:
      case DELTA_S:
      // Pawn push. The destination square must be empty.
          if (!square_is_empty(to))
              return false;
          break;

      case DELTA_NN:
      // Double white pawn push. The destination square must be on the fourth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
      if (   square_rank(to) != RANK_4
          || !square_is_empty(to)
          || !square_is_empty(from + DELTA_N))
          return false;
          break;

      case DELTA_SS:
      // Double black pawn push. The destination square must be on the fifth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
          if (   square_rank(to) != RANK_5
              || !square_is_empty(to)
              || !square_is_empty(from + DELTA_S))
              return false;
          break;

      default:
          return false;
      }
  }
  else if (!bit_is_set(attacks_from(pc, from), to))
      return false;

  STARTOLD
  // The move is pseudo-legal, check if it is also legal
  return in_check() ? pl_move_is_evasion(m, pinned) : pl_move_is_legal(m, pinned);
  ENDOLD
  
  STARTNEW
  // The move is pseudo-legal, check if it is also legal
  // legal capture moves are not recognized by pl_move_is_evasion
  // king moves to opponent king as an evasion are recognized by pl_move_is_evasion
  // since it calls pl_move_is_legal if king moves
  // TODO: adjust pl_move_is_evasion, the way we do it here is slow
  if (type_of_piece_on(to) == PIECE_TYPE_NONE) {
	  // non capture move
	  return in_check() ? pl_move_is_evasion(m, pinned) : pl_move_is_legal(m, pinned);
  } else {
	  // capture move
	  return pl_move_is_legal(m, pinned);
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movl %esi, %ebp
movq %rdi, %r14
testl $0xc000, %esi           # imm = 0xC000
je 0x1e841
movq %r14, %rdi
movl %ebp, %esi
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x1e7c0
movq %rdx, %rbx
movl 0x1090(%r14), %eax
movl %ebp, %edx
shrl $0x6, %edx
andl $0x3f, %edx
movl (%r14,%rdx,4), %esi
movl %esi, %ecx
sarl $0x3, %ecx
cmpl %eax, %ecx
jne 0x1e876
movl %ebp, %ecx
andl $0x3f, %ecx
movl %ecx, %r12d
movl (%r14,%r12,4), %r15d
movl %r15d, %edi
sarl $0x3, %edi
cmpl %eax, %edi
jne 0x1e881
xorl %eax, %eax
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movl %esi, %r8d
andl $0x7, %r8d
cmpl $0x1, %r8d
jne 0x1e8f3
testl %eax, %eax
sete %r8b
movl %ecx, %esi
subl %edx, %esi
setle %r9b
cmpb %r8b, %r9b
je 0x1e876
xorl $0x1, %eax
shrl $0x3, %ecx
cmpl $0x7, %ecx
je 0x1e8b0
testl %ecx, %ecx
jne 0x1e8b4
cmpl %eax, %edi
jne 0x1e876
leal 0x10(%rsi), %r8d
cmpl $0x9, %r8d
jbe 0x1e94a
addl $-0x7, %esi
cmpl $0x9, %esi
ja 0x1e876
leaq 0x133b7(%rip), %r8      # 0x31c88
movslq (%r8,%rsi,4), %rsi
addq %r8, %rsi
jmpq *%rsi
xorl $0x3, %ecx
movl %r15d, %eax
xorl $0x10, %eax
orl %ecx, %eax
jne 0x1e876
movl %edx, %eax
cmpl $0x10, 0x20(%r14,%rax,4)
jne 0x1e876
jmp 0x1e90c
movq %r14, %rdi
callq 0x1df92
leaq 0xf989e(%rip), %rcx     # 0x1181a0
testq %rax, (%rcx,%r12,8)
je 0x1e876
testb $0x7, %r15b
je 0x1e927
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x1e44a
movq 0x1938(%r14), %rax
cmpq $0x0, 0x40(%rax)
je 0x1e912
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x1e6e8
leaq 0x1330f(%rip), %rsi     # 0x31c60
movslq (%rsi,%r8,4), %r8
addq %rsi, %r8
jmpq *%r8
cmpl %eax, %edi
jne 0x1e876
jmp 0x1e90c
cmpl $0x10, %r15d
jne 0x1e876
jmp 0x1e90c
xorl $0x4, %ecx
movl %r15d, %eax
xorl $0x10, %eax
orl %ecx, %eax
jne 0x1e876
movl %edx, %eax
cmpl $0x10, -0x20(%r14,%rax,4)
jne 0x1e876
jmp 0x1e90c
nop