// File: /workspace/github_c_makefile_star2_O3/upcrob[P]garry/chess.c
// Function: main
int main(int argc, char* argv[])
{	
	//Initialize MPI
	Init(argc, argv);
	proc = COMM_WORLD.Get_rank();
	numProcs = COMM_WORLD.Get_size();

	//Require at least 1 slave node to run
	if (numProcs < 2)
	{
		if (proc == HEAD)
			printf("Program requires at least 1 slave node to run.\nTerminating.\n");
		Finalize();
		return 0;
	}

	//Divide between head and slave node program
	if (proc == HEAD)
	{
		//Head node code
		//======================================================================
		
		//initialize variables
		queueIndex = 0;
		queueFull = FALSE;
		moveQueue = (Move**) malloc(sizeof(Move*) * MQ_SIZE);
		int colorFlag = WHITE;
		MoveSet* moves;
		char* board = buildNewBoard();
		
		//setup empty previous move
		prev = newMove();
	
		//resume play from log file if requested
		if (streq(argv[argc - 1], (char*) "-r"))
		{
			printf("\n* * RESUMING GAME FROM LOG * *\n\n");
			
			int i = 0;
			char buffer[6];
			
			FILE* fp = fopen("chesslog.txt", "r");
			int c = fgetc(fp);
			while (c != EOF)
			{
				buffer[i++] = (char) c;
				if (c == '\n')
				{
					//Move read, execute it
					buffer[i] = '\0';
					Move* move = strToMove(buffer);
					if (move->startRow == CASTLE)
					{
						//Set player that is castling
						if (colorFlag == WHITE)
							move->pieceId = KING;
						else
							move->pieceId = KING + BLACK;
					}
					executeMove(board, move, prev);
					free(move);
					
					//Switch players
					if (colorFlag == WHITE)
						colorFlag = BLACK;
					else
						colorFlag = WHITE;
					i = 0;
				}
				c = fgetc(fp);
			}
			fclose(fp);
		} else {
			//initialize (clear) log file
			initLog("chesslog.txt");
		}
		
		//show board
		printBoard(board);
		printf("\n");
		
		//main game loop
		int i, j;
		while (TRUE)
		{
			if (colorFlag == WHITE)
				moves = getLegalMoves(board, WHITE, prev, 1);
			else
				moves = getLegalMoves(board, BLACK, prev, 1);

			//check for checkmate/stalemate
			if (moves->size == 0)
			{
				if (!kingInCheck(board, WHITE) && !kingInCheck(board, BLACK))
				{
					//stalemate
					printf("STALEMATE.\n");
				} else {
					//checkmate, determine color
					if (colorFlag == WHITE)
						printf("CHECKMATE: BLACK WINS.\n");
					else
						printf("CHECKMATE: WHITE WINS.\n");
				}
				
				//End program
				sendKillSig();
				free(board);
				Finalize();
				return 0;
			}

			//execute turns (ai or human)
			int status;
			if (colorFlag == WHITE)
			{
				//white's turn
				status = computeMove(TYPE_WHITE, board, moves, WHITE, FUNCTION_WHITE);		
				if (status == 0)
				{
					Finalize();
					return 0;
				}
			} else {
				//black's turn
				status = computeMove(TYPE_BLACK, board, moves, BLACK, FUNCTION_BLACK);
				if (status == 0)
				{
					Finalize();
					return 0;
				}
			}
			destroyMoveSet(moves);

			//Add move to queue
			Move* prevClone = cloneMove(prev);
			enqueueMove(prevClone);
			
			//Check queue for repeats
			if (moveLoopDetected())
			{
				printf("REPEATED MOVES DETECTED. GAME ENDS IN A DRAW.\n");
				sendKillSig();
				free(board);
				Finalize();
				return 0;
				
			}
			
			//Log move
			logMove("chesslog.txt", prev);
			
			//Swap turns
			if (colorFlag == WHITE)
				colorFlag = BLACK;
			else
				colorFlag = WHITE;
		}

		//free memory
		free(board);
		//======================================================================
	} else {
		//Slave node code
		//======================================================================
		int color;
		int depth;
		int evaluator;
		char board[64];
		while (TRUE)
		{
			//Receive data from HEAD node
			COMM_WORLD.Recv(&color, 1, MPI_INT, HEAD, 0);
			
			//Terminate program if color is -1
			if (color == -1)
				break;
			
			COMM_WORLD.Recv(&depth, 1, MPI_INT, HEAD, 0);
			COMM_WORLD.Recv(&evaluator, 1, MPI_INT, HEAD, 0);
			COMM_WORLD.Recv(&board, 64, MPI_CHAR, HEAD, 0);
			MoveSet* set = receiveMoveSet();
			Move* prevMove = receiveMove();
			
			//Determine best move
			MoveDef* bmd = bestMoveHelper(board, color, depth, set, prevMove, evaluator);
			
			//Send MoveDef back to head node
			sendMoveDef(bmd);
			
			//Free memory
			destroyMoveSet(set);
			free(bmd);
			free(prevMove);
		}
		//======================================================================
	}
	
	//Finalize MPI
	Finalize();
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
leaq -0x38(%rbp), %rax
movl %edi, (%rax)
leaq -0x40(%rbp), %rcx
movq %rsi, (%rcx)
movq %rax, %rdi
movq %rcx, %rsi
callq 0x1170
callq 0x11c0
movq 0xac5f(%rip), %r14      # 0xbfd0
movq 0x8(%r14), %rdi
leaq -0x80(%rbp), %rbx
movq %rbx, %rsi
callq 0x1160
movl (%rbx), %eax
movl %eax, 0xad87(%rip)      # 0xc110
movq 0x8(%r14), %rdi
movq %rbx, %rsi
callq 0x1100
movl (%rbx), %ecx
movl %ecx, 0xad77(%rip)      # 0xc114
movl 0xad6d(%rip), %eax      # 0xc110
cmpl $0x1, %ecx
jg 0x13c1
testl %eax, %eax
jne 0x1737
leaq 0x7d18(%rip), %rdi      # 0x90cf
callq 0x1190
jmp 0x1737
testl %eax, %eax
je 0x14e7
movq 0x8(%r14), %r9
movq $0x0, (%rsp)
movq 0xabfc(%rip), %rdx      # 0xbfd8
leaq -0x2c(%rbp), %rbx
movq %rbx, %rdi
movl $0x1, %esi
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x10a0
cmpl $-0x1, (%rbx)
je 0x1737
movq 0x8(%r14), %r9
xorl %eax, %eax
movq %rax, (%rsp)
leaq -0x34(%rbp), %rdi
movl $0x1, %esi
movq 0xabc3(%rip), %r13      # 0xbfd8
movq %r13, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x10a0
movq 0x8(%r14), %r9
xorl %ebx, %ebx
movq %rbx, (%rsp)
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
movq %r13, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x10a0
movq 0x8(%r14), %r9
movq %rbx, (%rsp)
leaq -0x80(%rbp), %rbx
movq %rbx, %rdi
movl $0x40, %esi
movq 0xab53(%rip), %rdx      # 0xbfb0
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x10a0
callq 0x8821
movq %rax, %r15
callq 0x8a04
movq %rax, %r12
movl -0x2c(%rbp), %esi
movl -0x34(%rbp), %edx
movl -0x30(%rbp), %r9d
movq %rbx, %rdi
movq %r15, %rcx
movq %rax, %r8
callq 0x849d
movq %r14, %rbx
movq %rax, %r14
movq %rax, %rdi
callq 0x899e
movq %r15, %rdi
callq 0x7e35
movq %r14, %rdi
movq %rbx, %r14
callq 0x1130
movq %r12, %rdi
callq 0x1130
movq 0x8(%rbx), %r9
xorl %eax, %eax
movq %rax, (%rsp)
leaq -0x2c(%rbp), %rdi
movl $0x1, %esi
movq %r13, %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x10a0
cmpl $-0x1, -0x2c(%rbp)
jne 0x13fb
jmp 0x1737
xorl %r13d, %r13d
movl %r13d, 0xac2f(%rip)     # 0xc120
movl %r13d, 0xac2c(%rip)     # 0xc124
movl $0xa0, %edi
callq 0x1140
movq %rax, 0xac0f(%rip)      # 0xc118
callq 0x1e18
movq %rax, %rbx
callq 0x8790
movq %rax, 0xabeb(%rip)      # 0xc108
movq -0x40(%rbp), %rax
movslq -0x38(%rbp), %rcx
movq -0x8(%rax,%rcx,8), %rdi
leaq 0x7ad3(%rip), %rsi      # 0x9004
callq 0x8af8
testl %eax, %eax
je 0x15f6
leaq 0x7b19(%rip), %rdi      # 0x905e
callq 0x1190
leaq 0x7ab6(%rip), %rdi      # 0x9007
leaq 0x7aad(%rip), %rsi      # 0x9005
callq 0x1120
movq %rax, %r14
movq %rax, %rdi
callq 0x11a0
cmpl $-0x1, %eax
je 0x15ec
xorl %r13d, %r13d
movl $0x32, %r15d
xorl %r12d, %r12d
movslq %r12d, %r12
movb %al, -0x80(%rbp,%r12)
incq %r12
cmpl $0xa, %eax
jne 0x15df
movb $0x0, -0x80(%rbp,%r12)
leaq -0x80(%rbp), %rdi
callq 0x1756
movq %rax, %r12
cmpb $-0x2, 0x1(%rax)
jne 0x15b5
testl %r13d, %r13d
movl $0x38, %eax
movl $0x6, %ecx
cmovel %ecx, %eax
movb %al, (%r12)
movq 0xab4c(%rip), %rdx      # 0xc108
movq %rbx, %rdi
movq %r12, %rsi
callq 0x78aa
movq %r12, %rdi
callq 0x1130
xorl %r12d, %r12d
testl %r13d, %r13d
movl $0x0, %r13d
cmovel %r15d, %r13d
movq %r14, %rdi
callq 0x11a0
cmpl $-0x1, %eax
jne 0x1579
movq %r14, %rdi
callq 0x10e0
jmp 0x1614
leaq 0x7a0a(%rip), %rdi      # 0x9007
leaq 0x7a56(%rip), %rsi      # 0x905a
callq 0x1120
movq %rax, %rdi
callq 0x10e0
xorl %r13d, %r13d
movq %rbx, %rdi
callq 0x1f82
movl $0xa, %edi
callq 0x1150
leaq 0x79da(%rip), %r14      # 0x9007
movl $0x32, %r12d
movq 0xaace(%rip), %rdx      # 0xc108
movq %rbx, %rdi
testl %r13d, %r13d
je 0x1670
movl $0x32, %esi
movl $0x1, %ecx
callq 0x2ce7
cmpl $0x0, 0x4(%rax)
je 0x16e8
movq %rax, %r15
movl $0x1, %edi
movq %rbx, %rsi
movq %rax, %rdx
movl $0x32, %ecx
jmp 0x168f
xorl %esi, %esi
movl $0x1, %ecx
callq 0x2ce7
cmpl $0x0, 0x4(%rax)
je 0x16e8
movq %rax, %r15
xorl %edi, %edi
movq %rbx, %rsi
movq %rax, %rdx
xorl %ecx, %ecx
movl $0x2, %r8d
callq 0x18c4
testl %eax, %eax
je 0x1737
movq %r15, %rdi
callq 0x7e35
movq 0xaa57(%rip), %rdi      # 0xc108
callq 0x87e5
movq %rax, %rdi
callq 0x1bb3
callq 0x1c18
testl %eax, %eax
jne 0x171e
movq 0xaa3a(%rip), %rsi      # 0xc108
movq %r14, %rdi
callq 0x1d5e
testl %r13d, %r13d
movl $0x0, %r13d
cmovel %r12d, %r13d
jmp 0x1633
movq %rbx, %rdi
xorl %esi, %esi
callq 0x20d8
testb %al, %al
jne 0x1707
movq %rbx, %rdi
movl $0x32, %esi
callq 0x20d8
testb %al, %al
je 0x174d
testl %r13d, %r13d
leaq 0x79a7(%rip), %rax      # 0x90b8
leaq 0x7a00(%rip), %rdi      # 0x9118
cmoveq %rax, %rdi
jmp 0x1725
leaq 0x795a(%rip), %rdi      # 0x907f
callq 0x1190
callq 0x185d
movq %rbx, %rdi
callq 0x1130
callq 0x1090
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x7959(%rip), %rdi      # 0x90ad
jmp 0x1725