// File: 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
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa0(%rbp)
addq $0x800, %rax            # imm = 0x800
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x6400
movq -0xa0(%rbp), %rdi
movl %eax, -0x14(%rbp)
addq $0x800, %rdi            # imm = 0x800
addq $0x960, %rdi            # imm = 0x960
callq 0x6400
movq -0xa0(%rbp), %rcx
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
cltd
idivl 0x1904(%rcx)
movl %eax, -0x1c(%rbp)
movl -0x18(%rbp), %eax
cltd
idivl 0x1904(%rcx)
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x18(%rbp)
movl -0x14(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x18(%rbp)
movl -0x14(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jle 0x8254
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %esi
callq 0x6500
movl %eax, %ecx
movl %ecx, -0x26(%rbp)
shrq $0x20, %rax
movw %ax, -0x22(%rbp)
movl -0x20(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jl 0x8244
movq -0x10(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x6500
movl %eax, %ecx
movl %ecx, -0x32(%rbp)
shrq $0x20, %rax
movw %ax, -0x2e(%rbp)
movzbl -0x26(%rbp), %eax
movzbl -0x32(%rbp), %ecx
cmpl %ecx, %eax
jne 0x8237
movzbl -0x25(%rbp), %eax
movzbl -0x31(%rbp), %ecx
cmpl %ecx, %eax
jle 0x8237
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x8244
jmp 0x8239
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x81f5
jmp 0x8246
movl -0x20(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x81c9
movl $0x1, -0x38(%rbp)
cmpl $0x7, -0x38(%rbp)
jg 0x846f
movq -0xa0(%rbp), %rax
addq $0x800, %rax            # imm = 0x800
movslq -0x38(%rbp), %rcx
imulq $0x12c, %rcx, %rcx      # imm = 0x12C
addq %rcx, %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
callq 0x6400
movl %eax, -0x44(%rbp)
movq -0x40(%rbp), %rdi
callq 0x6420
movl %eax, -0x48(%rbp)
movl -0x44(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x18(%rbp)
movl -0x48(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x48(%rbp)
jne 0x82b9
jmp 0x8461
movl -0x48(%rbp), %ecx
movl -0x44(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x44(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x1c, %edx
callq 0x3110
movl -0x44(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x74(%rbp)
cmpl $0x0, -0x74(%rbp)
jl 0x8312
movq -0x40(%rbp), %rdi
movl -0x74(%rbp), %esi
callq 0x6500
movl %eax, %ecx
movl %ecx, -0x7a(%rbp)
shrq $0x20, %rax
movw %ax, -0x76(%rbp)
movb -0x79(%rbp), %cl
movzbl -0x7a(%rbp), %eax
movb %cl, -0x70(%rbp,%rax)
movl -0x74(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x82dd
movl -0x48(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x80(%rbp)
cmpl $0x0, -0x80(%rbp)
jl 0x845f
movq -0x40(%rbp), %rdi
movl -0x80(%rbp), %esi
callq 0x64b0
movl %eax, %ecx
movl %ecx, -0x86(%rbp)
shrq $0x20, %rax
movw %ax, -0x82(%rbp)
movzbl -0x86(%rbp), %eax
movl %eax, %ecx
leaq -0x70(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x90(%rbp)
movb -0x85(%rbp), %al
movb %al, -0x91(%rbp)
movzbl -0x86(%rbp), %eax
addl $0x4, %eax
cltq
movzbl -0x70(%rbp,%rax), %eax
cmpl $0x0, %eax
jne 0x83af
movq -0x90(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x91(%rbp), %ecx
cmpl %ecx, %eax
jle 0x839b
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movb -0x91(%rbp), %cl
movq -0x90(%rbp), %rax
movb %cl, (%rax)
jmp 0x8451
movq -0x90(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x91(%rbp), %ecx
cmpl %ecx, %eax
jle 0x83f9
jmp 0x83c6
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
movq -0x90(%rbp), %rax
movb 0x4(%rax), %cl
movq -0x90(%rbp), %rax
movb %cl, (%rax)
movq -0x90(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x91(%rbp), %ecx
cmpl %ecx, %eax
jg 0x83c6
jmp 0x83f9
jmp 0x83fb
jmp 0x83fd
movq -0x90(%rbp), %rax
movb (%rax), %al
movb %al, -0x92(%rbp)
movb -0x91(%rbp), %cl
movq -0x90(%rbp), %rax
movb %cl, (%rax)
movb -0x92(%rbp), %al
movb %al, -0x91(%rbp)
movq -0x90(%rbp), %rax
movb 0x4(%rax), %cl
movq -0x90(%rbp), %rax
movb %cl, (%rax)
movq -0x90(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x91(%rbp), %ecx
cmpl %ecx, %eax
jl 0x83fd
jmp 0x8451
movl -0x80(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x80(%rbp)
jmp 0x831b
jmp 0x8461
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x825b
movl -0x18(%rbp), %eax
addq $0xa0, %rsp
popq %rbp
retq
nopl (%rax,%rax)