// File: /workspace/github_cpp_makefile_star2_O1/codeandkey[P]neocortex/src/search.cpp
// Function: neocortex::search::Search::alphabeta(neocortex::Position&, int, int, int, int, neocortex::PV*, std::atomic<bool>&)
int search::Search::alphabeta(Position& root, int depth, int alpha, int beta, int ply_dist, PV* pv_line, std::atomic<bool>& abort_watch) {
	PV local_pv;
	Move tt_move, tt_exact_move;
	int value;
	int depth_reduction = 1;
	int depth_extension = 0;

	if (allocated_time_expired() || abort_watch) {
		return score::INCOMPLETE;
	}

	/* Check for threefold repetition or 50-move rule */
	if (root.num_repetitions() >= 3 || root.halfmove_clock() >= 50) {
		return eval::CONTEMPT;
	}

	if (!depth) {
		return quiescence(root, search::QDEPTH, alpha, beta, ply_dist, pv_line);
	}

	int alpha_orig = alpha;

	/* Look up cached results in TT */

	tt::entry* entry = tt::lookup(root.get_tt_key());

	tt::lock(root.get_tt_key());
	if (entry->key == root.get_tt_key() && entry->depth >= 1) {
		if (entry->depth >= depth) {
			switch (entry->type) {
			case tt::entry::EXACT:
				/* Get exact pv move from TT */
				tt_exact_move = entry->pv_move;
			case tt::entry::LOWERBOUND:
				if (entry->value > alpha) alpha = entry->value;
				break;
			case tt::entry::UPPERBOUND:
				if (entry->value < beta) beta = entry->value;
				break;
			}
		}
		else {
			/* TT entry isn't deep enough to use, but we keep the PV move for ordering */
			if (entry->type == tt::entry::EXACT) {
				tt_move = entry->pv_move;
			}
		}
	}
	tt::unlock(root.get_tt_key());

	/* If there is an exact PV, just search under the PV move */
	if (tt_exact_move.is_valid()) {
		// Re-search under pv node to regenerate complete pv, should be fast as all should hit TT
		root.make_move(tt_exact_move);

		value = -alphabeta(root, depth + depth_extension - depth_reduction, -beta, -alpha, ply_dist + 1, &local_pv, abort_watch);

		pv_line->moves[0] = tt_exact_move;
		pv_line->len = local_pv.len + 1;

		memcpy(pv_line->moves + 1, local_pv.moves, local_pv.len * sizeof local_pv.moves[0]);
		root.unmake_move(tt_exact_move);

		return value;
	}

	/* Perform null move reduction if available */
	if (root.null_move_allowed() && depth >= search::NULL_MOVE_REDUCTION) {
		root.make_move(Move::null);
		int nm_score = -alphabeta(root, depth - search::NULL_MOVE_REDUCTION, -beta, -alpha, ply_dist + 1, &local_pv, abort_watch);
		root.unmake_move(Move::null);

		if (nm_score >= beta) {
			return beta; // cutoff
		}
	}

	/* Check / capture extension */
	if (depth >= 5) { // don't do excessive extensions near horizon
		if (root.check() || root.capture()) {
			depth_extension++;
		}
	}

	Move pl_moves[MAX_PL_MOVES];
	int num_pl_moves = root.pseudolegal_moves(pl_moves);
	int num_moves = 0; /* num of legal moves */

	root.order_moves(pl_moves, num_pl_moves, tt_move);

	for (int i = 0; i < num_pl_moves; ++i) {
		if (root.make_move(pl_moves[i])) {

			num_moves++;

			int new_depth = depth + depth_extension - depth_reduction;

			if (new_depth < 0) {
				new_depth = 0;
			}

			value = -alphabeta(root, new_depth, -beta, -alpha, ply_dist + 1, &local_pv, abort_watch);

			/*if (depth == 1) {
				neocortex_debug("Made move %s, resulting score %d\n", pl_moves[i].to_uci().c_str(), value);
			}*/

			root.unmake_move(pl_moves[i]);

			if (value == score::INCOMPLETE) {
				return value;
			}

			if (value >= beta) {
				// Add history bonus for cutoff in normal AB
				root.add_history_bonus(pl_moves[i], depth);
				return beta;
			}

			if (value > alpha) {
				alpha = value;

				pv_line->moves[0] = pl_moves[i];
				pv_line->len = local_pv.len + 1;

				memcpy(pv_line->moves + 1, local_pv.moves, local_pv.len * sizeof local_pv.moves[0]);
			}
		}
		else {
			root.unmake_move(pl_moves[i]);
		}
	}

	if (!num_moves) {
		if (root.check()) {
			pv_line->len = 0;
			return score::CHECKMATED + ply_dist;
		}
		else {
			pv_line->len = 0;
			return eval::CONTEMPT;
		}
	}

	/* Write result to TT */
	tt::lock(root.get_tt_key());
	entry->key = root.get_tt_key();
	entry->value = alpha;
	entry->depth = depth;

	if (alpha <= alpha_orig) {
		entry->type = tt::entry::UPPERBOUND;
	}
	else if (alpha >= beta) {
		entry->type = tt::entry::LOWERBOUND;
	}
	else {
		assert(pv_line->moves[0].is_valid());

		entry->pv_move = pv_line->moves[0];
		entry->type = tt::entry::EXACT;
	}
	tt::unlock(root.get_tt_key());

	return alpha;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb48, %rsp            # imm = 0xB48
movl %r9d, %r12d
movl %r8d, %r13d
movl %ecx, %r15d
movl %edx, %r14d
movq %rsi, %rbx
movq %rdi, %rbp
leaq 0x8c(%rsp), %rdi
callq 0x7a1c
leaq 0x50(%rsp), %rdi
callq 0x7648
leaq 0x18(%rsp), %rdi
callq 0x7648
movq %rbp, 0x28(%rsp)
movq %rbp, %rdi
callq 0x10f34
movl $0x80000000, %ebp       # imm = 0x80000000
testb %al, %al
jne 0x10e05
movq 0xb88(%rsp), %rax
movb (%rax), %al
testb $0x1, %al
jne 0x10e05
movq %rbx, %rdi
callq 0xedba
xorl %ebp, %ebp
cmpl $0x2, %eax
jg 0x10e05
movq %rbx, %rdi
callq 0xee0c
cmpl $0x31, %eax
jg 0x10e05
movl %r15d, 0x4(%rsp)
movq 0xb80(%rsp), %r15
testl %r14d, %r14d
je 0x10920
movq %r14, 0x10(%rsp)
movq %rbx, %rdi
callq 0xedae
movq %rax, %rdi
callq 0x121c0
movq %rax, %rbp
movq %rbx, %rdi
callq 0xedae
movq %rax, %rdi
callq 0x121de
movq (%rbp), %r14
movq %rbx, %rdi
callq 0xedae
cmpq %rax, %r14
movq %rbp, 0x30(%rsp)
jne 0x10915
movl 0x1c(%rbp), %ecx
testl %ecx, %ecx
jle 0x10915
movl 0x14(%rbp), %eax
movq 0x10(%rsp), %r14
cmpl %r14d, %ecx
jge 0x1094d
cmpl $0x2, %eax
jne 0x10983
movl 0x10(%rbp), %eax
movl %eax, 0x58(%rsp)
movq 0x8(%rbp), %rax
movq %rax, 0x50(%rsp)
jmp 0x10983
movl 0x4(%rsp), %ebp
movq 0x10(%rsp), %r14
jmp 0x10987
subq $0x8, %rsp
movq 0x30(%rsp), %rdi
movq %rbx, %rsi
movl $0x4, %edx
movl 0xc(%rsp), %ecx
movl %r13d, %r8d
movl %r12d, %r9d
pushq %r15
callq 0x10fa0
addq $0x10, %rsp
movl %eax, %ebp
jmp 0x10e05
testl %eax, %eax
je 0x1096b
cmpl $0x1, %eax
je 0x10979
cmpl $0x2, %eax
jne 0x10983
movl 0x10(%rbp), %eax
movl %eax, 0x20(%rsp)
movq 0x8(%rbp), %rax
movq %rax, 0x18(%rsp)
movl 0x18(%rbp), %ebp
movl 0x4(%rsp), %eax
cmpl %eax, %ebp
cmovlel %eax, %ebp
jmp 0x10987
movl 0x18(%rbp), %eax
cmpl %r13d, %eax
cmovll %eax, %r13d
movl 0x4(%rsp), %ebp
movq %rbx, %rdi
callq 0xedae
movq %rax, %rdi
callq 0x1221a
leaq 0x18(%rsp), %rdi
callq 0x794e
testb %al, %al
je 0x10a43
movq 0x18(%rsp), %rsi
movl 0x20(%rsp), %edx
movq %rbx, %rdi
callq 0x947c
decl %r14d
negl %r13d
negl %ebp
incl %r12d
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
movl %r14d, %edx
movl %r13d, %ecx
movl %ebp, %r8d
movl %r12d, %r9d
pushq 0xb88(%rsp)
leaq 0x94(%rsp), %rax
pushq %rax
callq 0x10802
addq $0x10, %rsp
movl %eax, %ebp
negl %ebp
movq 0x18(%rsp), %rax
movq %rax, 0x4(%r15)
movl 0x20(%rsp), %eax
movl %eax, 0xc(%r15)
leaq 0x90(%rsp), %rsi
movslq -0x4(%rsi), %rax
leal 0x1(%rax), %ecx
movl %ecx, (%r15)
addq $0x10, %r15
shlq $0x2, %rax
leaq (%rax,%rax,2), %rdx
movq %r15, %rdi
callq 0x4230
movq 0x18(%rsp), %rsi
movl 0x20(%rsp), %edx
movq %rbx, %rdi
callq 0x9a5e
jmp 0x10e05
movq 0x28(%rbx), %rax
orq 0x20(%rbx), %rax
orq 0x30(%rbx), %rax
orq 0x38(%rbx), %rax
movslq 0x170(%rbx), %rcx
testq %rax, 0x8(%rbx,%rcx,8)
je 0x10a71
movq 0x160(%rbx), %rax
cmpl $0x0, -0x14(%rax)
sete %al
jmp 0x10a73
xorl %eax, %eax
movl 0x4(%rsp), %r15d
movq %r12, 0x38(%rsp)
cmpl $0x3, %r14d
jl 0x10afd
testb %al, %al
je 0x10afd
leaq 0x1a10a(%rip), %r12     # 0x2ab98
movq (%r12), %rsi
movl 0x8(%r12), %edx
movq %rbx, %rdi
callq 0x947c
leal -0x3(%r14), %edx
movl %r13d, %ecx
negl %ecx
movl %ebp, %r8d
negl %r8d
movq 0x38(%rsp), %rax
leal 0x1(%rax), %r9d
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
pushq 0xb88(%rsp)
leaq 0x94(%rsp), %rax
pushq %rax
callq 0x10802
addq $0x10, %rsp
movl %eax, %r14d
negl %r14d
movq (%r12), %rsi
movl 0x8(%r12), %edx
movq %rbx, %rdi
callq 0x9a5e
cmpl %r14d, %r13d
movq 0x10(%rsp), %r14
jle 0x10d5d
xorl %r12d, %r12d
cmpl $0x5, %r14d
jl 0x10b1f
movq 0x160(%rbx), %rax
cmpl $0x0, -0x14(%rax)
jne 0x10b19
cmpl $-0x1, -0x24(%rax)
je 0x10b1f
movl $0x1, %r12d
movl %r13d, 0xc(%rsp)
xorl %r14d, %r14d
leaq (%rsp,%r14), %rdi
addq $0x690, %rdi            # imm = 0x690
callq 0x7648
addq $0xc, %r14
cmpq $0x4b0, %r14            # imm = 0x4B0
jne 0x10b27
leaq 0x690(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x9cc2
movl %eax, %r13d
movq 0x50(%rsp), %rcx
movl 0x58(%rsp), %r8d
movq %rbx, %rdi
movq %r14, %rsi
movl %eax, %edx
callq 0xca7a
testl %r13d, %r13d
setg %cl
jle 0x10d44
movb %cl, 0xb(%rsp)
movq 0x10(%rsp), %rdx
addl %edx, %r12d
cmpl $0x2, %r12d
movl $0x1, %eax
cmovgel %r12d, %eax
decl %eax
movl %eax, 0x4c(%rsp)
movl 0xc(%rsp), %eax
movl %eax, %ecx
negl %ecx
movl %ecx, 0x48(%rsp)
movq 0x38(%rsp), %rcx
incl %ecx
movl %ecx, 0x44(%rsp)
movl %edx, %ecx
imull %edx, %ecx
movl %ecx, 0x40(%rsp)
leaq 0x178(%rbx), %rcx
movq %rcx, 0x70(%rsp)
movq 0xb80(%rsp), %rcx
leaq 0x4(%rcx), %rdx
movq %rdx, 0x68(%rsp)
addq $0x10, %rcx
movq %rcx, 0x60(%rsp)
movl %r13d, %ecx
movl %eax, %r13d
movq %rcx, 0x80(%rsp)
negq %rcx
movq %rcx, 0x78(%rsp)
movl $0x0, 0x24(%rsp)
movl $0x1, %r12d
movq (%r14), %rsi
movl 0x8(%r14), %edx
movq %rbx, %rdi
callq 0x947c
testb %al, %al
je 0x10cc2
movl %ebp, %r8d
negl %r8d
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
movl 0x4c(%rsp), %edx
movl 0x48(%rsp), %ecx
movl 0x44(%rsp), %r9d
pushq 0xb88(%rsp)
leaq 0x94(%rsp), %rax
pushq %rax
callq 0x10802
addq $0x10, %rsp
movl %r13d, %r15d
movl %eax, %r13d
negl %r13d
movq (%r14), %rsi
movl 0x8(%r14), %edx
movq %rbx, %rdi
callq 0x9a5e
cmpl %r13d, %r15d
jle 0x10cd3
cmpl %r13d, %ebp
movl 0x4(%rsp), %r15d
jge 0x10cfd
movl 0x8(%r14), %eax
movq 0x68(%rsp), %rcx
movl %eax, 0x8(%rcx)
movq (%r14), %rax
movq %rax, (%rcx)
movslq 0x8c(%rsp), %rax
leal 0x1(%rax), %ecx
movq 0xb80(%rsp), %rdx
movl %ecx, (%rdx)
shlq $0x2, %rax
leaq (%rax,%rax,2), %rdx
movq 0x60(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x4230
movl %r13d, %ebp
jmp 0x10cfd
movq (%r14), %rsi
movl 0x8(%r14), %edx
movq %rbx, %rdi
callq 0x9a5e
jmp 0x10d0d
movslq 0x170(%rbx), %rax
movslq (%r14), %rcx
movslq 0x4(%r14), %rdx
shlq $0xe, %rax
addq 0x70(%rsp), %rax
shlq $0x8, %rcx
addq %rax, %rcx
movl 0x40(%rsp), %eax
addl %eax, (%rcx,%rdx,4)
movl 0x4(%rsp), %r15d
incl 0x24(%rsp)
movl 0xc(%rsp), %eax
cmpl %r13d, %eax
movl %eax, %r13d
jle 0x10d36
cmpq 0x80(%rsp), %r12
setb 0xb(%rsp)
addq $0xc, %r14
movq 0x78(%rsp), %rax
addq %r12, %rax
incq %rax
incq %r12
cmpq $0x1, %rax
jne 0x10c06
cmpl $0x0, 0x24(%rsp)
sete %al
movb 0xb(%rsp), %cl
jmp 0x10d4b
movb $0x1, %al
movl 0xc(%rsp), %r13d
testb $0x1, %cl
movq 0xb80(%rsp), %r14
movq 0x38(%rsp), %rcx
je 0x10d65
movl %r13d, %ebp
jmp 0x10e05
testb %al, %al
je 0x10d89
movq 0x160(%rbx), %rax
movl -0x14(%rax), %eax
addl $0xffc2f700, %ecx       # imm = 0xFFC2F700
testl %eax, %eax
movl $0x0, (%r14)
cmovel %eax, %ecx
movl %ecx, %ebp
jmp 0x10e05
movq %rbx, %rdi
callq 0xedae
movq %rax, %rdi
callq 0x121de
movq %rbx, %rdi
callq 0xedae
movq 0x30(%rsp), %rcx
movq %rax, (%rcx)
movl %ebp, 0x18(%rcx)
movq 0x10(%rsp), %rax
movl %eax, 0x1c(%rcx)
movl $0x1, %eax
cmpl %r15d, %ebp
jle 0x10ded
xorl %eax, %eax
cmpl %r13d, %ebp
jge 0x10ded
addq $0x4, %r14
movq %r14, %rdi
callq 0x794e
testb %al, %al
je 0x10e19
movl 0x8(%r14), %eax
movq 0x30(%rsp), %rcx
movl %eax, 0x10(%rcx)
movq (%r14), %rax
movq %rax, 0x8(%rcx)
movl $0x2, %eax
movq 0x30(%rsp), %rcx
movl %eax, 0x14(%rcx)
movq %rbx, %rdi
callq 0xedae
movq %rax, %rdi
callq 0x1221a
movl %ebp, %eax
addq $0xb48, %rsp            # imm = 0xB48
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8f50(%rip), %rdi      # 0x19d70
leaq 0x8f66(%rip), %rsi      # 0x19d8d
leaq 0x8f6e(%rip), %rcx      # 0x19d9c
movl $0x191, %edx            # imm = 0x191
callq 0x4190