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

	int won = board.won();
	if(won >= 0){
		if(won == 0)
			return SCORE_DRAW;
		if(won == board.toplay())
			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 = max(alpha, node->score); break;
		case UBOUND: beta  = 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.hash()) + ", orientation: " + to_str(board.orient()) + ", state: " + board.state() + "\n");
//				logerr(node->to_s(board.orient()) + "\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 (MoveIterator move(board); !move.done(); ++move) {
			int16_t value = -negamax(move.board(), -beta, -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.hash(), score, bestmove, depth, flag));
	}
	return score;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
incq 0x58(%rdi)
movq %rdi, %rbx
movq %rsi, %rdi
movl %r8d, %r15d
movl %ecx, %r13d
movl %edx, %ebp
movq %rsi, %r12
callq 0xae70
testb %al, %al
js 0x1acd5
je 0x1ad9b
movzbl 0x19(%r12), %ecx
movsbl %al, %eax
xorl %edx, %edx
cmpl %ecx, %eax
setne %dl
leal 0x7fff(%rdx,%rdx), %r13d
jmp 0x1ae46
testl %r15d, %r15d
jle 0x1ada3
cmpq $0x0, 0x38(%rbx)
movw $0x8001, %r14w          # imm = 0x8001
je 0x1ad07
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1af68
testq %rax, %rax
je 0x1ad07
movzbl 0x10(%rax), %ecx
cmpl %r15d, %ecx
jae 0x1ae58
movq %rbx, 0x8(%rsp)
movw $0x8efe, %bx            # imm = 0x8EFE
movq %r15, 0x18(%rsp)
movq %r12, 0x10(%rsp)
movl %r13d, 0x4(%rsp)
cmpw %r13w, %r14w
jge 0x1add7
leaq 0x20(%rsp), %rdi
pushq $-0x1
popq %rdx
movq %r12, %rsi
callq 0xac78
negl %r13d
leal -0x1(%r15), %r12d
movswl %r13w, %r15d
cmpb $0x23, 0x50(%rsp)
jg 0x1addc
cmpw %r14w, %bp
movl %r14d, %eax
cmovgl %ebp, %eax
negl %eax
movswl %ax, %ecx
movq 0x8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
movl %r15d, %edx
movl %r12d, %r8d
callq 0x1ac86
movl %eax, %r13d
negl %r13d
cmpw %r13w, %r14w
jge 0x1ad8f
movzwl 0x50(%rsp), %ebx
movl %r13d, %r14d
cmpw %r13w, 0x4(%rsp)
jle 0x1addf
leaq 0x20(%rsp), %rdi
callq 0xad32
jmp 0x1ad44
xorl %r13d, %r13d
jmp 0x1ae46
movq %r12, %rdi
callq 0x1b3f0
movl %eax, %r13d
movl 0x6c(%rbx), %eax
negl %r13d
testl %eax, %eax
je 0x1ae46
leaq 0x68(%rbx), %rdi
shlxl %eax, %r13d, %r13d
callq 0x1b7dc
movb 0x6c(%rbx), %cl
bzhil %ecx, %eax, %eax
subl %eax, %r13d
jmp 0x1ae46
movl %r14d, %r13d
jmp 0x1ade9
movl %r14d, %r13d
leaq 0x58(%rsp), %rdi
callq 0xb368
movq 0x8(%rsp), %r14
cmpq $0x0, 0x38(%r14)
je 0x1ae46
cmpw 0x4(%rsp), %r13w
movb $0x2, %cl
setl %al
subb %al, %cl
cmpw %bp, %r13w
movzbl %cl, %eax
pushq $0x3
popq %rbp
movq 0x10(%rsp), %rdi
cmovgl %eax, %ebp
callq 0x7f14
leaq 0x20(%rsp), %rsi
movzwl %bx, %ecx
movq %r14, %rdi
movq %rax, (%rsi)
movq 0x18(%rsp), %rax
movw %r13w, 0x8(%rsi)
movl %ecx, 0xc(%rsi)
movb %al, 0x10(%rsi)
movb %bpl, 0x11(%rsi)
movw $0xdead, 0x12(%rsi)     # imm = 0xDEAD
callq 0x1af80
movl %r13d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzbl 0x11(%rax), %ecx
cmpl $0x3, %ecx
je 0x1ae8c
cmpl $0x2, %ecx
je 0x1ae76
cmpl $0x1, %ecx
jne 0x1af1a
movzwl 0x8(%rax), %r13d
jmp 0x1ae46
movl %r13d, %edx
movzwl 0x8(%rax), %r13d
cmpw %bp, %r13w
movl %r13d, %ecx
cmovlel %ebp, %ecx
movl %ecx, %ebp
jmp 0x1aea0
movl %r13d, %edx
movzwl 0x8(%rax), %r13d
cmpw %dx, %r13w
movl %r13d, %ecx
cmovgel %edx, %ecx
movl %ecx, %edx
movl %edx, 0x4(%rsp)
cmpw %dx, %bp
jge 0x1ae46
movq %rbx, 0x8(%rsp)
movzwl 0xc(%rax), %ebx
cmpb $-0x4, %bl
jne 0x1aec1
movl 0x4(%rsp), %r13d
jmp 0x1ad0c
movq 0x20(%r12), %rax
leaq 0x20(%rsp), %rdi
movzwl %bx, %esi
movq %rax, 0x20(%rdi)
vmovups (%r12), %ymm0
vmovups %ymm0, (%rdi)
vzeroupper
callq 0x7ada
movl 0x4(%rsp), %r13d
testb %al, %al
je 0x1af33
movq 0x8(%rsp), %rdi
movl %r13d, %eax
negl %eax
movl %ebp, %ecx
negl %ecx
leal -0x1(%r15), %r8d
leaq 0x20(%rsp), %rsi
movswl %ax, %edx
movswl %cx, %ecx
callq 0x1ac86
movl %eax, %r14d
negl %r14d
jmp 0x1ad10
leaq 0x5a72(%rip), %rdi      # 0x20993
leaq 0x5a84(%rip), %rsi      # 0x209ac
leaq 0x5a89(%rip), %rcx      # 0x209b8
pushq $0x54
jmp 0x1af4a
leaq 0x231a(%rip), %rdi      # 0x1d254
leaq 0x5a6b(%rip), %rsi      # 0x209ac
leaq 0x5a70(%rip), %rcx      # 0x209b8
pushq $0x65
popq %rdx
callq 0x41c0
jmp 0x1af52
leaq 0x58(%rsp), %rdi
movq %rax, %rbx
callq 0xb368
movq %rbx, %rdi
callq 0x4590
nop