// File: 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
movq %rsp, %rbp
subq $0x22a0, %rsp           # imm = 0x22A0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x2210(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
leaq -0x820(%rbp), %rax
movq %rax, %rcx
addq $0x800, %rcx            # imm = 0x800
movq %rcx, -0x2208(%rbp)
movq %rax, -0x2200(%rbp)
movq -0x2200(%rbp), %rdi
movq %rdi, -0x2218(%rbp)
callq 0x5900
movq -0x2218(%rbp), %rax
movq -0x2208(%rbp), %rcx
addq $0x4, %rax
cmpq %rcx, %rax
movq %rax, -0x2200(%rbp)
jne 0x67b5
leaq -0x830(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ab0
leaq -0x840(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ab0
movq -0x2210(%rbp), %rax
movq 0xa800(%rax), %rsi
leaq -0x2158(%rbp), %rdi
movl $0x1918, %edx           # imm = 0x1918
callq 0x31d0
movl $0xa, -0x215c(%rbp)
movq -0x18(%rbp), %rdi
callq 0xee50
movl %eax, -0x221c(%rbp)
jmp 0x6840
movl -0x221c(%rbp), %ecx
movq -0x2210(%rbp), %rdx
xorl %eax, %eax
cmpl 0xa840(%rdx), %ecx
movb %al, -0x221d(%rbp)
jge 0x686d
cmpl $0x0, -0x215c(%rbp)
setg %al
movb %al, -0x221d(%rbp)
movb -0x221d(%rbp), %al
testb $0x1, %al
jne 0x687c
jmp 0x70ec
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xee70
jmp 0x6891
movq -0x2210(%rbp), %rax
movl 0xa83c(%rax), %eax
movl %eax, -0x2170(%rbp)
xorl %eax, %eax
cmpl $0x200, -0x2170(%rbp)   # imm = 0x200
movb %al, -0x221e(%rbp)
jge 0x68f3
movq -0x2210(%rbp), %rdi
movslq -0x2170(%rbp), %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0xeea0
movq %rax, -0x2228(%rbp)
jmp 0x68df
movq -0x2228(%rbp), %rax
cmpq $0x0, %rax
sete %al
movb %al, -0x221e(%rbp)
movb -0x221e(%rbp), %al
testb $0x1, %al
jne 0x68ff
jmp 0x693f
movl -0x2170(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2170(%rbp)
jmp 0x68a4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2168(%rbp)
movl %eax, -0x216c(%rbp)
leaq -0x840(%rbp), %rdi
callq 0x5b00
leaq -0x830(%rbp), %rdi
callq 0x5b00
jmp 0x710d
cmpl $0x200, -0x2170(%rbp)   # imm = 0x200
jl 0x69a0
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xeec0
jmp 0x6960
movl -0x215c(%rbp), %eax
decl %eax
movl %eax, -0x215c(%rbp)
movl $0x1, -0x217c(%rbp)
leaq -0x2178(%rbp), %rdi
leaq -0x217c(%rbp), %rsi
callq 0xef90
jmp 0x698d
leaq -0x2178(%rbp), %rdi
callq 0xeee0
jmp 0x699b
jmp 0x682f
movq -0x2210(%rbp), %rdi
movl $0xa, -0x215c(%rbp)
movl 0xa830(%rdi), %eax
decl %eax
movl %eax, 0xa830(%rdi)
movslq -0x2170(%rbp), %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0xefb0
movq %rax, -0x2230(%rbp)
jmp 0x69df
movq -0x2230(%rbp), %rsi
leaq -0x830(%rbp), %rdi
callq 0x5b20
movq -0x2210(%rbp), %rdi
movslq -0x2170(%rbp), %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0xefd0
jmp 0x6a12
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xeec0
jmp 0x6a27
leaq -0x2158(%rbp), %rdi
callq 0x7120
jmp 0x6a35
movl $0x0, -0x2180(%rbp)
leaq -0x840(%rbp), %rdi
leaq -0x830(%rbp), %rsi
callq 0x5b20
leaq -0x840(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xeff0
testb $0x1, %al
jne 0x6a68
jmp 0x6ab1
leaq -0x840(%rbp), %rdi
callq 0xf020
movq %rax, %rcx
movl -0x2180(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x2180(%rbp)
cltq
movl 0x10(%rcx), %ecx
movl %ecx, -0x820(%rbp,%rax,4)
leaq -0x840(%rbp), %rdi
callq 0xf020
movq %rax, %rsi
leaq -0x840(%rbp), %rdi
callq 0x5b20
jmp 0x6a52
jmp 0x6ab3
cmpl $0x0, -0x2180(%rbp)
jle 0x6af0
movslq -0x2180(%rbp), %rax
movl %eax, %ecx
decl %ecx
movl %ecx, -0x2180(%rbp)
movl -0x824(%rbp,%rax,4), %eax
movl %eax, -0x2184(%rbp)
movl -0x2184(%rbp), %esi
leaq -0x2158(%rbp), %rdi
callq 0x7150
jmp 0x6aee
jmp 0x6ab3
leaq -0x2158(%rbp), %rdi
callq 0x7380
jmp 0x6afe
jmp 0x6b00
leaq -0x2158(%rbp), %rdi
callq 0x7f00
movl %eax, -0x2234(%rbp)
jmp 0x6b14
movl -0x2234(%rbp), %eax
cmpl $0x1, %eax
jne 0x6bba
leaq -0x2158(%rbp), %rdi
xorl %esi, %esi
callq 0x7f20
movl %eax, -0x2238(%rbp)
jmp 0x6b39
movl -0x2238(%rbp), %eax
movl %eax, -0x2188(%rbp)
movl -0x2188(%rbp), %eax
movl %eax, -0x218c(%rbp)
movl -0x218c(%rbp), %esi
leaq -0x2158(%rbp), %rdi
callq 0x7150
jmp 0x6b65
leaq -0x21a0(%rbp), %rdi
leaq -0x2188(%rbp), %rsi
leaq -0x830(%rbp), %rdx
callq 0xf040
jmp 0x6b81
leaq -0x830(%rbp), %rdi
leaq -0x21a0(%rbp), %rsi
movq %rsi, -0x2240(%rbp)
callq 0x5ad0
movq -0x2240(%rbp), %rdi
callq 0x5b00
leaq -0x2158(%rbp), %rdi
callq 0x7380
jmp 0x6bb5
jmp 0x6b00
leaq -0x2158(%rbp), %rdi
callq 0x7f50
movl %eax, -0x2244(%rbp)
jmp 0x6bce
movl -0x2244(%rbp), %eax
movl %eax, -0x2180(%rbp)
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x2248(%rbp)
jmp 0x6bee
movl -0x2248(%rbp), %eax
movq -0x2210(%rbp), %rcx
cmpl 0xa834(%rcx), %eax
jg 0x6c49
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x224c(%rbp)
jmp 0x6c17
movl -0x224c(%rbp), %eax
movq -0x2210(%rbp), %rcx
cmpl 0xa834(%rcx), %eax
jne 0x6dd9
movq -0x2210(%rbp), %rax
movl 0xa838(%rax), %eax
cmpl -0x2180(%rbp), %eax
jle 0x6dd9
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xee70
jmp 0x6c5e
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x2250(%rbp)
jmp 0x6c72
movl -0x2250(%rbp), %eax
movq -0x2210(%rbp), %rcx
cmpl 0xa834(%rcx), %eax
jg 0x6ccd
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x2254(%rbp)
jmp 0x6c9b
movl -0x2254(%rbp), %eax
movq -0x2210(%rbp), %rcx
cmpl 0xa834(%rcx), %eax
jne 0x6dc2
movq -0x2210(%rbp), %rax
movl 0xa838(%rax), %eax
cmpl -0x2180(%rbp), %eax
jle 0x6dc2
movq -0x2210(%rbp), %rax
movl -0x2180(%rbp), %ecx
movl %ecx, 0xa838(%rax)
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x2258(%rbp)
jmp 0x6cf4
movq -0x2210(%rbp), %rax
movl -0x2258(%rbp), %ecx
movl %ecx, 0xa834(%rax)
leaq -0x2158(%rbp), %rdi
callq 0x80f0
movl %eax, -0x225c(%rbp)
jmp 0x6d1b
movl -0x225c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x21a4(%rbp)
cmpl $0x0, -0x21a4(%rbp)
jl 0x6d85
movl -0x21a4(%rbp), %esi
leaq -0x2158(%rbp), %rdi
callq 0x8110
movl %eax, -0x2260(%rbp)
jmp 0x6d4d
movq -0x2210(%rbp), %rax
movl -0x2260(%rbp), %ecx
movl %ecx, -0x21a8(%rbp)
movslq -0x21a4(%rbp), %rcx
movl -0x21a8(%rbp), %edx
movl %edx, 0xa000(%rax,%rcx,4)
movl -0x21a4(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x21a4(%rbp)
jmp 0x6d2a
movq -0x2210(%rbp), %rax
addq $0xa000, %rax           # imm = 0xA000
movq %rax, -0x2270(%rbp)
leaq -0x2158(%rbp), %rdi
callq 0x80f0
movl %eax, -0x2264(%rbp)
jmp 0x6dad
movq -0x2270(%rbp), %rax
movl -0x2264(%rbp), %ecx
movslq %ecx, %rcx
movb $-0x1, 0x2(%rax,%rcx,4)
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xeec0
jmp 0x6dd7
jmp 0x6e39
movq -0x2210(%rbp), %rax
cmpl $0x34, 0xa834(%rax)
jne 0x6e37
leaq -0x2158(%rbp), %rdi
callq 0x8130
movl %eax, -0x2274(%rbp)
jmp 0x6dfd
movq -0x2210(%rbp), %rcx
movl -0x2274(%rbp), %eax
movl %eax, -0x21ac(%rbp)
movl -0x2180(%rbp), %eax
addl -0x21ac(%rbp), %eax
movl %eax, -0x21ac(%rbp)
movl -0x21ac(%rbp), %eax
cmpl 0xa838(%rcx), %eax
jl 0x6e35
jmp 0x682f
jmp 0x6e37
jmp 0x6e39
leaq -0x2158(%rbp), %rdi
callq 0x7f00
movl %eax, -0x2278(%rbp)
jmp 0x6e4d
movl -0x2278(%rbp), %eax
movl %eax, -0x21b0(%rbp)
movl $0x0, -0x21b4(%rbp)
movl -0x21b4(%rbp), %eax
cmpl -0x21b0(%rbp), %eax
jge 0x70e7
movl -0x21b4(%rbp), %esi
leaq -0x2158(%rbp), %rdi
callq 0x7f20
movl %eax, -0x227c(%rbp)
jmp 0x6e8f
movl -0x227c(%rbp), %eax
movl %eax, -0x21b8(%rbp)
leaq -0x2158(%rbp), %rdi
leaq -0x21b8(%rbp), %rsi
callq 0x8480
movl %eax, -0x2280(%rbp)
jmp 0x6eb6
movl -0x2280(%rbp), %eax
movl %eax, -0x21bc(%rbp)
movl -0x21b8(%rbp), %eax
movl %eax, -0x21c0(%rbp)
movl -0x21c0(%rbp), %esi
leaq -0x2158(%rbp), %rdi
callq 0x7150
jmp 0x6ee2
movl -0x2180(%rbp), %ecx
movl -0x21bc(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x21bc(%rbp)
leaq -0x2158(%rbp), %rdi
callq 0x8130
movl %eax, -0x2284(%rbp)
jmp 0x6f0a
movq -0x2210(%rbp), %rax
movl -0x2284(%rbp), %ecx
addl -0x21bc(%rbp), %ecx
movl %ecx, -0x21bc(%rbp)
cmpl $0x34, 0xa834(%rax)
jl 0x6f45
movq -0x2210(%rbp), %rcx
movl -0x21bc(%rbp), %eax
cmpl 0xa838(%rcx), %eax
jge 0x70c3
movl -0x21bc(%rbp), %eax
movl %eax, -0x21c4(%rbp)
leaq -0x2158(%rbp), %rdi
callq 0x80d0
movl %eax, -0x2288(%rbp)
jmp 0x6f65
movl -0x2288(%rbp), %ecx
movl $0x34, %eax
subl %ecx, %eax
movl %eax, -0x2290(%rbp)
leaq -0x2158(%rbp), %rdi
callq 0x85e0
movl %eax, -0x228c(%rbp)
jmp 0x6f8c
movl -0x228c(%rbp), %eax
movl -0x2290(%rbp), %ecx
addl %eax, %ecx
movl -0x21c4(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x21c4(%rbp)
leaq -0x21d9(%rbp), %rdi
leaq -0x2158(%rbp), %rsi
callq 0x8600
jmp 0x6fbd
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xee70
jmp 0x6fd2
movq -0x18(%rbp), %rdi
leaq -0x21d9(%rbp), %rsi
leaq -0x21bc(%rbp), %rdx
callq 0xf0c0
movq %rax, -0x2298(%rbp)
jmp 0x6ff2
movq -0x2298(%rbp), %rax
movq %rax, -0x21e8(%rbp)
cmpq $0x0, -0x21e8(%rbp)
je 0x7020
movq -0x21e8(%rbp), %rax
movl 0x20(%rax), %eax
cmpl -0x21bc(%rbp), %eax
jle 0x70ac
leaq -0x21f8(%rbp), %rdi
leaq -0x21b8(%rbp), %rsi
leaq -0x830(%rbp), %rdx
callq 0xf040
jmp 0x703c
leaq -0x840(%rbp), %rdi
leaq -0x21f8(%rbp), %rsi
callq 0x5ad0
leaq -0x21f8(%rbp), %rdi
callq 0x5b00
cmpq $0x0, -0x21e8(%rbp)
je 0x7075
movl -0x21bc(%rbp), %ecx
movq -0x21e8(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x2210(%rbp), %rdi
movl 0xa830(%rdi), %eax
incl %eax
movl %eax, 0xa830(%rdi)
movslq -0x21c4(%rbp), %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
addq %rax, %rdi
leaq -0x840(%rbp), %rsi
callq 0xf2b0
jmp 0x70aa
jmp 0x70ac
movq -0x2210(%rbp), %rdi
addq $0xa808, %rdi           # imm = 0xA808
callq 0xeec0
jmp 0x70c1
jmp 0x70c3
leaq -0x2158(%rbp), %rdi
callq 0x89a0
jmp 0x70d1
jmp 0x70d3
movl -0x21b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x21b4(%rbp)
jmp 0x6e63
jmp 0x682f
leaq -0x840(%rbp), %rdi
callq 0x5b00
leaq -0x830(%rbp), %rdi
callq 0x5b00
addq $0x22a0, %rsp           # imm = 0x22A0
popq %rbp
retq
movq -0x2168(%rbp), %rdi
callq 0x33d0
nopl (%rax)