// File: /workspace/github_cpp_makefile_star2_O1/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 $0xb0b8, %rsp           # imm = 0xB0B8
movl %esi, %ebp
movq %rdi, %r14
callq 0x5658
cmpl $0x0, 0x1910(%r14)
movl 0x190c(%r14), %eax
je 0x687f
movl %eax, 0x8(%rsp)
xorl %ecx, %ecx
incl %ecx
movl $0x4, %eax
shll %cl, %eax
cmpl %ebp, %eax
jl 0x6798
leaq 0x90(%rsp), %rdi
movl %ecx, %esi
callq 0x9248
xorl %r15d, %r15d
leaq (%rsp,%r15), %rdi
addq $0x10b0, %rdi           # imm = 0x10B0
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 0x952c
addq $0x50, %r15
cmpq $0xa000, %r15           # imm = 0xA000
jne 0x67b7
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0x8b0, %rdi            # imm = 0x8B0
callq 0x373c
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x67ee
xorl %ebx, %ebx
leaq (%rsp,%rbx), %rdi
addq $0xb0, %rdi
callq 0x373c
addq $0x4, %rbx
cmpq $0x800, %rbx            # imm = 0x800
jne 0x680d
movb $-0x1, 0xb2(%rsp)
movq %r14, %rdi
callq 0x4cb4
movl %eax, %r15d
movq %r14, %rdi
callq 0x4bfc
movl %eax, %ebx
movl 0x1914(%r14), %eax
testl %eax, %eax
movl %ebx, 0x28(%rsp)
movl %r15d, 0x4(%rsp)
jle 0x688c
decl %eax
leaq (%r14,%rax,4), %rcx
leaq 0x38(%rsp), %rdi
movq $0x0, -0x8(%rdi)
leaq 0x30(%rsp), %rsi
leaq 0x50(%rsp), %rdx
callq 0x9b54
jmp 0x6894
xorl %ebx, %ebx
cmpl $0x34, %eax
sete %bl
jmp 0x6e76
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movl %ebp, 0x4c(%rsp)
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x18(%rsp)
movq %rax, 0x20(%rsp)
testq %rax, %rax
je 0x68c6
movq 0x7718(%rip), %rcx      # 0xdfd0
cmpb $0x0, (%rcx)
je 0x68c2
incl 0x8(%rax)
jmp 0x68c6
lock
incl 0x8(%rax)
movl 0x1914(%r14), %ebx
cmpl $0x2, %ebx
jl 0x695f
addl $-0x2, %ebx
leaq 0x58(%rsp), %r15
leaq (%r14,%rbx,4), %r12
incq %rbx
leaq 0x50(%rsp), %r13
leaq 0x70(%rsp), %rbp
movq $0x0, 0x50(%rsp)
movq %r15, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movq %r12, %rcx
callq 0x9b54
movq 0x18(%rsp), %rax
movaps 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x50(%rsp)
movq 0x8(%rax), %rdi
movups %xmm0, (%rax)
testq %rdi, %rdi
je 0x692c
callq 0x3794
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x693b
callq 0x3794
movq 0x18(%rsp), %rsi
movq (%rsi), %rax
movq %rax, 0x18(%rsp)
addq $0x8, %rsi
leaq 0x20(%rsp), %rdi
callq 0x3804
addq $-0x4, %r12
decq %rbx
jg 0x68ef
movl 0x28(%rsp), %r13d
addl 0x4(%rsp), %r13d
movslq %r13d, %r12
leaq (%r12,%r12,4), %rbx
shlq $0x4, %rbx
leaq (%rsp,%rbx), %rdi
addq $0x10b0, %rdi           # imm = 0x10B0
leaq 0x30(%rsp), %rsi
callq 0x9808
movl 0x8(%rsp), %r15d
leaq 0x10b0(%rsp), %rax
addq %rbx, %rax
addq $0x48, %rax
movq %rax, 0x80(%rsp)
incq %r12
movl $0x200, 0x14(%rsp)      # imm = 0x200
movl %r13d, 0x28(%rsp)
movq %r12, 0x88(%rsp)
movl 0x4c(%rsp), %eax
cmpl %eax, 0x98(%rsp)
jge 0x6ddc
movl %r13d, %ebp
cmpl $0x1ff, %r13d           # imm = 0x1FF
jg 0x6a42
movq 0x88(%rsp), %rax
movq 0x80(%rsp), %rcx
movl %r13d, %ebp
movq (%rcx), %rdx
movq %rdx, %rsi
subq -0x20(%rcx), %rsi
shrq $0x3, %rsi
cmpq $0x1, %rdx
adcq $-0x1, %rsi
shlq $0x5, %rsi
movq -0x28(%rcx), %rdx
movq -0x18(%rcx), %rdi
subq -0x10(%rcx), %rdi
sarq $0x4, %rdi
addq %rsi, %rdi
subq -0x38(%rcx), %rdx
sarq $0x4, %rdx
addq %rdi, %rdx
jne 0x6a42
incl %ebp
addq $0x50, %rcx
movq %rax, %rdx
incq %rdx
cmpl $0x200, %eax            # imm = 0x200
movq %rdx, %rax
jne 0x69ed
movl $0x200, %ebp            # imm = 0x200
cmpl $0x1ff, %ebp            # imm = 0x1FF
jg 0x6d98
movl %r15d, %r12d
movslq %ebp, %rax
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
leaq (%rsp,%rax), %r15
addq $0x10b0, %r15           # imm = 0x10B0
movq 0x30(%r15), %rsi
cmpq 0x38(%r15), %rsi
jne 0x6a81
movq 0x48(%r15), %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), %rbx
movq %rbx, %rdi
callq 0x3804
movq %r15, %rdi
callq 0x96a4
movl 0x1904(%r14), %esi
movq %r14, %rdi
callq 0x5aae
movq 0x30(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3804
movq 0x18(%rsp), %rsi
xorl %ebx, %ebx
testq %rsi, %rsi
je 0x6b05
movl 0x10(%rsi), %eax
movl %eax, 0x8b0(%rsp,%rbx,4)
incq %rbx
movq (%rsi), %rax
movq %rax, 0x18(%rsp)
addq $0x8, %rsi
movq %r15, %rdi
callq 0x3804
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
jne 0x6ad8
movl %ebx, %ebx
movl %r12d, %r15d
leaq 0x50(%rsp), %r12
testl %ebx, %ebx
jle 0x6b25
movl 0x8ac(%rsp,%rbx,4), %esi
decq %rbx
movq %r14, %rdi
callq 0x42a4
jmp 0x6b0d
movq %r14, %rdi
callq 0x4456
cmpl $0x1, 0x1910(%r14)
leaq 0x10(%rsp), %rbx
jne 0x6bb4
movl 0x1874(%r14), %esi
movl %esi, 0x70(%rsp)
movq %r14, %rdi
callq 0x42a4
movq $0x0, 0x50(%rsp)
leaq 0x58(%rsp), %rdi
movq %r12, %rsi
movq %rbx, %rdx
leaq 0x70(%rsp), %rcx
leaq 0x30(%rsp), %r8
callq 0x9718
movaps 0x50(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x50(%rsp)
movq 0x38(%rsp), %rdi
movaps %xmm0, 0x30(%rsp)
testq %rdi, %rdi
je 0x6b93
callq 0x3794
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x6ba2
callq 0x3794
movq %r14, %rdi
callq 0x4456
cmpl $0x1, 0x1910(%r14)
je 0x6b3c
movq %r14, %rdi
callq 0x4bfc
movl %eax, 0x8(%rsp)
movl 0x190c(%r14), %eax
movl %eax, 0x4(%rsp)
cmpl %r15d, %eax
jg 0x6be9
sete %al
movl 0x8(%rsp), %ecx
cmpl %ecx, 0x14(%rsp)
setg %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x6da6
movslq 0x1914(%r14), %rbx
testq %rbx, %rbx
jle 0x6c0d
leaq (,%rbx,4), %rdx
leaq 0xb0(%rsp), %rdi
movq %r14, %rsi
callq 0x2180
movb $-0x1, 0xb2(%rsp,%rbx,4)
movl 0x8(%rsp), %eax
movl %eax, 0x14(%rsp)
leaq 0x10(%rsp), %rbx
cmpl $0x0, 0x1910(%r14)
jle 0x6d93
xorl %r13d, %r13d
movl 0x1874(%r14,%r13,4), %eax
movl %eax, 0x10(%rsp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x4e52
movl %eax, 0xc(%rsp)
movl 0x10(%rsp), %esi
movq %r14, %rdi
callq 0x42a4
movl 0x8(%rsp), %eax
addl %eax, 0xc(%rsp)
movq %r14, %rdi
callq 0x4cb4
movl %eax, %r15d
cmpl $0x34, 0x4(%rsp)
setl %al
addl 0xc(%rsp), %r15d
movl %r15d, 0xc(%rsp)
cmpl 0x14(%rsp), %r15d
setl %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x6d6c
movl 0x1908(%r14), %ebx
subl 0x190c(%r14), %r15d
movq %r12, %rdi
movq %r14, %rsi
callq 0x4ede
leaq 0x90(%rsp), %rdi
movq %r12, %rsi
leaq 0xc(%rsp), %rdx
callq 0x911e
movq %rax, %r12
testq %rax, %rax
je 0x6cd7
movl 0x20(%r12), %eax
cmpl 0xc(%rsp), %eax
jle 0x6d62
movq $0x0, 0x70(%rsp)
leaq 0x78(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x2f(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0x30(%rsp), %r8
callq 0x9718
movaps 0x70(%rsp), %xmm0
xorps %xmm1, %xmm1
movaps %xmm1, 0x70(%rsp)
movq 0x20(%rsp), %rdi
movups %xmm0, 0x18(%rsp)
testq %rdi, %rdi
je 0x6d1f
callq 0x3794
movq 0x78(%rsp), %rdi
testq %rdi, %rdi
je 0x6d2e
callq 0x3794
testq %r12, %r12
je 0x6d3c
movl 0xc(%rsp), %eax
movl %eax, 0x20(%r12)
leal (%r15,%rbx), %eax
addl $0x34, %eax
cltq
leaq (%rax,%rax,4), %rax
shlq $0x4, %rax
leaq (%rsp,%rax), %rdi
addq $0x10b0, %rdi           # imm = 0x10B0
leaq 0x18(%rsp), %rsi
callq 0x9808
leaq 0x50(%rsp), %r12
leaq 0x10(%rsp), %rbx
movq %r14, %rdi
callq 0x50e4
incq %r13
movslq 0x1910(%r14), %rax
cmpq %rax, %r13
jl 0x6c33
movl 0x4(%rsp), %r15d
movl 0x28(%rsp), %r13d
jmp 0x6d98
movl 0x4(%rsp), %r15d
cmpl $0x200, %ebp            # imm = 0x200
jl 0x69bd
jmp 0x6ddc
cmpl $0x34, %r15d
jne 0x6dd2
movq %r14, %rdi
callq 0x4cb4
addl 0x8(%rsp), %eax
movl $0x34, 0x4(%rsp)
movl $0x34, %r15d
cmpl 0x14(%rsp), %eax
jl 0x6c22
jmp 0x6d98
movl %r15d, 0x4(%rsp)
jmp 0x6c22
movl 0x1904(%r14), %esi
movq %r14, %rdi
callq 0x5aae
cmpb $-0x1, 0xb2(%rsp)
leaq 0xb0(%rsp), %rbx
je 0x6e11
movl (%rbx), %esi
movq %r14, %rdi
callq 0x42a4
cmpb $-0x1, 0x6(%rbx)
leaq 0x4(%rbx), %rbx
jne 0x6dfd
xorl %eax, %eax
cmpl $0x34, %r15d
sete %al
leal -0x2(%rax), %ebx
movl 0x4c(%rsp), %ecx
cmpl %ecx, 0x98(%rsp)
cmovll %eax, %ebx
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x6e3a
callq 0x3794
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x6e49
callq 0x3794
movl $0x9fb0, %r14d          # imm = 0x9FB0
leaq (%rsp,%r14), %rdi
addq $0x10b0, %rdi           # imm = 0x10B0
callq 0x93d0
addq $-0x50, %r14
cmpq $-0x50, %r14
jne 0x6e4f
leaq 0x90(%rsp), %rdi
callq 0x9368
movl %ebx, %eax
addq $0xb0b8, %rsp           # imm = 0xB0B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x6e9c
jmp 0x6ece
jmp 0x6e9c
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6e9c
movq %rax, %rbx
jmp 0x6eef
movq %rax, %rbx
testq %r15, %r15
je 0x6f0f
leaq 0x1060(%rsp), %r14
leaq (%r14,%r15), %rdi
callq 0x93d0
addq $-0x50, %r15
jne 0x6eb1
jmp 0x6f0f
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
jmp 0x6ece
movq %rax, %rbx
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x6ee0
callq 0x3794
movq 0x38(%rsp), %rdi
testq %rdi, %rdi
je 0x6eef
callq 0x3794
movl $0x9fb0, %r14d          # imm = 0x9FB0
leaq (%rsp,%r14), %rdi
addq $0x10b0, %rdi           # imm = 0x10B0
callq 0x93d0
addq $-0x50, %r14
cmpq $-0x50, %r14
jne 0x6ef5
leaq 0x90(%rsp), %rdi
callq 0x9368
movq %rbx, %rdi
callq 0x22e0