// File: tewalds[P]morat/hex/agentpns.cpp
// Function: Morat::Hex::AgentPNS::AgentThread::pns(Morat::Hex::Board const&, Morat::Hex::AgentPNS::Node*, int, unsigned int, unsigned int)
bool AgentPNS::AgentThread::pns(const Board & board, Node * node, int depth, uint32_t tp, uint32_t td){
	// no children, create them
	if(node->children.empty()){
		treelen.add(depth);

		if(node->terminal())
			return true;

		if(agent->need_gc())
			return false;

		if(!node->children.lock())
			return false;

		CompactTree<Node>::Children temp;
		temp.alloc(board.moves_avail(), agent->ctmem);

		if(agent->lbdist)
			dists.run(&board);

		unsigned int i = 0;
		for (auto move : board) {
			unsigned int pd;
			Outcome outcome;

			if(agent->ab){
				Board next = board;
				next.move(move);

				pd = 0;
				outcome = (agent->ab == 1 ? solve1ply(next, pd) : solve2ply(next, pd));
			}else{
				pd = 1;
				outcome = board.test_outcome(move);
			}

			if(agent->lbdist && outcome != Outcome::UNKNOWN)
				pd = dists.get(move);

			temp[i] = Node(move).outcome(outcome, board.to_play(), agent->ties, pd);
			i++;
		}
		nodes_seen += i;
		PLUS(agent->nodes_seen, i);
		PLUS(agent->nodes, i);
		temp.shrink(i); //if symmetry, there may be extra moves to ignore
		node->children.swap(temp);
		assert(temp.unlock());

		updatePDnum(node);

		return (agent->nodes_seen >= agent->max_nodes_seen);
	}

	bool mem;
	do{
		Node * child = node->children.begin(), // the best move to explore
		     * child2 = node->children.begin();// second best for thresholds

		uint32_t tpc, tdc; // the thresholds

		if(agent->df){
			for(auto & i : node->children){
				if(i.refdelta() <= child->refdelta()){
					child2 = child;
					child = & i;
				}else if(i.refdelta() < child2->refdelta()){
					child2 = & i;
				}
			}

			tpc = std::min(INF32/2, (td + child->phi - node->delta));
			tdc = std::min(tp, (uint32_t)(child2->delta*(1.0 + agent->epsilon) + 1));
		}else{
			tpc = tdc = 0;
			for(auto & i : node->children)
				if(child->refdelta() > i.refdelta())
					child = & i;
		}

		Board next = board;
		next.move(child->move);

		child->ref();
		uint64_t seen_before = nodes_seen;
		mem = pns(next, child, depth + 1, tpc, tdc);
		child->deref();
		PLUS(child->work, nodes_seen - seen_before);

		if(updatePDnum(node) && !agent->df)
			break;

	}while(!agent->timeout && mem && (!agent->df || (node->phi < tp && node->delta < td)));

	return mem;
}

// Assembly:
subq $0x268, %rsp            # imm = 0x268
movq %rdi, 0x258(%rsp)
movq %rsi, 0x250(%rsp)
movq %rdx, 0x248(%rsp)
movl %ecx, 0x244(%rsp)
movl %r8d, 0x240(%rsp)
movl %r9d, 0x23c(%rsp)
movq 0x258(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x248(%rsp), %rdi
addq $0x18, %rdi
callq 0x305c0
testb $0x1, %al
jne 0x2e0fd
jmp 0x2e71b
movq 0x78(%rsp), %rdi
addq $0x9ca8, %rdi           # imm = 0x9CA8
movl 0x244(%rsp), %esi
callq 0x29180
movq 0x248(%rsp), %rdi
callq 0x305e0
testb $0x1, %al
jne 0x2e128
jmp 0x2e135
movb $0x1, 0x267(%rsp)
jmp 0x2ec01
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rdi
callq 0x30620
testb $0x1, %al
jne 0x2e149
jmp 0x2e156
movb $0x0, 0x267(%rsp)
jmp 0x2ec01
movq 0x248(%rsp), %rdi
addq $0x18, %rdi
callq 0x30650
testb $0x1, %al
jne 0x2e178
movb $0x0, 0x267(%rsp)
jmp 0x2ec01
leaq 0x230(%rsp), %rdi
callq 0x30690
movq 0x250(%rsp), %rdi
callq 0x1d310
movl %eax, 0x74(%rsp)
jmp 0x2e198
movl 0x74(%rsp), %esi
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rdx
addq $0x70, %rdx
leaq 0x230(%rsp), %rdi
callq 0x306b0
jmp 0x2e1b8
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rax
testb $0x1, 0x1535(%rax)
je 0x2e21a
movq 0x78(%rsp), %rdi
addq $0x48, %rdi
movq 0x250(%rsp), %rsi
leaq 0x3f2dc(%rip), %rax     # 0x6d4be
movb (%rax), %al
movb %al, 0x223(%rsp)
movzbl 0x223(%rsp), %ecx
movl $0x1, %edx
callq 0x29270
jmp 0x2e1ff
jmp 0x2e21a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
jmp 0x2e709
movl $0x0, 0x21c(%rsp)
movq 0x250(%rsp), %rax
movq %rax, 0x210(%rsp)
movq 0x210(%rsp), %rdi
callq 0x1d370
movq %rdx, 0x60(%rsp)
movq %rax, 0x68(%rsp)
jmp 0x2e24e
movq 0x60(%rsp), %rax
movq 0x68(%rsp), %rcx
movq %rcx, 0x1f0(%rsp)
movq %rax, 0x1f8(%rsp)
movq 0x1f0(%rsp), %rax
movq 0x1f5(%rsp), %rcx
movq %rcx, 0x205(%rsp)
movq %rax, 0x200(%rsp)
movq 0x210(%rsp), %rdi
callq 0x1d3a0
movq %rdx, 0x50(%rsp)
movq %rax, 0x58(%rsp)
jmp 0x2e2a1
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rcx
movq %rcx, 0x1d0(%rsp)
movq %rax, 0x1d8(%rsp)
movq 0x1d0(%rsp), %rax
movq %rax, 0x1e0(%rsp)
movl 0x1d8(%rsp), %eax
movl %eax, 0x1e8(%rsp)
movb 0x1dc(%rsp), %al
movb %al, 0x1ec(%rsp)
leaq 0x200(%rsp), %rdi
leaq 0x1e0(%rsp), %rsi
callq 0x1d3f0
movb %al, 0x4f(%rsp)
jmp 0x2e302
movb 0x4f(%rsp), %al
testb $0x1, %al
jne 0x2e30f
jmp 0x2e5f8
leaq 0x200(%rsp), %rdi
callq 0x1d420
movq %rax, 0x40(%rsp)
jmp 0x2e323
movq 0x40(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x1cc(%rsp)
leaq 0x1c7(%rsp), %rdi
callq 0xff40
jmp 0x2e340
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rax
cmpl $0x0, 0x1528(%rax)
je 0x2e439
movq 0x250(%rsp), %rsi
leaq 0x178(%rsp), %rdi
callq 0x118b0
jmp 0x2e36d
leaq 0x178(%rsp), %rdi
leaq 0x1cc(%rsp), %rsi
movl $0x1, %ecx
movl %ecx, %edx
callq 0x1f410
jmp 0x2e38b
movq 0x78(%rsp), %rax
movl $0x0, 0x1c8(%rsp)
movq 0x40(%rax), %rax
cmpl $0x1, 0x1528(%rax)
jne 0x2e3d0
leaq 0x178(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x30720
movb %al, 0x3f(%rsp)
jmp 0x2e3c3
movb 0x3f(%rsp), %al
movb %al, 0x177(%rsp)
jmp 0x2e3f6
leaq 0x178(%rsp), %rdi
leaq 0x1c8(%rsp), %rsi
callq 0x30870
movb %al, 0x3e(%rsp)
jmp 0x2e3eb
movb 0x3e(%rsp), %al
movb %al, 0x177(%rsp)
movb 0x177(%rsp), %al
movb %al, 0x1c7(%rsp)
leaq 0x178(%rsp), %rdi
callq 0xc040
jmp 0x2e478
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
leaq 0x178(%rsp), %rdi
callq 0xc040
jmp 0x2e709
movl $0x1, 0x1c8(%rsp)
movq 0x250(%rsp), %rdi
leaq 0x1cc(%rsp), %rsi
callq 0x29410
movb %al, 0x3d(%rsp)
jmp 0x2e45f
movb 0x3d(%rsp), %al
movb %al, 0x176(%rsp)
movb 0x176(%rsp), %al
movb %al, 0x1c7(%rsp)
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rax
testb $0x1, 0x1535(%rax)
je 0x2e4e2
leaq 0x3f02f(%rip), %rsi     # 0x6d4c0
leaq 0x1c7(%rsp), %rdi
callq 0x1b350
movb %al, 0x3c(%rsp)
jmp 0x2e4a4
movb 0x3c(%rsp), %al
testb $0x1, %al
jne 0x2e4ae
jmp 0x2e4e2
movq 0x78(%rsp), %rdi
addq $0x48, %rdi
movl 0x1cc(%rsp), %eax
movl %eax, 0x170(%rsp)
movl 0x170(%rsp), %esi
callq 0x30a50
movl %eax, 0x38(%rsp)
jmp 0x2e4d7
movl 0x38(%rsp), %eax
movl %eax, 0x1c8(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0x1cc(%rsp), %rsi
movl $0x1, %edx
callq 0x30070
jmp 0x2e4fe
movb 0x1c7(%rsp), %al
movb %al, 0x14f(%rsp)
movq 0x250(%rsp), %rdi
callq 0x1a8a0
movb %al, 0x37(%rsp)
jmp 0x2e51f
movq 0x78(%rsp), %rax
movb 0x37(%rsp), %cl
movb %cl, 0x14e(%rsp)
movq 0x40(%rax), %rax
movb 0x1534(%rax), %al
movb %al, 0x14d(%rsp)
movl 0x1c8(%rsp), %r8d
movzbl 0x14d(%rsp), %ecx
movzbl 0x14e(%rsp), %edx
movzbl 0x14f(%rsp), %esi
leaq 0x150(%rsp), %rdi
callq 0x30ad0
movq %rax, 0x28(%rsp)
jmp 0x2e574
movl 0x21c(%rsp), %esi
leaq 0x230(%rsp), %rdi
callq 0x30c20
movq %rax, 0x20(%rsp)
jmp 0x2e58f
movq 0x28(%rsp), %rsi
movq 0x20(%rsp), %rdi
callq 0x30cd0
jmp 0x2e5a0
leaq 0x150(%rsp), %rdi
callq 0x30100
movl 0x21c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x21c(%rsp)
leaq 0x200(%rsp), %rdi
callq 0x1d4b0
jmp 0x2e5cd
jmp 0x2e2e7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x30100
jmp 0x2e709
movq 0x78(%rsp), %rax
movl 0x21c(%rsp), %ecx
movl %ecx, %edx
movq 0x9cc8(%rax), %rcx
addq %rdx, %rcx
movq %rcx, 0x9cc8(%rax)
movq 0x40(%rax), %rdi
addq $0x1518, %rdi           # imm = 0x1518
leaq 0x21c(%rsp), %rsi
callq 0x1d5c0
jmp 0x2e631
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rdi
addq $0x58, %rdi
leaq 0x21c(%rsp), %rsi
callq 0x1d5c0
jmp 0x2e64d
movl 0x21c(%rsp), %esi
leaq 0x230(%rsp), %rdi
callq 0x30d60
jmp 0x2e663
movq 0x248(%rsp), %rdi
addq $0x18, %rdi
leaq 0x230(%rsp), %rsi
callq 0x30d90
jmp 0x2e67e
leaq 0x230(%rsp), %rdi
callq 0x30e10
movb %al, 0x1f(%rsp)
jmp 0x2e691
movb 0x1f(%rsp), %al
testb $0x1, %al
jne 0x2e69b
jmp 0x2e69d
jmp 0x2e6bc
leaq 0x1ff16(%rip), %rdi     # 0x4e5ba
leaq 0x201ad(%rip), %rsi     # 0x4e858
movl $0x89, %edx
leaq 0x20206(%rip), %rcx     # 0x4e8bd
callq 0x52a0
movq 0x78(%rsp), %rdi
movq 0x248(%rsp), %rsi
callq 0x2ec20
jmp 0x2e6d0
movq 0x78(%rsp), %rcx
movq 0x40(%rcx), %rax
movq 0x1518(%rax), %rax
movq 0x40(%rcx), %rcx
cmpq 0x1520(%rcx), %rax
setae %al
andb $0x1, %al
movb %al, 0x267(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x30e50
jmp 0x2ec01
leaq 0x230(%rsp), %rdi
callq 0x30e50
jmp 0x2ec12
jmp 0x2e71d
movq 0x248(%rsp), %rdi
addq $0x18, %rdi
callq 0x30e90
movq %rax, 0x140(%rsp)
movq 0x248(%rsp), %rdi
addq $0x18, %rdi
callq 0x30e90
movq %rax, %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x138(%rsp)
movq 0x40(%rax), %rax
testb $0x1, 0x152c(%rax)
je 0x2e923
movq 0x248(%rsp), %rax
addq $0x18, %rax
movq %rax, 0x128(%rsp)
movq 0x128(%rsp), %rdi
callq 0x30e90
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rdi
callq 0x30ee0
movq %rax, 0x118(%rsp)
movq 0x120(%rsp), %rax
cmpq 0x118(%rsp), %rax
je 0x2e86b
movq 0x120(%rsp), %rax
movq %rax, 0x110(%rsp)
movq 0x110(%rsp), %rdi
callq 0x30f30
movl %eax, 0x18(%rsp)
movq 0x140(%rsp), %rdi
callq 0x30f30
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
ja 0x2e816
movq 0x140(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x110(%rsp), %rax
movq %rax, 0x140(%rsp)
jmp 0x2e850
movq 0x110(%rsp), %rdi
callq 0x30f30
movl %eax, 0x14(%rsp)
movq 0x138(%rsp), %rdi
callq 0x30f30
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jae 0x2e84e
movq 0x110(%rsp), %rax
movq %rax, 0x138(%rsp)
jmp 0x2e850
jmp 0x2e852
movq 0x120(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x120(%rsp)
jmp 0x2e7a6
movl $0x1ffffffe, 0x10c(%rsp) # imm = 0x1FFFFFFE
movl 0x23c(%rsp), %eax
movq 0x140(%rsp), %rcx
movl (%rcx), %ecx
addl %ecx, %eax
movq 0x248(%rsp), %rcx
movl 0x4(%rcx), %ecx
subl %ecx, %eax
movl %eax, 0x108(%rsp)
leaq 0x10c(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x30f50
movq %rax, %rcx
movq 0x78(%rsp), %rax
movl (%rcx), %ecx
movl %ecx, 0x134(%rsp)
movq 0x138(%rsp), %rcx
vcvtusi2sdl 0x4(%rcx), %xmm0, %xmm1
movq 0x40(%rax), %rax
vmovss 0x1530(%rax), %xmm2
vcvtss2sd %xmm2, %xmm0, %xmm0
vmovsd 0x1d726(%rip), %xmm2    # 0x4c010
vaddsd %xmm2, %xmm0, %xmm0
vfmadd213sd %xmm2, %xmm1, %xmm0 # xmm0 = (xmm1 * xmm0) + xmm2
vcvttsd2usi %xmm0, %eax
movl %eax, 0x104(%rsp)
leaq 0x240(%rsp), %rdi
leaq 0x104(%rsp), %rsi
callq 0x30f50
movl (%rax), %eax
movl %eax, 0x130(%rsp)
jmp 0x2e9eb
movl $0x0, 0x130(%rsp)
movl $0x0, 0x134(%rsp)
movq 0x248(%rsp), %rax
addq $0x18, %rax
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x30e90
movq %rax, 0xf0(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x30ee0
movq %rax, 0xe8(%rsp)
movq 0xf0(%rsp), %rax
cmpq 0xe8(%rsp), %rax
je 0x2e9e9
movq 0xf0(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0x140(%rsp), %rdi
callq 0x30f30
movl %eax, 0x10(%rsp)
movq 0xe0(%rsp), %rdi
callq 0x30f30
movl %eax, %ecx
movl 0x10(%rsp), %eax
cmpl %ecx, %eax
jbe 0x2e9d1
movq 0xe0(%rsp), %rax
movq %rax, 0x140(%rsp)
jmp 0x2e9d3
movq 0xf0(%rsp), %rax
addq $0x20, %rax
movq %rax, 0xf0(%rsp)
jmp 0x2e977
jmp 0x2e9eb
movq 0x250(%rsp), %rsi
leaq 0x98(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x118b0
movq 0x8(%rsp), %rdi
movq 0x140(%rsp), %rsi
addq $0x12, %rsi
movl $0x1, %ecx
movl %ecx, %edx
callq 0x1c500
jmp 0x2ea24
movq 0x140(%rsp), %rdi
callq 0x30f90
jmp 0x2ea33
movq 0x78(%rsp), %rdi
movq 0x9cc8(%rdi), %rax
movq %rax, 0x90(%rsp)
movq 0x140(%rsp), %rdx
movl 0x244(%rsp), %ecx
incl %ecx
movl 0x134(%rsp), %r8d
movl 0x130(%rsp), %r9d
leaq 0x98(%rsp), %rsi
callq 0x2e0a0
movb %al, 0x7(%rsp)
jmp 0x2ea7b
movb 0x7(%rsp), %al
andb $0x1, %al
movb %al, 0x14c(%rsp)
movq 0x140(%rsp), %rdi
callq 0x30fc0
jmp 0x2ea97
movq 0x78(%rsp), %rax
movq 0x140(%rsp), %rdi
addq $0x8, %rdi
movq 0x9cc8(%rax), %rax
movq 0x90(%rsp), %rcx
subq %rcx, %rax
movq %rax, 0x88(%rsp)
leaq 0x88(%rsp), %rsi
callq 0x2a800
jmp 0x2ead1
movq 0x78(%rsp), %rdi
movq 0x248(%rsp), %rsi
callq 0x2ec20
movb %al, 0x6(%rsp)
jmp 0x2eae9
movb 0x6(%rsp), %al
testb $0x1, %al
jne 0x2eaf3
jmp 0x2eb38
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rax
testb $0x1, 0x152c(%rax)
jne 0x2eb38
movl $0x4, 0x84(%rsp)
jmp 0x2eb43
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
leaq 0x98(%rsp), %rdi
callq 0xc040
jmp 0x2ec12
movl $0x0, 0x84(%rsp)
leaq 0x98(%rsp), %rdi
callq 0xc040
movl 0x84(%rsp), %eax
testl %eax, %eax
je 0x2eb62
jmp 0x2eb5d
jmp 0x2ebf1
jmp 0x2eb64
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rax
movb 0x8(%rax), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, 0x5(%rsp)
jne 0x2ebe5
xorl %eax, %eax
testb $0x1, 0x14c(%rsp)
movb %al, 0x5(%rsp)
je 0x2ebe5
movq 0x78(%rsp), %rax
movq 0x40(%rax), %rcx
movb $0x1, %al
testb $0x1, 0x152c(%rcx)
movb %al, 0x4(%rsp)
je 0x2ebdd
movq 0x248(%rsp), %rax
movl (%rax), %ecx
xorl %eax, %eax
cmpl 0x240(%rsp), %ecx
movb %al, 0x3(%rsp)
jae 0x2ebd5
movq 0x248(%rsp), %rax
movl 0x4(%rax), %eax
cmpl 0x23c(%rsp), %eax
setb %al
movb %al, 0x3(%rsp)
movb 0x3(%rsp), %al
movb %al, 0x4(%rsp)
movb 0x4(%rsp), %al
movb %al, 0x5(%rsp)
movb 0x5(%rsp), %al
testb $0x1, %al
jne 0x2e71d
movb 0x14c(%rsp), %al
andb $0x1, %al
movb %al, 0x267(%rsp)
movb 0x267(%rsp), %al
andb $0x1, %al
addq $0x268, %rsp            # imm = 0x268
retq
movq 0x228(%rsp), %rdi
callq 0x5760
nop