// File: /workspace/github_cpp_makefile_star2_O2/tewalds[P]morat/pentago/agentab.cpp
// Function: Morat::Pentago::AgentAB::negamax(Morat::Pentago::Board const&, short, short, int)
int16_t AgentAB::negamax(const Board & board, int16_t alpha, int16_t beta, int depth) {
	nodes_seen++;

	Outcome won = board.outcome();
	if(won >= Outcome::DRAW){
		if(won == Outcome::DRAW)
			return SCORE_DRAW;
		if(won == +board.to_play())
			return SCORE_WIN;
		return SCORE_LOSS;
	}

	if (depth <= 0){ //terminal node?
		int16_t score = -board.score();
		if(randomness){
			score <<= randomness;
			score -= rand() & ((1 << randomness)-1);
		}
		return score;
	}

	int16_t score = SCORE_LOSS;
	Move bestmove = M_RESIGN;
	Node * node;

	if(TT && (node = tt_get(board)) && node->depth >= depth){
		switch(node->flag){
		case VALID:  return node->score;
		case LBOUND: alpha = std::max(alpha, node->score); break;
		case UBOUND: beta  = std::min(beta,  node->score); break;
		default:     assert(false && "Unknown flag!");
		}
		if(alpha >= beta)
			return node->score;

		if(node->bestmove != M_UNKNOWN){
			//try the previous best move first
			bestmove = node->bestmove;
			Board n = board;
			bool move_success = n.move(bestmove);

			if(!move_success){
				logerr("FAIL!!!\nhash: " + to_str(board.simple_hash()) + ", state: " + board.state() + "\n");
				logerr(node->to_s() + "\n");
				logerr(board.to_s());
			}

			assert(move_success);
			score = -negamax(n, -beta, -alpha, depth-1);
		}
	}

	if (score < beta) { // no cutoff from bestmove
		//TODO: sort moves first?

		//generate moves
		for (RandomMoveIterator<XORShift_uint32> move(board, rand); !move.done(); ++move) {
//		for (MoveIterator move(board); !move.done(); ++move) {
			int16_t value = -negamax(move.board(), -beta, -std::max(alpha, score), depth-1);
			if (score < value) {
				score = value;
				bestmove = *move;
				if (score >= beta){
					break;
				}
			}
		}
	}

	if (TT) {
		uint8_t flag = (score <= alpha ? UBOUND :
		                score >= beta  ? LBOUND : VALID);
		tt_set(Node(board.simple_hash(), score, bestmove, depth, flag));
	}
	return score;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
incq 0x58(%rdi)
movq %rdi, %r15
movq %rsi, %rdi
movl %r8d, %ebx
movl %ecx, %r14d
movl %edx, %ebp
movq %rsi, %r12
callq 0xa9d0
leaq 0x1ab3d(%rip), %rcx     # 0x24c19
movb (%rcx), %cl
cmpb %cl, %al
jge 0xa1d9
testl %ebx, %ebx
jle 0xa1fa
cmpq $0x0, 0x38(%r15)
movq %rbx, 0x10(%rsp)
movb $-0x2, %al
movb $0xe, %r13b
movw $0x8001, %bx            # imm = 0x8001
movl %r14d, 0x4(%rsp)
movl %ebp, 0x8(%rsp)
movl %eax, 0xc(%rsp)
je 0xa12e
movq %r15, %rdi
movq %r12, %rsi
callq 0xa5aa
testq %rax, %rax
je 0xa12e
movzbl 0xc(%rax), %ecx
cmpl 0x10(%rsp), %ecx
jae 0xa2c3
movl 0x4(%rsp), %ebp
movq %r12, 0x18(%rsp)
cmpw %bp, %bx
jge 0xa231
leaq 0x68(%r15), %rdx
leaq 0x40(%rsp), %rdi
pushq $-0x1
popq %rcx
movq %r12, %rsi
callq 0xb12a
movq 0x10(%rsp), %rcx
movl %ebp, %eax
negl %eax
movswl %ax, %ebp
leal -0x1(%rcx), %r12d
cmpl $0x0, 0x80(%rsp)
js 0xa239
movl 0x8(%rsp), %ecx
movl %ebx, %eax
cmpw %bx, %cx
cmovgl %ecx, %eax
negl %eax
movswl %ax, %ecx
leaq 0x48(%rsp), %rsi
movq %r15, %r14
movq %r15, %rdi
movl %ebp, %edx
movl %r12d, %r8d
callq 0xa0aa
movl %eax, %r15d
negl %r15d
cmpw %r15w, %bx
jge 0xa1ca
movq 0x78(%rsp), %rax
movslq 0x80(%rsp), %rcx
movl %r15d, %ebx
movzwl (%rax,%rcx,2), %r13d
movl %r13d, 0xc(%rsp)
shrl $0x8, %r13d
cmpw %r15w, 0x4(%rsp)
jle 0xa23f
leaq 0x40(%rsp), %rdi
callq 0xb226
movq %r14, %r15
jmp 0xa164
jne 0xa1e3
xorl %r15d, %r15d
jmp 0xa2ae
xorl %ecx, %ecx
cmpb 0x19(%r12), %al
setne %cl
leal 0x7fff(%rcx,%rcx), %r15d
jmp 0xa2ae
movq %r12, %rdi
callq 0xad50
movq %r15, %rbx
movl %eax, %r15d
movl 0x6c(%rbx), %eax
negl %r15d
testl %eax, %eax
je 0xa2ae
leaq 0x68(%rbx), %rdi
shlxl %eax, %r15d, %r15d
callq 0xb794
movb 0x6c(%rbx), %cl
bzhil %ecx, %eax, %eax
subl %eax, %r15d
jmp 0xa2ae
movq %r15, %r14
movl %ebx, %r15d
jmp 0xa249
movq %r15, %r14
movl %ebx, %r15d
leaq 0x40(%rsp), %rdi
callq 0xb292
cmpq $0x0, 0x38(%r14)
je 0xa2ae
cmpw 0x4(%rsp), %r15w
movb $0x2, %cl
setl %al
subb %al, %cl
cmpw 0x8(%rsp), %r15w
movzbl %cl, %eax
pushq $0x3
popq %rbx
movq 0x18(%rsp), %rdi
cmovgl %eax, %ebx
callq 0xae62
leaq 0x40(%rsp), %rsi
movzbl 0xc(%rsp), %edx
movzbl %r13b, %ecx
movq %r14, %rdi
movq %rax, (%rsi)
movq 0x10(%rsp), %rax
shll $0x8, %ecx
movw %r15w, 0x8(%rsi)
orl %ecx, %edx
movw %dx, 0xa(%rsi)
movb %al, 0xc(%rsi)
movb %bl, 0xd(%rsi)
movw $0xdead, 0xe(%rsi)      # imm = 0xDEAD
callq 0xa5c2
movl %r15d, %eax
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzbl 0xd(%rax), %ecx
cmpl $0x3, %ecx
je 0xa2fd
cmpl $0x2, %ecx
je 0xa2e1
cmpl $0x1, %ecx
jne 0xa3a0
movzwl 0x8(%rax), %r15d
jmp 0xa2ae
movq %r15, %rbp
movzwl 0x8(%rax), %r15d
movl 0x8(%rsp), %ecx
cmpw %cx, %r15w
movl %r15d, %edx
cmovlel %ecx, %edx
movl 0x4(%rsp), %ecx
jmp 0xa319
movq %r15, %rbp
movzwl 0x8(%rax), %r15d
movl 0x4(%rsp), %ecx
cmpw %cx, %r15w
movl %r15d, %edx
cmovgel %ecx, %edx
movl %edx, %ecx
movl 0x8(%rsp), %edx
movl %edx, 0x8(%rsp)
movl %ecx, 0x4(%rsp)
cmpw %cx, %dx
jge 0xa2ae
cmpb $-0x4, 0xa(%rax)
jne 0xa334
movq %rbp, %r15
jmp 0xa12e
movq 0x20(%r12), %rcx
leaq 0x40(%rsp), %rdi
movzwl 0xa(%rax), %r13d
movq %rax, %r14
movq %rcx, 0x20(%rdi)
movl %r13d, %esi
vmovups (%r12), %ymm0
vmovups %ymm0, (%rdi)
vzeroupper
callq 0xad6a
testb %al, %al
je 0xa3bd
movl 0x4(%rsp), %eax
movl 0x8(%rsp), %ecx
movq 0x10(%rsp), %rdx
leaq 0x40(%rsp), %rsi
movl %r13d, 0xc(%rsp)
movq %rbp, %r15
shrl $0x8, %r13d
movq %rbp, %rdi
negl %ecx
negl %eax
leal -0x1(%rdx), %r8d
movswl %ax, %edx
movswl %cx, %ecx
callq 0xa0aa
movl %eax, %ebx
negl %ebx
jmp 0xa12e
leaq 0x15e04(%rip), %rdi     # 0x201ab
leaq 0x15e16(%rip), %rsi     # 0x201c4
leaq 0x15e23(%rip), %rcx     # 0x201d8
pushq $0x5a
popq %rdx
callq 0x5220
movq %r12, %rdi
movq %r12, %r15
callq 0xae62
leaq 0xe8(%rsp), %rbx
movq %rax, %rsi
movq %rbx, %rdi
callq 0xaba2
leaq 0x15e45(%rip), %rsi     # 0x20227
leaq 0xa8(%rsp), %rdi
movq %rbx, %rdx
callq 0xaac0
leaq 0x15e3d(%rip), %rdx     # 0x20236
leaq 0xc8(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x7b4d
leaq 0x88(%rsp), %rdi
movq %r15, %rsi
callq 0x15e6c
leaq 0x20(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
leaq 0x88(%rsp), %rdx
callq 0xab3b
leaq 0x153d9(%rip), %rdx     # 0x1f818
leaq 0x128(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x7b4d
leaq 0x128(%rsp), %rbx
movq %rbx, %rdi
callq 0xaaae
movq %rbx, %rdi
callq 0x5170
leaq 0x20(%rsp), %rdi
callq 0x5170
leaq 0x88(%rsp), %rdi
callq 0x5170
leaq 0xc8(%rsp), %rdi
callq 0x5170
leaq 0xa8(%rsp), %rdi
callq 0x5170
leaq 0xe8(%rsp), %rdi
callq 0x5170
leaq 0x20(%rsp), %rbx
movq %r14, %rsi
movq %rbx, %rdi
callq 0xaefa
leaq 0x1535a(%rip), %rdx     # 0x1f818
leaq 0x108(%rsp), %rdi
movq %rbx, %rsi
callq 0x7b4d
leaq 0x108(%rsp), %rbx
movq %rbx, %rdi
callq 0xaaae
movq %rbx, %rdi
callq 0x5170
leaq 0x20(%rsp), %rdi
callq 0x5170
leaq 0x148(%rsp), %rbx
pushq $0x1
popq %rdx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x15f06
movq %rbx, %rdi
callq 0xaaae
movq %rbx, %rdi
callq 0x5170
leaq 0x15d23(%rip), %rdi     # 0x20240
leaq 0x15ca0(%rip), %rsi     # 0x201c4
leaq 0x15cad(%rip), %rcx     # 0x201d8
pushq $0x6b
jmp 0xa3b7
leaq 0x20(%rsp), %rdi
movq %rax, %rbx
jmp 0xa58c
leaq 0x20(%rsp), %rdi
movq %rax, %rbx
callq 0x5170
jmp 0xa54e
movq %rax, %rbx
leaq 0x88(%rsp), %rdi
callq 0x5170
jmp 0xa560
movq %rax, %rbx
leaq 0xc8(%rsp), %rdi
callq 0x5170
jmp 0xa572
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x5170
jmp 0xa584
movq %rax, %rbx
leaq 0xe8(%rsp), %rdi
callq 0x5170
jmp 0xa5a2
jmp 0xa595
leaq 0x40(%rsp), %rdi
movq %rax, %rbx
callq 0xb292
movq %rbx, %rdi
callq 0x5690