// File: pgrouchy[P]NoiseWorld/mathNet.cpp
// Function: Genome::setNearestNeighbor(std::__cxx11::list<gridEntry*, std::allocator<gridEntry*>>*, bool&, Population*)
void Genome::setNearestNeighbor(list<gridEntry*> *fullGrid, bool &isWithinReproductionDistance, Population *myPop) {
    list<Genome*>::iterator curGenome, curGenome2; 
    list<gridEntry*> innerEntriesToCheck;
    list<gridEntry*> outerEntriesToCheck;
    list<gridEntry*>::iterator curGridEntry;
    double minDist, myDist, closestIndDist = DBL_MAX;
    int i, j, xGridBlock, yGridBlock;
    int counter = 1;
    bool neighbourFound = false;

    // first check the grid location that is also occupied by the agent
    for (curGridEntry = fullGrid[this->mainGridLocation[1]*(int)(ISLAND_SIZE/NN_BLOCK_SIZE) + this->mainGridLocation[0]].begin(); curGridEntry != fullGrid[this->mainGridLocation[1]*(int)(ISLAND_SIZE/NN_BLOCK_SIZE) + this->mainGridLocation[0]].end(); ++curGridEntry) {
        if (((*curGridEntry)->myGenome != this)) {
            (*curGridEntry)->myDist = sqrt(pow((this->myPosition[0] - (*curGridEntry)->myGenome->myPosition[0]),2.0) + pow((this->myPosition[1] - (*curGridEntry)->myGenome->myPosition[1]),2.0));
            innerEntriesToCheck.push_back((*curGridEntry));
        }
    }

    do { // check next group of grid sqaures
        for (i = (-1*counter); i <= counter; i++) {
            for (j = (-1*counter); j <= counter; j++) {
                if ((i == (-1*counter)) || (j == (-1*counter)) || (i == counter) || (j == counter)) {
                    xGridBlock = this->mainGridLocation[0] + i;
                    if (xGridBlock >= (int)(ISLAND_SIZE/NN_BLOCK_SIZE)) {
                        continue;
                    } else if (xGridBlock < 0) {
                        continue;
                    }
                    yGridBlock = this->mainGridLocation[1] + j;
                    if (yGridBlock >= (int)(ISLAND_SIZE/NN_BLOCK_SIZE)) {
                        continue;
                    } else if (yGridBlock < 0) {
                        continue;
                    }
                    for (curGridEntry = fullGrid[yGridBlock*(int)(ISLAND_SIZE/NN_BLOCK_SIZE) + xGridBlock].begin(); curGridEntry != fullGrid[yGridBlock*(int)(ISLAND_SIZE/NN_BLOCK_SIZE) + xGridBlock].end(); ++curGridEntry) {
                        (*curGridEntry)->myDist = sqrt(pow((this->myPosition[0] - (*curGridEntry)->myGenome->myPosition[0]),2.0) + pow((this->myPosition[1] - (*curGridEntry)->myGenome->myPosition[1]),2.0));
                        outerEntriesToCheck.push_back((*curGridEntry));
                    }
                }
            }
        }

        // first check the inner grid locations for a neighbor
        for (curGridEntry = innerEntriesToCheck.begin(); curGridEntry != innerEntriesToCheck.end(); ++curGridEntry) {
            if ((*curGridEntry)->myDist < closestIndDist) {
                neighbourFound = true;
                closestIndDist = (*curGridEntry)->myDist;
                this->closestInd = (*curGridEntry)->myGenome;
            }
        }

        if (neighbourFound) { // if we find a neighbor, we still need to search the next layer of grid locations as a closer neighbor may be located there
            for (curGridEntry = outerEntriesToCheck.begin(); curGridEntry != outerEntriesToCheck.end(); ++curGridEntry) {
                if ((*curGridEntry)->myDist < closestIndDist) {
                    closestIndDist = (*curGridEntry)->myDist;
                    this->closestInd = (*curGridEntry)->myGenome;
                }
            }
        } else { // get ready to check the next layer
            innerEntriesToCheck.clear();
            innerEntriesToCheck.splice(innerEntriesToCheck.begin(), outerEntriesToCheck);
            outerEntriesToCheck.clear();
            counter++;
        }
    } while ((!neighbourFound) && (counter <= 2));

    if (!neighbourFound) { // if after 5 layers no neighbor is found, do a search of the entire population
        minDist = DBL_MAX;
        for (curGenome = myPop->genomes.begin(); curGenome != myPop->genomes.end(); ++curGenome) {
            if ((*curGenome) != this) {
                myDist = sqrt(pow((this->myPosition[0] - (*curGenome)->myPosition[0]), 2.0) + pow((this->myPosition[1] - (*curGenome)->myPosition[1]), 2.0));
                if (myDist < minDist) {
                    minDist = myDist;
                    this->closestInd = (*curGenome);
                    closestIndDist = minDist;
                }
            }
        }
    }

    isWithinReproductionDistance = false;
    if (closestIndDist < REPRODUCTION_DIST) {
        isWithinReproductionDistance = true;
    }
}

// Assembly:
subq $0x198, %rsp            # imm = 0x198
movq %rdi, 0x190(%rsp)
movq %rsi, 0x188(%rsp)
movq %rdx, 0x180(%rsp)
movq %rcx, 0x178(%rsp)
movq 0x190(%rsp), %rax
movq %rax, 0x88(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x7cb0
leaq 0x168(%rsp), %rdi
callq 0x7cb0
leaq 0x150(%rsp), %rdi
callq 0x7d40
leaq 0x138(%rsp), %rdi
callq 0x7d40
leaq 0x130(%rsp), %rdi
callq 0x7d20
movq 0x88(%rsp), %rcx
movsd 0x30e0(%rip), %xmm0     # 0x15038
movsd %xmm0, 0x118(%rsp)
movl $0x1, 0x104(%rsp)
movb $0x0, 0x103(%rsp)
movq 0x188(%rsp), %rdi
imull $0xa0, 0x4c(%rcx), %eax
addl 0x48(%rcx), %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x13620
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x88(%rsp), %rcx
movq 0x188(%rsp), %rdi
imull $0xa0, 0x4c(%rcx), %eax
addl 0x48(%rcx), %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x13670
movq %rax, 0xf0(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x13650
testb $0x1, %al
jne 0x11ffa
jmp 0x1214c
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq 0x88(%rsp), %rcx
movq (%rax), %rax
cmpq %rcx, (%rax)
je 0x12138
movq 0x88(%rsp), %rax
movsd 0x68(%rax), %xmm0
movsd %xmm0, 0x58(%rsp)
leaq 0x130(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x136a0
movsd 0x58(%rsp), %xmm0
movq (%rax), %rax
movq (%rax), %rax
movsd 0x68(%rax), %xmm1
subsd %xmm1, %xmm0
movsd 0x31d0(%rip), %xmm1     # 0x15230
movsd %xmm1, 0x68(%rsp)
callq 0x3420
movq 0x88(%rsp), %rax
movq 0x80(%rsp), %rdi
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rax), %xmm0
movsd %xmm0, 0x60(%rsp)
callq 0x136a0
movsd 0x60(%rsp), %xmm0
movsd 0x68(%rsp), %xmm1
movq (%rax), %rax
movq (%rax), %rax
movsd 0x70(%rax), %xmm2
subsd %xmm2, %xmm0
callq 0x3420
movaps %xmm0, %xmm1
movsd 0x70(%rsp), %xmm0
addsd %xmm1, %xmm0
callq 0x31e0
movq 0x80(%rsp), %rdi
movsd %xmm0, 0x78(%rsp)
callq 0x136a0
movsd 0x78(%rsp), %xmm0
movq 0x80(%rsp), %rdi
movq (%rax), %rax
movsd %xmm0, 0x8(%rax)
callq 0x136a0
movq %rax, %rsi
leaq 0x150(%rsp), %rdi
callq 0x136c0
jmp 0x12103
jmp 0x12138
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe8(%rsp)
movl %eax, 0xe4(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x137b0
leaq 0x150(%rsp), %rdi
callq 0x137b0
jmp 0x12850
jmp 0x1213a
leaq 0x130(%rsp), %rdi
callq 0x13700
jmp 0x11fac
jmp 0x1214e
imull $0xffffffff, 0x104(%rsp), %eax # imm = 0xFFFFFFFF
movl %eax, 0x114(%rsp)
movl 0x114(%rsp), %eax
cmpl 0x104(%rsp), %eax
jg 0x12412
imull $0xffffffff, 0x104(%rsp), %eax # imm = 0xFFFFFFFF
movl %eax, 0x110(%rsp)
movl 0x110(%rsp), %eax
cmpl 0x104(%rsp), %eax
jg 0x123fa
movl 0x114(%rsp), %eax
imull $0xffffffff, 0x104(%rsp), %ecx # imm = 0xFFFFFFFF
cmpl %ecx, %eax
je 0x121ea
movl 0x110(%rsp), %eax
imull $0xffffffff, 0x104(%rsp), %ecx # imm = 0xFFFFFFFF
cmpl %ecx, %eax
je 0x121ea
movl 0x114(%rsp), %eax
cmpl 0x104(%rsp), %eax
je 0x121ea
movl 0x110(%rsp), %eax
cmpl 0x104(%rsp), %eax
jne 0x123e2
movq 0x88(%rsp), %rax
movl 0x48(%rax), %eax
addl 0x114(%rsp), %eax
movl %eax, 0x10c(%rsp)
cmpl $0xa0, 0x10c(%rsp)
jl 0x12215
jmp 0x123e4
cmpl $0x0, 0x10c(%rsp)
jge 0x12224
jmp 0x123e4
jmp 0x12226
movq 0x88(%rsp), %rax
movl 0x4c(%rax), %eax
addl 0x110(%rsp), %eax
movl %eax, 0x108(%rsp)
cmpl $0xa0, 0x108(%rsp)
jl 0x12251
jmp 0x123e4
cmpl $0x0, 0x108(%rsp)
jge 0x12260
jmp 0x123e4
jmp 0x12262
movq 0x188(%rsp), %rdi
imull $0xa0, 0x108(%rsp), %eax
addl 0x10c(%rsp), %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x13620
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x188(%rsp), %rdi
imull $0xa0, 0x108(%rsp), %eax
addl 0x10c(%rsp), %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x13670
movq %rax, 0xd0(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x13650
testb $0x1, %al
jne 0x122f0
jmp 0x123e0
movq 0x88(%rsp), %rax
movsd 0x68(%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
leaq 0x130(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x136a0
movsd 0x28(%rsp), %xmm0
movq (%rax), %rax
movq (%rax), %rax
movsd 0x68(%rax), %xmm1
subsd %xmm1, %xmm0
movsd 0x2efe(%rip), %xmm1     # 0x15230
movsd %xmm1, 0x38(%rsp)
callq 0x3420
movq 0x88(%rsp), %rax
movq 0x50(%rsp), %rdi
movsd %xmm0, 0x40(%rsp)
movsd 0x70(%rax), %xmm0
movsd %xmm0, 0x30(%rsp)
callq 0x136a0
movsd 0x30(%rsp), %xmm0
movsd 0x38(%rsp), %xmm1
movq (%rax), %rax
movq (%rax), %rax
movsd 0x70(%rax), %xmm2
subsd %xmm2, %xmm0
callq 0x3420
movaps %xmm0, %xmm1
movsd 0x40(%rsp), %xmm0
addsd %xmm1, %xmm0
callq 0x31e0
movq 0x50(%rsp), %rdi
movsd %xmm0, 0x48(%rsp)
callq 0x136a0
movsd 0x48(%rsp), %xmm0
movq 0x50(%rsp), %rdi
movq (%rax), %rax
movsd %xmm0, 0x8(%rax)
callq 0x136a0
movq %rax, %rsi
leaq 0x138(%rsp), %rdi
callq 0x136c0
jmp 0x123cc
jmp 0x123ce
leaq 0x130(%rsp), %rdi
callq 0x13700
jmp 0x122a2
jmp 0x123e2
jmp 0x123e4
movl 0x110(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x110(%rsp)
jmp 0x12186
jmp 0x123fc
movl 0x114(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x114(%rsp)
jmp 0x12160
leaq 0x150(%rsp), %rdi
callq 0x13620
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x13670
movq %rax, 0xc0(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x13650
testb $0x1, %al
jne 0x1246a
jmp 0x124ea
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq (%rax), %rax
movsd 0x8(%rax), %xmm1
movsd 0x118(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x124d6
movb $0x1, 0x103(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq (%rax), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x118(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq %rax, %rcx
movq 0x88(%rsp), %rax
movq (%rcx), %rcx
movq (%rcx), %rcx
movq %rcx, 0x50(%rax)
jmp 0x124d8
leaq 0x130(%rsp), %rdi
callq 0x13700
jmp 0x12437
testb $0x1, 0x103(%rsp)
je 0x125c7
leaq 0x138(%rsp), %rdi
callq 0x13620
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x13670
movq %rax, 0xb0(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x13650
testb $0x1, %al
jne 0x1254d
jmp 0x125c5
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq (%rax), %rax
movsd 0x8(%rax), %xmm1
movsd 0x118(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x125b1
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq (%rax), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x118(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x136a0
movq %rax, %rcx
movq 0x88(%rsp), %rax
movq (%rcx), %rcx
movq (%rcx), %rcx
movq %rcx, 0x50(%rax)
jmp 0x125b3
leaq 0x130(%rsp), %rdi
callq 0x13700
jmp 0x1251d
jmp 0x12639
leaq 0x150(%rsp), %rdi
callq 0x13720
leaq 0x150(%rsp), %rdi
callq 0x13620
movq %rax, 0xa0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x13790
movq 0xa8(%rsp), %rsi
leaq 0x150(%rsp), %rdi
leaq 0x138(%rsp), %rdx
callq 0x13750
leaq 0x138(%rsp), %rdi
callq 0x13720
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0x1263b
xorl %eax, %eax
testb $0x1, 0x103(%rsp)
movb %al, 0x27(%rsp)
jne 0x1265a
cmpl $0x2, 0x104(%rsp)
setle %al
movb %al, 0x27(%rsp)
movb 0x27(%rsp), %al
testb $0x1, %al
jne 0x1214e
testb $0x1, 0x103(%rsp)
jne 0x12805
movsd 0x29bc(%rip), %xmm0     # 0x15038
movsd %xmm0, 0x128(%rsp)
movq 0x178(%rsp), %rdi
callq 0x7e70
movq %rax, 0x98(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x170(%rsp)
movq 0x178(%rsp), %rdi
callq 0x7ec0
movq %rax, 0x90(%rsp)
leaq 0x170(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x7ea0
testb $0x1, %al
jne 0x126dd
jmp 0x12803
leaq 0x170(%rsp), %rdi
callq 0x7ef0
movq 0x88(%rsp), %rcx
cmpq %rcx, (%rax)
je 0x127ef
movq 0x88(%rsp), %rax
movsd 0x68(%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x7ef0
movsd 0x8(%rsp), %xmm0
movq (%rax), %rax
subsd 0x68(%rax), %xmm0
movsd 0x2aff(%rip), %xmm1     # 0x15230
callq 0x3420
movq 0x88(%rsp), %rax
movsd %xmm0, 0x18(%rsp)
movsd 0x70(%rax), %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x7ef0
movsd 0x10(%rsp), %xmm0
movq (%rax), %rax
subsd 0x70(%rax), %xmm0
movsd 0x2abe(%rip), %xmm1     # 0x15230
callq 0x3420
movaps %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm0
callq 0x31e0
movsd %xmm0, 0x120(%rsp)
movsd 0x120(%rsp), %xmm1
movsd 0x128(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x127ed
movsd 0x120(%rsp), %xmm0
movsd %xmm0, 0x128(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x7ef0
movq %rax, %rcx
movq 0x88(%rsp), %rax
movq (%rcx), %rcx
movq %rcx, 0x50(%rax)
movsd 0x128(%rsp), %xmm0
movsd %xmm0, 0x118(%rsp)
jmp 0x127ef
jmp 0x127f1
leaq 0x170(%rsp), %rdi
callq 0x7f10
jmp 0x126aa
jmp 0x12805
movq 0x180(%rsp), %rax
movb $0x0, (%rax)
movsd 0x2a58(%rip), %xmm0     # 0x15270
ucomisd 0x118(%rsp), %xmm0
jbe 0x1282e
movq 0x180(%rsp), %rax
movb $0x1, (%rax)
leaq 0x138(%rsp), %rdi
callq 0x137b0
leaq 0x150(%rsp), %rdi
callq 0x137b0
addq $0x198, %rsp            # imm = 0x198
retq
movq 0xe8(%rsp), %rdi
callq 0x3430
nopl (%rax)