// File: /workspace/github_cpp_makefile_star2_O1/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
movl %r8d, %r12d
movl %ecx, %r13d
movl %edx, %ebp
movq %rsi, %r15
movq %rdi, %rbx
incq 0x58(%rdi)
cmpb $-0x4, 0x1a(%rsi)
jne 0x26dfa
movq %r15, %rdi
callq 0xdab0
movb %al, 0x1a(%r15)
movsbl 0x1a(%r15), %eax
testl %eax, %eax
js 0x26e24
testb %al, %al
je 0x26f1a
movzbl 0x19(%r15), %ecx
xorl %edx, %edx
cmpl %ecx, %eax
setne %dl
leal 0x7fff(%rdx,%rdx), %r13d
jmp 0x27012
testl %r12d, %r12d
jle 0x26f22
movw $0x8001, %r14w          # imm = 0x8001
cmpq $0x0, 0x38(%rbx)
je 0x26e84
movq %r15, %rdi
callq 0x973a
movq %rax, %rcx
shrq $0x11, %rax
xorq %rcx, %rax
movq %rax, %rdx
shlq $0x1f, %rdx
xorq %rax, %rdx
movq %rdx, %rax
shrq $0x8, %rax
xorq %rdx, %rax
movq 0x38(%rbx), %rsi
xorl %edx, %edx
divq 0x40(%rbx)
leaq (%rdx,%rdx,2), %rax
cmpq %rcx, (%rsi,%rax,8)
jne 0x26e84
leaq (%rsi,%rax,8), %rax
movzbl 0x10(%rax), %ecx
cmpl %r12d, %ecx
jge 0x27024
movq %r15, (%rsp)
movq %rbx, 0x8(%rsp)
movw $0x8efe, %r15w          # imm = 0x8EFE
cmpw %r13w, %r14w
movq %r12, 0x18(%rsp)
movl %r13d, 0x14(%rsp)
jge 0x26f78
leaq 0x20(%rsp), %rdi
movq (%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0xd316
negl %r13d
decl %r12d
movswl %r13w, %ebx
cmpb $0x23, 0x50(%rsp)
jg 0x26f7d
cmpw %r14w, %bp
movl %r14d, %eax
cmovgl %ebp, %eax
negl %eax
movswl %ax, %ecx
movq 0x8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
movl %ebx, %edx
movl %r12d, %r8d
callq 0x26dc8
movl %eax, %r13d
negl %r13d
cmpw %r13w, %r14w
jge 0x26f0e
movzwl 0x50(%rsp), %r15d
movl %r13d, %r14d
cmpw %r13w, 0x14(%rsp)
jle 0x26f80
leaq 0x20(%rsp), %rdi
callq 0xd402
jmp 0x26ec3
xorl %r13d, %r13d
jmp 0x27012
cmpw $0xdead, 0x1c(%r15)     # imm = 0xDEAD
jne 0x26f38
movq %r15, %rdi
callq 0x21e14
movw %ax, 0x1c(%r15)
xorl %r13d, %r13d
subw 0x1c(%r15), %r13w
movl 0x6c(%rbx), %eax
testl %eax, %eax
je 0x27012
shlxl %eax, %r13d, %r13d
movl 0x68(%rbx), %ecx
movl %ecx, %edx
shll $0xd, %edx
xorl %ecx, %edx
movl %edx, %ecx
shrl $0x11, %ecx
xorl %edx, %ecx
movl %ecx, %edx
shll $0x5, %edx
xorl %ecx, %edx
movl %edx, 0x68(%rbx)
bzhil %eax, %edx, %eax
subl %eax, %r13d
jmp 0x27012
movl %r14d, %r13d
jmp 0x26f8f
movl %r14d, %r13d
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x26f8f
callq 0x43d0
movq 0x8(%rsp), %r14
cmpq $0x0, 0x38(%r14)
je 0x27012
cmpw 0x14(%rsp), %r13w
setl %al
movb $0x2, %cl
subb %al, %cl
cmpw %bp, %r13w
movzbl %cl, %eax
movl $0x3, %ebx
cmovgl %eax, %ebx
movq (%rsp), %rdi
callq 0x973a
movq %rax, %rcx
movzwl %r15w, %esi
shrq $0x11, %rax
xorq %rcx, %rax
movq %rax, %rdx
shlq $0x1f, %rdx
xorq %rax, %rdx
movq %rdx, %rax
shrq $0x8, %rax
xorq %rdx, %rax
movq 0x38(%r14), %rdi
xorl %edx, %edx
divq 0x40(%r14)
leaq (%rdx,%rdx,2), %rax
movq %rcx, (%rdi,%rax,8)
movw %r13w, 0x8(%rdi,%rax,8)
movl %esi, 0xc(%rdi,%rax,8)
movq 0x18(%rsp), %rcx
movb %cl, 0x10(%rdi,%rax,8)
movb %bl, 0x11(%rdi,%rax,8)
movw $0xdead, 0x12(%rdi,%rax,8) # imm = 0xDEAD
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 0x27068
cmpl $0x2, %ecx
je 0x2705a
cmpl $0x1, %ecx
je 0x270ec
leaq 0x6ac1(%rip), %rdi      # 0x2db03
leaq 0x6ad3(%rip), %rsi      # 0x2db1c
leaq 0x6ad8(%rip), %rcx      # 0x2db28
movl $0x54, %edx
callq 0x41b0
movzwl 0x8(%rax), %ecx
cmpw %bp, %cx
cmovlel %ebp, %ecx
movl %ecx, %ebp
jmp 0x27077
movzwl 0x8(%rax), %ecx
cmpw %r13w, %cx
cmovgel %r13d, %ecx
movl %ecx, %r13d
cmpw %r13w, %bp
jge 0x270ec
movq %r15, (%rsp)
movq %rbx, 0x8(%rsp)
movzwl 0xc(%rax), %r15d
cmpb $-0x4, %r15b
je 0x26e8d
movzwl %r15w, %esi
movq (%rsp), %rcx
movq 0x20(%rcx), %rax
leaq 0x20(%rsp), %rdi
movq %rax, 0x20(%rdi)
vmovups (%rcx), %ymm0
vmovups %ymm0, (%rdi)
vzeroupper
callq 0x9240
testb %al, %al
je 0x270f6
movl %r13d, %eax
negl %eax
movl %ebp, %ecx
negl %ecx
leal -0x1(%r12), %r8d
movswl %ax, %edx
movswl %cx, %ecx
leaq 0x20(%rsp), %rsi
movq 0x8(%rsp), %rdi
callq 0x26dc8
movl %eax, %r14d
negl %r14d
jmp 0x26e92
movzwl 0x8(%rax), %r13d
jmp 0x27012
leaq 0x3197(%rip), %rdi      # 0x2a294
leaq 0x6a18(%rip), %rsi      # 0x2db1c
leaq 0x6a1d(%rip), %rcx      # 0x2db28
movl $0x65, %edx
callq 0x41b0
jmp 0x27117
movq %rax, %rbx
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x27129
callq 0x43d0
movq %rbx, %rdi
callq 0x45b0
nop