// File: /workspace/github_cpp_makefile_star2_O3/ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: Solitaire::SolveMinimal(int)
SolveResult Solitaire::SolveMinimal(int maxClosedCount) {
	MakeAutoMoves();
	if (movesAvailableCount == 0) { return foundationCount == 52 ? SolvedMinimal : Impossible; }

	int openCount = 1;
	int maxFoundationCount = foundationCount;
	int bestSolutionMoveCount = 512;
	int totalOpenCount = 1;

	int powerOf2 = 1;
	while (maxClosedCount > (1 << (powerOf2 + 2))) {
		powerOf2++;
	}
	HashMap<int> closed(powerOf2);
	stack<shared_ptr<MoveNode>> open[512];
	Move movesToMake[512];
	Move bestSolution[512];
	bestSolution[0].Count = 255;
	int startMoves = MinimumMovesLeft() + MovesMadeNormalizedCount();

	shared_ptr<MoveNode> firstNode = movesMadeCount > 0 ? make_shared<MoveNode>(movesMade[movesMadeCount - 1]) : NULL;
	shared_ptr<MoveNode> node = firstNode;
	for (int i = movesMadeCount - 2; i >= 0; i--) {
		node->Parent = make_shared<MoveNode>(movesMade[i]);
		node = node->Parent;
	}
	open[startMoves].push(firstNode);
	while (closed.Size() < maxClosedCount) {
		//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) { break; }

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

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

		//Make any auto moves
		UpdateAvailableMoves();
		while (movesAvailableCount == 1) {
			Move move = movesAvailable[0];
			MakeMove(move);
			firstNode = make_shared<MoveNode>(move, firstNode);
			UpdateAvailableMoves();
		}
		movesTotal = MovesMadeNormalizedCount();

		//Check for best solution to foundations
		if (foundationCount > maxFoundationCount || (foundationCount == maxFoundationCount && bestSolutionMoveCount > movesTotal)) {
			bestSolutionMoveCount = movesTotal;
			maxFoundationCount = foundationCount;

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

		//Make available moves and add them to be evaulated
		for (int i = 0; i < movesAvailableCount; i++) {
			Move move = movesAvailable[i];
			int movesAdded = MovesAdded(move);

			MakeMove(move);

			movesAdded += movesTotal;
			movesAdded += MinimumMovesLeft();
			if (maxFoundationCount < 52 || movesAdded < bestSolutionMoveCount) {
				int helper = movesAdded;
				helper += 52 - foundationCount + roundCount;
				HashKey key = GameState();
				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; }

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

			UndoMove();
		}
	}

	//Reset game to best solution found
	ResetGame(drawCount);
	for (int i = 0; bestSolution[i].Count < 255; i++) {
		MakeMove(bestSolution[i]);
	}
	return closed.Size() >= maxClosedCount ? (maxFoundationCount == 52 ? SolvedMayNotBeMinimal : CouldNotComplete) : (maxFoundationCount == 52 ? SolvedMinimal : Impossible);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb0c8, %rsp           # imm = 0xB0C8
movl %esi, %ebp
movq %rdi, %r14
callq 0x54ec
cmpl $0x0, 0x1910(%r14)
movl 0x190c(%r14), %r12d
je 0x6819
xorl %ecx, %ecx
incl %ecx
movl $0x4, %eax
shll %cl, %eax
cmpl %ebp, %eax
jl 0x66f2
leaq 0xa0(%rsp), %rdi
movl %ecx, %esi
callq 0x916a
xorl %r15d, %r15d
leaq (%rsp,%r15), %rdi
addq $0x10c0, %rdi           # imm = 0x10C0
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rdi)
movaps %xmm0, 0x30(%rdi)
movaps %xmm0, 0x20(%rdi)
movaps %xmm0, 0x10(%rdi)
movaps %xmm0, (%rdi)
xorl %esi, %esi
callq 0x944c
addq $0x50, %r15
cmpq $0xa000, %r15           # imm = 0xA000
jne 0x6711
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0x8c0, %rdi            # imm = 0x8C0
callq 0x3704
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x6748
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0xc0, %rdi
callq 0x3704
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x6767
movb $-0x1, 0xc2(%rsp)
movq %r14, %rdi
callq 0x4b36
movl %eax, %r13d
movq %r14, %rdi
callq 0x4a7e
movl %eax, %ebx
movl 0x1914(%r14), %eax
testl %eax, %eax
movl %ebp, 0x28(%rsp)
movl %r12d, 0x24(%rsp)
movl %ebx, 0xc(%rsp)
movl %r13d, 0x4(%rsp)
jle 0x6827
decl %eax
leaq (%r14,%rax,4), %rcx
leaq 0x48(%rsp), %r15
movq $0x0, -0x8(%r15)
leaq 0x40(%rsp), %rsi
leaq 0x50(%rsp), %rdx
movq %r15, %rdi
callq 0x9a6a
movq 0x40(%rsp), %rcx
movq 0x48(%rsp), %rax
leaq 0x38(%rsp), %rdx
movq %rcx, -0x8(%rdx)
movq %rax, (%rdx)
testq %rax, %rax
movq %r15, 0x18(%rsp)
movq %rdx, 0x68(%rsp)
je 0x684c
movq 0x77c1(%rip), %rcx      # 0xdfd0
cmpb $0x0, (%rcx)
je 0x6848
incl 0x8(%rax)
jmp 0x684c
xorl %ebx, %ebx
cmpl $0x34, %r12d
sete %bl
jmp 0x6e3b
xorps %xmm0, %xmm0
leaq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
movaps %xmm0, -0x8(%rax)
leaq 0x38(%rsp), %rax
movq %rax, 0x68(%rsp)
movaps %xmm0, -0x8(%rax)
jmp 0x684c
lock
incl 0x8(%rax)
movl 0x1914(%r14), %r12d
cmpl $0x2, %r12d
jl 0x68e7
addl $-0x2, %r12d
leaq 0x58(%rsp), %r15
leaq (%r14,%r12,4), %r13
incq %r12
leaq 0x50(%rsp), %rbp
leaq 0x70(%rsp), %rbx
movq $0x0, 0x50(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
movq %r13, %rcx
callq 0x9a6a
movq 0x30(%rsp), %rax
movaps 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x50(%rsp)
movq 0x8(%rax), %rdi
movups %xmm0, (%rax)
testq %rdi, %rdi
je 0x68b4
callq 0x3748
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x68c3
callq 0x3748
movq 0x30(%rsp), %rsi
movq (%rsi), %rax
movq %rax, 0x30(%rsp)
addq $0x8, %rsi
movq 0x68(%rsp), %rdi
callq 0x37b8
addq $-0x4, %r13
decq %r12
jg 0x6877
movl 0xc(%rsp), %ebp
addl 0x4(%rsp), %ebp
movslq %ebp, %r13
leaq (,%r13,4), %rbx
addq %r13, %rbx
shlq $0x4, %rbx
leaq (%rsp,%rbx), %rdi
addq $0x10c0, %rdi           # imm = 0x10C0
leaq 0x40(%rsp), %rsi
callq 0x971a
movl 0x28(%rsp), %eax
cmpl %eax, 0xa8(%rsp)
jge 0x6d97
leaq 0x58(%rsp), %r15
movq %r13, %rax
shlq $0x20, %rax
movq %rax, 0x98(%rsp)
leaq 0x10c0(%rsp), %rax
addq %rbx, %rax
addq $0x48, %rax
movq %rax, 0x90(%rsp)
incq %r13
movl $0x200, 0x4(%rsp)       # imm = 0x200
movl 0x24(%rsp), %r10d
movq 0x18(%rsp), %r9
cmpl $0x1ff, %ebp            # imm = 0x1FF
jg 0x6d97
movq %r13, %rcx
movq 0x90(%rsp), %rdx
movq 0x98(%rsp), %rax
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 0x69e7
movabsq $0x100000000, %rsi      # imm = 0x100000000
addq %rsi, %rax
addq $0x50, %rdx
movq %rcx, %rsi
incq %rsi
cmpl $0x200, %ecx            # imm = 0x200
movq %rsi, %rcx
jne 0x6986
jmp 0x6d9e
movl %r10d, 0xc(%rsp)
movq %r9, 0x18(%rsp)
sarq $0x20, %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
leaq (%rsp,%rax), %rbx
addq $0x10c0, %rbx           # imm = 0x10C0
movq 0x30(%rbx), %rsi
cmpq 0x38(%rbx), %rsi
jne 0x6a22
movq 0x48(%rbx), %rax
movq -0x8(%rax), %rsi
movl $0x200, %eax            # imm = 0x200
addq %rax, %rsi
movq -0x10(%rsi), %rax
movq %rax, 0x40(%rsp)
addq $-0x8, %rsi
movq 0x18(%rsp), %r12
movq %r12, %rdi
callq 0x37b8
movq %rbx, %rdi
callq 0x95c4
movl 0x1904(%r14), %esi
movq %r14, %rdi
callq 0x5958
movq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x68(%rsp), %rdi
movq %r12, %rsi
callq 0x37b8
movq 0x30(%rsp), %rsi
testq %rsi, %rsi
je 0x6ab5
movq %r13, %r15
xorl %ebx, %ebx
movq 0x68(%rsp), %r12
movl 0x10(%rsi), %eax
movl %eax, 0x8c0(%rsp,%rbx,4)
incq %rbx
movq (%rsi), %rax
movq %rax, 0x30(%rsp)
addq $0x8, %rsi
movq %r12, %rdi
callq 0x37b8
movq 0x30(%rsp), %rsi
testq %rsi, %rsi
jne 0x6a7e
movl %ebx, %ebx
movq %r15, %r13
leaq 0x58(%rsp), %r15
jmp 0x6ab7
xorl %ebx, %ebx
testl %ebx, %ebx
jle 0x6acf
movl 0x8bc(%rsp,%rbx,4), %esi
decq %rbx
movq %r14, %rdi
callq 0x4232
jmp 0x6ab7
movq %r14, %rdi
callq 0x43e4
movl 0x1910(%r14), %ebx
cmpl $0x1, %ebx
jne 0x6b55
movl 0x1874(%r14), %esi
movl %esi, 0x70(%rsp)
movq %r14, %rdi
callq 0x4232
movq $0x0, 0x50(%rsp)
movq %r15, %rdi
leaq 0x50(%rsp), %rsi
leaq 0x14(%rsp), %rdx
leaq 0x70(%rsp), %rcx
leaq 0x40(%rsp), %r8
callq 0x9638
movaps 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x50(%rsp)
movq 0x48(%rsp), %rdi
movaps %xmm0, 0x40(%rsp)
testq %rdi, %rdi
je 0x6b4b
callq 0x3748
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x6b4b
callq 0x3748
movq %r14, %rdi
callq 0x43e4
jmp 0x6ad7
movq %r14, %rdi
callq 0x4a7e
movl %eax, 0x10(%rsp)
movl 0x190c(%r14), %eax
movl 0xc(%rsp), %edx
movl %eax, %r12d
cmpl %edx, %eax
jg 0x6b8c
sete %al
movl 0x10(%rsp), %ecx
cmpl %ecx, 0x4(%rsp)
setg %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x6d61
movslq 0x1914(%r14), %r15
testq %r15, %r15
jle 0x6bb0
leaq (,%r15,4), %rdx
leaq 0xc0(%rsp), %rdi
movq %r14, %rsi
callq 0x2180
movb $-0x1, 0xc2(%rsp,%r15,4)
movl 0x10(%rsp), %eax
movl %eax, 0x4(%rsp)
leaq 0x58(%rsp), %r15
testl %ebx, %ebx
jle 0x6d46
movq %r13, 0x88(%rsp)
movl %ebp, 0xc(%rsp)
xorl %r13d, %r13d
leaq 0x50(%rsp), %rbx
movl 0x1874(%r14,%r13,4), %eax
movl %eax, 0x14(%rsp)
movq %r14, %rdi
leaq 0x14(%rsp), %rsi
callq 0x4cbe
movl %eax, 0x8(%rsp)
movl 0x14(%rsp), %esi
movq %r14, %rdi
callq 0x4232
movl 0x10(%rsp), %eax
addl %eax, 0x8(%rsp)
movq %r14, %rdi
callq 0x4b36
movl %eax, %r15d
cmpl $0x34, %r12d
setl %al
addl 0x8(%rsp), %r15d
movl %r15d, 0x8(%rsp)
cmpl 0x4(%rsp), %r15d
setl %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x6d13
movl 0x1908(%r14), %ebp
subl 0x190c(%r14), %r15d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4d4a
leaq 0xa0(%rsp), %rdi
movq %rbx, %rsi
leaq 0x8(%rsp), %rdx
callq 0x9050
movq %rax, %rbx
testq %rax, %rax
je 0x6c85
movl 0x20(%rbx), %eax
cmpl 0x8(%rsp), %eax
jle 0x6d0e
movq $0x0, 0x70(%rsp)
leaq 0x78(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x2f(%rsp), %rdx
leaq 0x14(%rsp), %rcx
leaq 0x40(%rsp), %r8
callq 0x9638
movaps 0x70(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x70(%rsp)
movq 0x38(%rsp), %rdi
movaps %xmm0, 0x30(%rsp)
testq %rdi, %rdi
je 0x6cdc
callq 0x3748
movq 0x78(%rsp), %rdi
testq %rdi, %rdi
je 0x6cdc
callq 0x3748
testq %rbx, %rbx
je 0x6ce8
movl 0x8(%rsp), %eax
movl %eax, 0x20(%rbx)
leal (%r15,%rbp), %eax
addl $0x34, %eax
cltq
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
leaq (%rsp,%rax), %rdi
addq $0x10c0, %rdi           # imm = 0x10C0
leaq 0x30(%rsp), %rsi
callq 0x971a
leaq 0x50(%rsp), %rbx
movq %r14, %rdi
callq 0x4f6e
incq %r13
movslq 0x1910(%r14), %rax
cmpq %rax, %r13
jl 0x6be2
movl 0xc(%rsp), %ebp
movq 0x18(%rsp), %r9
movq 0x88(%rsp), %r13
leaq 0x58(%rsp), %r15
jmp 0x6d4b
movq 0x18(%rsp), %r9
movl %r12d, %r10d
movl 0x28(%rsp), %eax
cmpl %eax, 0xa8(%rsp)
jl 0x6967
jmp 0x6da1
cmpl $0x34, %edx
jne 0x6d8f
movq %r14, %rdi
callq 0x4b36
addl 0x10(%rsp), %eax
movl $0x34, %r12d
cmpl 0x4(%rsp), %eax
movq 0x18(%rsp), %r9
jge 0x6d4b
movl 0x1910(%r14), %ebx
jmp 0x6bc6
movl %edx, %r12d
jmp 0x6bc6
movl 0x24(%rsp), %r12d
jmp 0x6da1
movl %r10d, %r12d
movl 0x1904(%r14), %esi
movq %r14, %rdi
callq 0x5958
movl 0x28(%rsp), %ebp
cmpb $-0x1, 0xc2(%rsp)
je 0x6dda
leaq 0xc0(%rsp), %rbx
movl (%rbx), %esi
movq %r14, %rdi
callq 0x4232
cmpb $-0x1, 0x6(%rbx)
leaq 0x4(%rbx), %rbx
jne 0x6dc6
xorl %eax, %eax
cmpl $0x34, %r12d
sete %al
leal -0x2(%rax), %ebx
cmpl %ebp, 0xa8(%rsp)
cmovll %eax, %ebx
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x6dff
callq 0x3748
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x6e0e
callq 0x3748
movl $0x9fb0, %r14d          # imm = 0x9FB0
leaq (%rsp,%r14), %rdi
addq $0x10c0, %rdi           # imm = 0x10C0
callq 0x92e2
addq $-0x50, %r14
cmpq $-0x50, %r14
jne 0x6e14
leaq 0xa0(%rsp), %rdi
callq 0x927a
movl %ebx, %eax
addq $0xb0c8, %rsp           # imm = 0xB0C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e6d
jmp 0x6e6d
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e93
jmp 0x6e6d
movq %rax, %rbx
jmp 0x6eb4
movq %rax, %rbx
testq %r15, %r15
je 0x6ed4
leaq 0x1070(%rsp), %r14
leaq (%r14,%r15), %rdi
callq 0x92e2
addq $-0x50, %r15
jne 0x6e82
jmp 0x6ed4
movq %rax, %rbx
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x6ea5
callq 0x3748
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x6eb4
callq 0x3748
movl $0x9fb0, %r14d          # imm = 0x9FB0
leaq (%rsp,%r14), %rdi
addq $0x10c0, %rdi           # imm = 0x10C0
callq 0x92e2
addq $-0x50, %r14
cmpq $-0x50, %r14
jne 0x6eba
leaq 0xa0(%rsp), %rdi
callq 0x927a
movq %rbx, %rdi
callq 0x22e0
nop