// File: /workspace/github_cpp_makefile_star2_O3/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 $0x21b8, %rsp           # imm = 0x21B8
movq %rsi, 0x70(%rsp)
movq %rdi, %r14
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0x19b0, %rdi           # imm = 0x19B0
callq 0x3704
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x3c19
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0x20(%rsp)
movq 0xa800(%r14), %rsi
leaq 0x98(%rsp), %rdi
movl $0x1918, %edx           # imm = 0x1918
callq 0x2180
movq 0x70(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0xa840(%r14), %eax
jge 0x41ad
leaq 0xa808(%r14), %rax
movq %rax, 0x10(%rsp)
leaq 0x28(%rsp), %r13
leaq 0x48(%rsp), %rbp
leaq 0xa000(%r14), %rax
movq %rax, 0x80(%rsp)
leaq 0x48(%r14), %rax
movq %rax, 0x88(%rsp)
movl $0xa, %ebx
leaq 0x98(%rsp), %r12
leaq 0x40(%rsp), %r15
movq %r14, 0x78(%rsp)
movq 0x10(%rsp), %rdi
callq 0x2250
testl %eax, %eax
jne 0x41d5
movslq 0xa83c(%r14), %rax
cmpq $0x1ff, %rax            # imm = 0x1FF
jg 0x3d47
movq %rax, %rcx
shlq $0x20, %rcx
leaq (%rax,%rax,4), %rdx
shlq $0x4, %rdx
addq 0x88(%rsp), %rdx
addq $-0x200, %rax           # imm = 0xFE00
movq (%rdx), %rsi
movq %rsi, %rdi
subq -0x20(%rdx), %rdi
shrq $0x3, %rdi
cmpq $0x1, %rsi
adcq $-0x1, %rdi
shlq $0x5, %rdi
movq -0x28(%rdx), %rsi
movq -0x18(%rdx), %r8
subq -0x10(%rdx), %r8
sarq $0x4, %r8
addq %rdi, %r8
subq -0x38(%rdx), %rsi
sarq $0x4, %rsi
addq %r8, %rsi
jne 0x3da9
movabsq $0x100000000, %rsi      # imm = 0x100000000
addq %rsi, %rcx
addq $0x50, %rdx
incq %rax
jne 0x3cf7
movq 0x10(%rsp), %rdi
callq 0x2160
movq $0x0, 0x40(%rsp)
movq $0xf4240, 0x48(%rsp)    # imm = 0xF4240
movq %r15, %rdi
movq %r15, %rsi
callq 0x2080
cmpl $-0x1, %eax
jne 0x3d7d
callq 0x2040
cmpl $0x4, (%rax)
je 0x3d63
decl %ebx
movl %ebx, 0x18(%rsp)
movq 0x70(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0xa840(%r14), %eax
movl 0x18(%rsp), %ebx
jge 0x419e
testl %ebx, %ebx
jg 0x3cb9
jmp 0x419e
decl 0xa830(%r14)
sarq $0x20, %rcx
leaq (%rcx,%rcx,4), %rax
shlq $0x4, %rax
leaq (%r14,%rax), %rbx
movq 0x30(%r14,%rax), %rsi
cmpq 0x38(%r14,%rax), %rsi
jne 0x3ddc
movq 0x48(%rbx), %rax
movq -0x8(%rax), %rsi
movl $0x200, %eax            # imm = 0x200
addq %rax, %rsi
movq -0x10(%rsi), %rax
movq %rax, 0x30(%rsp)
addq $-0x8, %rsi
leaq 0x38(%rsp), %r14
movq %r14, %rdi
callq 0x37b8
movq %rbx, %rdi
callq 0x95c4
movq 0x10(%rsp), %rdi
callq 0x2160
movl 0x199c(%rsp), %esi
movq %r12, %rdi
callq 0x5958
movq 0x30(%rsp), %rax
movq %rax, 0x20(%rsp)
movq %r13, %rdi
movq %r14, %rsi
callq 0x37b8
movq 0x20(%rsp), %rsi
xorl %ebx, %ebx
testq %rsi, %rsi
je 0x3e6c
movq 0x78(%rsp), %r14
movl 0x10(%rsi), %eax
movl %eax, 0x19b0(%rsp,%rbx,4)
incq %rbx
movq (%rsi), %rax
movq %rax, 0x20(%rsp)
addq $0x8, %rsi
movq %r13, %rdi
callq 0x37b8
movq 0x20(%rsp), %rsi
testq %rsi, %rsi
jne 0x3e3d
movl %ebx, %ebx
jmp 0x3e71
movq 0x78(%rsp), %r14
testl %ebx, %ebx
jle 0x3e89
movl 0x19ac(%rsp,%rbx,4), %esi
decq %rbx
movq %r12, %rdi
callq 0x4232
jmp 0x3e71
movq %r12, %rdi
callq 0x43e4
cmpl $0x1, 0x19a8(%rsp)
leaq 0xc(%rsp), %rbx
jne 0x3f16
movl 0x190c(%rsp), %esi
movl %esi, 0x60(%rsp)
movq %r12, %rdi
callq 0x4232
movq $0x0, 0x40(%rsp)
movq %rbp, %rdi
movq %r15, %rsi
movq %rbx, %rdx
leaq 0x60(%rsp), %rcx
leaq 0x30(%rsp), %r8
callq 0x9638
movaps 0x40(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x40(%rsp)
movq 0x38(%rsp), %rdi
movaps %xmm0, 0x30(%rsp)
testq %rdi, %rdi
je 0x3f04
callq 0x3748
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x3f04
callq 0x3748
movq %r12, %rdi
callq 0x43e4
cmpl $0x1, 0x19a8(%rsp)
je 0x3ea0
movq %r12, %rdi
callq 0x4a7e
movl %eax, 0x8(%rsp)
movl 0xa834(%r14), %eax
cmpl %eax, 0x19a4(%rsp)
jg 0x3f49
jne 0x416f
movl 0x8(%rsp), %ecx
cmpl %ecx, 0xa838(%r14)
jle 0x416f
movq 0x10(%rsp), %rdi
callq 0x2250
testl %eax, %eax
jne 0x41dc
movl 0x19a4(%rsp), %eax
cmpl 0xa834(%r14), %eax
jg 0x3f7a
jne 0x3fba
movl 0x8(%rsp), %ecx
cmpl %ecx, 0xa838(%r14)
jle 0x3fba
movl 0x8(%rsp), %ecx
movl %ecx, 0xa838(%r14)
movl %eax, 0xa834(%r14)
movslq 0x19ac(%rsp), %rbx
testq %rbx, %rbx
movq 0x80(%rsp), %r15
jle 0x3fb4
leaq (,%rbx,4), %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x2180
movb $-0x1, 0x2(%r15,%rbx,4)
movq 0x10(%rsp), %rdi
callq 0x2160
leaq 0x40(%rsp), %r15
leaq 0xc(%rsp), %rbx
movslq 0x19a8(%rsp), %rax
movl $0xa, 0x18(%rsp)
movq %rax, 0x90(%rsp)
testq %rax, %rax
jle 0x3d83
movq %r14, %rbp
xorl %r14d, %r14d
movl 0x190c(%rsp,%r14,4), %eax
movl %eax, 0xc(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x4cbe
movl %eax, 0x4(%rsp)
movl 0xc(%rsp), %esi
movq %r12, %rdi
callq 0x4232
movl 0x8(%rsp), %eax
addl %eax, 0x4(%rsp)
movq %r12, %rdi
callq 0x4b36
movl %eax, %r13d
addl 0x4(%rsp), %r13d
movl %r13d, 0x4(%rsp)
cmpl $0x34, 0xa834(%rbp)
jl 0x404f
cmpl 0xa838(%rbp), %r13d
jge 0x413f
movl 0x19a0(%rsp), %ebx
subl 0x19a4(%rsp), %r13d
movq %r15, %rdi
movq %r12, %rsi
callq 0x4d4a
movq 0x10(%rsp), %rdi
callq 0x2250
testl %eax, %eax
jne 0x41ce
movq 0x70(%rsp), %rdi
movq %r15, %rsi
leaq 0x4(%rsp), %rdx
callq 0x9050
movq %rax, %r15
testq %rax, %rax
je 0x40a3
movl 0x20(%r15), %eax
cmpl 0x4(%rsp), %eax
jle 0x412b
movq $0x0, 0x60(%rsp)
leaq 0x68(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x1f(%rsp), %rdx
leaq 0xc(%rsp), %rcx
leaq 0x30(%rsp), %r8
callq 0x9638
movaps 0x60(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x60(%rsp)
movq 0x28(%rsp), %rdi
movaps %xmm0, 0x20(%rsp)
testq %rdi, %rdi
je 0x40fa
callq 0x3748
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x40fa
callq 0x3748
testq %r15, %r15
je 0x4107
movl 0x4(%rsp), %eax
movl %eax, 0x20(%r15)
leal (%rbx,%r13), %eax
addl $0x34, %eax
incl 0xa830(%rbp)
cltq
leaq (%rax,%rax,4), %rdi
shlq $0x4, %rdi
addq %rbp, %rdi
leaq 0x20(%rsp), %rsi
callq 0x971a
movq 0x10(%rsp), %rdi
callq 0x2160
leaq 0x40(%rsp), %r15
leaq 0xc(%rsp), %rbx
movq %r12, %rdi
callq 0x4f6e
incq %r14
cmpq %r14, 0x90(%rsp)
jne 0x3ff5
movq %rbp, %r14
leaq 0x40(%rsp), %r15
leaq 0x28(%rsp), %r13
leaq 0x48(%rsp), %rbp
jmp 0x3d83
cmpl $0x34, %eax
jne 0x3fce
movq %r12, %rdi
callq 0x4b36
addl 0x8(%rsp), %eax
movl $0xa, 0x18(%rsp)
cmpl 0xa838(%r14), %eax
jge 0x3d83
jmp 0x3fce
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x41ad
callq 0x3748
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x41bc
callq 0x3748
addq $0x21b8, %rsp           # imm = 0x21B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %eax, %edi
callq 0x2120
movl %eax, %edi
callq 0x2120
movl %eax, %edi
callq 0x2120
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
jmp 0x41fd
movq %rax, %rbx
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x420f
callq 0x3748
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x421e
callq 0x3748
movq %rbx, %rdi
callq 0x22e0