// File: codeandkey[P]neocortex/src/position.cpp
// Function: neocortex::Position::see(int, int)
int Position::see(int sq, int attacking_col) {
	bitboard ctm = board.get_color_occ(attacking_col);
	int lva = square::null;

#ifndef NDEBUG
	zobrist::Key starting_bkey = board.get_tt_key();
#endif

	/* Find least valuable attacker */

	// Search for pawn attacks
	bitboard pawn_attackers = attacks::pawn(!attacking_col, sq) & board.get_piece_occ(piece::PAWN) & ctm;

	if (pawn_attackers) {
		lva = bb::poplsb(pawn_attackers);
	}
	else {
		// Find bishop attackers
		bitboard bishop_attacks = attacks::bishop(sq, board.get_global_occ());
		bitboard bishop_attackers = bishop_attacks & ctm & board.get_piece_occ(piece::BISHOP);

		if (bishop_attackers) {
			lva = bb::poplsb(bishop_attackers);
		}
		else {
			// Find knight attackers
			bitboard knight_attackers = attacks::knight(sq) & ctm & board.get_piece_occ(piece::KNIGHT);

			if (knight_attackers) {
				lva = bb::poplsb(knight_attackers);
			}
			else {
				// Find rook attackers
				bitboard rook_attacks = attacks::rook(sq, board.get_global_occ());
				bitboard rook_attackers = rook_attacks & ctm & board.get_piece_occ(piece::ROOK);

				if (rook_attackers) {
					lva = bb::poplsb(rook_attackers);
				}
				else {
					// Find queen attackers
					bitboard queen_attackers = (bishop_attacks | rook_attacks) & ctm & board.get_piece_occ(piece::QUEEN);

					if (queen_attackers) {
						lva = bb::poplsb(queen_attackers);
					}
					else {
						// Find king attackers
						bitboard king_attackers = attacks::king(sq) & ctm & board.get_piece_occ(piece::KING);

						if (king_attackers) {
							lva = bb::poplsb(king_attackers);
						}
					}
				}
			}
		}
	}

	if (square::is_valid(lva)) {
		/* Remove LVA from board */
		int removed = board.remove(lva);

		/* Perform capture with LVA, record material gain */
		int dst_removed = board.replace(sq, removed);
		int dst_value = eval::MATERIAL_MG[piece::type(dst_removed)];

		int ret = dst_value - see(sq, !attacking_col);

		/* Undo capture */
		board.replace(sq, dst_removed);
		board.place(lva, removed);

		assert(board.get_tt_key() == starting_bkey);
		return ret;
	} else {
		// No valid attackers, SEE is 0
		assert(board.get_tt_key() == starting_bkey);
		return 0;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x90(%rbp)
movl -0x18(%rbp), %esi
callq 0x14e30
movq -0x90(%rbp), %rdi
movq %rax, -0x20(%rbp)
movl $0xffffffff, -0x24(%rbp) # imm = 0xFFFFFFFF
callq 0x14a40
movq %rax, -0x30(%rbp)
cmpl $0x0, -0x18(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
movl -0x14(%rbp), %esi
callq 0x8dc0
movq -0x90(%rbp), %rdi
movq %rax, -0x88(%rbp)
xorl %esi, %esi
callq 0x14e50
movq %rax, %rcx
movq -0x88(%rbp), %rax
andq %rcx, %rax
andq -0x20(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x1210b
leaq -0x38(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122d4
movq -0x90(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, -0x9c(%rbp)
callq 0x14e70
movl -0x9c(%rbp), %edi
movq %rax, %rsi
callq 0x8e10
movq -0x90(%rbp), %rdi
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
andq -0x20(%rbp), %rax
movq %rax, -0x98(%rbp)
movl $0x1, %esi
callq 0x14e50
movq %rax, %rcx
movq -0x98(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x1217b
leaq -0x48(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122d2
movl -0x14(%rbp), %edi
callq 0x8df0
movq -0x90(%rbp), %rdi
andq -0x20(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl $0x2, %esi
callq 0x14e50
movq %rax, %rcx
movq -0xa8(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
je 0x121c8
leaq -0x50(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122d0
movq -0x90(%rbp), %rdi
movl -0x14(%rbp), %eax
movl %eax, -0xb4(%rbp)
callq 0x14e70
movl -0xb4(%rbp), %edi
movq %rax, %rsi
callq 0x8eb0
movq -0x90(%rbp), %rdi
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
andq -0x20(%rbp), %rax
movq %rax, -0xb0(%rbp)
movl $0x3, %esi
callq 0x14e50
movq %rax, %rcx
movq -0xb0(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
je 0x12238
leaq -0x60(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122ce
movq -0x90(%rbp), %rdi
movq -0x40(%rbp), %rax
orq -0x58(%rbp), %rax
andq -0x20(%rbp), %rax
movq %rax, -0xc0(%rbp)
movl $0x4, %esi
callq 0x14e50
movq %rax, %rcx
movq -0xc0(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
je 0x12282
leaq -0x68(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122cc
movl -0x14(%rbp), %edi
callq 0x8f50
movq -0x90(%rbp), %rdi
andq -0x20(%rbp), %rax
movq %rax, -0xc8(%rbp)
movl $0x5, %esi
callq 0x14e50
movq %rax, %rcx
movq -0xc8(%rbp), %rax
andq %rcx, %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x122ca
leaq -0x70(%rbp), %rdi
callq 0x8f70
movl %eax, -0x24(%rbp)
jmp 0x122cc
jmp 0x122ce
jmp 0x122d0
jmp 0x122d2
jmp 0x122d4
movl -0x24(%rbp), %edi
callq 0x6d10
testb $0x1, %al
jne 0x122e5
jmp 0x123b6
movq -0x90(%rbp), %rdi
movl -0x24(%rbp), %esi
callq 0x7da0
movq -0x90(%rbp), %rdi
movl %eax, -0x74(%rbp)
movl -0x14(%rbp), %esi
movl -0x74(%rbp), %edx
callq 0x7f10
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %edi
callq 0x8d20
movq -0x90(%rbp), %rdi
movslq %eax, %rcx
leaq 0x1456b(%rip), %rax     # 0x26890
movl (%rax,%rcx,4), %eax
movl %eax, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
movl %eax, -0xcc(%rbp)
movl -0x14(%rbp), %esi
cmpl $0x0, -0x18(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edx
callq 0x12070
movq -0x90(%rbp), %rdi
movl %eax, %ecx
movl -0xcc(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x80(%rbp)
movl -0x14(%rbp), %esi
movl -0x78(%rbp), %edx
callq 0x7f10
movq -0x90(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x74(%rbp), %edx
callq 0x7b80
movq -0x90(%rbp), %rdi
callq 0x14a40
cmpq -0x30(%rbp), %rax
jne 0x1238f
jmp 0x123ae
leaq 0x15734(%rip), %rdi     # 0x27aca
leaq 0x15428(%rip), %rsi     # 0x277c5
movl $0x4ce, %edx            # imm = 0x4CE
leaq 0x15745(%rip), %rcx     # 0x27aee
callq 0x5290
movl -0x80(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x123f0
movq -0x90(%rbp), %rdi
callq 0x14a40
cmpq -0x30(%rbp), %rax
jne 0x123ca
jmp 0x123e9
leaq 0x156f9(%rip), %rdi     # 0x27aca
leaq 0x153ed(%rip), %rsi     # 0x277c5
movl $0x4d2, %edx            # imm = 0x4D2
leaq 0x1570a(%rip), %rcx     # 0x27aee
callq 0x5290
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xd0, %rsp
popq %rbp
retq
nopl (%rax)