// File: /workspace/github_c_makefile_star2_O0/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
subq $0x150, %rsp            # imm = 0x150
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
callq 0xa510
movq 0x18293(%rip), %rdi     # 0x20fc0
callq 0xa540
movl %eax, 0x188b8(%rip)     # 0x215f0
movq 0x18281(%rip), %rdi     # 0x20fc0
callq 0xa570
movl %eax, 0x188aa(%rip)     # 0x215f4
cmpl $0x2, 0x188a3(%rip)     # 0x215f4
jge 0x8d7b
cmpl $0x0, 0x18896(%rip)     # 0x215f0
jne 0x8d6a
leaq 0x122e1(%rip), %rdi     # 0x1b044
movb $0x0, %al
callq 0x8040
callq 0xa5a0
movl $0x0, -0x4(%rbp)
jmp 0x92fc
cmpl $0x0, 0x1886e(%rip)     # 0x215f0
jne 0x90bb
movl $0x0, 0x1886e(%rip)     # 0x21600
movl $0x0, 0x18868(%rip)     # 0x21604
movl $0xa0, %edi
callq 0x8780
movq %rax, 0x1884b(%rip)     # 0x215f8
movl $0x0, -0x14(%rbp)
callq 0xe7d0
movq %rax, -0x28(%rbp)
callq 0x19b30
movq %rax, 0x1881f(%rip)     # 0x215e8
movq -0x10(%rbp), %rax
movl -0x8(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x122a0(%rip), %rsi     # 0x1b081
callq 0x1a3b0
cmpl $0x0, %eax
je 0x8ede
leaq 0x1228e(%rip), %rdi     # 0x1b084
movb $0x0, %al
callq 0x8040
movl $0x0, -0x2c(%rbp)
leaq 0x1229b(%rip), %rdi     # 0x1b0a6
leaq 0x12270(%rip), %rsi     # 0x1b082
callq 0x8670
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
callq 0x8910
movl %eax, -0x44(%rbp)
cmpl $-0x1, -0x44(%rbp)
je 0x8ed3
movl -0x44(%rbp), %eax
movb %al, %cl
movl -0x2c(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x2c(%rbp)
cltq
movb %cl, -0x32(%rbp,%rax)
cmpl $0xa, -0x44(%rbp)
jne 0x8ec2
movslq -0x2c(%rbp), %rax
movb $0x0, -0x32(%rbp,%rax)
leaq -0x32(%rbp), %rdi
callq 0x9320
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movsbl 0x1(%rax), %eax
cmpl $-0x2, %eax
jne 0x8e88
cmpl $0x0, -0x14(%rbp)
jne 0x8e7f
movq -0x50(%rbp), %rax
movb $0x6, (%rax)
jmp 0x8e86
movq -0x50(%rbp), %rax
movb $0x38, (%rax)
jmp 0x8e88
movq -0x28(%rbp), %rdi
movq -0x50(%rbp), %rsi
movq 0x18751(%rip), %rdx     # 0x215e8
callq 0x180a0
movq -0x50(%rbp), %rdi
callq 0x8680
cmpl $0x0, -0x14(%rbp)
jne 0x8eb4
movl $0x32, -0x14(%rbp)
jmp 0x8ebb
movl $0x0, -0x14(%rbp)
movl $0x0, -0x2c(%rbp)
movq -0x40(%rbp), %rdi
callq 0x8910
movl %eax, -0x44(%rbp)
jmp 0x8e27
movq -0x40(%rbp), %rdi
callq 0x8560
jmp 0x8eea
leaq 0x121c1(%rip), %rdi     # 0x1b0a6
callq 0x9610
movq -0x28(%rbp), %rdi
callq 0xec20
leaq 0x121aa(%rip), %rdi     # 0x1b0a4
movb $0x0, %al
callq 0x8040
cmpl $0x0, -0x14(%rbp)
jne 0x8f24
movq -0x28(%rbp), %rdi
movq 0x186d6(%rip), %rdx     # 0x215e8
xorl %esi, %esi
movl $0x1, %ecx
callq 0xff20
movq %rax, -0x20(%rbp)
jmp 0x8f42
movq -0x28(%rbp), %rdi
movq 0x186b9(%rip), %rdx     # 0x215e8
movl $0x32, %esi
movl $0x1, %ecx
callq 0xff20
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x8fc2
movq -0x28(%rbp), %rdi
xorl %esi, %esi
callq 0xee60
cmpb $0x0, %al
jne 0x8f7d
movq -0x28(%rbp), %rdi
movl $0x32, %esi
callq 0xee60
cmpb $0x0, %al
jne 0x8f7d
leaq 0x1213f(%rip), %rdi     # 0x1b0b3
movb $0x0, %al
callq 0x8040
jmp 0x8fa3
cmpl $0x0, -0x14(%rbp)
jne 0x8f93
leaq 0x12135(%rip), %rdi     # 0x1b0bf
movb $0x0, %al
callq 0x8040
jmp 0x8fa1
leaq 0x1213d(%rip), %rdi     # 0x1b0d7
movb $0x0, %al
callq 0x8040
jmp 0x8fa3
callq 0x9660
movq -0x28(%rbp), %rdi
callq 0x8680
callq 0xa5a0
movl $0x0, -0x4(%rbp)
jmp 0x92fc
cmpl $0x0, -0x14(%rbp)
jne 0x8ffb
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
xorl %ecx, %ecx
movl $0x2, %r8d
movl %ecx, %edi
callq 0x9700
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jne 0x8ff9
callq 0xa5a0
movl $0x0, -0x4(%rbp)
jmp 0x92fc
jmp 0x9034
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl $0x1, %edi
movl $0x32, %ecx
movl $0x2, %r8d
callq 0x9700
movl %eax, -0x5c(%rbp)
cmpl $0x0, -0x5c(%rbp)
jne 0x9032
callq 0xa5a0
movl $0x0, -0x4(%rbp)
jmp 0x92fc
jmp 0x9034
movq -0x20(%rbp), %rdi
callq 0x188a0
movq 0x185a4(%rip), %rdi     # 0x215e8
callq 0x19c00
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
callq 0x9a40
callq 0x9ac0
cmpl $0x0, %eax
je 0x908d
leaq 0x12088(%rip), %rdi     # 0x1b0ef
movb $0x0, %al
callq 0x8040
callq 0x9660
movq -0x28(%rbp), %rdi
callq 0x8680
callq 0xa5a0
movl $0x0, -0x4(%rbp)
jmp 0x92fc
movq 0x18554(%rip), %rsi     # 0x215e8
leaq 0x1200b(%rip), %rdi     # 0x1b0a6
callq 0x9cc0
cmpl $0x0, -0x14(%rbp)
jne 0x90af
movl $0x32, -0x14(%rbp)
jmp 0x90b6
movl $0x0, -0x14(%rbp)
jmp 0x8f01
jmp 0x90bd
movq 0x17f0c(%rip), %rsi     # 0x20fd0
leaq -0xd0(%rbp), %rdi
movq %rdi, -0x130(%rbp)
callq 0x9e80
movq -0x130(%rbp), %rcx
movq 0x17edb(%rip), %rdi     # 0x20fc0
leaq -0x6c(%rbp), %rsi
movl $0x1, %edx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0xa5b0
jmp 0x90fb
leaq -0xd0(%rbp), %rdi
callq 0xa620
cmpl $-0x1, -0x6c(%rbp)
jne 0x9135
jmp 0x92ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0xa620
jmp 0x9308
movq 0x17e94(%rip), %rsi     # 0x20fd0
leaq -0xf0(%rbp), %rdi
movq %rdi, -0x138(%rbp)
callq 0x9e80
movq -0x138(%rbp), %rcx
movq 0x17e63(%rip), %rdi     # 0x20fc0
leaq -0x70(%rbp), %rsi
movl $0x1, %edx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0xa5b0
jmp 0x9173
leaq -0xf0(%rbp), %rdi
callq 0xa620
movq 0x17e4a(%rip), %rsi     # 0x20fd0
leaq -0x100(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0x9e80
movq -0x140(%rbp), %rcx
movq 0x17e19(%rip), %rdi     # 0x20fc0
leaq -0x74(%rbp), %rsi
movl $0x1, %edx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0xa5b0
jmp 0x91bd
leaq -0x100(%rbp), %rdi
callq 0xa620
movq 0x17dd0(%rip), %rsi     # 0x20fa0
leaq -0x110(%rbp), %rdi
movq %rdi, -0x148(%rbp)
callq 0x9e80
movq -0x148(%rbp), %rcx
movq 0x17dcf(%rip), %rdi     # 0x20fc0
leaq -0xc0(%rbp), %rsi
movl $0x40, %edx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0xa5b0
jmp 0x920a
leaq -0x110(%rbp), %rdi
callq 0xa620
callq 0x19c80
movq %rax, -0x118(%rbp)
callq 0x1a100
movq %rax, -0x120(%rbp)
leaq -0xc0(%rbp), %rdi
movl -0x6c(%rbp), %esi
movl -0x70(%rbp), %edx
movq -0x118(%rbp), %rcx
movq -0x120(%rbp), %r8
movl -0x74(%rbp), %r9d
callq 0x19720
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rdi
callq 0x1a020
movq -0x118(%rbp), %rdi
callq 0x188a0
movq -0x128(%rbp), %rdi
callq 0x8680
movq -0x120(%rbp), %rdi
callq 0x8680
jmp 0x90bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0xa620
jmp 0x9308
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x100(%rbp), %rdi
callq 0xa620
jmp 0x9308
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0x110(%rbp), %rdi
callq 0xa620
jmp 0x9308
jmp 0x92f0
callq 0xa5a0
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0xd8(%rbp), %rdi
callq 0x8a50
nopw %cs:(%rax,%rax)