// File: /workspace/github_cpp_makefile_star2_O2/tewalds[P]morat/pentago/agentmctsthread.cpp
// Function: Morat::Pentago::AgentMCTS::do_backup(Morat::Pentago::AgentMCTS::Node*, Morat::Pentago::AgentMCTS::Node*, Morat::Side)
bool AgentMCTS::do_backup(Node * node, 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){
		uint64_t sims = 0, bestsims = 0, outcome = 0, best_outcome = 0;
		backup = NULL;

		Node * child = node->children.begin(),
			 * end = node->children.end();

		for( ; child != end; child++){
			Outcome child_outcome = child->outcome; //save a copy to avoid race conditions

			if(proofdepth < child->proofdepth+1)
				proofdepth = child->proofdepth+1;

			//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;
				outcome = 6;
				proofdepth = child->proofdepth+1;
				break;
			}else if(child_outcome == ~to_play){ //loss
				outcome = 0;
			}else if(child_outcome == Outcome::DRAW){ //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");
			}

			sims = child->exp.num();
			if(best_outcome < outcome){ //better outcome is always preferable
				best_outcome = outcome;
				bestsims = sims;
				backup = child;
			}else if(best_outcome == outcome && ((outcome == 0 && bestsims < sims) || bestsims > sims)){
				//find long losses or easy wins/draws
				bestsims = sims;
				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;
	}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 0x12fc3(%rip), %r13     # 0x24c19
movl %ecx, %r14d
movl %r14d, %eax
movb $0x3, %bpl
leaq 0x12(%rsi), %rbx
movq %rdx, %r12
movq %rsi, 0x10(%rsp)
negb %al
subb %r14b, %bpl
movq %rbx, 0x18(%rsp)
movb %al, 0xa(%rsp)
leal -0x3(%r14), %eax
movl %eax, 0xc(%rsp)
movb (%rbx), %r11b
movb (%r13), %dl
cmpb %dl, %r11b
setge %al
jge 0x11e2c
leaq 0x12f7b(%rip), %rcx     # 0x24c16
movb 0x12(%r12), %r8b
movb (%rcx), %sil
cmpb %sil, %r8b
je 0x11e30
movb 0x13(%r12), %dil
cmpb %r14b, %r8b
jne 0x11cc1
movl %r14d, %eax
movl %edi, %r15d
jmp 0x11df6
movq 0x10(%rsp), %r8
movl $0x0, %r12d
movq 0x18(%r8), %r10
movl $0x0, %r8d
leaq 0x10(%r10), %r9
cmpq $0x2, %r10
cmovaeq %r9, %r12
jb 0x11cf3
movzwl 0x6(%r10), %r8d
shll $0x5, %r8d
addq %r8, %r9
movq %r9, %r8
xorl %r9d, %r9d
cmpb 0xc(%rsp), %r11b
movb %r11b, 0x9(%rsp)
sete %r9b
xorl %r10d, %r10d
xorl %r11d, %r11d
xorl %r13d, %r13d
leaq 0x2(%r9,%r9), %rcx
movq %rcx, 0x20(%rsp)
cmpq %r8, %r12
je 0x11dd4
movb 0x12(%r12), %bl
movb %bl, 0xb(%rsp)
movb 0x13(%r12), %r9b
leal 0x1(%r9), %r15d
cmpb %dil, %r9b
movzbl %dil, %r9d
movzbl %r15b, %edi
cmovbl %r9d, %edi
cmpb %sil, %bl
jne 0x11d4f
xorl %r15d, %r15d
pushq $0x3
popq %r9
jmp 0x11d71
cmpb %r14b, %bl
je 0x11dda
cmpb %bpl, %bl
jne 0x11d65
movb $0x1, %r15b
xorl %r9d, %r9d
jmp 0x11d71
cmpb %dl, %bl
jne 0x11db7
movq 0x20(%rsp), %r9
xorl %r15d, %r15d
movq 0x8(%r12), %rbx
cmpq %r9, %r10
jae 0x11d86
movq %r9, %r10
movq %rbx, %r11
movq %r12, %r13
jmp 0x11dae
jne 0x11dae
cmpq %rbx, %r11
movl %ebp, %ecx
setb %r9b
seta %bpl
andb %r9b, %r15b
movq %r12, %r9
orb %bpl, %r15b
jne 0x11da6
movq %r11, %rbx
movq %r13, %r9
movl %ecx, %ebp
movq %rbx, %r11
movq %r9, %r13
addq $0x20, %r12
jmp 0x11d17
cmpb 0xa(%rsp), %bl
jne 0x11dc4
xorl %r15d, %r15d
pushq $0x5
jmp 0x11d4b
cmpb 0xc(%rsp), %bl
jne 0x11e44
xorl %r15d, %r15d
pushq $0x1
jmp 0x11d4b
movl %edi, %r15d
movq %r13, %r12
movq 0x18(%rsp), %rbx
leaq 0x12e33(%rip), %r13     # 0x24c19
movb 0x9(%rsp), %r11b
cmpq $0x3, %r10
je 0x11e32
movb 0x12(%r12), %al
movzbl %r11b, %esi
movzbl %al, %edx
movq %rbx, %rdi
callq 0x1df6e
testb %al, %al
je 0x11c81
movzwl 0x14(%r12), %eax
movq 0x10(%rsp), %rcx
movw %ax, 0x16(%rcx)
movb %r15b, 0x13(%rcx)
movb 0x12(%rcx), %al
cmpb (%r13), %al
setge %al
jmp 0x11e32
movb $0x1, %al
jmp 0x11e32
xorl %eax, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x48(%rsp), %rbx
leaq 0xb(%rsp), %rsi
movq %rbx, %rdi
callq 0x1ddb6
leaq 0xfb8b(%rip), %rsi      # 0x219e8
leaq 0x28(%rsp), %rdi
movq %rbx, %rdx
callq 0xaac0
leaq 0xd9a7(%rip), %rdx      # 0x1f818
leaq 0x68(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x7b4d
leaq 0x68(%rsp), %rbx
movq %rbx, %rdi
callq 0xaaae
movq %rbx, %rdi
callq 0x5170
leaq 0x28(%rsp), %rdi
callq 0x5170
leaq 0x48(%rsp), %rdi
callq 0x5170
leaq 0xfb4a(%rip), %rdi      # 0x219fa
leaq 0xfa4a(%rip), %rsi      # 0x21901
leaq 0xfb7d(%rip), %rcx      # 0x21a3b
movl $0xfa, %edx
callq 0x5220
leaq 0x28(%rsp), %rdi
movq %rax, %rbx
callq 0x5170
jmp 0x11eda
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x5170
movq %rbx, %rdi
callq 0x5690