// File: /workspace/github_c_makefile_star2_O1/upcrob[P]garry/moves.c
// Function: bestMove(char*, int, Move*, int, int)
Move* bestMove(char* board, int color, Move* prevMove, int depth, int evaluator)
{
	MoveSet* legalMoves = getLegalMoves(board, color, prevMove, evaluator);
	
	if (legalMoves == NULL)
	{
		//No moves left
		return NULL;
	} else {
		//Divide up problem space
		int i, j;
		int proc = COMM_WORLD.Get_rank();
		int numProcs = COMM_WORLD.Get_size();
		int segSize, procCap;
		if (legalMoves->size >= numProcs - 1)
		{
			//There were more moves than processors
			segSize = legalMoves->size / (numProcs - 1);
			procCap = numProcs;
		} else {
			//There are more processors than legal moves
			segSize = 1;
			procCap = legalMoves->size + 1;
		}

		//Distribute board and move data to slave nodes
		MoveSet* sub;
		for (i = 1, j = 0; i < procCap - 1; i++, j++)
		{
			sub = subMoveSet(legalMoves, j * segSize, segSize);
			COMM_WORLD.Send(&color, 1, MPI_INT, i, 0);
			COMM_WORLD.Send(&depth, 1, MPI_INT, i, 0);
			COMM_WORLD.Send(&evaluator, 1, MPI_INT, i, 0);
			COMM_WORLD.Send(board, 64, MPI_CHAR, i, 0);
			sendMoveSet(i, sub);
			sendMove(i, prevMove);
			free(sub);
		}

		//Distribute last (potentially larger) segment
		sub = subMoveSet(legalMoves, j * segSize, segSize + legalMoves->size % (procCap - 1));
		COMM_WORLD.Send(&color, 1, MPI_INT, i, 0);
		COMM_WORLD.Send(&depth, 1, MPI_INT, i, 0);
		COMM_WORLD.Send(&evaluator, 1, MPI_INT, i, 0);
		COMM_WORLD.Send(board, 64, MPI_CHAR, i, 0);
		sendMoveSet(i, sub);
		sendMove(i, prevMove);
		free(sub);

		//Initialize "best" variable
		MoveDef* best = (MoveDef*) malloc(sizeof(MoveDef));
		best->index = 0;
		if (color == WHITE)
			best->value = -INFINITY;
		else
			best->value = INFINITY;

		//Retrieve other processed segments and determine best
		MoveDef* tmp;
		MoveDef* m;
		for (i = 1; i < procCap; i++)
		{
			m = receiveMoveDef(i);
			if (color == WHITE && m->value > best->value)
			{
				//New best found (white), update pointers
				tmp = best;
				best = m;
				
				//Make index relative to "legalMoves"
				best->index = (i - 1) * segSize + best->index;
			} else if (color == BLACK && m->value < best->value) {
				//New best found (black), update pointers
				tmp = best;
				best = m;
				
				//Make index relative to "legalMoves"
				best->index = (i - 1) * segSize + best->index;
			} else {
				tmp = m;
			}
			free(tmp);
		}
		
		//Return move
		Move* move = getMove(legalMoves, best->index);
		return move;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %rbx
movq %rdi, %r14
movl %esi, -0x2c(%rbp)
movl %ecx, -0x38(%rbp)
movl %r8d, -0x34(%rbp)
movl %r8d, %ecx
callq 0x2f28
testq %rax, %rax
je 0x7e72
movq %rax, %r13
movq %r14, -0x58(%rbp)
movq %rbx, -0x60(%rbp)
movq 0x419a(%rip), %r15      # 0xbfd0
movq 0x8(%r15), %rdi
leaq -0x50(%rbp), %rsi
callq 0x1160
movq 0x8(%r15), %rdi
leaq -0x50(%rbp), %rbx
movq %rbx, %rsi
callq 0x1100
movl (%rbx), %r14d
movl 0x4(%r13), %eax
leal -0x1(%r14), %ecx
cmpl %ecx, %eax
movq %rax, -0x70(%rbp)
jge 0x7e79
leal 0x1(%rax), %r14d
movl $0x1, %r8d
jmp 0x7e7f
xorl %eax, %eax
jmp 0x8103
cltd
idivl %ecx
movl %eax, %r8d
movq %rcx, -0x78(%rbp)
leal -0x1(%r14), %ecx
cmpl $0x3, %r14d
movq %r13, -0x48(%rbp)
movl %r8d, -0x30(%rbp)
jl 0x7f91
movl %ecx, -0x4c(%rbp)
movq %r14, -0x68(%rbp)
leal -0x3(%r14), %eax
movl %eax, -0x40(%rbp)
movl $0x1, %ebx
xorl %r12d, %r12d
movl %ebx, %r13d
movq -0x48(%rbp), %rdi
movl %r12d, %esi
movl %r8d, %edx
callq 0x8112
movq %rax, %rbx
movq 0x4105(%rip), %r14      # 0xbfd0
movq 0x8(%r14), %r9
leaq -0x2c(%rbp), %rdi
movl $0x1, %esi
movq 0x40f9(%rip), %r15      # 0xbfd8
movq %r15, %rdx
movl %r13d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r14), %r9
leaq -0x38(%rbp), %rdi
movl $0x1, %esi
movq %r15, %rdx
movl %r13d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r14), %r9
leaq -0x34(%rbp), %rdi
movl $0x1, %esi
movq %r15, %rdx
movl %r13d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r14), %r9
movq -0x58(%rbp), %rdi
movl $0x40, %esi
movq 0x4079(%rip), %rdx      # 0xbfb0
movl %r13d, %ecx
xorl %r8d, %r8d
callq 0x1060
movl %r13d, %edi
movq %rbx, %rsi
callq 0x8188
movl %r13d, %edi
movq -0x60(%rbp), %rsi
callq 0x82cf
movq %rbx, %rdi
callq 0x1130
movl -0x30(%rbp), %r8d
leal 0x1(%r13), %ebx
addl %r8d, %r12d
decl %r13d
cmpl -0x40(%rbp), %r13d
jne 0x7eaf
movl %ebx, %esi
decl %esi
movq -0x48(%rbp), %r13
movq -0x68(%rbp), %r14
movq 0x4044(%rip), %r15      # 0xbfd0
movl -0x4c(%rbp), %ecx
jmp 0x7f98
movl $0x1, %ebx
xorl %esi, %esi
imull %r8d, %esi
movl 0x4(%r13), %eax
cltd
idivl %ecx
addl %r8d, %edx
movq %r13, %rdi
callq 0x8112
movq %rax, -0x40(%rbp)
movq 0x8(%r15), %r9
movq 0x401b(%rip), %rdx      # 0xbfd8
leaq -0x2c(%rbp), %rdi
movl $0x1, %r12d
xorl %r13d, %r13d
movl $0x1, %esi
movl %ebx, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x38(%rbp), %rdi
movl $0x1, %esi
movq 0x3feb(%rip), %rdx      # 0xbfd8
movl %ebx, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x34(%rbp), %rdi
movl $0x1, %esi
movq 0x3fcd(%rip), %rdx      # 0xbfd8
movl %ebx, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
movq 0x3f90(%rip), %rdx      # 0xbfb0
movq -0x58(%rbp), %rdi
movl $0x40, %esi
movl %ebx, %ecx
xorl %r8d, %r8d
callq 0x1060
movl %ebx, %edi
movq -0x40(%rbp), %r15
movq %r15, %rsi
callq 0x8188
movl %ebx, %edi
movq -0x60(%rbp), %rsi
callq 0x82cf
movq %r15, %rdi
callq 0x1130
movl $0x8, %edi
callq 0x1140
movq %rax, %rbx
movl $0x0, (%rax)
leaq -0x2c(%rbp), %rax
cmpl $0x0, (%rax)
movl $0x82d48b00, %eax       # imm = 0x82D48B00
movl $0x7d2b7500, %ecx       # imm = 0x7D2B7500
cmovel %eax, %ecx
movl %ecx, 0x4(%rbx)
cmpl $0x2, %r14d
jl 0x80f1
movq -0x78(%rbp), %r14
movq -0x70(%rbp), %rax
cmpl %r14d, %eax
cmovll %eax, %r14d
negl %r14d
movl %r12d, %edi
callq 0x839d
movl -0x2c(%rbp), %ecx
cmpl $0x32, %ecx
je 0x80b7
testl %ecx, %ecx
jne 0x80c7
movl 0x4(%rax), %edx
cmpl 0x4(%rbx), %edx
jg 0x80bf
cmpl $0x32, %ecx
jne 0x80c7
movl 0x4(%rax), %ecx
cmpl 0x4(%rbx), %ecx
jge 0x80c7
addl %r13d, (%rax)
movq %rax, %r15
jmp 0x80cd
movq %rbx, %r15
movq %rax, %rbx
movq %rbx, %rdi
callq 0x1130
addl -0x30(%rbp), %r13d
leal (%r14,%r12), %eax
incl %eax
movl %r12d, %ecx
incl %ecx
movq %r15, %rbx
movl %ecx, %r12d
cmpl $0x1, %eax
jne 0x8096
jmp 0x80f4
movq %rbx, %r15
movslq (%r15), %rax
movq -0x48(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq (%rcx,%rax,8), %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq