// File: /workspace/github_cpp_makefile_star2_O2/ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: SolitaireWorker::RunMinimalWorker(void*)
void SolitaireWorker::RunMinimalWorker(void * closedPointer) {
	HashMap<int> & closed = *reinterpret_cast<HashMap<int>*>(closedPointer);
	Move movesToMake[512];
	shared_ptr<MoveNode> firstNode = NULL;
	shared_ptr<MoveNode> node = NULL;
	Solitaire s = *solitaire;
	int doneCount = 10;
	while (closed.Size() < maxClosedCount && doneCount > 0) {
		mtx.lock();
		//Check for lowest score length
		int index = startMoves;
		while (index < 512 && open[index].size() == 0) { index++; }

		//End solver if no more states
		if (index >= 512) {
			mtx.unlock();
			doneCount--;
			this_thread::sleep_for(chrono::milliseconds(1));
			continue;
		}

		doneCount = 10;

		//Get next state to evaluate
		openCount--;
		firstNode = open[index].top();
		open[index].pop();
		mtx.unlock();

		//Initialize game to the found state
		s.ResetGame();
		int movesTotal = 0;
		node = firstNode;
		while (node != NULL) {
			movesToMake[movesTotal++] = node->Value;
			node = node->Parent;
		}
		while (movesTotal > 0) {
			s.MakeMove(movesToMake[--movesTotal]);
		}

		//Make any auto moves
		s.UpdateAvailableMoves();
		while (s.MovesAvailableCount() == 1) {
			Move move = s.GetMoveAvailable(0);
			s.MakeMove(move);
			firstNode = make_shared<MoveNode>(move, firstNode);
			s.UpdateAvailableMoves();
		}
		movesTotal = s.MovesMadeNormalizedCount();


		//Check for best solution to foundations
		if (s.FoundationCount() > maxFoundationCount || (s.FoundationCount() == maxFoundationCount && bestSolutionMoveCount > movesTotal)) {
			mtx.lock();
			if (s.FoundationCount() > maxFoundationCount || (s.FoundationCount() == maxFoundationCount && bestSolutionMoveCount > movesTotal)) {
				bestSolutionMoveCount = movesTotal;
				maxFoundationCount = s.FoundationCount();

				//Save solution
				for (int i = s.MovesMadeCount() - 1; i >= 0; i--) {
					bestSolution[i] = s[i];
				}
				bestSolution[s.MovesMadeCount()].Count = 255;
			}
			mtx.unlock();
		} else if (maxFoundationCount == 52) {
			//Dont check state if above or equal to current best solution
			int helper = s.MinimumMovesLeft();
			helper += movesTotal;
			if (helper >= bestSolutionMoveCount) { continue; }
		}

		int movesAvailableCount = s.MovesAvailableCount();
		//Make available moves and add them to be evaulated
		for (int i = 0; i < movesAvailableCount; i++) {
			Move move = s.GetMoveAvailable(i);
			int movesAdded = s.MovesAdded(move);

			s.MakeMove(move);

			movesAdded += movesTotal;
			movesAdded += s.MinimumMovesLeft();
			if (maxFoundationCount < 52 || movesAdded < bestSolutionMoveCount) {
				int helper = movesAdded;
				helper += 52 - s.FoundationCount() + s.RoundCount();
				HashKey key = s.GameState();

				mtx.lock();
				KeyValue<int> * result = closed.Add(key, movesAdded);
				if (result == NULL || result->Value > movesAdded) {
					node = make_shared<MoveNode>(move, firstNode);
					if (result != NULL) { result->Value = movesAdded; }

					openCount++;
					open[helper].push(node);
				}
				mtx.unlock();
			}

			s.UndoMove();
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2198, %rsp           # imm = 0x2198
movq %rsi, 0x40(%rsp)
movq %rdi, (%rsp)
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0x1990, %rdi           # imm = 0x1990
callq 0x34b4
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x3a02
xorps %xmm0, %xmm0
leaq 0x30(%rsp), %rax
movaps %xmm0, (%rax)
leaq 0x20(%rsp), %rdi
movaps %xmm0, (%rdi)
movq (%rsp), %rbx
movq 0xa800(%rbx), %rsi
leaq 0x78(%rsp), %r13
movl $0x1918, %edx           # imm = 0x1918
movq %r13, %rdi
callq 0x2170
leaq 0xa808(%rbx), %rax
movq %rax, 0x10(%rsp)
pushq $0xa
popq %rbx
movq 0x40(%rsp), %rax
movl 0x8(%rax), %eax
movq (%rsp), %rcx
cmpl 0xa840(%rcx), %eax
jge 0x3e16
testl %ebx, %ebx
jle 0x3e16
movq 0x10(%rsp), %rdi
callq 0x7ed2
movq (%rsp), %rax
movslq 0xa83c(%rax), %rbp
movq %rbp, %r12
shlq $0x20, %r12
imulq $0x50, %rbp, %r15
addq %rax, %r15
cmpq $0x1ff, %rbp            # imm = 0x1FF
jg 0x3acd
movq %r15, %rdi
callq 0x8634
testq %rax, %rax
jne 0x3af1
incq %rbp
movabsq $0x100000000, %rax      # imm = 0x100000000
addq %rax, %r12
addq $0x50, %r15
jmp 0x3aa1
movq 0x10(%rsp), %rdi
callq 0x2150
movq $0x1, 0x60(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x7ee5
decl %ebx
jmp 0x3a5e
movq (%rsp), %rcx
decl 0xa830(%rcx)
sarq $0x20, %r12
imulq $0x50, %r12, %rax
leaq (%rcx,%rax), %r15
movq 0x30(%rcx,%rax), %rsi
cmpq 0x38(%rcx,%rax), %rsi
jne 0x3b23
movq 0x48(%r15), %rax
movq -0x8(%rax), %rsi
movl $0x200, %eax            # imm = 0x200
addq %rax, %rsi
addq $-0x10, %rsi
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x3588
movq %r15, %rdi
callq 0x867c
movq 0x10(%rsp), %rdi
callq 0x2150
movq %r13, %rdi
callq 0x3e72
leaq 0x20(%rsp), %r15
leaq 0x68(%rsp), %r12
leaq 0x50(%rsp), %r14
movq %rbx, %rsi
xorl %ebx, %ebx
movq %r15, %rdi
callq 0x3588
movq 0x20(%rsp), %rsi
testq %rsi, %rsi
je 0x3b83
movl 0x10(%rsi), %eax
movl %eax, 0x1990(%rsp,%rbx,4)
incq %rbx
jmp 0x3b62
leaq 0x60(%rsp), %r15
testq %rbx, %rbx
jle 0x3ba1
movl 0x198c(%rsp,%rbx,4), %esi
decq %rbx
movq %r13, %rdi
callq 0x3e7e
jmp 0x3b88
movq %r13, %rdi
callq 0x4030
leaq 0x30(%rsp), %rbx
cmpl $0x1, 0x1988(%rsp)
jne 0x3bf6
movl 0x18ec(%rsp), %esi
movl %esi, 0x50(%rsp)
movq %r13, %rdi
callq 0x3e7e
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x7f3a
movq %rbx, %rdi
movq %r15, %rsi
callq 0x35ee
movq %r12, %rdi
callq 0x350c
movq %r13, %rdi
callq 0x4030
jmp 0x3bae
movq %r13, %rdi
callq 0x46cc
movl %eax, 0xc(%rsp)
movq (%rsp), %rax
movl 0xa834(%rax), %eax
cmpl %eax, 0x1984(%rsp)
jg 0x3c51
jne 0x3c27
movq (%rsp), %rcx
movl 0xc(%rsp), %edx
cmpl %edx, 0xa838(%rcx)
jg 0x3c51
cmpl $0x34, %eax
jne 0x3cce
movq %r13, %rdi
callq 0x477e
addl 0xc(%rsp), %eax
pushq $0xa
popq %rbx
movq (%rsp), %rcx
cmpl 0xa838(%rcx), %eax
jge 0x3a5e
jmp 0x3cce
movq 0x10(%rsp), %rdi
callq 0x7ed2
movl 0x1984(%rsp), %eax
movq (%rsp), %rcx
cmpl 0xa834(%rcx), %eax
jg 0x3c80
jne 0x3cc4
movq (%rsp), %rcx
movl 0xc(%rsp), %edx
cmpl %edx, 0xa838(%rcx)
jle 0x3cc4
movq (%rsp), %rcx
movl 0xc(%rsp), %edx
movl %edx, 0xa838(%rcx)
movl %eax, 0xa834(%rcx)
movl 0x198c(%rsp), %eax
movq %rax, %rcx
testl %ecx, %ecx
jle 0x3cb6
movl 0x74(%rsp,%rcx,4), %edx
movq (%rsp), %rsi
movl %edx, 0x9ffc(%rsi,%rcx,4)
decq %rcx
jmp 0x3c9e
cltq
movq (%rsp), %rcx
movb $-0x1, 0xa002(%rcx,%rax,4)
movq 0x10(%rsp), %rdi
callq 0x2150
movl 0x1988(%rsp), %ecx
testl %ecx, %ecx
movl $0x0, %eax
cmovlel %eax, %ecx
movq %rcx, 0x48(%rsp)
xorl %r12d, %r12d
cmpq %r12, 0x48(%rsp)
je 0x3a5b
movl 0x18ec(%rsp,%r12,4), %eax
movl %eax, 0x1c(%rsp)
movq %r13, %rdi
leaq 0x1c(%rsp), %rsi
callq 0x48fe
movl %eax, 0x8(%rsp)
movl 0x1c(%rsp), %esi
movq %r13, %rdi
callq 0x3e7e
movl 0xc(%rsp), %eax
addl %eax, 0x8(%rsp)
movq %r13, %rdi
callq 0x477e
movl %eax, %ebp
addl 0x8(%rsp), %ebp
movl %ebp, 0x8(%rsp)
movq (%rsp), %rax
cmpl $0x34, 0xa834(%rax)
jl 0x3d52
movq (%rsp), %rax
cmpl 0xa838(%rax), %ebp
jge 0x3e06
movl 0x1980(%rsp), %ebx
subl 0x1984(%rsp), %ebp
movq %r15, %rdi
movq %r13, %rsi
callq 0x4986
movq 0x10(%rsp), %rdi
callq 0x7ed2
movq 0x40(%rsp), %rdi
movq %r15, %rsi
leaq 0x8(%rsp), %rdx
callq 0x7f5c
movq %rax, %r15
testq %rax, %rax
je 0x3d99
movl 0x20(%r15), %eax
cmpl 0x8(%rsp), %eax
jle 0x3df7
leaq 0x50(%rsp), %r14
movq %r14, %rdi
leaq 0x1c(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x7f3a
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0x35ee
leaq 0x58(%rsp), %rdi
callq 0x350c
testq %r15, %r15
je 0x3dd4
movl 0x8(%rsp), %eax
movl %eax, 0x20(%r15)
movq (%rsp), %rcx
incl 0xa830(%rcx)
leal (%rbx,%rbp), %eax
addl $0x34, %eax
cltq
imulq $0x50, %rax, %rdi
addq %rcx, %rdi
leaq 0x20(%rsp), %rsi
callq 0x891e
movq 0x10(%rsp), %rdi
callq 0x2150
leaq 0x60(%rsp), %r15
movq %r13, %rdi
callq 0x4b72
incq %r12
jmp 0x3ce7
leaq 0x28(%rsp), %rdi
callq 0x350c
leaq 0x38(%rsp), %rdi
callq 0x350c
addq $0x2198, %rsp           # imm = 0x2198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
jmp 0x3e52
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x350c
leaq 0x38(%rsp), %rdi
callq 0x350c
movq %rbx, %rdi
callq 0x2300
nop