// File: /workspace/github_c_makefile_star2_O3/upcrob[P]garry/moves.c
// Function: bestMoveHelper(char*, int, int, MoveSet*, Move*, int)
MoveDef* bestMoveHelper(char* board, int color, int depth, MoveSet* legalMoves, Move* prevMove, int evaluator)
{
	//Save state of castle variables
	char tmpWKC = whiteKCastleInvalid;
	char tmpWQC = whiteQCastleInvalid;
	char tmpBKC = blackKCastleInvalid;
	char tmpBQC = blackQCastleInvalid;
	
	if (depth == 0)
	{
		//we have reached the end of the search (base case)
		//determine best greedy legal move
		int i, best;
		if (color == WHITE)
			best = -INFINITY;
		else
			best = INFINITY;
		for (i = 0; i < legalMoves->size; i++)
		{
			Move* move = getMove(legalMoves, i);
			if (color == WHITE)
			{
				//white
				if (move->boardScore > best)
					best = move->boardScore;	//update best move
			} else {
				//black
				if (move->boardScore < best)
					best = move->boardScore;	//update best move
			}
		}
		
		//choose random best move if multiple close to best
		int icount = 0;
		int* indices = (int*) malloc(sizeof(int) * legalMoves->size);
		for (i = 0; i < legalMoves->size; i++)
		{
			Move* move = getMove(legalMoves, i);
			if (abs(best - move->boardScore) <= RAND_RANGE)
				indices[icount++] = i;
		}
		
		MoveDef* m = (MoveDef*) malloc(sizeof(MoveDef));
		if (icount == 0)
			m->index = indices[0];
		else
			m->index = indices[(int) rand() % icount];
		m->value = best;
		free(indices);
		
		return m;
	} else {
		//recursive case
		//execute each move and recurse
		int i;
		
		//declare variables for the next move and an empty board
		char* nextBoard = buildNewBoard();
		MoveSet* nextLegal;
		char nextColor;
		
		//initialize variables, best holds the "best" next move
		MoveDef* best;
		best = (MoveDef*) malloc(sizeof(MoveDef));
		best->index = 0;
		if (color == WHITE)
		{
			nextColor = BLACK;
			best->value = -INFINITY;
		} else {
			nextColor = WHITE;
			best->value = INFINITY;
		}
		
		//recursively search each next legal move for the one
		//that leads to the best end case
		for (i = 0; i < legalMoves->size; i++)
		{
			cloneBoard(board, nextBoard);	//copy board
			Move* testMove = getMove(legalMoves, i);	//get move from the set of legal moves
			executeMove(nextBoard, testMove, prevMove);	//execute it
			nextLegal = getLegalMoves(nextBoard, nextColor, testMove, evaluator);	//get the next set of legal moves available
			MoveDef* m;
			if (nextLegal->size == 0)
			{
				//no legal moves available, either a checkmate or stalemate
				m = (MoveDef*) malloc(sizeof(MoveDef));
				m->index = 0;
				if (color == WHITE)
				{
					//check for stalemate
					if (kingInCheck(nextBoard, BLACK))
					{
						m->value = CHECKMATE_VALUE;	//black's king in checkmate
					} else {
						m->value = 0;	//stalemate
					}
				} else {
					//check for stalemate
					if (kingInCheck(nextBoard, WHITE))
					{
						m->value = -CHECKMATE_VALUE;	//white's king in checkmate
					} else {
						m->value = 0;	//stalemate
					}
				}
			} else {
				//recurse
				m = bestMoveHelper(nextBoard, nextColor, depth - 1, nextLegal, testMove, evaluator);
			}

			if (color == WHITE)
			{
				//white
				if (m->value > best->value)
				{
					//update current best move found
					best->index = i;
					best->value = m->value;
				}
			} else {
				//black
				if (m->value < best->value)
				{
					//update current best most found
					best->index = i;
					best->value = m->value;
				}
			}
			
			//free memory
			free(m);
			destroyMoveSet(nextLegal);
		}
		
		//free memory
		free(nextBoard);
		
		//restore castling variables
		whiteKCastleInvalid = tmpWKC;
		whiteQCastleInvalid = tmpWQC;
		blackKCastleInvalid = tmpBKC;
		blackQCastleInvalid = tmpBQC;
		
		//return best index
		return best;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r8, -0x68(%rbp)
movq %rcx, %r12
movl %esi, %r14d
movq %rdi, -0x60(%rbp)
movl %edx, -0x30(%rbp)
testl %edx, %edx
je 0x8698
movl %r9d, -0x50(%rbp)
movb 0x3c58(%rip), %al       # 0xc129
movb %al, -0x29(%rbp)
movb 0x3c50(%rip), %al       # 0xc12a
movb %al, -0x2a(%rbp)
movb 0x3c48(%rip), %al       # 0xc12b
movb %al, -0x2b(%rbp)
movb 0x3c40(%rip), %al       # 0xc12c
movb %al, -0x2c(%rbp)
callq 0x1e18
movq %rax, %r13
movl $0x8, %edi
callq 0x1140
xorl %esi, %esi
movl %r14d, -0x34(%rbp)
testl %r14d, %r14d
movl $0x82d48b00, %ecx       # imm = 0x82D48B00
movl $0x7d2b7500, %edx       # imm = 0x7D2B7500
cmovel %ecx, %edx
movl $0x32, %r14d
cmovnel %esi, %r14d
movl $0x0, (%rax)
movq %rax, -0x40(%rbp)
movl %edx, 0x4(%rax)
cmpl $0x0, 0x4(%r12)
jle 0x865b
decl -0x30(%rbp)
xorl %r15d, %r15d
movl %r14d, -0x4c(%rbp)
movq %r13, -0x48(%rbp)
movq %r12, -0x58(%rbp)
movq -0x60(%rbp), %rdi
movq %r13, %rsi
callq 0x1f51
movq 0x8(%r12), %rax
movq (%rax,%r15,8), %rbx
movq %r13, %rdi
movq %rbx, %rsi
movq -0x68(%rbp), %rdx
callq 0x78aa
movq %r13, %rdi
movl %r14d, %esi
movq %rbx, %rdx
movl %r14d, %r12d
movl -0x50(%rbp), %r14d
movl %r14d, %ecx
callq 0x2ce7
cmpl $0x0, 0x4(%rax)
je 0x85b9
movq %r13, %rdi
movl %r12d, %esi
movl -0x30(%rbp), %edx
movq %rax, %r12
movq %rax, %rcx
movq %rbx, %r8
movl %r14d, %r9d
callq 0x849d
movq %rax, %rbx
movl 0x4(%rax), %eax
cmpl $0x0, -0x34(%rbp)
jne 0x85f2
jmp 0x8650
movq %rax, %r12
movl $0x8, %edi
callq 0x1140
movq %rax, %rbx
movl $0x0, (%rax)
cmpl $0x0, -0x34(%rbp)
je 0x8630
movq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x20d8
testb %al, %al
movl $0xffff3cb0, %eax       # imm = 0xFFFF3CB0
movl $0x0, %ecx
cmovel %ecx, %eax
movl %eax, 0x4(%rbx)
movq -0x40(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x8601
movl %r15d, (%rcx)
movl %eax, 0x4(%rcx)
movq %rbx, %rdi
callq 0x1130
movq %r12, %rdi
callq 0x7e35
incq %r15
movq -0x58(%rbp), %r12
movslq 0x4(%r12), %rax
cmpq %rax, %r15
movl -0x4c(%rbp), %r14d
movq -0x48(%rbp), %r13
jl 0x854c
jmp 0x865b
movq -0x48(%rbp), %rdi
movl $0x32, %esi
callq 0x20d8
testb %al, %al
movl $0xc350, %eax           # imm = 0xC350
movl $0x0, %ecx
cmovel %ecx, %eax
movl %eax, 0x4(%rbx)
movq -0x40(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jg 0x85fb
jmp 0x8601
movq %r13, %rdi
callq 0x1130
movb -0x29(%rbp), %al
andb $0x1, %al
movb %al, 0x3abb(%rip)       # 0xc129
movb -0x2a(%rbp), %al
andb $0x1, %al
movb %al, 0x3ab1(%rip)       # 0xc12a
movb -0x2b(%rbp), %al
andb $0x1, %al
movb %al, 0x3aa7(%rip)       # 0xc12b
movb -0x2c(%rbp), %al
andb $0x1, %al
movb %al, 0x3a9d(%rip)       # 0xc12c
movq -0x40(%rbp), %rbx
jmp 0x877e
testl %r14d, %r14d
movl $0x82d48b00, %eax       # imm = 0x82D48B00
movl $0x7d2b7500, %ebx       # imm = 0x7D2B7500
cmovel %eax, %ebx
movslq 0x4(%r12), %r15
testq %r15, %r15
jle 0x874d
movq 0x8(%r12), %rax
xorl %ecx, %ecx
movq (%rax,%rcx,8), %rdx
movl 0x8(%rdx), %edx
testl %r14d, %r14d
je 0x86d0
cmpl %ebx, %edx
cmovll %edx, %ebx
jmp 0x86d5
cmpl %ebx, %edx
cmovgl %edx, %ebx
incq %rcx
cmpq %rcx, %r15
jne 0x86bd
leaq (,%r15,4), %rdi
callq 0x1140
movq %rax, %r14
testl %r15d, %r15d
jle 0x875c
movq 0x8(%r12), %rax
xorl %ecx, %ecx
xorl %r12d, %r12d
movq (%rax,%rcx,8), %rdx
movl %ebx, %esi
subl 0x8(%rdx), %esi
movl %esi, %edx
negl %edx
cmovsl %esi, %edx
cmpl $0x14, %edx
ja 0x871b
movslq %r12d, %rdx
incl %r12d
movl %ecx, (%r14,%rdx,4)
incq %rcx
cmpq %rcx, %r15
jne 0x86fc
movl $0x8, %edi
callq 0x1140
movq %rax, %rcx
testl %r12d, %r12d
je 0x8769
movq %rcx, %r15
callq 0x1050
movq %r15, %rcx
cltd
idivl %r12d
movslq %edx, %rax
leaq (%r14,%rax,4), %rax
jmp 0x876c
shlq $0x2, %r15
movq %r15, %rdi
callq 0x1140
movq %rax, %r14
movl $0x8, %edi
callq 0x1140
movq %rax, %rcx
movq %r14, %rax
movl (%rax), %eax
movl %eax, (%rcx)
movl %ebx, 0x4(%rcx)
movq %r14, %rdi
movq %rcx, %rbx
callq 0x1130
movq %rbx, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq