// File: /workspace/github_cpp_makefile_star2_O2/jeffreyan11[P]go-engine/board.cpp
// Function: Board::doMove(int, unsigned short)
void Board::doMove(Player p, Move m) {
    if (m == MOVE_PASS)
        return;

    int x = getX(m);
    int y = getY(m);

    assert(pieces[index(x, y)] == EMPTY);
    assert(chainID[index(x, y)] == 0);
    
    pieces[index(x, y)] = p;
    zobristKey ^= zobristTable[zobristIndex(p, x, y)];

    Player victim = otherPlayer(p);

    Stone east = pieces[index(x+1, y)];
    Stone west = pieces[index(x-1, y)];
    Stone north = pieces[index(x, y+1)];
    Stone south = pieces[index(x, y-1)];
    int connectionCount = (east == p) + (west == p) + (north == p) + (south == p);

    // If the stone placed is a new chain
    if (connectionCount == 0) {
        // Record which chain this square is a part of
        chainID[index(x, y)] = nextID;

        // Add this chain to the list of chains
        Chain *cargo = new Chain(p, nextID);
        cargo->add(m);
        cargo->liberties = 0;
        if (east == EMPTY)
            cargo->addLiberty(coordToMove(x+1, y));
        if (west == EMPTY)
            cargo->addLiberty(coordToMove(x-1, y));
        if (north == EMPTY)
            cargo->addLiberty(coordToMove(x, y+1));
        if (south == EMPTY)
            cargo->addLiberty(coordToMove(x, y-1));

        chainList.add(cargo);

        nextID++;
    }

    // If the stone placed is added to an existing chain
    else if (connectionCount == 1) {
        // Find the ID of the chain we are adding this stone to
        int thisID;
        if (east == p)
            thisID = chainID[index(x+1, y)];
        else if (west == p)
            thisID = chainID[index(x-1, y)];
        else if (north == p)
            thisID = chainID[index(x, y+1)];
        else
            thisID = chainID[index(x, y-1)];

        chainID[index(x, y)] = thisID;
        Chain *node = nullptr;
        searchChainsByID(node, thisID);
        node->add(m);

        // The new stone occupies a previous liberty, but adds on however many
        // liberties it itself has
        node->removeLiberty(node->findLiberty(m));
        updateLiberty(node, x, y);
    }

    // If the stone possibly connects two existing chains
    else {
        int eastID = (east == p) * chainID[index(x+1, y)];
        int westID = (west == p) * chainID[index(x-1, y)];
        int northID = (north == p) * chainID[index(x, y+1)];
        int southID = (south == p) * chainID[index(x, y-1)];
        Chain *node = nullptr;
        bool added = false;

        if (eastID) {
            chainID[index(x, y)] = eastID;
            searchChainsByID(node, eastID);

            node->add(m);
            node->removeLiberty(node->findLiberty(m));
            updateLiberty(node, x, y);
            added = true;
        }

        if (westID) {
            if (added) {
                // If two stones from the same chain are adjacent, do nothing
                // If they are from different chains, we need to combine...
                if (westID != eastID)
                    mergeChains(node, westID, m);
            }
            else {
                chainID[index(x, y)] = westID;
                searchChainsByID(node, westID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }

        if (northID) {
            if (added) {
                if (northID != eastID && northID != westID)
                    mergeChains(node, northID, m);
            }
            else {
                chainID[index(x, y)] = northID;
                searchChainsByID(node, northID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }

        if (southID) {
            if (added) {
                if (southID != eastID && southID != westID && southID != northID)
                    mergeChains(node, southID, m);
            }
            else {
                chainID[index(x, y)] = southID;
                searchChainsByID(node, southID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }
    }


    // Update opponent liberties
    int eastID = (east == victim) * chainID[index(x+1, y)];
    int westID = (west == victim) * chainID[index(x-1, y)];
    int northID = (north == victim) * chainID[index(x, y+1)];
    int southID = (south == victim) * chainID[index(x, y-1)];

    if (eastID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, eastID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (westID && westID != eastID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, westID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (northID && northID != eastID && northID != westID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, northID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (southID && southID != eastID && southID != westID && southID != northID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, southID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    // Check for a suicide
    int selfID = chainID[index(x, y)];
    Chain *node = nullptr;
    int nodeIndex = searchChainsByID(node, selfID);

    if (node->liberties == 0)
        captureChain(node, nodeIndex);


    // A debugging check
    assert(!checkChains());

    // Check if p captured any of the other player's stones with move m
    /*
    doCaptures<true>(victim, coordToMove(x+1, y));
    doCaptures<true>(victim, coordToMove(x-1, y));
    doCaptures<true>(victim, coordToMove(x, y+1));
    doCaptures<true>(victim, coordToMove(x, y-1));

    // Check if p suicided with move m
    doCaptures<true>(p, coordToMove(x, y));
    */
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
cmpl $0x8000, %edx           # imm = 0x8000
je 0x3481
movq %rdi, %r13
movzwl %dx, %eax
movl %eax, (%rsp)
movl %eax, %r11d
shrl $0x8, %r11d
movzbl %dl, %ebp
movq (%rdi), %r8
movl 0x847c(%rip), %eax      # 0xb174
imull %ebp, %eax
addl %r11d, %eax
cltq
movl %esi, (%r8,%rax,4)
leal -0x2(,%rbp,2), %eax
imull 0x845e(%rip), %eax      # 0xb170
leal (%rsi,%r11,2), %ecx
addl %ecx, %eax
addl $-0x3, %eax
cltq
leaq 0x848c(%rip), %rcx      # 0xb1b0
movq (%rcx,%rax,8), %rax
xorq %rax, 0x10(%rdi)
movl 0x8442(%rip), %edi      # 0xb174
movl %edi, %eax
imull %ebp, %eax
leal (%rax,%r11), %ecx
incl %ecx
movslq %ecx, %rcx
movq %rcx, 0x28(%rsp)
movl (%r8,%rcx,4), %ebx
leal -0x1(%rax,%r11), %edx
movslq %edx, %rdx
movl (%r8,%rdx,4), %r15d
leal 0x1(%rbp), %r9d
movl %edi, %r10d
movl %r9d, 0x48(%rsp)
imull %r9d, %r10d
addl %r11d, %r10d
movslq %r10d, %rcx
leal -0x1(%rbp), %r9d
movl %r9d, 0x4c(%rsp)
imull %r9d, %edi
addl %r11d, %edi
xorl %r9d, %r9d
cmpl %esi, %ebx
sete %r9b
xorl %r10d, %r10d
cmpl %esi, %r15d
sete %r10b
addl %r9d, %r10d
movl (%r8,%rcx,4), %r12d
movslq %edi, %rdi
movl (%r8,%rdi,4), %r14d
xorl %r9d, %r9d
movl %r12d, 0x4(%rsp)
cmpl %esi, %r12d
movq %rsi, %r12
sete %r9b
xorl %r8d, %r8d
movl %r14d, 0x34(%rsp)
cmpl %r12d, %r14d
sete %r8b
addl %r9d, %r8d
addl %r10d, %r8d
leal 0x1(%r11), %r14d
movq %r11, 0x18(%rsp)
leal -0x1(%r11), %esi
movl %esi, 0x44(%rsp)
cmpl $0x1, %r8d
movq %r13, 0x10(%rsp)
movq %rbp, 0x38(%rsp)
movl %r15d, 0x50(%rsp)
movl %ebx, 0x24(%rsp)
je 0x2ec4
testl %r8d, %r8d
jne 0x2f5e
movl 0x18(%r13), %ebx
movq 0x20(%r13), %rcx
addl 0x18(%rsp), %eax
cltq
movl %ebx, (%rcx,%rax,4)
movl $0x610, %edi            # imm = 0x610
callq 0x21a0
movq %rax, %r15
movq %rax, %rdi
movl %r12d, %esi
movl %ebx, %edx
callq 0x5300
movq %r15, %rdi
movl (%rsp), %esi
callq 0x5368
andl $0x0, 0xc(%r15)
movl 0x24(%rsp), %ebx
testl %ebx, %ebx
jne 0x2e50
movl %r14d, %eax
shll $0x8, %eax
orl %ebp, %eax
movzwl %ax, %esi
movq %r15, %rdi
callq 0x539c
cmpl $0x0, 0x50(%rsp)
jne 0x2e6b
movl 0x44(%rsp), %eax
shll $0x8, %eax
orl %ebp, %eax
movzwl %ax, %esi
movq %r15, %rdi
callq 0x539c
cmpl $0x0, 0x4(%rsp)
jne 0x2e88
movq 0x18(%rsp), %rax
movl %eax, %esi
shll $0x8, %esi
orl 0x48(%rsp), %esi
movq %r15, %rdi
callq 0x539c
cmpl $0x0, 0x34(%rsp)
jne 0x2ea6
movq 0x18(%rsp), %rax
shll $0x8, %eax
orl 0x4c(%rsp), %eax
movzwl %ax, %esi
movq %r15, %rdi
callq 0x539c
movl 0x1028(%r13), %eax
movq %r15, 0x28(%r13,%rax,8)
incl %eax
movl %eax, 0x1028(%r13)
incl 0x18(%r13)
jmp 0x326a
cmpl %r12d, 0x4(%rsp)
cmoveq %rcx, %rdi
cmpl %r12d, %r15d
cmoveq %rdx, %rdi
cmpl %r12d, %ebx
movq 0x20(%r13), %rsi
cmoveq 0x28(%rsp), %rdi
movl (%rsi,%rdi,4), %edx
movq 0x18(%rsp), %rbp
addl %ebp, %eax
cltq
movl %edx, (%rsi,%rax,4)
leaq 0x8(%rsp), %rbx
andq $0x0, (%rbx)
movq %r13, %rdi
movq %rbx, %rsi
callq 0x5100
movq (%rbx), %rdi
movq %r12, %rbx
movl %r14d, %r12d
movl (%rsp), %r14d
movl %r14d, %esi
callq 0x5368
leaq 0x8(%rsp), %rax
movq (%rax), %r15
movq %r15, %rdi
movl %r14d, %esi
movl %r12d, %r14d
movq %rbx, %r12
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
leaq 0x8(%rsp), %rax
movq (%rax), %rsi
movl 0x24(%rsp), %ebx
movq %r13, %rdi
movl %ebp, %edx
movq 0x38(%rsp), %rbp
movl %ebp, %ecx
callq 0x34a8
jmp 0x326a
movq %rdx, %rsi
xorl %ebx, %ebx
movq 0x20(%r13), %r8
movl $0x0, %edx
cmpl %r12d, 0x24(%rsp)
jne 0x2f7c
movq 0x28(%rsp), %rdx
movl (%r8,%rdx,4), %edx
movl $0x0, %r13d
cmpl %r12d, %r15d
jne 0x2f8b
movl (%r8,%rsi,4), %r13d
movl $0x0, %r9d
cmpl %r12d, 0x4(%rsp)
jne 0x2f9c
movl (%r8,%rcx,4), %r9d
movl $0x0, %ecx
cmpl %r12d, 0x34(%rsp)
jne 0x2fac
movl (%r8,%rdi,4), %ecx
movl %ecx, 0x54(%rsp)
movl %r14d, 0x20(%rsp)
andq $0x0, 0x8(%rsp)
testl %edx, %edx
movl %r9d, 0x28(%rsp)
movl %edx, 0x30(%rsp)
movl %r13d, 0x40(%rsp)
je 0x3036
movq 0x18(%rsp), %rbp
addl %ebp, %eax
cltq
movl %edx, (%r8,%rax,4)
leaq 0x8(%rsp), %rbx
movq 0x10(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
callq 0x5100
movq (%rbx), %rdi
movl (%rsp), %r14d
movl %r14d, %esi
callq 0x5368
movq (%rbx), %r15
movq %r15, %rdi
movl %r14d, %esi
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
movq (%rbx), %rsi
movq %r13, %rdi
movl 0x40(%rsp), %r13d
movl %ebp, %edx
movq 0x38(%rsp), %rbp
movl %ebp, %ecx
callq 0x34a8
movl 0x28(%rsp), %r9d
movb $0x1, %bl
testl %r13d, %r13d
je 0x30e9
testb %bl, %bl
je 0x306a
cmpl 0x30(%rsp), %r13d
je 0x30e9
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdi
movl %r13d, %edx
movl (%rsp), %ecx
callq 0x35de
movl 0x28(%rsp), %r9d
jmp 0x30e9
movq 0x10(%rsp), %rbx
movq 0x20(%rbx), %rax
movl 0x80fb(%rip), %ecx      # 0xb174
imull %ebp, %ecx
movq 0x18(%rsp), %rbp
addl %ebp, %ecx
movslq %ecx, %rcx
movl %r13d, (%rax,%rcx,4)
leaq 0x8(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
movl %r13d, %edx
callq 0x5100
movq (%r14), %rdi
movl (%rsp), %r14d
movl %r14d, %esi
callq 0x5368
leaq 0x8(%rsp), %rax
movq (%rax), %r15
movq %r15, %rdi
movl %r14d, %esi
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
leaq 0x8(%rsp), %rax
movq (%rax), %rsi
movq %rbx, %rdi
movl %ebp, %edx
movq 0x38(%rsp), %rbp
movl %ebp, %ecx
callq 0x34a8
movl 0x28(%rsp), %r9d
movb $0x1, %bl
testl %r9d, %r9d
je 0x31ad
testb %bl, %bl
je 0x3130
movl 0x30(%rsp), %eax
cmpl %eax, %r9d
je 0x31ad
cmpl %r13d, %r9d
movl 0x20(%rsp), %r14d
je 0x31b2
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdi
movl %r9d, %edx
movl (%rsp), %ecx
callq 0x35de
movl 0x28(%rsp), %r9d
jmp 0x31b2
movq 0x10(%rsp), %rbx
movq 0x20(%rbx), %rax
movl 0x8035(%rip), %ecx      # 0xb174
imull %ebp, %ecx
movq 0x18(%rsp), %rbp
addl %ebp, %ecx
movslq %ecx, %rcx
movl %r9d, (%rax,%rcx,4)
leaq 0x8(%rsp), %r13
movq %rbx, %rdi
movq %r13, %rsi
movl %r9d, %edx
callq 0x5100
movq (%r13), %rdi
movl (%rsp), %r14d
movl %r14d, %esi
callq 0x5368
movq (%r13), %r15
movq %r15, %rdi
movl %r14d, %esi
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
movq (%r13), %rsi
movl 0x40(%rsp), %r13d
movq %rbx, %rdi
movl %ebp, %edx
movq 0x38(%rsp), %rbp
movl %ebp, %ecx
callq 0x34a8
movl 0x28(%rsp), %r9d
movb $0x1, %bl
movl 0x20(%rsp), %r14d
movl 0x54(%rsp), %edx
testl %edx, %edx
je 0x3261
testb %bl, %bl
je 0x31f2
cmpl 0x30(%rsp), %edx
je 0x3261
cmpl %r13d, %edx
je 0x3261
cmpl %r9d, %edx
je 0x3261
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdi
movl (%rsp), %ecx
callq 0x35de
jmp 0x3261
movq 0x10(%rsp), %r13
movq 0x20(%r13), %rax
movl 0x7f73(%rip), %ecx      # 0xb174
imull %ebp, %ecx
movq 0x18(%rsp), %rbp
addl %ebp, %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
leaq 0x8(%rsp), %rbx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x5100
movq (%rbx), %rdi
movl (%rsp), %r14d
movl %r14d, %esi
callq 0x5368
movq (%rbx), %r15
movq %r15, %rdi
movl %r14d, %esi
movl 0x20(%rsp), %r14d
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
movq (%rbx), %rsi
movq %r13, %rdi
movl %ebp, %edx
movq 0x38(%rsp), %rbp
movl %ebp, %ecx
callq 0x34a8
movq 0x10(%rsp), %r13
movl 0x24(%rsp), %ebx
pushq $0x3
popq %rdx
subl %r12d, %edx
movl 0x7efe(%rip), %eax      # 0xb174
movl %eax, %esi
imull %ebp, %esi
xorl %r12d, %r12d
movq 0x20(%r13), %rcx
movl $0x0, %r13d
cmpl %edx, %ebx
jne 0x3296
addl %esi, %r14d
movslq %r14d, %rdi
movl (%rcx,%rdi,4), %r13d
movl $0x0, %ebp
cmpl %edx, 0x50(%rsp)
jne 0x32ab
addl 0x44(%rsp), %esi
movslq %esi, %rsi
movl (%rcx,%rsi,4), %ebp
movl $0x0, %r15d
cmpl %edx, 0x4(%rsp)
jne 0x32c9
movl 0x48(%rsp), %esi
imull %eax, %esi
addl 0x18(%rsp), %esi
movslq %esi, %rsi
movl (%rcx,%rsi,4), %r15d
cmpl %edx, 0x34(%rsp)
jne 0x32de
imull 0x4c(%rsp), %eax
addl 0x18(%rsp), %eax
cltq
movl (%rcx,%rax,4), %r12d
testl %r13d, %r13d
je 0x332f
leaq 0x8(%rsp), %rbx
andq $0x0, (%rbx)
movq 0x10(%rsp), %rdi
movq %rbx, %rsi
movl %r13d, %edx
callq 0x5100
movl %eax, 0x4(%rsp)
movq (%rbx), %r14
movq %r14, %rdi
movl (%rsp), %esi
callq 0x5378
movq %r14, %rdi
movl %eax, %esi
callq 0x53ae
movq (%rbx), %rsi
cmpl $0x0, 0xc(%rsi)
jne 0x332f
movq 0x10(%rsp), %rdi
movl 0x4(%rsp), %edx
callq 0x36d8
testl %ebp, %ebp
je 0x3383
cmpl %r13d, %ebp
je 0x3383
leaq 0x8(%rsp), %r14
andq $0x0, (%r14)
movq 0x10(%rsp), %rdi
movq %r14, %rsi
movl %ebp, %edx
callq 0x5100
movl %eax, 0x4(%rsp)
movq (%r14), %rbx
movq %rbx, %rdi
movl (%rsp), %esi
callq 0x5378
movq %rbx, %rdi
movl %eax, %esi
callq 0x53ae
movq (%r14), %rsi
cmpl $0x0, 0xc(%rsi)
jne 0x3383
movq 0x10(%rsp), %rdi
movl 0x4(%rsp), %edx
callq 0x36d8
testl %r15d, %r15d
je 0x33de
cmpl %r13d, %r15d
je 0x33de
cmpl %ebp, %r15d
je 0x33de
leaq 0x8(%rsp), %r14
andq $0x0, (%r14)
movq 0x10(%rsp), %rdi
movq %r14, %rsi
movl %r15d, %edx
callq 0x5100
movl %eax, 0x4(%rsp)
movq (%r14), %rbx
movq %rbx, %rdi
movl (%rsp), %esi
callq 0x5378
movq %rbx, %rdi
movl %eax, %esi
callq 0x53ae
movq (%r14), %rsi
cmpl $0x0, 0xc(%rsi)
jne 0x33de
movq 0x10(%rsp), %rdi
movl 0x4(%rsp), %edx
callq 0x36d8
testl %r12d, %r12d
je 0x343b
cmpl %r13d, %r12d
je 0x343b
cmpl %ebp, %r12d
je 0x343b
cmpl %r15d, %r12d
je 0x343b
leaq 0x8(%rsp), %r14
andq $0x0, (%r14)
movq 0x10(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movl %r12d, %edx
callq 0x5100
movl %eax, %ebx
movq (%r14), %r15
movq %r15, %rdi
movl (%rsp), %esi
callq 0x5378
movq %r15, %rdi
movl %eax, %esi
callq 0x53ae
movq (%r14), %rsi
cmpl $0x0, 0xc(%rsi)
jne 0x343b
movq %r13, %rdi
movl %ebx, %edx
callq 0x36d8
movq 0x38(%rsp), %rcx
imull 0x7d2d(%rip), %ecx      # 0xb174
movq 0x10(%rsp), %r14
movq 0x20(%r14), %rax
addl 0x18(%rsp), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
leaq 0x8(%rsp), %rbx
andq $0x0, (%rbx)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5100
movq (%rbx), %rsi
cmpl $0x0, 0xc(%rsi)
jne 0x3481
movq %r14, %rdi
movl %eax, %edx
callq 0x36d8
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movl $0x610, %esi            # imm = 0x610
movq %r15, %rdi
callq 0x21b0
movq %rbx, %rdi
callq 0x2290