// File: /workspace/github_c_makefile_star2_O2/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
movl %esi, -0x30(%rbp)
movl %ecx, -0x48(%rbp)
movl %r8d, -0x44(%rbp)
movq %rdi, -0x70(%rbp)
movq %rdx, -0x78(%rbp)
movl %r8d, %ecx
callq 0x41dc
testq %rax, %rax
je 0x8ee6
movq %rax, %r12
movq 0x411c(%rip), %rbx      # 0xcfd0
movq %rbx, %rdi
callq 0x2f64
movq %rbx, %rdi
callq 0x2f84
movl %eax, %ecx
movl 0x4(%r12), %eax
leal -0x1(%rcx), %r8d
cmpl %r8d, %eax
jge 0x8eed
leal 0x1(%rax), %ecx
movq %rcx, -0x60(%rbp)
pushq $0x1
popq %rcx
movl %ecx, -0x2c(%rbp)
movl %eax, %r8d
jmp 0x8ef8
xorl %eax, %eax
jmp 0x918e
movq %rcx, -0x60(%rbp)
cltd
idivl %r8d
movl %eax, -0x2c(%rbp)
pushq $0x1
popq %r14
xorl %esi, %esi
movq %r12, -0x68(%rbp)
movl %r8d, -0x54(%rbp)
pushq $0x1
popq %r13
cmpl %r8d, %r14d
jge 0x900c
movq %r12, %rdi
movl -0x2c(%rbp), %edx
movl %esi, -0x50(%rbp)
callq 0x919d
movq %rax, -0x80(%rbp)
leaq 0x3cfc(%rip), %r15      # 0xcc28
movq %r15, -0x40(%rbp)
movq 0x40a1(%rip), %rax      # 0xcfd8
movq %rax, -0x38(%rbp)
movq 0x408e(%rip), %r12      # 0xcfd0
movq %r12, %rdi
leaq -0x30(%rbp), %rsi
movl %r13d, %edx
leaq -0x40(%rbp), %rbx
movq %rbx, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
movq %r15, -0x40(%rbp)
movq 0x406f(%rip), %rax      # 0xcfd8
movq %rax, -0x38(%rbp)
movq %r12, %rdi
leaq -0x48(%rbp), %rsi
movl %r13d, %edx
movq %rbx, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
movq %r15, -0x40(%rbp)
movq 0x4048(%rip), %rax      # 0xcfd8
movq %rax, -0x38(%rbp)
movq %r12, %rdi
leaq -0x44(%rbp), %rsi
movl %r13d, %edx
movq %rbx, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
movq %r15, -0x40(%rbp)
movq 0x3ff9(%rip), %rax      # 0xcfb0
movq %rax, -0x38(%rbp)
movq %r12, %rdi
movq -0x70(%rbp), %rsi
pushq $0x40
popq %rdx
movq %rbx, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
movl %r14d, %edi
movq -0x80(%rbp), %rbx
movq %rbx, %rsi
callq 0x920c
movl %r14d, %edi
movq -0x78(%rbp), %rsi
callq 0x93b7
movq %rbx, %rdi
movq -0x68(%rbp), %r12
callq 0x2200
movl -0x50(%rbp), %esi
movl -0x54(%rbp), %r8d
incl %r14d
addl -0x2c(%rbp), %esi
jmp 0x8f0a
movl 0x4(%r12), %eax
cltd
idivl %r8d
addl -0x2c(%rbp), %edx
movq %r12, %rdi
callq 0x919d
movq %rax, -0x50(%rbp)
leaq -0x40(%rbp), %r15
leaq 0x3bf9(%rip), %r13      # 0xcc28
movq %r13, (%r15)
movq 0x3f9f(%rip), %rax      # 0xcfd8
movq %rax, 0x8(%r15)
movq 0x3f8c(%rip), %r13      # 0xcfd0
leaq -0x30(%rbp), %rsi
pushq $0x1
popq %rbx
xorl %r12d, %r12d
movq %r13, %rdi
movl %ebx, %edx
movq %r15, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
leaq 0x3bc0(%rip), %rax      # 0xcc28
movq %rax, (%r15)
movq 0x3f66(%rip), %rax      # 0xcfd8
movq %rax, 0x8(%r15)
leaq -0x48(%rbp), %rsi
movq %r13, %rdi
movl %ebx, %edx
movq %r15, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
leaq 0x3b94(%rip), %rax      # 0xcc28
movq %rax, (%r15)
movq 0x3f3a(%rip), %rax      # 0xcfd8
movq %rax, 0x8(%r15)
leaq -0x44(%rbp), %rsi
movq %r13, %rdi
movl %ebx, %edx
movq %r15, %rcx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
leaq 0x3b68(%rip), %rax      # 0xcc28
movq %rax, (%r15)
movq 0x3ee6(%rip), %rax      # 0xcfb0
movq %rax, 0x8(%r15)
pushq $0x40
popq %rdx
leaq -0x40(%rbp), %rcx
movq %r13, %rdi
movq -0x70(%rbp), %rsi
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x2f32
movl %r14d, %edi
movq -0x50(%rbp), %r15
movq %r15, %rsi
callq 0x920c
movl %r14d, %edi
movq -0x78(%rbp), %rsi
callq 0x93b7
movq %r15, %rdi
callq 0x2200
pushq $0x8
popq %rdi
callq 0x2250
movq %rax, %r14
andl $0x0, (%rax)
leaq -0x30(%rbp), %rax
cmpl $0x0, (%rax)
movl $0x82d48b00, %eax       # imm = 0x82D48B00
movl $0x7d2b7500, %ecx       # imm = 0x7D2B7500
cmovel %eax, %ecx
movl %ecx, 0x4(%r14)
movq -0x60(%rbp), %r13
cmpl %r13d, %ebx
jge 0x917f
movl %ebx, %edi
callq 0x94ff
movl -0x30(%rbp), %ecx
cmpl $0x32, %ecx
je 0x915d
testl %ecx, %ecx
jne 0x9166
movl 0x4(%rax), %ecx
cmpl 0x4(%r14), %ecx
jle 0x9166
addl %r12d, (%rax)
movq %rax, %r15
jmp 0x916c
movl 0x4(%rax), %ecx
cmpl 0x4(%r14), %ecx
jl 0x9155
movq %r14, %r15
movq %rax, %r14
movq %r14, %rdi
callq 0x2200
incl %ebx
addl -0x2c(%rbp), %r12d
movq %r15, %r14
jmp 0x9134
movslq (%r14), %rax
movq -0x68(%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