// File: ShootMe[P]Klondike-Solver/Solitaire.cpp
// Function: Solitaire::SolveRandom(int, int)
SolveResult Solitaire::SolveRandom(int numberOfTimesToPlay, int solutionsToFind) {
	MakeAutoMoves();
	if (movesAvailableCount == 0) { return foundationCount == 52 ? SolvedMinimal : Impossible; }

	Move bestSolution[512];
	bestSolution[0].Count = 255;
	int bestSolutionMoveCount = 512;
	int maxFoundationCount = 0;
	int bestRoundCount = 10;

	shared_ptr<MoveNode> firstNode = movesMadeCount > 0 ? make_shared<MoveNode>(movesMade[0]) : NULL;
	shared_ptr<MoveNode> node = firstNode;
	for (int i = 1; i < movesMadeCount; i++) {
		node->Parent = make_shared<MoveNode>(movesMade[i]);
		node = node->Parent;
	}

	int solutionCount = 0;
	while ((maxFoundationCount < 52 || solutionCount < solutionsToFind) && numberOfTimesToPlay-- > 0) {
		while (foundationCount < 52 && movesAvailableCount > 0 && movesMadeCount < 500 && roundCount <= 10) {
			int drawIndex = -1;
			for (int i = 0; i < movesAvailableCount; i++) {
				if (movesAvailable[i].From == WASTE) {
					drawIndex = i;
					break;
				}
			}

			if (drawIndex <= 0) {
				MakeMove(random.Next1() % movesAvailableCount);
			} else {
				int r = random.Next1() % (drawIndex + (random.Next1() & 1) + (movesAvailableCount >> 3));
				if (r >= drawIndex) {
					MakeMove((random.Next1() % (movesAvailableCount - drawIndex)) + drawIndex);
				} else {
					MakeMove(r);
				}
			}
			UpdateAvailableMoves();
		}

		if (foundationCount == 52 || foundationCount > maxFoundationCount) {
			int movesTotal = MovesMadeNormalizedCount();
			if (foundationCount == 52) { solutionCount++; }
			if (foundationCount < 52 || movesTotal < bestSolutionMoveCount) {
				if (foundationCount == 52) {
					bestRoundCount = roundCount;
					bestSolutionMoveCount = movesTotal;
				}
				maxFoundationCount = foundationCount;

				//Save solution
				for (int i = 0; i < movesMadeCount; i++) {
					bestSolution[i] = movesMade[i];
				}
				bestSolution[movesMadeCount].Count = 255;
			}
		}

		//Reset game
		node = firstNode;
		ResetGame(drawCount);
		while (node != NULL) {
			MakeMove(node->Value);
			node = node->Parent;
		}
		UpdateAvailableMoves();
	}

	//Reset game to best solution found
	ResetGame(drawCount);
	for (int i = 0; bestSolution[i].Count < 255; i++) {
		MakeMove(bestSolution[i]);
	}
	return foundationCount == 52 ? SolvedMayNotBeMinimal : CouldNotComplete;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x8e0, %rsp            # imm = 0x8E0
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x8a0(%rbp)
callq 0x9260
movq -0x8a0(%rbp), %rax
cmpl $0x0, 0x1910(%rax)
jne 0x9327
movq -0x8a0(%rbp), %rax
movl 0x190c(%rax), %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x34, %edx
cmovel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x9989
leaq -0x820(%rbp), %rax
movq %rax, %rcx
addq $0x800, %rcx            # imm = 0x800
movq %rcx, -0x8b0(%rbp)
movq %rax, -0x8a8(%rbp)
movq -0x8a8(%rbp), %rdi
movq %rdi, -0x8b8(%rbp)
callq 0x5900
movq -0x8b8(%rbp), %rax
movq -0x8b0(%rbp), %rcx
addq $0x4, %rax
cmpq %rcx, %rax
movq %rax, -0x8a8(%rbp)
jne 0x9346
movq -0x8a0(%rbp), %rax
movb $-0x1, -0x81e(%rbp)
movl $0x200, -0x824(%rbp)    # imm = 0x200
movl $0x0, -0x828(%rbp)
movl $0xa, -0x82c(%rbp)
cmpl $0x0, 0x1914(%rax)
jle 0x93c1
movq -0x8a0(%rbp), %rsi
leaq -0x840(%rbp), %rdi
callq 0xf6b0
jmp 0x93d1
leaq -0x840(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5ab0
leaq -0x850(%rbp), %rdi
leaq -0x840(%rbp), %rsi
callq 0xf490
movl $0x1, -0x854(%rbp)
movq -0x8a0(%rbp), %rcx
movl -0x854(%rbp), %eax
cmpl 0x1914(%rcx), %eax
jge 0x94ac
movq -0x8a0(%rbp), %rax
movslq -0x854(%rbp), %rcx
leaq (%rax,%rcx,4), %rsi
leaq -0x868(%rbp), %rdi
callq 0xf6b0
jmp 0x9427
leaq -0x850(%rbp), %rdi
callq 0xf020
movq %rax, %rdi
leaq -0x868(%rbp), %rsi
callq 0x5ad0
leaq -0x868(%rbp), %rdi
callq 0x5b00
leaq -0x850(%rbp), %rdi
callq 0xf020
movq %rax, %rsi
leaq -0x850(%rbp), %rdi
callq 0x5b20
movl -0x854(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x854(%rbp)
jmp 0x93ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x870(%rbp)
movl %eax, -0x874(%rbp)
leaq -0x850(%rbp), %rdi
callq 0x5b00
leaq -0x840(%rbp), %rdi
callq 0x5b00
jmp 0x9995
movl $0x0, -0x878(%rbp)
cmpl $0x34, -0x828(%rbp)
jl 0x94d2
movl -0x878(%rbp), %ecx
xorl %eax, %eax
cmpl -0x18(%rbp), %ecx
movb %al, -0x8b9(%rbp)
jge 0x94e9
movl -0x14(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x14(%rbp)
cmpl $0x0, %eax
setg %al
movb %al, -0x8b9(%rbp)
movb -0x8b9(%rbp), %al
testb $0x1, %al
jne 0x94f8
jmp 0x98e2
jmp 0x94fa
movq -0x8a0(%rbp), %rcx
xorl %eax, %eax
cmpl $0x34, 0x190c(%rcx)
movb %al, -0x8ba(%rbp)
jge 0x955c
movq -0x8a0(%rbp), %rcx
xorl %eax, %eax
cmpl $0x0, 0x1910(%rcx)
movb %al, -0x8ba(%rbp)
jle 0x955c
movq -0x8a0(%rbp), %rcx
xorl %eax, %eax
cmpl $0x1f4, 0x1914(%rcx)    # imm = 0x1F4
movb %al, -0x8ba(%rbp)
jge 0x955c
movq -0x8a0(%rbp), %rax
cmpl $0xa, 0x1908(%rax)
setle %al
movb %al, -0x8ba(%rbp)
movb -0x8ba(%rbp), %al
testb $0x1, %al
jne 0x956b
jmp 0x9717
movl $0xffffffff, -0x87c(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x880(%rbp)
movq -0x8a0(%rbp), %rcx
movl -0x880(%rbp), %eax
cmpl 0x1910(%rcx), %eax
jge 0x95d0
movq -0x8a0(%rbp), %rax
movslq -0x880(%rbp), %rcx
movzbl 0x1874(%rax,%rcx,4), %eax
cmpl $0x0, %eax
jne 0x95bd
movl -0x880(%rbp), %eax
movl %eax, -0x87c(%rbp)
jmp 0x95d0
jmp 0x95bf
movl -0x880(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x880(%rbp)
jmp 0x957f
cmpl $0x0, -0x87c(%rbp)
jg 0x9618
movq -0x8a0(%rbp), %rdi
addq $0x18f4, %rdi           # imm = 0x18F4
callq 0x13150
movl %eax, -0x8c0(%rbp)
jmp 0x95f4
movq -0x8a0(%rbp), %rdi
movl -0x8c0(%rbp), %eax
movl 0x1910(%rdi), %ecx
cltd
idivl %ecx
movl %edx, %esi
callq 0x99b0
jmp 0x9613
jmp 0x9704
movq -0x8a0(%rbp), %rdi
addq $0x18f4, %rdi           # imm = 0x18F4
callq 0x13150
movl %eax, -0x8c4(%rbp)
jmp 0x9633
movq -0x8a0(%rbp), %rdi
movl -0x87c(%rbp), %eax
movl %eax, -0x8cc(%rbp)
addq $0x18f4, %rdi           # imm = 0x18F4
callq 0x13150
movl %eax, -0x8c8(%rbp)
jmp 0x965a
movl -0x8c4(%rbp), %eax
movq -0x8a0(%rbp), %rdx
movl -0x8cc(%rbp), %ecx
movl -0x8c8(%rbp), %esi
andl $0x1, %esi
addl %esi, %ecx
movl 0x1910(%rdx), %edx
sarl $0x3, %edx
addl %edx, %ecx
cltd
idivl %ecx
movl %edx, -0x884(%rbp)
movl -0x884(%rbp), %eax
cmpl -0x87c(%rbp), %eax
jl 0x96ec
movq -0x8a0(%rbp), %rdi
addq $0x18f4, %rdi           # imm = 0x18F4
callq 0x13150
movl %eax, -0x8d0(%rbp)
jmp 0x96b5
movq -0x8a0(%rbp), %rdi
movl -0x8d0(%rbp), %eax
movl 0x1910(%rdi), %ecx
movl -0x87c(%rbp), %edx
movl %edx, -0x8d4(%rbp)
subl %edx, %ecx
cltd
idivl %ecx
movl -0x8d4(%rbp), %eax
movl %edx, %esi
addl %eax, %esi
callq 0x99b0
jmp 0x96ea
jmp 0x9702
movq -0x8a0(%rbp), %rdi
movl -0x884(%rbp), %esi
callq 0x99b0
jmp 0x9700
jmp 0x9702
jmp 0x9704
movq -0x8a0(%rbp), %rdi
callq 0x7380
jmp 0x9712
jmp 0x94fa
movq -0x8a0(%rbp), %rax
cmpl $0x34, 0x190c(%rax)
je 0x9740
movq -0x8a0(%rbp), %rax
movl 0x190c(%rax), %eax
cmpl -0x828(%rbp), %eax
jle 0x984a
movq -0x8a0(%rbp), %rdi
callq 0x7f50
movl %eax, -0x8d8(%rbp)
jmp 0x9754
movq -0x8a0(%rbp), %rax
movl -0x8d8(%rbp), %ecx
movl %ecx, -0x888(%rbp)
cmpl $0x34, 0x190c(%rax)
jne 0x977f
movl -0x878(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x878(%rbp)
movq -0x8a0(%rbp), %rax
cmpl $0x34, 0x190c(%rax)
jl 0x97a1
movl -0x888(%rbp), %eax
cmpl -0x824(%rbp), %eax
jge 0x9848
movq -0x8a0(%rbp), %rax
cmpl $0x34, 0x190c(%rax)
jne 0x97d0
movq -0x8a0(%rbp), %rax
movl 0x1908(%rax), %eax
movl %eax, -0x82c(%rbp)
movl -0x888(%rbp), %eax
movl %eax, -0x824(%rbp)
movq -0x8a0(%rbp), %rax
movl 0x190c(%rax), %eax
movl %eax, -0x828(%rbp)
movl $0x0, -0x88c(%rbp)
movq -0x8a0(%rbp), %rcx
movl -0x88c(%rbp), %eax
cmpl 0x1914(%rcx), %eax
jge 0x9832
movq -0x8a0(%rbp), %rcx
movslq -0x88c(%rbp), %rdx
movslq -0x88c(%rbp), %rax
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x820(%rbp,%rax,4)
movl -0x88c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88c(%rbp)
jmp 0x97ed
movq -0x8a0(%rbp), %rax
movslq 0x1914(%rax), %rax
movb $-0x1, -0x81e(%rbp,%rax,4)
jmp 0x984a
leaq -0x850(%rbp), %rdi
leaq -0x840(%rbp), %rsi
callq 0x5b20
movq -0x8a0(%rbp), %rdi
movl 0x1904(%rdi), %esi
callq 0x99e0
jmp 0x9871
jmp 0x9873
leaq -0x850(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xeff0
testb $0x1, %al
jne 0x9889
jmp 0x98cf
leaq -0x850(%rbp), %rdi
callq 0xf020
movq -0x8a0(%rbp), %rdi
movl 0x10(%rax), %eax
movl %eax, -0x890(%rbp)
movl -0x890(%rbp), %esi
callq 0x7150
jmp 0x98b2
leaq -0x850(%rbp), %rdi
callq 0xf020
movq %rax, %rsi
leaq -0x850(%rbp), %rdi
callq 0x5b20
jmp 0x9873
movq -0x8a0(%rbp), %rdi
callq 0x7380
jmp 0x98dd
jmp 0x94b6
movq -0x8a0(%rbp), %rdi
movl 0x1904(%rdi), %esi
callq 0x99e0
jmp 0x98f6
movl $0x0, -0x894(%rbp)
movslq -0x894(%rbp), %rax
movzbl -0x81e(%rbp,%rax,4), %eax
cmpl $0xff, %eax
jge 0x9951
movq -0x8a0(%rbp), %rdi
movslq -0x894(%rbp), %rax
movl -0x820(%rbp,%rax,4), %eax
movl %eax, -0x898(%rbp)
movl -0x898(%rbp), %esi
callq 0x7150
jmp 0x993e
jmp 0x9940
movl -0x894(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x894(%rbp)
jmp 0x9900
movq -0x8a0(%rbp), %rax
movl 0x190c(%rax), %edx
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpl $0x34, %edx
cmovel %ecx, %eax
movl %eax, -0x4(%rbp)
leaq -0x850(%rbp), %rdi
callq 0x5b00
leaq -0x840(%rbp), %rdi
callq 0x5b00
movl -0x4(%rbp), %eax
addq $0x8e0, %rsp            # imm = 0x8E0
popq %rbp
retq
movq -0x870(%rbp), %rdi
callq 0x33d0
nopw %cs:(%rax,%rax)