// File: ATOMIC-LICHESS[P]ATOMKRAFT/position.cpp
// Function: Position::see(Square, Square) const
int Position::see(Square from, Square to) const {

  assert(square_is_ok(from));
  assert(square_is_ok(to));
  
  STARTNEW
  // there are no capture sequences in atomic chess
  // we just sum up the total material gain/loss
  
  // TODO: en passant? (type_of_piece_on(to) == PIECE_TYPE_NONE)
  
  if (!type_of_piece_on(from) || !type_of_piece_on(to)) {
	  return 0;
  }
  
  int score = midgame_value_of_piece_on(to) - midgame_value_of_piece_on(from);
  Color us = side_to_move();
  Color them = opposite_color(us);
  
  for (int k = 1; k < explSq[to].size; ++k) {
	  if (type_of_piece_on(explSq[to].square[k]) != PAWN) {
		  if (color_of_piece_on(explSq[to].square[k]) == us) {
			  score -= midgame_value_of_piece_on(explSq[to].square[k]);
		  } else if (color_of_piece_on(explSq[to].square[k]) == them) {
			  score += midgame_value_of_piece_on(explSq[to].square[k]);
		  }
		  
		  // bonus if we can explode king
		  if (type_of_piece_on(explSq[to].square[k]) == KING) {
			  if (color_of_piece_on(explSq[to].square[k]) == us) {
				  return -25000;	// immediate return if we would capture own king
			  } else if (color_of_piece_on(explSq[to].square[k]) == them) {
				  score += 25000;
			  }
		  }
  	  }
  }
  
  // add MinorPiecePawnValueDiff so minorpiece-pawn captures have see 0?
  return score;
  ENDNEW
  
  Bitboard occupied, attackers, stmAttackers, b;
  int swapList[32], slIndex = 1;
  PieceType capturedType, pt;
  Color stm;



  capturedType = type_of_piece_on(to);

  // King cannot be recaptured
  if (capturedType == KING)
      return seeValues[capturedType];

  occupied = occupied_squares();

  // Handle en passant moves
  if (st->epSquare == to && type_of_piece_on(from) == PAWN)
  {
      Square capQq = (side_to_move() == WHITE ? to - DELTA_N : to - DELTA_S);

      assert(capturedType == PIECE_TYPE_NONE);
      assert(type_of_piece_on(capQq) == PAWN);

      // Remove the captured pawn
      clear_bit(&occupied, capQq);
      capturedType = PAWN;
  }

  // Find all attackers to the destination square, with the moving piece
  // removed, but possibly an X-ray attacker added behind it.
  clear_bit(&occupied, from);
  attackers =  (rook_attacks_bb(to, occupied)  & pieces(ROOK, QUEEN))
             | (bishop_attacks_bb(to, occupied)& pieces(BISHOP, QUEEN))
             | (attacks_from<KNIGHT>(to)       & pieces(KNIGHT))
             | (attacks_from<KING>(to)         & pieces(KING))
             | (attacks_from<PAWN>(to, WHITE)  & pieces(PAWN, BLACK))
             | (attacks_from<PAWN>(to, BLACK)  & pieces(PAWN, WHITE));

  // If the opponent has no attackers we are finished
  stm = opposite_color(color_of_piece_on(from));
  stmAttackers = attackers & pieces_of_color(stm);
  if (!stmAttackers)
      return seeValues[capturedType];

  // The destination square is defended, which makes things rather more
  // difficult to compute. We proceed by building up a "swap list" containing
  // the material gain or loss at each stop in a sequence of captures to the
  // destination square, where the sides alternately capture, and always
  // capture with the least valuable piece. After each capture, we look for
  // new X-ray attacks from behind the capturing piece.
  swapList[0] = seeValues[capturedType];
  capturedType = type_of_piece_on(from);

  do {
      // Locate the least valuable attacker for the side to move. The loop
      // below looks like it is potentially infinite, but it isn't. We know
      // that the side to move still has at least one attacker left.
      for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
          assert(pt < KING);

      // Remove the attacker we just found from the 'occupied' bitboard,
      // and scan for new X-ray attacks behind the attacker.
      b = stmAttackers & pieces(pt);
      occupied ^= (b & (~b + 1));
      attackers |=  (rook_attacks_bb(to, occupied)   & pieces(ROOK, QUEEN))
                  | (bishop_attacks_bb(to, occupied) & pieces(BISHOP, QUEEN));

      attackers &= occupied; // Cut out pieces we've already done

      // Add the new entry to the swap list
      assert(slIndex < 32);
      swapList[slIndex] = -swapList[slIndex - 1] + seeValues[capturedType];
      slIndex++;

      // Remember the value of the capturing piece, and change the side to
      // move before beginning the next iteration.
      capturedType = pt;
      stm = opposite_color(stm);
      stmAttackers = attackers & pieces_of_color(stm);

      // Stop before processing a king capture
      if (capturedType == KING && stmAttackers)
      {
          assert(slIndex < 32);
          swapList[slIndex++] = QueenValueMidgame*10;
          break;
      }
  } while (stmAttackers);

  // Having built the swap list, we negamax through it to find the best
  // achievable score from the point of view of the side to move.
  while (--slIndex)
      swapList[slIndex-1] = Min(-swapList[slIndex], swapList[slIndex-1]);

  return swapList[0];
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movl %esi, 0xd4(%rsp)
movl %edx, 0xd0(%rsp)
movq 0xd8(%rsp), %rdi
movq %rdi, 0x8(%rsp)
movl 0xd4(%rsp), %esi
callq 0x11f10
cmpl $0x0, %eax
je 0x3d1c1
movq 0x8(%rsp), %rdi
movl 0xd0(%rsp), %esi
callq 0x11f10
cmpl $0x0, %eax
jne 0x3d1d1
movl $0x0, 0xe4(%rsp)
jmp 0x3d45c
movq 0x8(%rsp), %rdi
movl 0xd0(%rsp), %esi
callq 0x347f0
movq 0x8(%rsp), %rdi
movl %eax, 0x4(%rsp)
movl 0xd4(%rsp), %esi
callq 0x347f0
movl 0x4(%rsp), %edi
movl %eax, %esi
callq 0x1b300
movq 0x8(%rsp), %rdi
movl %eax, 0xcc(%rsp)
callq 0xf5d0
movl %eax, 0xc8(%rsp)
movl 0xc8(%rsp), %edi
callq 0x122b0
movl %eax, 0xc4(%rsp)
movl $0x1, 0xc0(%rsp)
movl 0xc0(%rsp), %eax
movslq 0xd0(%rsp), %rdx
leaq 0x2f352(%rip), %rcx     # 0x6c5a0
imulq $0x4c, %rdx, %rdx
addq %rdx, %rcx
cmpl 0x48(%rcx), %eax
jge 0x3d44e
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f32e(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x11f10
cmpl $0x1, %eax
je 0x3d436
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f2fa(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x3df80
cmpl 0xc8(%rsp), %eax
jne 0x3d305
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f2c6(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x347f0
movl %eax, %ecx
movl 0xcc(%rsp), %eax
subl %ecx, %eax
movl %eax, 0xcc(%rsp)
jmp 0x3d374
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f287(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x3df80
cmpl 0xc4(%rsp), %eax
jne 0x3d372
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f253(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x347f0
addl 0xcc(%rsp), %eax
movl %eax, 0xcc(%rsp)
jmp 0x3d374
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f218(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x11f10
cmpl $0x6, %eax
jne 0x3d434
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f1e4(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x3df80
cmpl 0xc8(%rsp), %eax
jne 0x3d3e9
movl $0xffff9e58, 0xe4(%rsp) # imm = 0xFFFF9E58
jmp 0x3d45c
movq 0x8(%rsp), %rdi
movslq 0xd0(%rsp), %rcx
leaq 0x2f1a3(%rip), %rax     # 0x6c5a0
imulq $0x4c, %rcx, %rcx
addq %rcx, %rax
movslq 0xc0(%rsp), %rcx
movl (%rax,%rcx,4), %esi
callq 0x3df80
cmpl 0xc4(%rsp), %eax
jne 0x3d430
movl 0xcc(%rsp), %eax
addl $0x61a8, %eax           # imm = 0x61A8
movl %eax, 0xcc(%rsp)
jmp 0x3d432
jmp 0x3d434
jmp 0x3d436
jmp 0x3d438
movl 0xc0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc0(%rsp)
jmp 0x3d238
movl 0xcc(%rsp), %eax
movl %eax, 0xe4(%rsp)
movl 0xe4(%rsp), %eax
addq $0xe8, %rsp
retq
nopl (%rax,%rax)