// File: /workspace/github_c_makefile_star2_O3/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 0x2ce7
testq %rax, %rax
je 0x7ef0
movq %rax, %r13
movq %r14, -0x50(%rbp)
movq %rbx, -0x58(%rbp)
movq 0x411a(%rip), %r15      # 0xbfd0
movq 0x8(%r15), %rdi
leaq -0x48(%rbp), %rsi
callq 0x1160
movq 0x8(%r15), %rdi
leaq -0x48(%rbp), %rbx
movq %rbx, %rsi
callq 0x1100
movl (%rbx), %edi
movl 0x4(%r13), %r10d
leal -0x1(%rdi), %ecx
cmpl %ecx, %r10d
jge 0x7ef7
leal 0x1(%r10), %edi
movl $0x1, %r8d
movl %r10d, %r9d
jmp 0x7f03
xorl %eax, %eax
jmp 0x8176
movl %r10d, %eax
cltd
idivl %ecx
movl %eax, %r8d
movl %ecx, %r9d
movq %rcx, -0x70(%rbp)
cmpl $0x3, %edi
movq %r13, -0x60(%rbp)
movl %r8d, -0x30(%rbp)
movq %r10, -0x68(%rbp)
movq %rdi, -0x78(%rbp)
jl 0x800b
leal -0x1(%r9), %eax
movl %eax, -0x44(%rbp)
movl $0x1, %r12d
xorl %ebx, %ebx
movq %r9, -0x40(%rbp)
movq %r13, %rdi
movl %ebx, %esi
movl %r8d, %edx
callq 0x8185
movq %rax, %r13
movq 0x4086(%rip), %r15      # 0xbfd0
movq 0x8(%r15), %r9
leaq -0x2c(%rbp), %rdi
movl $0x1, %esi
movq 0x407a(%rip), %r14      # 0xbfd8
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x38(%rbp), %rdi
movl $0x1, %esi
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x34(%rbp), %rdi
movl $0x1, %esi
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
movq -0x50(%rbp), %rdi
movl $0x40, %esi
movq 0x3ffa(%rip), %rdx      # 0xbfb0
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movl %r12d, %edi
movq %r13, %rsi
callq 0x81fb
movl %r12d, %edi
movq -0x58(%rbp), %rsi
callq 0x8342
movq %r13, %rdi
movq -0x60(%rbp), %r13
callq 0x1130
movq -0x40(%rbp), %r9
movl -0x30(%rbp), %r8d
incl %r12d
addl %r8d, %ebx
cmpl %r12d, %r9d
jne 0x7f33
movl 0x4(%r13), %eax
movq 0x3fca(%rip), %r15      # 0xbfd0
movl -0x44(%rbp), %esi
jmp 0x8016
movl $0x1, %r12d
xorl %esi, %esi
movl %r10d, %eax
imull %r8d, %esi
cltd
idivl %r9d
addl %r8d, %edx
movq %r13, %rdi
callq 0x8185
movq %rax, -0x40(%rbp)
movq 0x8(%r15), %r9
movq 0x3fa0(%rip), %r14      # 0xbfd8
leaq -0x2c(%rbp), %rdi
movl $0x1, %ebx
xorl %r13d, %r13d
movl $0x1, %esi
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x38(%rbp), %rdi
movl $0x1, %esi
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
leaq -0x34(%rbp), %rdi
movl $0x1, %esi
movq %r14, %rdx
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movq 0x8(%r15), %r9
movq 0x3f18(%rip), %rdx      # 0xbfb0
movq -0x50(%rbp), %rdi
movl $0x40, %esi
movl %r12d, %ecx
xorl %r8d, %r8d
callq 0x1060
movl %r12d, %edi
movq -0x40(%rbp), %r14
movq %r14, %rsi
callq 0x81fb
movl %r12d, %edi
movq -0x58(%rbp), %rsi
callq 0x8342
movq %r14, %rdi
callq 0x1130
movl $0x8, %edi
callq 0x1140
movq %rax, %r15
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(%r15)
cmpl $0x2, -0x78(%rbp)
jl 0x816a
movq -0x70(%rbp), %r14
movq -0x68(%rbp), %rax
cmpl %r14d, %eax
cmovll %eax, %r14d
negl %r14d
movq %r15, %r12
movl %ebx, %edi
callq 0x8410
movl -0x2c(%rbp), %ecx
cmpl $0x32, %ecx
je 0x813a
testl %ecx, %ecx
jne 0x8144
movl 0x4(%rax), %ecx
cmpl 0x4(%r12), %ecx
jle 0x8144
addl %r13d, (%rax)
movq %rax, %r15
jmp 0x814a
movl 0x4(%rax), %ecx
cmpl 0x4(%r12), %ecx
jl 0x8132
movq %r12, %r15
movq %rax, %r12
movq %r12, %rdi
callq 0x1130
addl -0x30(%rbp), %r13d
leal (%r14,%rbx), %eax
incl %eax
movl %ebx, %ecx
incl %ecx
movl %ecx, %ebx
cmpl $0x1, %eax
jne 0x8112
movslq (%r15), %r13
movq -0x60(%rbp), %rax
movq 0x8(%rax), %rax
movq (%rax,%r13,8), %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq