// File: ATOMIC-LICHESS[P]ATOMKRAFT/position.cpp
// Function: Position::pl_move_is_legal(Move, unsigned long) const
bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
  STARTNEW
  // any move is illegal if a king exploded
  if (piece_count(WHITE, KING) == 0 || piece_count(BLACK, KING) == 0) {
	  return false;
  }
  ENDNEW
  
  assert(is_ok());
  assert(move_is_ok(m));
  assert(pinned == pinned_pieces(side_to_move()));

  // Castling moves are checked for legality during move generation.
  if (move_is_castle(m))
      return true;
  
  
  STARTNEW
  // As en passant, capture moves are tricky as well...
  // we handle these as in Position::move_gives_check
  Square to = move_to(m);
  int is_capture = type_of_piece_on(to) || move_is_ep(m);
  
  if (is_capture) {	// is capture move?
	  Color us = side_to_move();
	  Color them = opposite_color(us);
	  Square from = move_from(m);
	  assert(piece_count(us, KING));
	  Square ksq = king_square(us);
	  Bitboard b = occupied_squares();
	  
	  // a capture is always legal if it explodes the opponent king
	  // except it explodes our own king as well, then it is always illegal
	  assert(piece_count(them, KING));
	  if (squares_touch[ksq][to]) return false;
	  if (squares_touch[king_square(them)][to]) return true;
	  
	  // get pawns which don't explode
	  Bitboard notexpl_pawns_bb = pieces(PAWN);
	  clear_bit(&notexpl_pawns_bb, from);	// the from-pawn always explodes
	  
	  if (move_is_ep(m)) {
		  // the captured en passant piece explodes
		  clear_bit(&notexpl_pawns_bb, make_square(square_file(to), square_rank(from)));
	  } else {
		  clear_bit(&notexpl_pawns_bb, to);	// the to-pawn explodes
	  }
	  
	  clear_bit(&b, from);		// clear the from bit
	  b &= ~explBB[to];			// clear all bits which are involved in the capture/explosion
	  b |= notexpl_pawns_bb;	// and restore pawns
	  
	  
	  //DEBUG
//	  cout << "------------------" << endl << endl;
//	  cout << move_to_uci(m, 0) << endl;
//	  print_bb(b);
//	  print_bb(rook_attacks_bb(ksq, b));
//	  print_bb(pieces(ROOK, QUEEN, them));
//	  print_bb(bishop_attacks_bb(ksq, b));
//	  print_bb(pieces(BISHOP, QUEEN, them));
	  //ENDDEBUG
	  
	  // test if opponent pieces now give check
      return  !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them) & b)
            && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them) & b);
  }
  ENDNEW
  
  
  NEW // this is a special case of the new code above
  STARTOLD
  // En passant captures are a tricky special case. Because they are
  // rather uncommon, we do it simply by testing whether the king is attacked
  // after the move is made
  if (move_is_ep(m))
  {
      Color us = side_to_move();
      Color them = opposite_color(us);
      Square from = move_from(m);
      Square to = move_to(m);
      Square capsq = make_square(square_file(to), square_rank(from));
      Square ksq = king_square(us);
      Bitboard b = occupied_squares();

      assert(to == ep_square());
      assert(piece_on(from) == make_piece(us, PAWN));
      assert(piece_on(capsq) == make_piece(them, PAWN));
      assert(piece_on(to) == PIECE_NONE);

      clear_bit(&b, from);
      clear_bit(&b, capsq);
      set_bit(&b, to);

      return   !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
            && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
  }
  ENDOLD
  

  Color us = side_to_move();
  Square from = move_from(m);
  
  STARTNEW
#ifndef NDEBUG
  if (color_of_piece_on(from) != us) {
	  cout << "from: " << from << endl;
	  cout << "to: " << move_to(m) << endl;
	  cout << "us: " << us << endl;
	  print_debuginfo(*this);
  }
#endif
  ENDNEW
  
  assert(color_of_piece_on(from) == us);
  NEW assert(piece_count(us, KING));
  assert(piece_on(king_square(us)) == make_piece(us, KING));

  // If the moving piece is a king, check whether the destination
  // square is attacked by the opponent.
  if (type_of_piece_on(from) == KING) {
      OLD return !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us)));
      
      
      
      STARTNEW
      Square to = move_to(m);
      
      // sort out capture moves by the king
      if (type_of_piece_on(to)) 
    	  return false;
      
      
      assert(piece_count(opposite_color(us), KING));
      Square opp_ksq = king_square(opposite_color(us));
	  // if both kings directly face each other after the move it is always legal
	  if (squares_touch[to][opp_ksq]) {
		  return true;
	  }
      
	  
      // this is replacing the old code
	  // first we need to update the king in occupied squares
	  // since it may be possible (e.g. kings adjacent) for a king to move along 
	  // an x-ray of an opponent sliding piece and we couldn't detect it
	  Bitboard occ = occupied_squares();
	  do_move_bb(&occ, make_move_bb(from, to));
	  
      Bitboard attackers_to_bb = 
    		    (attacks_from<PAWN>(to, BLACK) & pieces(PAWN, WHITE))	// this is exactly
              | (attacks_from<PAWN>(to, WHITE) & pieces(PAWN, BLACK))	// what attackers_to()
              | (attacks_from<KNIGHT>(to)      & pieces(KNIGHT))		// produces except
              | (rook_attacks_bb(to, occ)      & pieces(ROOK, QUEEN))	// ORing the king-
              | (bishop_attacks_bb(to, occ)    & pieces(BISHOP, QUEEN));// bitboard
      
      return !(attackers_to_bb & pieces_of_color(opposite_color(us)));
      ENDNEW
  }

  // A non-king move is legal if and only if it is not pinned or it
  // is moving along the ray towards or away from the king.
  NEW assert(piece_count(us, KING));
  return   !pinned
        || !bit_is_set(pinned, from)
        ||  squares_aligned(from, move_to(m), king_square(us));
}

// Assembly:
subq $0xf8, %rsp
movq %rdi, 0xe8(%rsp)
movl %esi, 0xe4(%rsp)
movq %rdx, 0xd8(%rsp)
movq 0xe8(%rsp), %rdi
movq %rdi, 0x88(%rsp)
xorl %esi, %esi
movl $0x6, %edx
callq 0x164c0
cmpl $0x0, %eax
je 0x38edb
movq 0x88(%rsp), %rdi
movl $0x1, %esi
movl $0x6, %edx
callq 0x164c0
cmpl $0x0, %eax
jne 0x38ee8
movb $0x0, 0xf7(%rsp)
jmp 0x39526
movl 0xe4(%rsp), %edi
callq 0x12970
cmpl $0x0, %eax
je 0x38f06
movb $0x1, 0xf7(%rsp)
jmp 0x39526
movl 0xe4(%rsp), %edi
callq 0xf690
movq 0x88(%rsp), %rdi
movl %eax, 0xd4(%rsp)
movl 0xd4(%rsp), %esi
callq 0x11f10
movl %eax, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, 0x87(%rsp)
jne 0x38f56
movl 0xe4(%rsp), %edi
callq 0x2e360
cmpl $0x0, %eax
setne %al
movb %al, 0x87(%rsp)
movb 0x87(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0xd0(%rsp)
cmpl $0x0, 0xd0(%rsp)
je 0x391f2
movq 0x88(%rsp), %rdi
callq 0xf5d0
movl %eax, 0xcc(%rsp)
movl 0xcc(%rsp), %edi
callq 0x122b0
movl %eax, 0xc8(%rsp)
movl 0xe4(%rsp), %edi
callq 0xf680
movq 0x88(%rsp), %rdi
movl %eax, 0xc4(%rsp)
movl 0xcc(%rsp), %esi
callq 0x1b250
movq 0x88(%rsp), %rdi
movl %eax, 0xc0(%rsp)
callq 0xf510
movq %rax, 0xb8(%rsp)
movslq 0xc0(%rsp), %rcx
leaq 0x348b0(%rip), %rax     # 0x6d8a0
shlq $0x6, %rcx
addq %rcx, %rax
movslq 0xd4(%rsp), %rcx
cmpb $0x0, (%rax,%rcx)
je 0x39012
movb $0x0, 0xf7(%rsp)
jmp 0x39526
movq 0x88(%rsp), %rdi
movl 0xc8(%rsp), %esi
callq 0x1b250
movslq %eax, %rcx
leaq 0x34870(%rip), %rax     # 0x6d8a0
shlq $0x6, %rcx
addq %rcx, %rax
movslq 0xd4(%rsp), %rcx
cmpb $0x0, (%rax,%rcx)
je 0x39052
movb $0x1, 0xf7(%rsp)
jmp 0x39526
movq 0x88(%rsp), %rdi
movl $0x1, %esi
callq 0x33a70
movq %rax, 0xb0(%rsp)
movl 0xc4(%rsp), %esi
leaq 0xb0(%rsp), %rdi
callq 0x29eb0
movl 0xe4(%rsp), %edi
callq 0x2e360
cmpl $0x0, %eax
je 0x390cf
movl 0xd4(%rsp), %edi
callq 0xce10
movl %eax, 0x80(%rsp)
movl 0xc4(%rsp), %edi
callq 0xce40
movl 0x80(%rsp), %edi
movl %eax, %esi
callq 0xd740
movl %eax, %esi
leaq 0xb0(%rsp), %rdi
callq 0x29eb0
jmp 0x390e3
movl 0xd4(%rsp), %esi
leaq 0xb0(%rsp), %rdi
callq 0x29eb0
movl 0xc4(%rsp), %esi
leaq 0xb8(%rsp), %rdi
callq 0x29eb0
movslq 0xd4(%rsp), %rcx
leaq 0x21dca(%rip), %rax     # 0x5aed0
movq (%rax,%rcx,8), %rax
xorq $-0x1, %rax
andq 0xb8(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xb0(%rsp), %rax
orq 0xb8(%rsp), %rax
movq %rax, 0xb8(%rsp)
movl 0xc0(%rsp), %edi
movq 0xb8(%rsp), %rsi
callq 0xe8c0
movq 0x88(%rsp), %rdi
movq %rax, 0x70(%rsp)
movl 0xc8(%rsp), %ecx
movl $0x4, %esi
movl $0x5, %edx
callq 0x29b80
movq 0x70(%rsp), %rcx
andq %rax, %rcx
andq 0xb8(%rsp), %rcx
xorl %eax, %eax
cmpq $0x0, %rcx
movb %al, 0x7f(%rsp)
jne 0x391e0
movl 0xc0(%rsp), %edi
movq 0xb8(%rsp), %rsi
callq 0xe820
movq 0x88(%rsp), %rdi
movq %rax, 0x68(%rsp)
movl 0xc8(%rsp), %ecx
movl $0x3, %esi
movl $0x5, %edx
callq 0x29b80
movq %rax, %rcx
movq 0x68(%rsp), %rax
andq %rcx, %rax
andq 0xb8(%rsp), %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
movb %al, 0x7f(%rsp)
movb 0x7f(%rsp), %al
andb $0x1, %al
movb %al, 0xf7(%rsp)
jmp 0x39526
movq 0x88(%rsp), %rdi
callq 0xf5d0
movl %eax, 0xac(%rsp)
movl 0xe4(%rsp), %edi
callq 0xf680
movq 0x88(%rsp), %rdi
movl %eax, 0xa8(%rsp)
movl 0xa8(%rsp), %esi
callq 0x11f10
cmpl $0x6, %eax
jne 0x394a3
movl 0xe4(%rsp), %edi
callq 0xf690
movq 0x88(%rsp), %rdi
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %esi
callq 0x11f10
cmpl $0x0, %eax
je 0x3926f
movb $0x0, 0xf7(%rsp)
jmp 0x39526
movl 0xac(%rsp), %edi
callq 0x122b0
movq 0x88(%rsp), %rdi
movl %eax, %esi
callq 0x1b250
movl %eax, 0xa0(%rsp)
movslq 0xa4(%rsp), %rcx
leaq 0x34600(%rip), %rax     # 0x6d8a0
shlq $0x6, %rcx
addq %rcx, %rax
movslq 0xa0(%rsp), %rcx
cmpb $0x0, (%rax,%rcx)
je 0x392c2
movb $0x1, 0xf7(%rsp)
jmp 0x39526
movq 0x88(%rsp), %rdi
callq 0xf510
movq %rax, 0x98(%rsp)
movl 0xa8(%rsp), %edi
movl 0xa4(%rsp), %esi
callq 0x3e630
movq %rax, %rsi
leaq 0x98(%rsp), %rdi
callq 0x3e610
movq 0x88(%rsp), %rdi
movl 0xa4(%rsp), %esi
movl $0x1, %edx
callq 0x1b460
movq 0x88(%rsp), %rdi
movq %rax, 0x18(%rsp)
movl $0x1, %esi
xorl %edx, %edx
callq 0x16530
movq 0x88(%rsp), %rdi
movq %rax, %rcx
movq 0x18(%rsp), %rax
andq %rcx, %rax
movq %rax, 0x28(%rsp)
movl 0xa4(%rsp), %esi
xorl %edx, %edx
callq 0x1b460
movq 0x88(%rsp), %rdi
movq %rax, 0x20(%rsp)
movl $0x1, %edx
movl %edx, %esi
callq 0x16530
movq 0x20(%rsp), %rcx
movq 0x88(%rsp), %rdi
movq %rax, %rdx
movq 0x28(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x38(%rsp)
movl 0xa4(%rsp), %esi
callq 0x29aa0
movq 0x88(%rsp), %rdi
movq %rax, 0x30(%rsp)
movl $0x2, %esi
callq 0x33a70
movq 0x30(%rsp), %rcx
movq %rax, %rdx
movq 0x38(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x48(%rsp)
movl 0xa4(%rsp), %edi
movq 0x98(%rsp), %rsi
callq 0xe8c0
movq 0x88(%rsp), %rdi
movq %rax, 0x40(%rsp)
movl $0x4, %esi
movl $0x5, %edx
callq 0x33a90
movq 0x40(%rsp), %rcx
movq %rax, %rdx
movq 0x48(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x58(%rsp)
movl 0xa4(%rsp), %edi
movq 0x98(%rsp), %rsi
callq 0xe820
movq 0x88(%rsp), %rdi
movq %rax, 0x50(%rsp)
movl $0x3, %esi
movl $0x5, %edx
callq 0x33a90
movq 0x50(%rsp), %rcx
movq %rax, %rdx
movq 0x58(%rsp), %rax
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x60(%rsp)
movl 0xac(%rsp), %edi
callq 0x122b0
movq 0x88(%rsp), %rdi
movl %eax, %esi
callq 0x298c0
movq %rax, %rcx
movq 0x60(%rsp), %rax
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0xf7(%rsp)
jmp 0x39526
movb $0x1, %al
cmpq $0x0, 0xd8(%rsp)
movb %al, 0x17(%rsp)
je 0x39519
movq 0xd8(%rsp), %rdi
movl 0xa8(%rsp), %esi
callq 0xd760
movq %rax, %rcx
movb $0x1, %al
cmpq $0x0, %rcx
movb %al, 0x17(%rsp)
je 0x39519
movl 0xa8(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0xe4(%rsp), %edi
callq 0xf690
movq 0x88(%rsp), %rdi
movl %eax, 0x10(%rsp)
movl 0xac(%rsp), %esi
callq 0x1b250
movl 0xc(%rsp), %edi
movl 0x10(%rsp), %esi
movl %eax, %edx
callq 0x3e660
movb %al, 0x17(%rsp)
movb 0x17(%rsp), %al
andb $0x1, %al
movb %al, 0xf7(%rsp)
movb 0xf7(%rsp), %al
andb $0x1, %al
addq $0xf8, %rsp
retq
nopw (%rax,%rax)