// File: ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: SolitaireWorker::Run(int)
SolveResult SolitaireWorker::Run(int numThreads) {
	solitaire->MakeAutoMoves();
	if (solitaire->MovesAvailableCount() == 0) { return solitaire->FoundationCount() == 52 ? SolvedMinimal : Impossible; }

	openCount = 1;
	maxFoundationCount = solitaire->FoundationCount();
	bestSolutionMoveCount = 512;
	bestSolution[0].Count = 255;
	startMoves = solitaire->MinimumMovesLeft() + solitaire->MovesMadeNormalizedCount();
	int powerOf2 = 1;
	while (maxClosedCount > (1 << (powerOf2 + 2))) {
		powerOf2++;
	}
	HashMap<int> * closed = new HashMap<int>(powerOf2);

	shared_ptr<MoveNode> firstNode = solitaire->MovesMadeCount() > 0 ? make_shared<MoveNode>(solitaire->GetMoveMade(solitaire->MovesMadeCount() - 1)) : NULL;
	shared_ptr<MoveNode> node = firstNode;
	for (int i = solitaire->MovesMadeCount() - 2; i >= 0; i--) {
		node->Parent = make_shared<MoveNode>(solitaire->GetMoveMade(i));
		node = node->Parent;
	}
	open[startMoves].push(firstNode);

	thread * threads = new thread[numThreads];
	for (int i = 0; i < numThreads; i++) {
		threads[i] = thread(&SolitaireWorker::RunMinimalWorker, this, (void*)closed);
		this_thread::sleep_for(chrono::milliseconds(23));
	}

	for (int i = 0; i < numThreads; i++) {
		threads[i].join();
	}
	delete[] threads;

	//Reset game to best solution found
	solitaire->ResetGame();
	for (int i = 0; bestSolution[i].Count < 255; i++) {
		solitaire->MakeMove(bestSolution[i]);
	}

	SolveResult result = closed->Size() >= maxClosedCount ? (maxFoundationCount == 52 ? SolvedMayNotBeMinimal : CouldNotComplete) : (maxFoundationCount == 52 ? SolvedMinimal : Impossible);
	delete closed;
	return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq 0xa800(%rax), %rdi
callq 0x9260
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
callq 0x7f00
cmpl $0x0, %eax
jne 0x8c3b
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
callq 0x80d0
movl %eax, %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x34, %edx
cmovel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x924a
movq -0xd8(%rbp), %rax
movl $0x1, 0xa830(%rax)
movq 0xa800(%rax), %rdi
callq 0x80d0
movl %eax, %ecx
movq -0xd8(%rbp), %rax
movl %ecx, 0xa834(%rax)
movl $0x200, 0xa838(%rax)    # imm = 0x200
movb $-0x1, 0xa002(%rax)
movq 0xa800(%rax), %rdi
callq 0x8130
movl %eax, %ecx
movq -0xd8(%rbp), %rax
movl %ecx, -0xdc(%rbp)
movq 0xa800(%rax), %rdi
callq 0x7f50
movl -0xdc(%rbp), %ecx
movl %eax, %edx
movq -0xd8(%rbp), %rax
addl %edx, %ecx
movl %ecx, 0xa83c(%rax)
movl $0x1, -0x18(%rbp)
movq -0xd8(%rbp), %rax
movl 0xa840(%rax), %eax
movl -0x18(%rbp), %ecx
addl $0x2, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
cmpl %ecx, %eax
jle 0x8ce8
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x8cbd
movl $0x20, %edi
callq 0x3240
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
movl -0x18(%rbp), %esi
callq 0xf2e0
jmp 0x8d09
movq -0xd8(%rbp), %rax
movq -0xe8(%rbp), %rcx
movq %rcx, -0x20(%rbp)
movq 0xa800(%rax), %rdi
callq 0x80f0
cmpl $0x0, %eax
jle 0x8d70
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rcx
movq %rcx, -0xf0(%rbp)
movq 0xa800(%rax), %rdi
callq 0x80f0
movq -0xf0(%rbp), %rdi
movl %eax, %esi
subl $0x1, %esi
callq 0x92b0
movl %eax, -0x44(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x44(%rbp), %rsi
callq 0xf420
jmp 0x8d7d
leaq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ab0
leaq -0x58(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0xf490
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
callq 0x80f0
movl %eax, -0xf4(%rbp)
jmp 0x8da5
movl -0xf4(%rbp), %eax
subl $0x2, %eax
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jl 0x8e74
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
movl -0x5c(%rbp), %esi
callq 0x92b0
movl %eax, -0xf8(%rbp)
jmp 0x8dd9
movl -0xf8(%rbp), %eax
movl %eax, -0x74(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x74(%rbp), %rsi
callq 0xf420
jmp 0x8df1
leaq -0x58(%rbp), %rdi
callq 0xf020
movq %rax, %rdi
leaq -0x70(%rbp), %rsi
callq 0x5ad0
leaq -0x70(%rbp), %rdi
callq 0x5b00
leaq -0x58(%rbp), %rdi
callq 0xf020
movq %rax, %rsi
leaq -0x58(%rbp), %rdi
callq 0x5b20
movl -0x5c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x8db1
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl $0x20, %esi
callq 0x3250
jmp 0x9256
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x5b00
leaq -0x40(%rbp), %rdi
callq 0x5b00
jmp 0x9256
movq -0xd8(%rbp), %rdi
movslq 0xa83c(%rdi), %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
addq %rax, %rdi
leaq -0x40(%rbp), %rsi
callq 0xf2b0
jmp 0x8e98
movslq -0x14(%rbp), %rax
movq %rax, -0x108(%rbp)
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
addq $0x8, %rdi
movq $-0x1, %rax
cmovbq %rax, %rdi
testb %cl, %cl
cmovneq %rax, %rdi
callq 0x3030
movq %rax, -0x100(%rbp)
jmp 0x8ed4
movq -0x108(%rbp), %rax
movq -0x100(%rbp), %rcx
movq %rax, (%rcx)
addq $0x8, %rcx
movq %rcx, -0x110(%rbp)
cmpq $0x0, %rax
je 0x8f4d
movq -0x110(%rbp), %rax
movq -0x108(%rbp), %rdx
shlq $0x3, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, -0x120(%rbp)
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0xf4c0
movq -0x128(%rbp), %rax
movq -0x120(%rbp), %rcx
addq $0x8, %rax
cmpq %rcx, %rax
movq %rax, -0x118(%rbp)
jne 0x8f1c
movq -0x110(%rbp), %rax
movq %rax, -0x80(%rbp)
movl $0x0, -0x84(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x9037
movq -0xd8(%rbp), %rax
leaq -0x280f(%rip), %rcx     # 0x6770
movq %rcx, -0xa0(%rbp)
movq $0x0, -0x98(%rbp)
movq %rax, -0xa8(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0xa8(%rbp), %rdx
leaq -0xb0(%rbp), %rcx
callq 0xf4e0
jmp 0x8fc6
movq -0x80(%rbp), %rax
movslq -0x84(%rbp), %rcx
leaq (%rax,%rcx,8), %rdi
leaq -0x90(%rbp), %rsi
movq %rsi, -0x130(%rbp)
callq 0xf5b0
movq -0x130(%rbp), %rdi
callq 0xf5f0
movl $0x17, -0xbc(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0xbc(%rbp), %rsi
callq 0xef90
jmp 0x9013
leaq -0xb8(%rbp), %rdi
callq 0xeee0
jmp 0x9021
jmp 0x9023
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x8f62
movl $0x0, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x9075
movq -0x80(%rbp), %rax
movslq -0xc0(%rbp), %rcx
leaq (%rax,%rcx,8), %rdi
callq 0x33a0
jmp 0x9062
jmp 0x9064
movl -0xc0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc0(%rbp)
jmp 0x9041
movq -0x80(%rbp), %rax
movq %rax, -0x138(%rbp)
cmpq $0x0, %rax
je 0x910c
movq -0x138(%rbp), %rcx
movq %rcx, %rax
addq $-0x8, %rax
movq %rax, -0x150(%rbp)
movq -0x8(%rcx), %rdx
movq %rdx, -0x148(%rbp)
shlq $0x3, %rdx
movq %rcx, %rax
addq %rdx, %rax
cmpq %rax, %rcx
movq %rax, -0x140(%rbp)
je 0x90f1
movq -0x140(%rbp), %rdi
addq $-0x8, %rdi
movq %rdi, -0x158(%rbp)
callq 0xf5f0
movq -0x138(%rbp), %rcx
movq -0x158(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x140(%rbp)
jne 0x90c0
movq -0x150(%rbp), %rdi
movq -0x148(%rbp), %rsi
shlq $0x3, %rsi
addq $0x8, %rsi
callq 0x3420
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
callq 0x7120
jmp 0x9121
movl $0x0, -0xc4(%rbp)
movq -0xd8(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movzbl 0xa002(%rax,%rcx,4), %eax
cmpl $0xff, %eax
jge 0x918a
movq -0xd8(%rbp), %rax
movq 0xa800(%rax), %rdi
movslq -0xc4(%rbp), %rcx
movl 0xa000(%rax,%rcx,4), %eax
movl %eax, -0xc8(%rbp)
movl -0xc8(%rbp), %esi
callq 0x7150
jmp 0x9177
jmp 0x9179
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x912b
movq -0x20(%rbp), %rdi
callq 0xee50
movl %eax, -0x15c(%rbp)
jmp 0x919b
movl -0x15c(%rbp), %eax
movq -0xd8(%rbp), %rcx
cmpl 0xa840(%rcx), %eax
jl 0x91d5
movq -0xd8(%rbp), %rax
movl 0xa834(%rax), %edx
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpl $0x34, %edx
cmovel %ecx, %eax
movl %eax, -0x160(%rbp)
jmp 0x91f5
movq -0xd8(%rbp), %rax
movl 0xa834(%rax), %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x34, %edx
cmovel %ecx, %eax
movl %eax, -0x160(%rbp)
movl -0x160(%rbp), %eax
movl %eax, -0xcc(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x168(%rbp)
cmpq $0x0, %rax
je 0x922f
movq -0x168(%rbp), %rdi
callq 0xf620
movq -0x168(%rbp), %rdi
movl $0x20, %esi
callq 0x3250
movl -0xcc(%rbp), %eax
movl %eax, -0x4(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x5b00
leaq -0x40(%rbp), %rdi
callq 0x5b00
movl -0x4(%rbp), %eax
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x33d0
nop