// File: eugene87222[P]Game-of-Life/gol.cpp
// Function: main
int main(int argc, char *argv[]) {
    bool gosper=false, simkin=false;
    const char* const short_opts = "h";
    const option long_opts[] = {
            {"gosper", no_argument, nullptr, 'g'},
            {"simkin", no_argument, nullptr, 's'},
            {"help", no_argument, nullptr, 'h'},
            {nullptr, no_argument, nullptr, 0}
    };
    while(true) {
        const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);

        if(opt == -1) break;

        switch(opt) {
        case 'g':
            gosper = true;
            break;
        case 's':
            simkin = true;
            break;
        case 'h':
        case '?':
        default:
            printHelp();
            break;
        }
    }

    setlocale(LC_ALL,"");
    initscr();
	clear();
	noecho();
	cbreak();
	keypad(stdscr, TRUE);
	curs_set(0);
	nodelay(stdscr, TRUE);

    int rows, cols, height, width, ms, p_size;
	getmaxyx(stdscr, rows, cols);
    height = rows - 2;
    width = (cols-2) / 2;
    ms = 100;
    p_size = height / thd_num;
    thds = vector<thread>(thd_num);

    char status_background[29];
	memset(status_background, ' ', 29);
	status_background[28] = '\0';

    if(gosper && height>=11 && width>=38) Gosperglidergun(height, width);
    else if(simkin && height>=24 && width>=35) Simkinglidergun(height, width);
    else randomBoard(height, width);

    int keyin, gen = 0;
    bool pause = false;
	while(true) {
		keyin = getch();
		switch(keyin) {
		case 'q':
		case 'Q':
            goodBye();
            break;					
		case 'r':
		case 'R':
            randomBoard(height, width);
			break;
        case 'p':
        case 'P':
        case KEY_SREPLACE:
            pause = !pause;
            if(pause) mvprintw(height+1, 3, "/ PAUSED /");
			else mvprintw(height+1, 3, "══════════");
            break;
		case KEY_LEFT:
            if(ms > 9) ms -= 10;
			break;
		case KEY_RIGHT:
            ms += 10;
			break;
		default:
            break;
		}

        if(!pause) {
            draw(height, width, status_background, gen, ms);
            // update(height, width);
            new_board = board;
            for(int i=0; i<thd_num; i++) {
                thds[i] = thread(update_thd, p_size*i+1, i==thd_num-1?height:p_size*(i+1), 1, width);
            }
            for(int i=0; i<thd_num; i++) {
                thds[i].join();
            }
            board = new_board;
            gen++;
        }
        usleep(ms*1000);
	}

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movb $0x0, -0x11(%rbp)
movb $0x0, -0x12(%rbp)
leaq 0x5762(%rip), %rax      # 0x90da
movq %rax, -0x20(%rbp)
leaq -0xa0(%rbp), %rdi
leaq 0xa336(%rip), %rsi      # 0xdcc0
movl $0x80, %edx
callq 0x2120
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq -0xa0(%rbp), %rcx
leaq 0x5731(%rip), %rdx      # 0x90da
xorl %eax, %eax
movl %eax, %r8d
callq 0x2230
movl %eax, -0xa4(%rbp)
cmpl $-0x1, -0xa4(%rbp)
jne 0x39c4
jmp 0x3a13
movl -0xa4(%rbp), %eax
movl %eax, -0x13c(%rbp)
subl $0x3f, %eax
je 0x3a0a
jmp 0x39d7
movl -0x13c(%rbp), %eax
subl $0x67, %eax
je 0x39fe
jmp 0x39e4
movl -0x13c(%rbp), %eax
subl $0x68, %eax
je 0x3a0a
jmp 0x39f1
movl -0x13c(%rbp), %eax
subl $0x73, %eax
je 0x3a04
jmp 0x3a0c
movb $0x1, -0x11(%rbp)
jmp 0x3a11
movb $0x1, -0x12(%rbp)
jmp 0x3a11
jmp 0x3a0c
callq 0x2480
jmp 0x3994
movl $0x6, %edi
leaq 0x5683(%rip), %rsi      # 0x90a2
callq 0x2140
callq 0x20f0
callq 0x21b0
callq 0x2290
callq 0x2060
movq 0xa589(%rip), %rax      # 0xdfc8
movq (%rax), %rdi
movl $0x1, %esi
callq 0x2080
xorl %edi, %edi
callq 0x2110
movq 0xa56e(%rip), %rax      # 0xdfc8
movq (%rax), %rdi
movl $0x1, %esi
callq 0x20d0
xorl %eax, %eax
movq 0xa558(%rip), %rcx      # 0xdfc8
cmpq (%rcx), %rax
je 0x3a8e
movq 0xa54c(%rip), %rax      # 0xdfc8
movq (%rax), %rax
movswl 0x4(%rax), %eax
addl $0x1, %eax
movl %eax, -0x140(%rbp)
jmp 0x3a9b
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0x140(%rbp)
jmp 0x3a9b
movl -0x140(%rbp), %eax
movl %eax, -0xa8(%rbp)
xorl %eax, %eax
movq 0xa518(%rip), %rcx      # 0xdfc8
cmpq (%rcx), %rax
je 0x3ace
movq 0xa50c(%rip), %rax      # 0xdfc8
movq (%rax), %rax
movswl 0x6(%rax), %eax
addl $0x1, %eax
movl %eax, -0x144(%rbp)
jmp 0x3adb
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0x144(%rbp)
jmp 0x3adb
movl -0x144(%rbp), %eax
movl %eax, -0xac(%rbp)
movl -0xa8(%rbp), %eax
addl $-0x2, %eax
movl %eax, -0xb0(%rbp)
movl -0xac(%rbp), %ecx
movl %ecx, %edx
addl $-0x2, %edx
movl %ecx, %eax
shrl $0x1f, %edx
movl %edx, %ecx
leal -0x2(%rax,%rcx), %eax
sarl %eax
movl %eax, -0xb4(%rbp)
movl $0x64, -0xb8(%rbp)
movl -0xb0(%rbp), %eax
movl 0xa636(%rip), %ecx      # 0xe160
cltd
idivl %ecx
movl %eax, -0xbc(%rbp)
movslq 0xa626(%rip), %rax      # 0xe160
movq %rax, -0x158(%rbp)
leaq -0xd9(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x4500
movq -0x158(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0xd8(%rbp), %rdi
callq 0x4520
jmp 0x3b70
leaq 0xa639(%rip), %rdi      # 0xe1b0
leaq -0xd8(%rbp), %rsi
callq 0x4590
leaq -0xd8(%rbp), %rdi
callq 0x4000
leaq -0xd9(%rbp), %rdi
callq 0x45c0
leaq -0x110(%rbp), %rdi
movl $0x20, %esi
movl $0x1d, %edx
callq 0x20c0
movb $0x0, -0xf4(%rbp)
testb $0x1, -0x11(%rbp)
je 0x3c06
cmpl $0xb, -0xb0(%rbp)
jl 0x3c06
cmpl $0x26, -0xb4(%rbp)
jl 0x3c06
movl -0xb0(%rbp), %edi
movl -0xb4(%rbp), %esi
callq 0x2670
jmp 0x3c44
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0xd9(%rbp), %rdi
callq 0x45c0
jmp 0x3f4d
testb $0x1, -0x12(%rbp)
je 0x3c31
cmpl $0x18, -0xb0(%rbp)
jl 0x3c31
cmpl $0x23, -0xb4(%rbp)
jl 0x3c31
movl -0xb0(%rbp), %edi
movl -0xb4(%rbp), %esi
callq 0x2ba0
jmp 0x3c42
movl -0xb0(%rbp), %edi
movl -0xb4(%rbp), %esi
callq 0x2590
jmp 0x3c44
movl $0x0, -0x118(%rbp)
movb $0x0, -0x119(%rbp)
movq 0xa36c(%rip), %rax      # 0xdfc8
movq (%rax), %rdi
callq 0x21d0
movl %eax, -0x114(%rbp)
movl -0x114(%rbp), %eax
movl %eax, -0x15c(%rbp)
subl $0x50, %eax
je 0x3d1a
jmp 0x3c81
movl -0x15c(%rbp), %eax
subl $0x51, %eax
je 0x3cfa
jmp 0x3c8e
movl -0x15c(%rbp), %eax
subl $0x52, %eax
je 0x3d04
jmp 0x3c9b
movl -0x15c(%rbp), %eax
subl $0x70, %eax
je 0x3d1a
jmp 0x3ca8
movl -0x15c(%rbp), %eax
subl $0x71, %eax
je 0x3cfa
jmp 0x3cb5
movl -0x15c(%rbp), %eax
subl $0x72, %eax
je 0x3d04
jmp 0x3cc2
movl -0x15c(%rbp), %eax
subl $0x104, %eax            # imm = 0x104
je 0x3d6f
jmp 0x3cd5
movl -0x15c(%rbp), %eax
subl $0x105, %eax            # imm = 0x105
je 0x3d89
jmp 0x3ce8
movl -0x15c(%rbp), %eax
subl $0x191, %eax            # imm = 0x191
je 0x3d1a
jmp 0x3d9a
callq 0x3930
jmp 0x3d9c
movl -0xb0(%rbp), %edi
movl -0xb4(%rbp), %esi
callq 0x2590
jmp 0x3d9c
movb -0x119(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x119(%rbp)
testb $0x1, -0x119(%rbp)
je 0x3d51
movl -0xb0(%rbp), %edi
addl $0x1, %edi
movl $0x3, %esi
leaq 0x53a7(%rip), %rdx      # 0x90ef
movb $0x0, %al
callq 0x2280
jmp 0x3d6d
movl -0xb0(%rbp), %edi
addl $0x1, %edi
movl $0x3, %esi
leaq 0x5394(%rip), %rdx      # 0x90fa
movb $0x0, %al
callq 0x2280
jmp 0x3d9c
cmpl $0x9, -0xb8(%rbp)
jle 0x3d87
movl -0xb8(%rbp), %eax
subl $0xa, %eax
movl %eax, -0xb8(%rbp)
jmp 0x3d9c
movl -0xb8(%rbp), %eax
addl $0xa, %eax
movl %eax, -0xb8(%rbp)
jmp 0x3d9c
jmp 0x3d9c
testb $0x1, -0x119(%rbp)
jne 0x3f39
movl -0xb0(%rbp), %edi
movl -0xb4(%rbp), %esi
leaq -0x110(%rbp), %rdx
movl -0x118(%rbp), %ecx
movl -0xb8(%rbp), %r8d
callq 0x3600
leaq 0xa3c3(%rip), %rdi      # 0xe198
leaq 0xa3a4(%rip), %rsi      # 0xe180
callq 0x42b0
movl $0x0, -0x120(%rbp)
movl -0x120(%rbp), %eax
cmpl 0xa369(%rip), %eax      # 0xe160
jge 0x3ed3
movl -0xbc(%rbp), %eax
imull -0x120(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x12c(%rbp)
movl -0x120(%rbp), %eax
movl 0xa341(%rip), %ecx      # 0xe160
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x3e34
movl -0xb0(%rbp), %eax
movl %eax, -0x160(%rbp)
jmp 0x3e4c
movl -0xbc(%rbp), %eax
movl -0x120(%rbp), %ecx
addl $0x1, %ecx
imull %ecx, %eax
movl %eax, -0x160(%rbp)
movl -0x160(%rbp), %eax
movl %eax, -0x130(%rbp)
movl $0x1, -0x134(%rbp)
leaq -0x128(%rbp), %rdi
leaq -0xda0(%rip), %rsi      # 0x30d0
leaq -0x12c(%rbp), %rdx
leaq -0x130(%rbp), %rcx
leaq -0x134(%rbp), %r8
leaq -0xb4(%rbp), %r9
callq 0x45e0
movslq -0x120(%rbp), %rsi
leaq 0xa311(%rip), %rdi      # 0xe1b0
callq 0x46c0
movq %rax, %rdi
leaq -0x128(%rbp), %rsi
callq 0x46e0
leaq -0x128(%rbp), %rdi
callq 0x4720
movl -0x120(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x120(%rbp)
jmp 0x3deb
movl $0x0, -0x138(%rbp)
movl -0x138(%rbp), %eax
cmpl 0xa277(%rip), %eax      # 0xe160
jge 0x3f17
movslq -0x138(%rbp), %rsi
leaq 0xa2b7(%rip), %rdi      # 0xe1b0
callq 0x46c0
movq %rax, %rdi
callq 0x2240
movl -0x138(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x138(%rbp)
jmp 0x3edd
leaq 0xa262(%rip), %rdi      # 0xe180
leaq 0xa273(%rip), %rsi      # 0xe198
callq 0x42b0
movl -0x118(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x118(%rbp)
imull $0x3e8, -0xb8(%rbp), %edi # imm = 0x3E8
callq 0x21e0
jmp 0x3c55
movq -0xe8(%rbp), %rdi
callq 0x2250
nopl (%rax)