// File: /workspace/github_cpp_makefile_star2_O3/jeffreyan11[P]go-engine/board.cpp
// Function: Board::countTerritory(int&, int&)
void Board::countTerritory(int &whiteTerritory, int &blackTerritory) {
    whiteTerritory = 0;
    blackTerritory = 0;
    Stone *visited = new Stone[arraySize*arraySize];
    Stone *territory = new Stone[arraySize*arraySize];
    Stone *region = new Stone[arraySize*arraySize]; 

    // Count territory for both sides
    for (Player p = BLACK; p <= WHITE; p++) {
        // Reset the visited array
        for (int i = 0; i < arraySize*arraySize; i++)
            visited[i] = 0;

        // Main loop
        for (int j = 1; j <= boardSize; j++) {
            for (int i = 1; i <= boardSize; i++) {
                // Don't recount territory
                if (visited[index(i, j)])
                    continue;
                // Only use empty squares as seeds
                if (pieces[index(i, j)])
                    continue;

                if (isEye(p, coordToMove(i, j))) {
                    visited[index(i, j)] = 1;
                    if (p == BLACK)
                        blackTerritory++;
                    else
                        whiteTerritory++;
                    continue;
                }
                
                for (int k = 0; k < arraySize*arraySize; k++)
                    territory[k] = 0;
                int territorySize = 0;
                int boundarySize = 0;

                getTerritory(p, i, j, visited, territory, territorySize, boundarySize);

                // Check if territory was actually sectioned off
                if (territorySize + boundarySize == boardSize*boardSize)
                    continue;

                // Detect life/death of internal stones
                // Initialize region to 0 if territory is 1, and vice versa
                // This acts as our "visited" array, so that we only explore areas
                // inside the territory
                // bool isContested = false;
                // for (int n = 1; n <= boardSize; n++) {
                //     for (int m = 1; m <= boardSize; m++) {
                //         if (!territory[index(m, n)])
                //             continue;
                //         if (pieces[index(m, n)] == otherPlayer(p)) {
                //             isContested = true;
                //             break;
                //         }
                //     }
                // }

                // if (!isContested) {
                //     if (p == BLACK)
                //         blackTerritory += territorySize;
                //     else
                //         whiteTerritory += territorySize;
                // }
                
                for (int k = 0; k < arraySize*arraySize; k++)
                    region[k] = territory[k] ^ 1;
                int internalRegions = 0;

                for (int n = 1; n <= boardSize; n++) {
                    for (int m = 1; m <= boardSize; m++) {
                        if (region[index(m, n)])
                            continue;
                        if (pieces[index(m, n)])
                            continue;

                        MoveList eye;
                        if (isSurrounded(EMPTY, p, m, n, region, eye))
                            internalRegions++;
                    }
                }

                int territoryCount = 0;
                if (internalRegions == 0) {
                    territoryCount += territorySize;
                    // Score dead stones
                    for (int k = 0; k < arraySize*arraySize; k++)
                        if (territory[k] && pieces[k] == otherPlayer(p))
                            territoryCount++;
                }

                if (p == BLACK)
                    blackTerritory += territoryCount;
                else
                    whiteTerritory += territoryCount;
            }
        }
    }

    delete[] visited;
    delete[] territory;
    delete[] region;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x488, %rsp            # imm = 0x488
movq %rdi, %r14
xorl %eax, %eax
movq %rsi, 0x48(%rsp)
movl %eax, (%rsi)
movq %rdx, 0x50(%rsp)
movl %eax, (%rdx)
movl 0x7d5c(%rip), %ebx      # 0xc18c
imull %ebx, %ebx
shlq $0x2, %rbx
movq %rbx, %rdi
callq 0x2030
movq %rax, %r12
movq %rbx, %rdi
callq 0x2030
movq %rax, %r13
movq %rbx, %rdi
callq 0x2030
movq %r14, %rdi
movq %rax, %rbp
movl $0x1, %r15d
movq %r14, 0x18(%rsp)
movq %r12, 0x60(%rsp)
movq %r13, 0x58(%rsp)
movl 0x7d16(%rip), %edx      # 0xc18c
testl %edx, %edx
je 0x4496
imull %edx, %edx
cmpl $0x1, %edx
adcl $0x0, %edx
shlq $0x2, %rdx
movq %r12, %rdi
xorl %esi, %esi
callq 0x20f0
movq 0x18(%rsp), %rdi
movl 0x7cec(%rip), %ebx      # 0xc188
testl %ebx, %ebx
jle 0x4746
movl $0x3, %eax
subl %r15d, %eax
movl %eax, 0x24(%rsp)
cmpl $0x1, %r15d
movq 0x48(%rsp), %rax
cmoveq 0x50(%rsp), %rax
movq %rax, 0x68(%rsp)
movl $0x1, %ecx
movl %r15d, 0xc(%rsp)
testl %ebx, %ebx
jle 0x4739
movl $0x1, %edx
movq %rcx, 0x30(%rsp)
movslq 0x7ca5(%rip), %rsi      # 0xc18c
movq %rsi, %rax
movq %rsi, 0x10(%rsp)
imull %ecx, %eax
addl %edx, %eax
movslq %eax, %r14
cmpl $0x0, (%r12,%r14,4)
jne 0x4726
movq (%rdi), %rax
cmpl $0x0, (%rax,%r14,4)
jne 0x4726
movq %rdx, 0x38(%rsp)
movl %edx, %eax
shll $0x8, %eax
orl %ecx, %eax
movzwl %ax, %edx
movl %r15d, %esi
callq 0x4034
testb %al, %al
je 0x4547
movl $0x1, (%r12,%r14,4)
cmpl $0x1, %r15d
jne 0x46c5
movq 0x50(%rsp), %rax
jmp 0x46ca
movq 0x10(%rsp), %rax
movl %eax, %r15d
imull %r15d, %r15d
testl %eax, %eax
je 0x456f
cmpl $0x1, %r15d
movl %r15d, %edx
adcl $0x0, %edx
shlq $0x2, %rdx
movq %r13, %rdi
xorl %esi, %esi
callq 0x20f0
xorl %eax, %eax
movl %eax, 0x2c(%rsp)
movl %eax, 0x28(%rsp)
movq 0x18(%rsp), %r14
movq %r14, %rdi
movl 0xc(%rsp), %esi
movq 0x38(%rsp), %rdx
movq 0x30(%rsp), %rcx
movq %r12, %r8
movq %r13, %r9
leaq 0x28(%rsp), %rax
pushq %rax
leaq 0x34(%rsp), %rax
pushq %rax
callq 0x477e
movq %r14, %rdi
addq $0x10, %rsp
movl 0x2c(%rsp), %r9d
movl 0x28(%rsp), %eax
addl %r9d, %eax
movl %ebx, %ecx
imull %ebx, %ecx
cmpl %ecx, %eax
je 0x4717
cmpl $0x0, 0x10(%rsp)
je 0x45ed
cmpl $0x1, %r15d
movl %r15d, %eax
adcl $0x0, %eax
xorl %ecx, %ecx
movl (%r13,%rcx,4), %edx
xorl $0x1, %edx
movl %edx, (%rbp,%rcx,4)
incq %rcx
cmpq %rcx, %rax
jne 0x45d9
testl %ebx, %ebx
jle 0x46d3
movl %r9d, 0x44(%rsp)
movq %r15, 0x70(%rsp)
incl %ebx
movq 0x10(%rsp), %rax
leaq 0x1(%rax), %r15
xorl %r12d, %r12d
movl $0x1, %r13d
movq %r15, 0x78(%rsp)
movl $0x1, %r14d
cmpl $0x0, (%rbp,%r15,4)
jne 0x4670
movq (%rdi), %rax
cmpl $0x0, (%rax,%r15,4)
jne 0x4670
movl $0x0, 0x484(%rsp)
subq $0x8, %rsp
movq 0x20(%rsp), %rdi
xorl %esi, %esi
movl 0x14(%rsp), %edx
movl %r14d, %ecx
movl %r13d, %r8d
movq %rbp, %r9
leaq 0x8c(%rsp), %rax
pushq %rax
callq 0x4264
movq 0x28(%rsp), %rdi
addq $0x10, %rsp
movzbl %al, %eax
addl %eax, %r12d
incq %r14
incq %r15
cmpq %r14, %rbx
jne 0x461e
incq %r13
movq 0x78(%rsp), %r15
addq 0x10(%rsp), %r15
cmpq %rbx, %r13
jne 0x4613
cmpl $0x0, 0x10(%rsp)
sete %cl
testl %r12d, %r12d
setne %dl
movl 0x44(%rsp), %r9d
movl %r9d, %eax
movl $0x0, %esi
cmovnel %esi, %eax
orb %cl, %dl
movq 0x60(%rsp), %r12
movq 0x58(%rsp), %r13
movl 0x24(%rsp), %r8d
movq 0x70(%rsp), %r15
je 0x46df
jmp 0x4710
movq 0x48(%rsp), %rax
incl (%rax)
movq 0x18(%rsp), %rdi
jmp 0x471c
cmpl $0x0, 0x10(%rsp)
movl 0x24(%rsp), %r8d
je 0x470d
movq (%rdi), %rcx
cmpl $0x1, %r15d
adcl $0x0, %r15d
xorl %edx, %edx
movl %r9d, %eax
cmpl $0x0, (%r13,%rdx,4)
je 0x4703
xorl %esi, %esi
cmpl %r8d, (%rcx,%rdx,4)
sete %sil
addl %esi, %eax
incq %rdx
cmpq %rdx, %r15
jne 0x46ef
jmp 0x4710
movl %r9d, %eax
movq 0x68(%rsp), %rcx
addl %eax, (%rcx)
movl 0xc(%rsp), %r15d
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rdx
leal 0x1(%rdx), %eax
movl 0x7a59(%rip), %ebx      # 0xc188
cmpl %ebx, %edx
movl %eax, %edx
jl 0x44e0
leal 0x1(%rcx), %eax
cmpl %ebx, %ecx
movl %eax, %ecx
jl 0x44ce
incl %r15d
cmpl $0x3, %r15d
jne 0x4470
movq %r12, %rdi
callq 0x2200
movq %r13, %rdi
callq 0x2200
movq %rbp, %rdi
callq 0x2200
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop