// File: /workspace/github_cpp_makefile_star2_O2/tewalds[P]morat/hex/agentmctsthread.cpp
// Function: Morat::Hex::AgentMCTS::do_backup(Morat::Hex::AgentMCTS::Node*, Morat::Hex::AgentMCTS::Node const*, Morat::Side)
bool AgentMCTS::do_backup(Node * node, const Node * backup, Side to_play){
	Outcome node_outcome = node->outcome;
	if(node_outcome >= Outcome::DRAW) //already proven, probably by a different thread
		return true;

	if(backup->outcome == Outcome::UNKNOWN) //nothing proven by this child, so no chance
		return false;

	uint8_t proofdepth = backup->proofdepth;
	if(backup->outcome != to_play){
		int best_outcome = 0;
		backup = NULL;

		for (const auto& child : node->children) {
			Outcome child_outcome = child.outcome; //save a copy to avoid race conditions
			int outcome = 0;

			//these should be sorted in likelyness of matching, most likely first
			if(child_outcome == Outcome::UNKNOWN){ // win/draw/loss
				outcome = 3;
			}else if(child_outcome == to_play){ //win
				backup = &child;
				best_outcome = 6;
				proofdepth = child.proofdepth;
				break;
			}else if(child_outcome == ~to_play){ //loss
				outcome = 0;
			}else if(child_outcome == Outcome::DRAW ||
			         child_outcome == Outcome::DRAW2){ //draw
				if(node_outcome == -to_play) //draw/loss, ie I can't win
					outcome = 4;
				else
					outcome = 2;
			}else if(child_outcome == -~to_play){ //win/draw, ie opponent can't win
				outcome = 5;
			}else if(child_outcome == -to_play){ //draw/loss, ie I can't win
				outcome = 1;
			}else{
				logerr("child_outcome == " + child_outcome.to_s() + "\n");
				assert(false && "How'd I get here? All outcomes should be tested above");
			}

			if(proofdepth < child.proofdepth)
				proofdepth = child.proofdepth;

			auto better_than_best = [&]() -> bool {
				// any child is better than nothing
				if (backup == NULL)
					return true;

				// a better outcome is always preferable
				if (best_outcome < outcome)
					return true;
				if (best_outcome > outcome)
					return false;

				// do we care about depth? if so, take the longest.
				if (longestloss) {
					if (backup->proofdepth < child.proofdepth)
						return true;
					if (backup->proofdepth > child.proofdepth)
						return false;
				}

				// all else equal, take the hardest to solve
				return (backup->exp.num() < child.exp.num());
			};

			if (better_than_best()) {
				best_outcome = outcome;
				backup = &child;
			}
		}

		if(best_outcome == 3) //no win, but found an unknown
			return false;
	}

	if(node->outcome.cas(node_outcome, backup->outcome)){
		node->bestmove = backup->move;
		node->proofdepth = proofdepth + 1;
	}else //if it was in a race, try again, might promote a partial solve to full solve
		return do_backup(node, backup, to_play);

	return (node->outcome >= Outcome::DRAW);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
leaq 0x1568d(%rip), %r12     # 0x26eb1
movl %ecx, %r14d
movb $0x3, %al
movq %rdx, %r13
movl %r14d, %edx
leaq 0x22(%rsi), %rbx
leal -0x3(%r14), %ecx
movq %rdi, 0x20(%rsp)
movq %rsi, 0x18(%rsp)
subb %r14b, %al
negb %dl
movl %ecx, 0xc(%rsp)
movb %al, 0x6(%rsp)
movb %dl, 0x4(%rsp)
pushq $0x3
popq %rbp
movq %rbx, 0x10(%rsp)
movb (%rbx), %cl
movb (%r12), %dl
cmpb %dl, %cl
setge %r8b
jge 0x119e5
leaq 0x1563b(%rip), %rax     # 0x26eae
movb 0x22(%r13), %dil
movb (%rax), %sil
cmpb %sil, %dil
je 0x119ed
movb 0x23(%r13), %r15b
cmpb %r14b, %dil
jne 0x11894
movl %r14d, %eax
jmp 0x119ae
movq 0x18(%rsp), %rax
movl %r8d, 0x8(%rsp)
movl $0x0, %r13d
movl $0x0, %edi
movq 0x28(%rax), %r9
leaq 0x10(%r9), %r8
cmpq $0x2, %r9
cmovaeq %r8, %r13
jb 0x118ca
movzwl 0x6(%r9), %edi
imulq $0x30, %rdi, %rdi
addq %rdi, %r8
movq %r8, %rdi
leaq 0x155e3(%rip), %rax     # 0x26eb4
xorl %r8d, %r8d
cmpb 0xc(%rsp), %cl
movb (%rax), %al
sete %r8b
xorl %r9d, %r9d
xorl %r12d, %r12d
leal 0x2(%r8,%r8), %r10d
movb %al, 0x5(%rsp)
movq 0x20(%rsp), %rax
movb 0xb0(%rax), %al
cmpq %rdi, %r13
je 0x1198c
movb 0x22(%r13), %r8b
movl %ebp, %ebx
movb %r8b, 0x7(%rsp)
cmpb %sil, %r8b
je 0x11923
cmpb %r14b, %r8b
je 0x1199b
xorl %ebx, %ebx
cmpb 0x6(%rsp), %r8b
jne 0x11964
movzbl 0x23(%r13), %r8d
movzbl %r15b, %r11d
cmpb %r8b, %r11b
movl %r8d, %r15d
cmoval %r11d, %r15d
testq %r9, %r9
je 0x11958
cmpl %ebx, %r12d
jl 0x11958
ja 0x1195e
testb $0x1, %al
je 0x1194e
cmpb %r8b, 0x23(%r9)
jb 0x11958
ja 0x1195e
movq 0x18(%r9), %r8
cmpq 0x18(%r13), %r8
jae 0x1195e
movq %r13, %r9
movl %ebx, %r12d
addq $0x30, %r13
jmp 0x118f8
movl %r10d, %ebx
cmpb %dl, %r8b
je 0x11923
movl %r10d, %ebx
cmpb 0x5(%rsp), %r8b
je 0x11923
pushq $0x5
popq %rbx
cmpb 0x4(%rsp), %r8b
je 0x11923
pushq $0x1
popq %rbx
cmpb 0xc(%rsp), %r8b
je 0x11923
jmp 0x11a0b
cmpl $0x3, %r12d
je 0x119f5
movb 0x22(%r9), %al
movq %r9, %r13
jmp 0x119a2
movb 0x23(%r13), %r15b
movl %r14d, %eax
movq 0x10(%rsp), %rbx
leaq 0x15503(%rip), %r12     # 0x26eb1
movzbl %cl, %esi
movzbl %al, %edx
movq %rbx, %rdi
callq 0x20e62
testb %al, %al
je 0x1185a
movzwl 0x24(%r13), %eax
movq 0x18(%rsp), %rcx
incb %r15b
movw %ax, 0x26(%rcx)
movb %r15b, 0x23(%rcx)
movb 0x22(%rcx), %al
cmpb (%r12), %al
setge %al
jmp 0x119e7
movb $0x1, %al
movl %eax, 0x8(%rsp)
jmp 0x119f5
movl $0x0, 0x8(%rsp)
movl 0x8(%rsp), %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x48(%rsp), %rbx
leaq 0x7(%rsp), %rsi
movq %rbx, %rdi
callq 0x20caa
leaq 0x12be8(%rip), %rsi     # 0x2460c
leaq 0x28(%rsp), %rdi
movq %rbx, %rdx
callq 0xcf8b
leaq 0x10ea4(%rip), %rdx     # 0x228dc
leaq 0x68(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x8051
leaq 0x68(%rsp), %rbx
movq %rbx, %rdi
callq 0xd451
movq %rbx, %rdi
callq 0x5150
leaq 0x28(%rsp), %rdi
callq 0x5150
leaq 0x48(%rsp), %rdi
callq 0x5150
leaq 0x12ba7(%rip), %rdi     # 0x2461e
leaq 0x12abb(%rip), %rsi     # 0x24539
leaq 0x12bda(%rip), %rcx     # 0x2465f
movl $0x116, %edx            # imm = 0x116
callq 0x51f0
leaq 0x28(%rsp), %rdi
movq %rax, %rbx
callq 0x5150
jmp 0x11aa1
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x5150
movq %rbx, %rdi
callq 0x5650
nop