// File: /workspace/github_cpp_makefile_star2_O2/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 %rbx
pushq %rax
movl %esi, %ebp
movq %rdi, %r14
testw $0xc000, %bp            # imm = 0xC000
je 0x18bbd
movq %r14, %rdi
movl %ebp, %esi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x18b3c
movq %rdx, %rbx
movl 0x1090(%r14), %ecx
movl %ebp, %edx
shrl $0x6, %edx
andl $0x3f, %edx
movl (%r14,%rdx,4), %esi
movl %esi, %eax
sarl $0x3, %eax
cmpl %ecx, %eax
jne 0x18bf4
movl %ebp, %edi
andl $0x3f, %edi
movl %edi, %r15d
movl (%r14,%r15,4), %eax
movl %eax, %r8d
sarl $0x3, %r8d
cmpl %ecx, %r8d
jne 0x18c01
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movl %esi, %r9d
andl $0x7, %r9d
cmpl $0x1, %r9d
jne 0x18c71
testl %ecx, %ecx
sete %r9b
movl %edi, %esi
subl %edx, %esi
setle %r10b
cmpb %r9b, %r10b
je 0x18bf4
xorl $0x1, %ecx
shrl $0x3, %edi
cmpl $0x7, %edi
je 0x18c30
testl %edi, %edi
jne 0x18c35
cmpl %ecx, %r8d
jne 0x18bf4
leal 0x10(%rsi), %r9d
cmpl $0x9, %r9d
jbe 0x18cce
addl $-0x7, %esi
cmpl $0x9, %esi
ja 0x18bf4
leaq 0x10e76(%rip), %r9      # 0x29ac8
movslq (%r9,%rsi,4), %rsi
addq %r9, %rsi
jmpq *%rsi
xorl $0x3, %edi
xorl $0x10, %eax
orl %edi, %eax
jne 0x18bf4
movl %edx, %eax
cmpl $0x10, 0x20(%r14,%rax,4)
jne 0x18bf4
jmp 0x18c92
movq %r14, %rdi
callq 0x18638
leaq 0xf8520(%rip), %rcx     # 0x1111a0
testq %rax, (%rcx,%r15,8)
je 0x18bf4
movl (%r14,%r15,4), %eax
testb $0x7, %al
jne 0x18cb7
movq 0x1938(%r14), %rax
cmpq $0x0, 0x40(%rax)
je 0x18cb7
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x18a64
movq %r14, %rdi
movl %ebp, %esi
movq %rbx, %rdx
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x187c6
leaq 0x10dcb(%rip), %rsi     # 0x29aa0
movslq (%rsi,%r9,4), %r9
addq %rsi, %r9
jmpq *%r9
cmpl %ecx, %r8d
jne 0x18bf4
jmp 0x18c8e
cmpl $0x10, %eax
jne 0x18bf4
jmp 0x18c92
xorl $0x4, %edi
xorl $0x10, %eax
orl %edi, %eax
jne 0x18bf4
movl %edx, %eax
cmpl $0x10, -0x20(%r14,%rax,4)
jne 0x18bf4
jmp 0x18c92