// File: /workspace/github_cpp_makefile_star2_O1/ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: Solitaire::UpdateAvailableMoves()
void Solitaire::UpdateAvailableMoves() {
	movesAvailableCount = 0;
	int foundationMin = FoundationMin();
	Card talon[24];
	int talonMoves[24];
	int talonCount = GetTalonCards(talon, talonMoves);

	//Check tableau to foundation, Check tableau to tableau
	for (int i = TABLEAU1; i <= TABLEAU7; ++i) {
		Pile & pile1 = piles[i];
		int pile1Size = pile1.Size();

		if (pile1Size == 0) { continue; }

		int pile1UpSize = pile1.UpSize();
		Card card1 = pile1.Low();
		int cardFoundation = card1.Foundation;

		if (card1.Rank - piles[cardFoundation].Size() == 1) {
			//logic used to tell if we can safely move a card to its foundation
			if (card1.Rank < foundationMin) {
				movesAvailable[0].Set(i, cardFoundation, 1, pile1UpSize == 1 && pile1Size > 1 ? 1 : 0);
				movesAvailableCount = 1;
				return;
			}

			movesAvailable[movesAvailableCount++].Set(i, cardFoundation, 1, pile1UpSize == 1 && pile1Size > 1 ? 1 : 0);
		}

		Card card2 = pile1.High();
		int pile1Length = card2.Rank - card1.Rank + 1;
		bool kingMoved = false;

		for (int j = TABLEAU1; j <= TABLEAU7; ++j) {
			if (i == j) { continue; }

			Pile & pile2 = piles[j];

			if (pile2.Size() == 0) {
				if (card2.Rank == KING && pile1Size != pile1Length && !kingMoved) {
					movesAvailable[movesAvailableCount++].Set(i, j, pile1Length, 1);
					//only create one move for a blank spot
					kingMoved = true;
				}
				continue;
			}

			Card card3 = pile2.Low();
			//logic used to determine if a pile of cards can be moved ontop of another pile of cards
			if (card1.Rank >= card3.Rank || card2.Rank + 1 < card3.Rank || ((card3.IsRed ^ card1.IsRed) ^ (card3.IsOdd ^ card1.IsOdd)) != 0) {
				continue;
			}

			int pile1Moved = card3.Rank - card1.Rank;

			if (pile1Moved == pile1Length) {//we are moving all face up cards
				movesAvailable[movesAvailableCount++].Set(i, j, pile1Moved, pile1Size > pile1Moved ? 1 : 0);
				continue;
			}

			//look to see if we are covering a card that can be moved to the foundation
			Card card4 = pile1[pile1UpSize - pile1Moved - 1];
			if (card4.Rank - piles[card4.Foundation].Size() == 1) {
				movesAvailable[movesAvailableCount++].Set(i, j, pile1Moved, 0);
			}
		}
	}

	//Check talon cards
	for (int j = 0; j < talonCount; j++) {
		Card talonCard = talon[j];
		int foundation = talonCard.Foundation;
		int cardsToDraw = talonMoves[j];

		if (talonCard.Rank - piles[foundation].Size() == 1) {
			if (talonCard.Rank <= foundationMin) {
				if (drawCount == 1) {
					if (cardsToDraw == 0 || movesAvailableCount == 0) {
						movesAvailable[0].Set(WASTE, foundation, 1, cardsToDraw);
						movesAvailableCount = 1;
						return;
					} else {
						movesAvailable[movesAvailableCount++].Set(WASTE, foundation, 1, cardsToDraw);
						break;
					}
				} else {
					movesAvailable[movesAvailableCount++].Set(WASTE, foundation, 1, cardsToDraw);
					continue;
				}
			}

			movesAvailable[movesAvailableCount++].Set(WASTE, foundation, 1, cardsToDraw);
		}

		for (int i = TABLEAU1; i <= TABLEAU7; ++i) {
			Pile & pile = piles[i];

			if (pile.Size() != 0) {
				Card tableauCard = pile.Low();

				if (tableauCard.Rank - talonCard.Rank != 1 || tableauCard.IsRed == talonCard.IsRed) {
					continue;
				}

				movesAvailable[movesAvailableCount++].Set(WASTE, i, 1, cardsToDraw);
			} else if (talonCard.Rank == KING) {
				movesAvailable[movesAvailableCount++].Set(WASTE, i, 1, cardsToDraw);
				break;
			}
		}
	}

	if (foundationCount == 0) { return; }
	//Check foundation to tableau, very rarely needed to solve optimally
	Move lastMove = movesMade[movesMadeCount - 1];
	for (int i = FOUNDATION1C; i <= FOUNDATION4H; ++i) {
		Pile & pile1 = piles[i];
		int foundationRank = pile1.Size();
		if (foundationRank == 0 || foundationRank <= foundationMin) { continue; }

		for (int j = TABLEAU1; j <= TABLEAU7; ++j) {
			Pile & pile2 = piles[j];

			if (pile2.Size() != 0) {
				Card card = pile2.Low();

				if ((card.Foundation & 1) == (i & 1) || card.Rank - foundationRank != 1) {
					continue;
				}

				if (lastMove.From != j && lastMove.To != i) {
					movesAvailable[movesAvailableCount++].Set(i, j, 1, 0);
				}
			} else if (foundationRank == KING) {
				if (lastMove.From != j && lastMove.To != i) {
					movesAvailable[movesAvailableCount++].Set(i, j, 1, 0);
				}
				break;
			}
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rdi, %rbx
movl $0x0, 0x1910(%rdi)
callq 0x714c
movl %eax, 0x18(%rsp)
leaq 0x70(%rsp), %rsi
leaq 0x100(%rsp), %rdx
movq %rbx, %rdi
callq 0x6f24
movl %eax, 0x48(%rsp)
leaq 0x800(%rbx), %r12
leaq 0x1874(%rbx), %rax
movq %rax, 0x8(%rsp)
movq %rbx, (%rsp)
leaq 0x92c(%rbx), %rax
movq %rax, 0x60(%rsp)
movl $0x1, %eax
xorl %r13d, %r13d
movq %r12, 0x30(%rsp)
movq %rax, 0x10(%rsp)
imulq $0x12c, %rax, %r14      # imm = 0x12C
addq %r12, %r14
movq %r14, %rdi
callq 0x3aae
testl %eax, %eax
je 0x4573
movl %eax, %ebp
movq %r14, %rdi
callq 0x3abe
movl %eax, 0x1c(%rsp)
movq %r14, %rdi
callq 0x3b1a
movq %rax, %rcx
shrq $0x20, %rcx
movzbl %cl, %r15d
movq %rax, 0x68(%rsp)
movzbl %ah, %ebx
imulq $0x12c, %r15, %rdi      # imm = 0x12C
addq %r12, %rdi
callq 0x3aae
movl %ebx, %ecx
subl %eax, %ecx
cmpl $0x1, %ecx
jne 0x45c0
cmpl 0x18(%rsp), %ebx
jge 0x457d
cmpl $0x1, 0x1c(%rsp)
sete %al
cmpl $0x2, %ebp
setge %cl
andb %al, %cl
movzbl %cl, %r8d
movzbl 0x10(%rsp), %esi
movl $0x1, %ebx
movq 0x8(%rsp), %rdi
movl %r15d, %edx
movl $0x1, %ecx
callq 0x374c
movq (%rsp), %rax
movl $0x1, 0x1910(%rax)
jmp 0x47a9
movl $0x4, %ebx
jmp 0x47a9
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
cmpl $0x1, 0x1c(%rsp)
sete %al
cmpl $0x2, %ebp
setge %cl
andb %al, %cl
movzbl %cl, %r8d
movzbl 0x10(%rsp), %esi
movl %r15d, %edx
movl $0x1, %ecx
callq 0x374c
movq %r14, %rdi
callq 0x3b3c
movzbl %ah, %eax
movl %ebx, 0x28(%rsp)
movl %ebx, %ecx
negl %ecx
addl %eax, %ecx
incl %ecx
leal 0x1(%rax), %edx
movl %edx, 0x20(%rsp)
cmpl $0xd, %eax
setne %al
movl %ebp, 0x4c(%rsp)
movl %ecx, 0x44(%rsp)
cmpl %ecx, %ebp
sete %cl
orb %al, %cl
movb %cl, 0x38(%rsp)
xorl %r12d, %r12d
movq 0x60(%rsp), %rbp
movq $0x0, 0x58(%rsp)
movq 0x10(%rsp), %rbx
movq %r14, 0x50(%rsp)
cmpq %r12, %r13
jne 0x462c
incq %r12
addq $0x12c, %rbp            # imm = 0x12C
cmpq $0x7, %r12
jne 0x4612
jmp 0x47a2
movq %rbp, %rdi
callq 0x3aae
testl %eax, %eax
je 0x46bd
movq %rbp, %rdi
callq 0x3b1a
movzbl %ah, %ecx
movl %ecx, %r15d
subl 0x28(%rsp), %r15d
jbe 0x4617
cmpl %ecx, 0x20(%rsp)
jb 0x4617
xorl 0x68(%rsp), %eax
movl %eax, %ecx
shrl $0x18, %ecx
shrl $0x10, %eax
movzbl %al, %eax
cmpl %eax, %ecx
jne 0x4617
cmpl 0x44(%rsp), %r15d
jne 0x4717
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
leal 0x1(%r12), %edx
xorl %r8d, %r8d
cmpl %r15d, 0x4c(%rsp)
setg %r8b
movl $0xff, %eax
andl %eax, %r15d
andl %eax, %edx
movzbl %bl, %esi
movl %r15d, %ecx
callq 0x374c
jmp 0x4617
cmpb $0x0, 0x38(%rsp)
jne 0x4617
testb $0x1, 0x58(%rsp)
jne 0x4617
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
leal 0x1(%r12), %eax
movzbl %bl, %esi
movzbl 0x44(%rsp), %ecx
movzbl %al, %edx
movl $0x1, %r8d
callq 0x374c
movb $0x1, %al
movq %rax, 0x58(%rsp)
jmp 0x4617
movl %r15d, %esi
notl %esi
addl 0x1c(%rsp), %esi
movq %r14, %rdi
callq 0x3ac6
movzbl %ah, %ebx
shrq $0x20, %rax
movzbl %al, %eax
imulq $0x12c, %rax, %rdi      # imm = 0x12C
addq 0x30(%rsp), %rdi
callq 0x3aae
subl %eax, %ebx
cmpl $0x1, %ebx
jne 0x4793
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
leal 0x1(%r12), %edx
movl $0xff, %eax
andl %eax, %r15d
andl %eax, %edx
movq 0x10(%rsp), %rbx
movzbl %bl, %esi
movl %r15d, %ecx
xorl %r8d, %r8d
callq 0x374c
movq 0x50(%rsp), %r14
jmp 0x4617
movq 0x50(%rsp), %r14
movq 0x10(%rsp), %rbx
jmp 0x4617
xorl %ebx, %ebx
movq 0x30(%rsp), %r12
testb $0x3, %bl
jne 0x4bd6
movq 0x10(%rsp), %rax
incq %rax
incq %r13
cmpq $0x8, %rax
jne 0x44c6
movl 0x48(%rsp), %eax
testl %eax, %eax
jle 0x4a36
movl %eax, %eax
movq %rax, 0x10(%rsp)
movq (%rsp), %rax
addq $0x92c, %rax            # imm = 0x92C
movq %rax, 0x38(%rsp)
xorl %r15d, %r15d
leaq (%r15,%r15,2), %rax
movzbl 0x71(%rsp,%rax,2), %r13d
movzbl 0x73(%rsp,%rax,2), %ecx
movl %ecx, 0x28(%rsp)
movzbl 0x74(%rsp,%rax,2), %ebx
movl 0x100(%rsp,%r15,4), %ebp
imulq $0x12c, %rbx, %rdi      # imm = 0x12C
addq %r12, %rdi
callq 0x3aae
movl %r13d, %ecx
subl %eax, %ecx
cmpl $0x1, %ecx
movq %r15, 0x20(%rsp)
jne 0x4865
cmpl %r13d, 0x18(%rsp)
jge 0x4955
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
movzbl %bl, %edx
movzbl %bpl, %r8d
xorl %esi, %esi
movl $0x1, %ecx
callq 0x374c
movq $-0x7, %rbx
movzbl %bpl, %ebp
movq 0x38(%rsp), %r15
movq %r15, %rdi
callq 0x3aae
testl %eax, %eax
je 0x48eb
movq %r15, %rdi
callq 0x3b1a
movzbl %ah, %ecx
subl %r13d, %ecx
cmpl $0x1, %ecx
sete %cl
shrl $0x18, %eax
cmpl 0x28(%rsp), %eax
setne %r12b
andb %cl, %r12b
movl $0xd, %r14d
cmpb $0x1, %r12b
jne 0x48e4
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
leal 0x8(%rbx), %eax
movzbl %al, %edx
xorl %r14d, %r14d
xorl %esi, %esi
movl $0x1, %ecx
movl %ebp, %r8d
callq 0x374c
testb %r12b, %r12b
jne 0x492b
jmp 0x492e
cmpb $0xd, %r13b
jne 0x492b
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
leal 0x8(%rbx), %eax
movzbl %al, %edx
xorl %esi, %esi
movl $0x1, %ecx
movl %ebp, %r8d
callq 0x374c
movl $0xb, %r14d
jmp 0x492e
xorl %r14d, %r14d
xorl %r12d, %r12d
cmpl $0xd, %r14d
je 0x4940
testl %r14d, %r14d
jne 0x49ff
addq $0x12c, %r15            # imm = 0x12C
incq %rbx
jne 0x4875
jmp 0x49ff
movq (%rsp), %r14
cmpl $0x1, 0x1904(%r14)
jne 0x49a1
testl %ebp, %ebp
je 0x49d6
movslq 0x1910(%r14), %rax
testq %rax, %rax
je 0x49d6
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%r14)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
movzbl %bl, %edx
movzbl %bpl, %r8d
xorl %esi, %esi
movl $0x1, %ecx
callq 0x374c
movl $0x8, %r12d
jmp 0x49ff
movslq 0x1910(%r14), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%r14)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
movzbl %bl, %edx
movzbl %bpl, %r8d
xorl %esi, %esi
movl $0x1, %ecx
callq 0x374c
movl $0xa, %r12d
jmp 0x49ff
movzbl %bl, %edx
movzbl %bpl, %r8d
movl $0x1, %r12d
movq 0x8(%rsp), %rdi
xorl %esi, %esi
movl $0x1, %ecx
callq 0x374c
movl $0x1, 0x1910(%r14)
cmpl $0xa, %r12d
je 0x4a0a
testl %r12d, %r12d
jne 0x4a28
movq 0x20(%rsp), %r15
incq %r15
cmpq 0x10(%rsp), %r15
movq 0x30(%rsp), %r12
jne 0x47ec
movl $0x8, %r12d
cmpl $0x8, %r12d
setne %al
movq 0x30(%rsp), %r12
jmp 0x4a38
xorl %eax, %eax
testb %al, %al
jne 0x4bd6
movq (%rsp), %rax
cmpl $0x0, 0x190c(%rax)
je 0x4bd6
movq (%rsp), %rcx
movslq 0x1914(%rcx), %rax
movzbl -0x4(%rcx,%rax,4), %edx
movq %rdx, 0x28(%rsp)
movzbl -0x3(%rcx,%rax,4), %eax
movq %rax, 0x20(%rsp)
leaq 0x92c(%rcx), %rax
movq %rax, 0x38(%rsp)
movl $0x9, %r13d
imulq $0x12c, %r13, %rdi      # imm = 0x12C
addq %r12, %rdi
callq 0x3aae
movl %eax, %ebp
testl %eax, %eax
sete %al
cmpl 0x18(%rsp), %ebp
setle %cl
orb %al, %cl
jne 0x4bc4
movl $0x1, %r15d
movzbl %r13b, %eax
movl %eax, 0x10(%rsp)
movq 0x38(%rsp), %r12
movq %r12, %rdi
callq 0x3aae
testl %eax, %eax
je 0x4aea
movq %r12, %rdi
callq 0x3b1a
movq %rax, %rcx
shrq $0x20, %rcx
xorl %r13d, %ecx
movl $0x13, %ebx
testb $0x1, %cl
jne 0x4b44
xorl %r14d, %r14d
jmp 0x4ba0
cmpl $0xd, %ebp
jne 0x4ba5
cmpq 0x20(%rsp), %r13
sete %al
cmpq %r15, 0x28(%rsp)
sete %cl
orb %al, %cl
movl $0x11, %ebx
jne 0x4ba7
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
movzbl %r15b, %edx
movl 0x10(%rsp), %esi
movl $0x1, %ecx
xorl %r8d, %r8d
callq 0x374c
jmp 0x4ba7
movzbl %ah, %eax
subl %ebp, %eax
xorl %r14d, %r14d
cmpl $0x1, %eax
jne 0x4ba0
cmpq 0x20(%rsp), %r13
sete %al
cmpq %r15, 0x28(%rsp)
sete %cl
orb %al, %cl
movb $0x1, %r14b
je 0x4b6c
xorl %ebx, %ebx
jmp 0x4ba0
movq (%rsp), %rdx
movslq 0x1910(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x1910(%rdx)
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rdi
movzbl %r15b, %edx
xorl %ebx, %ebx
movl 0x10(%rsp), %esi
movl $0x1, %ecx
xorl %r8d, %r8d
callq 0x374c
testb %r14b, %r14b
je 0x4ba7
xorl %ebx, %ebx
cmpl $0x13, %ebx
je 0x4bb0
testl %ebx, %ebx
jne 0x4bc4
incq %r15
addq $0x12c, %r12            # imm = 0x12C
cmpq $0x8, %r15
jne 0x4aba
incq %r13
cmpq $0xd, %r13
movq 0x30(%rsp), %r12
jne 0x4a82
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq