// File: /workspace/github_c_makefile_star2_O0/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
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl %r9d, -0x2c(%rbp)
movb 0x7ec2(%rip), %al       # 0x21609
movb %al, -0x2d(%rbp)
movb 0x7eba(%rip), %al       # 0x2160a
movb %al, -0x2e(%rbp)
movb 0x7eb2(%rip), %al       # 0x2160b
movb %al, -0x2f(%rbp)
movb 0x7eaa(%rip), %al       # 0x2160c
movb %al, -0x30(%rbp)
cmpl $0x0, -0x18(%rbp)
jne 0x198ce
cmpl $0x0, -0x14(%rbp)
jne 0x1977e
movl $0x82d48b00, -0x38(%rbp) # imm = 0x82D48B00
jmp 0x19785
movl $0x7d2b7500, -0x38(%rbp) # imm = 0x7D2B7500
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x197eb
movq -0x20(%rbp), %rdi
movl -0x34(%rbp), %esi
callq 0x18080
movq %rax, -0x40(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x197c6
movq -0x40(%rbp), %rax
movl 0x8(%rax), %eax
cmpl -0x38(%rbp), %eax
jle 0x197c4
movq -0x40(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x38(%rbp)
jmp 0x197de
movq -0x40(%rbp), %rax
movl 0x8(%rax), %eax
cmpl -0x38(%rbp), %eax
jge 0x197dc
movq -0x40(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x38(%rbp)
jmp 0x197de
jmp 0x197e0
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x1978c
movl $0x0, -0x44(%rbp)
movq -0x20(%rbp), %rax
movslq 0x4(%rax), %rdi
shlq $0x2, %rdi
callq 0x8780
movq %rax, -0x50(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x19865
movq -0x20(%rbp), %rdi
movl -0x34(%rbp), %esi
callq 0x18080
movq %rax, -0x58(%rbp)
movl -0x38(%rbp), %eax
movq -0x58(%rbp), %rcx
subl 0x8(%rcx), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
cmpl $0x14, %eax
jg 0x19858
movl -0x34(%rbp), %edx
movq -0x50(%rbp), %rax
movl -0x44(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x44(%rbp)
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x1985a
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x1980e
movl $0x8, %edi
callq 0x8780
movq %rax, -0x60(%rbp)
cmpl $0x0, -0x44(%rbp)
jne 0x19887
movq -0x50(%rbp), %rax
movl (%rax), %ecx
movq -0x60(%rbp), %rax
movl %ecx, (%rax)
jmp 0x198ae
movq -0x50(%rbp), %rax
movq %rax, -0xa0(%rbp)
callq 0x8150
cltd
idivl -0x44(%rbp)
movq -0xa0(%rbp), %rax
movslq %edx, %rcx
movl (%rax,%rcx,4), %ecx
movq -0x60(%rbp), %rax
movl %ecx, (%rax)
movl -0x38(%rbp), %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x50(%rbp), %rdi
callq 0x8680
movq -0x60(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x19b16
callq 0xe7d0
movq %rax, -0x70(%rbp)
movl $0x8, %edi
callq 0x8780
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movl $0x0, (%rax)
cmpl $0x0, -0x14(%rbp)
jne 0x1990f
movb $0x32, -0x79(%rbp)
movq -0x88(%rbp), %rax
movl $0x82d48b00, 0x4(%rax)  # imm = 0x82D48B00
jmp 0x19921
movb $0x0, -0x79(%rbp)
movq -0x88(%rbp), %rax
movl $0x7d2b7500, 0x4(%rax)  # imm = 0x7D2B7500
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x19ade
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rsi
callq 0xeb90
movq -0x20(%rbp), %rdi
movl -0x64(%rbp), %esi
callq 0x18080
movq %rax, -0x90(%rbp)
movq -0x70(%rbp), %rdi
movq -0x90(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x180a0
movq -0x70(%rbp), %rdi
movsbl -0x79(%rbp), %esi
movq -0x90(%rbp), %rdx
movl -0x2c(%rbp), %ecx
callq 0xff20
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x19a1c
movl $0x8, %edi
callq 0x8780
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rax
movl $0x0, (%rax)
cmpl $0x0, -0x14(%rbp)
jne 0x199eb
movq -0x70(%rbp), %rdi
movl $0x32, %esi
callq 0xee60
cmpb $0x0, %al
je 0x199db
movq -0x98(%rbp), %rax
movl $0xc350, 0x4(%rax)      # imm = 0xC350
jmp 0x199e9
movq -0x98(%rbp), %rax
movl $0x0, 0x4(%rax)
jmp 0x19a1a
movq -0x70(%rbp), %rdi
xorl %esi, %esi
callq 0xee60
cmpb $0x0, %al
je 0x19a0a
movq -0x98(%rbp), %rax
movl $0xffff3cb0, 0x4(%rax)  # imm = 0xFFFF3CB0
jmp 0x19a18
movq -0x98(%rbp), %rax
movl $0x0, 0x4(%rax)
jmp 0x19a1a
jmp 0x19a45
movq -0x70(%rbp), %rdi
movsbl -0x79(%rbp), %esi
movl -0x18(%rbp), %edx
subl $0x1, %edx
movq -0x78(%rbp), %rcx
movq -0x90(%rbp), %r8
movl -0x2c(%rbp), %r9d
callq 0x19720
movq %rax, -0x98(%rbp)
cmpl $0x0, -0x14(%rbp)
jne 0x19a83
movq -0x98(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x88(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jle 0x19a81
movl -0x64(%rbp), %ecx
movq -0x88(%rbp), %rax
movl %ecx, (%rax)
movq -0x98(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x88(%rbp), %rax
movl %ecx, 0x4(%rax)
jmp 0x19abb
movq -0x98(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x88(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x19ab9
movl -0x64(%rbp), %ecx
movq -0x88(%rbp), %rax
movl %ecx, (%rax)
movq -0x98(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x88(%rbp), %rax
movl %ecx, 0x4(%rax)
jmp 0x19abb
movq -0x98(%rbp), %rdi
callq 0x8680
movq -0x78(%rbp), %rdi
callq 0x188a0
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x19928
movq -0x70(%rbp), %rdi
callq 0x8680
movb -0x2d(%rbp), %al
movb %al, 0x7b19(%rip)       # 0x21609
movb -0x2e(%rbp), %al
movb %al, 0x7b11(%rip)       # 0x2160a
movb -0x2f(%rbp), %al
movb %al, 0x7b09(%rip)       # 0x2160b
movb -0x30(%rbp), %al
movb %al, 0x7b01(%rip)       # 0x2160c
movq -0x88(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)