// File: /workspace/github_cpp_makefile_star2_O1/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), %r13
movq %r13, %rdi
callq 0x3aae
movl %eax, %r14d
leaq 0x1160(%rbx), %rdi
callq 0x3aae
movl %eax, %ebp
cltd
idivl 0x1904(%rbx)
addl %r14d, %ebp
addl %eax, %ebp
cmpl $0x1, %edx
sbbl $-0x1, %ebp
cmpl $0x2, %r14d
jl 0x4d5d
movl %r14d, %r12d
leal -0x1(%r12), %esi
movq %r13, %rdi
movl %esi, 0x8(%rsp)
callq 0x3afc
movq %rax, %rbx
leal -0x2(%r12), %r15d
movzbl %bh, %eax
movl %eax, %r14d
movq %r13, %rdi
movl %r15d, %esi
callq 0x3afc
movb $0x1, %cl
movl %eax, %edx
xorb %bl, %dl
jne 0x4d42
movzbl %ah, %eax
xorl %edx, %edx
cmpl %eax, %r14d
setbe %cl
seta %dl
addl %edx, %ebp
testb %cl, %cl
je 0x4d52
leal -0x1(%r15), %eax
testl %r15d, %r15d
movl %eax, %r15d
jg 0x4d1f
cmpl $0x2, %r12d
movl 0x8(%rsp), %r14d
jg 0x4cfd
movl $0x1, %r12d
imulq $0x12c, %r12, %r14      # imm = 0x12C
addq %r13, %r14
movq %r14, %rdi
callq 0x3aae
movl %eax, %ebx
movq %r14, %rdi
callq 0x3ab6
addl %ebx, %ebp
addl %eax, %ebp
testl %eax, %eax
je 0x4e33
movl %eax, %r15d
movq %r12, 0x8(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0x1c(%rsp)
movaps %xmm0, 0x10(%rsp)
notl %eax
addl %ebx, %eax
js 0x4dc0
subl %r15d, %ebx
decl %ebx
movq %r14, %rdi
movl %ebx, %esi
callq 0x3afc
movzbl %al, %ecx
movb %ah, 0x10(%rsp,%rcx)
testl %ebx, %ebx
jg 0x4da9
testl %r15d, %r15d
movabsq $0xffffffffff00, %rbx   # imm = 0xFFFFFFFFFF00
jle 0x4e2e
leal -0x1(%r15), %r12d
movq %r14, %rdi
movl %r12d, %esi
callq 0x3ae4
movzbl %al, %ecx
andq %rbx, %rax
shrq $0x8, %rax
leaq 0x10(%rsp), %rdx
cmpb $0x0, 0x4(%rcx,%rdx)
je 0x4e14
movzbl 0x10(%rsp,%rcx), %edx
movzbl %al, %esi
cmpl %edx, %esi
jae 0x4e0e
movb 0x14(%rsp,%rcx), %dl
incl %ebp
cmpb %al, %dl
ja 0x4e04
movb %dl, 0x10(%rsp,%rcx)
movb 0x14(%rsp,%rcx), %al
jmp 0x4e21
movzbl 0x10(%rsp,%rcx), %edx
movzbl %al, %esi
cmpl %edx, %esi
adcl $0x0, %ebp
movb %al, 0x10(%rsp,%rcx)
cmpl $0x1, %r15d
movl %r12d, %r15d
jg 0x4dcf
movq 0x8(%rsp), %r12
incq %r12
cmpq $0x8, %r12
jne 0x4d63
movl %ebp, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop