// File: /workspace/github_cpp_makefile_star2_O2/ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: Solitaire::MinimumMovesLeft()
int Solitaire::MinimumMovesLeft() {
	Pile & waste = piles[WASTE];
	int wasteSize = waste.Size();
	int win = piles[STOCK].Size();
	int stockCount = win / drawCount;
	stockCount += (win % drawCount) == 0 ? 0 : 1;
	win += stockCount;
	win += wasteSize;

	for (int i = wasteSize - 1; i > 0; --i) {
		Card card1 = waste.Up(i);

		for (int j = i - 1; j >= 0; --j) {
			Card card2 = waste.Up(j);

			if (card1.Suit == card2.Suit && card1.Rank > card2.Rank) {
				++win;
				break;
			}
		}
	}

	for (int i = TABLEAU1; i <= TABLEAU7; ++i) {
		Pile & pile = piles[i];
		int pileSize = pile.Size();
		int downSize = pile.DownSize();
		win += pileSize;
		win += downSize;
		if (downSize == 0) { continue; }

		pileSize -= downSize;
		unsigned char mins[28] = {};

		for (int j = pileSize - 1; j >= 0; j--) {
			Card card1 = pile.Up(j);

			mins[card1.Suit] = card1.Rank;
		}

		for (int j = downSize - 1; j >= 0; j--) {
			Card card1 = pile.Down(j);

			unsigned char & rank = mins[card1.Suit];
			unsigned char cardRank = card1.Rank;
			if (mins[card1.Suit + 4] == EMPTY) {
				if (rank > cardRank) {
					win++;
				}
				rank = cardRank;
				continue;
			} else if (rank > cardRank) {
				do {
					win++;
					rank = *(&rank + 4);
				} while (rank > cardRank);
			}

			do {
				unsigned char temp = rank;
				rank = cardRank;
				cardRank = temp;
				rank = *(&rank + 4);
			} while (rank < cardRank);
		}
	}

	return win;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %rbx
leaq 0x800(%rdi), %r12
movq %r12, %rdi
callq 0x3874
movl %eax, %r14d
leaq 0x1160(%rbx), %rdi
callq 0x3874
movl %eax, %ebp
cltd
idivl 0x1904(%rbx)
addl %r14d, %ebp
addl %eax, %ebp
cmpl $0x1, %edx
sbbl $-0x1, %ebp
cmpl $0x1, %r14d
jle 0x4815
leal -0x1(%r14), %r15d
movq %r12, %rdi
movl %r15d, %esi
callq 0x38c2
movq %rax, %rbx
addl $-0x2, %r14d
movzbl %bh, %eax
movl %eax, %r13d
testl %r14d, %r14d
js 0x4810
movq %r12, %rdi
movl %r14d, %esi
callq 0x38c2
movl %ebx, %ecx
xorb %al, %cl
jne 0x480b
movzbl %ah, %eax
xorl %ecx, %ecx
cmpl %eax, %r13d
seta %cl
addl %ecx, %ebp
cmpl %eax, %r13d
ja 0x4810
decl %r14d
jmp 0x47e3
movl %r15d, %r14d
jmp 0x47c1
pushq $0x1
popq %rbx
leaq 0x10(%rsp), %r13
cmpq $0x8, %rbx
je 0x48ec
movq %rbx, 0x8(%rsp)
imulq $0x12c, %rbx, %r14      # imm = 0x12C
addq %r12, %r14
movq %r14, %rdi
callq 0x3874
movl %eax, %ebx
movq %r14, %rdi
callq 0x387c
addl %ebx, %ebp
addl %eax, %ebp
testl %eax, %eax
je 0x48df
movl %eax, %r15d
xorps %xmm0, %xmm0
movups %xmm0, 0x1c(%rsp)
movaps %xmm0, 0x10(%rsp)
notl %eax
addl %eax, %ebx
testl %ebx, %ebx
js 0x4881
movq %r14, %rdi
movl %ebx, %esi
callq 0x38c2
movzbl %al, %ecx
movb %ah, 0x10(%rsp,%rcx)
decl %ebx
jmp 0x4868
movq 0x8(%rsp), %rbx
testl %r15d, %r15d
jle 0x48e4
decl %r15d
movq %r14, %rdi
movl %r15d, %esi
callq 0x38aa
movzbl %al, %ecx
movabsq $0xffffffffff00, %rdx   # imm = 0xFFFFFFFFFF00
andq %rdx, %rax
shrq $0x8, %rax
movb 0x4(%rcx,%r13), %dl
testb %dl, %dl
je 0x48ca
movzbl 0x10(%rsp,%rcx), %esi
movzbl %al, %edi
cmpl %esi, %edi
jae 0x48d9
incl %ebp
cmpb %al, %dl
ja 0x48c2
jmp 0x48d9
movzbl 0x10(%rsp,%rcx), %edx
movzbl %al, %esi
cmpl %edx, %esi
adcl $0x0, %ebp
movl %eax, %edx
movb %dl, 0x10(%rsp,%rcx)
jmp 0x4886
movq 0x8(%rsp), %rbx
incq %rbx
jmp 0x481d
movl %ebp, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop