// File: /workspace/github_cpp_makefile_star2_O1/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 $0x48, %rsp
cmpl $0x8000, %edx           # imm = 0x8000
je 0x384d
movl %esi, %r12d
movq %rdi, %rbx
movzwl %dx, %eax
movl %eax, 0x8(%rsp)
movl %eax, %r15d
shrl $0x8, %r15d
movzbl %dl, %ebp
movq (%rdi), %r8
movl 0x910c(%rip), %eax      # 0xc18c
imull %ebp, %eax
addl %r15d, %eax
cltq
movl %esi, (%r8,%rax,4)
leal -0x2(,%rbp,2), %eax
imull 0x90ee(%rip), %eax      # 0xc188
leal (%r12,%r15,2), %ecx
addl %ecx, %eax
addl $-0x3, %eax
cltq
leaq 0x9124(%rip), %rcx      # 0xc1d0
movq (%rcx,%rax,8), %rax
xorq %rax, 0x10(%rdi)
movl 0x90d2(%rip), %edi      # 0xc18c
movl %edi, %eax
imull %ebp, %eax
leal (%rax,%r15), %ecx
incl %ecx
movslq %ecx, %rcx
movl (%r8,%rcx,4), %r10d
leal -0x1(%rax,%r15), %edx
movslq %edx, %rdx
movl (%r8,%rdx,4), %r11d
leal 0x1(%rbp), %r9d
movl %edi, %esi
movl %r9d, 0x40(%rsp)
imull %r9d, %esi
addl %r15d, %esi
movslq %esi, %rsi
leal -0x1(%rbp), %r14d
imull %r14d, %edi
addl %r15d, %edi
xorl %r9d, %r9d
movl %r10d, 0x28(%rsp)
cmpl %r12d, %r10d
sete %r9b
xorl %r10d, %r10d
movl %r11d, 0x4(%rsp)
cmpl %r12d, %r11d
sete %r10b
addl %r9d, %r10d
movl (%r8,%rsi,4), %r13d
movslq %edi, %rdi
movl (%r8,%rdi,4), %r11d
xorl %r9d, %r9d
movl %r13d, 0x24(%rsp)
cmpl %r12d, %r13d
sete %r9b
xorl %r8d, %r8d
movl %r11d, 0x2c(%rsp)
cmpl %r12d, %r11d
sete %r8b
addl %r9d, %r8d
addl %r10d, %r8d
leal 0x1(%r15), %r9d
movl %r9d, 0x38(%rsp)
leal -0x1(%r15), %r9d
movl %r9d, 0x3c(%rsp)
cmpl $0x1, %r8d
movq %rbp, 0x30(%rsp)
movl %r14d, 0x44(%rsp)
je 0x323a
testl %r8d, %r8d
jne 0x32ba
movl 0x18(%rbx), %ecx
movq 0x20(%rbx), %rdx
addl %r15d, %eax
cltq
movl %ecx, (%rdx,%rax,4)
movl $0x610, %edi            # imm = 0x610
callq 0x21b0
movq %rax, %r13
movl 0x18(%rbx), %edx
movq %rax, %rdi
movl %r12d, %esi
callq 0x57f4
movq %r13, %rdi
movl 0x8(%rsp), %esi
callq 0x585c
movl $0x0, 0xc(%r13)
cmpl $0x0, 0x28(%rsp)
jne 0x31d0
movl 0x38(%rsp), %eax
shll $0x8, %eax
orl %ebp, %eax
movzwl %ax, %esi
movq %r13, %rdi
callq 0x5892
cmpl $0x0, 0x4(%rsp)
jne 0x31eb
movl 0x3c(%rsp), %eax
shll $0x8, %eax
orl %ebp, %eax
movzwl %ax, %esi
movq %r13, %rdi
callq 0x5892
cmpl $0x0, 0x24(%rsp)
jne 0x3204
movl %r15d, %esi
shll $0x8, %esi
orl 0x40(%rsp), %esi
movq %r13, %rdi
callq 0x5892
cmpl $0x0, 0x2c(%rsp)
jne 0x321f
movl %r15d, %eax
shll $0x8, %eax
orl %r14d, %eax
movzwl %ax, %esi
movq %r13, %rdi
callq 0x5892
movl 0x1028(%rbx), %eax
movq %r13, 0x28(%rbx,%rax,8)
incl %eax
movl %eax, 0x1028(%rbx)
incl 0x18(%rbx)
jmp 0x35ed
cmpl %r12d, 0x24(%rsp)
cmoveq %rsi, %rdi
cmpl %r12d, 0x4(%rsp)
cmoveq %rdx, %rdi
cmpl %r12d, 0x28(%rsp)
movq 0x20(%rbx), %rdx
cmoveq %rcx, %rdi
movl (%rdx,%rdi,4), %ecx
addl %r15d, %eax
cltq
movl %ecx, (%rdx,%rax,4)
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x3284
xorl %edx, %edx
movslq %edx, %rsi
movq 0x28(%rbx,%rsi,8), %r13
cmpl %ecx, (%r13)
je 0x3287
incl %edx
cmpl %edx, %eax
jne 0x3270
xorl %r13d, %r13d
movq %r13, %rdi
movl 0x8(%rsp), %r14d
movl %r14d, %esi
callq 0x585c
movq %r13, %rdi
movl %r14d, %esi
callq 0x586c
movq %r13, %rdi
movl %eax, %esi
callq 0x58a4
movq %rbx, %rdi
movq %r13, %rsi
movl %r15d, %edx
jmp 0x35e6
xorl %r13d, %r13d
movq 0x20(%rbx), %r8
movl $0x0, %r9d
cmpl %r12d, 0x28(%rsp)
jne 0x32d2
movl (%r8,%rcx,4), %r9d
movl $0x0, %r10d
cmpl %r12d, 0x4(%rsp)
jne 0x32e3
movl (%r8,%rdx,4), %r10d
movl $0x0, %r11d
cmpl %r12d, 0x24(%rsp)
jne 0x32f4
movl (%r8,%rsi,4), %r11d
movl $0x0, %edx
cmpl %r12d, 0x2c(%rsp)
jne 0x3304
movl (%r8,%rdi,4), %edx
testl %r9d, %r9d
movl %edx, 0x14(%rsp)
movl %r9d, 0x18(%rsp)
movl %r10d, 0x10(%rsp)
movl %r11d, 0xc(%rsp)
je 0x3390
addl %r15d, %eax
cltq
movl %r9d, (%r8,%rax,4)
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x3345
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %r13
cmpl %r9d, (%r13)
je 0x3348
incl %ecx
cmpl %ecx, %eax
jne 0x3331
xorl %r13d, %r13d
movq %r13, %rdi
movl 0x8(%rsp), %r14d
movl %r14d, %esi
callq 0x585c
movq %r13, %rdi
movl %r14d, %esi
callq 0x586c
movq %r13, %rdi
movl %eax, %esi
callq 0x58a4
movq %rbx, %rdi
movq %r13, %rsi
movl %r15d, %edx
movl %ebp, %ecx
callq 0x388a
movl 0xc(%rsp), %r11d
movl 0x10(%rsp), %r10d
movl 0x14(%rsp), %edx
movb $0x1, %r14b
jmp 0x3393
xorl %r14d, %r14d
testl %r10d, %r10d
je 0x33d3
testb %r14b, %r14b
je 0x33dc
movl 0x18(%rsp), %eax
cmpl %eax, %r10d
je 0x346b
movq %rbx, %rdi
movq %r13, %rsi
movl %r10d, %edx
movl 0x8(%rsp), %ecx
callq 0x39c0
movl 0xc(%rsp), %r11d
movl 0x10(%rsp), %r10d
movl 0x18(%rsp), %eax
movl 0x14(%rsp), %edx
jmp 0x346b
movl 0x18(%rsp), %eax
jmp 0x346b
movq 0x20(%rbx), %rax
movl 0x8da6(%rip), %ecx      # 0xc18c
imull %ebp, %ecx
addl %r15d, %ecx
movslq %ecx, %rcx
movl %r10d, (%rax,%rcx,4)
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x3413
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %rbp
cmpl %r10d, (%rbp)
je 0x3416
incl %ecx
cmpl %ecx, %eax
jne 0x33ff
movq %r13, %rbp
movq %rbp, %rdi
movl 0x8(%rsp), %r14d
movl %r14d, %esi
callq 0x585c
movq %rbp, %rdi
movl %r14d, %esi
callq 0x586c
movq %rbp, %rdi
movl %eax, %esi
callq 0x58a4
movq %rbx, %rdi
movq %rbp, %rsi
movl %r15d, %edx
movq 0x30(%rsp), %rcx
callq 0x388a
movl 0xc(%rsp), %r11d
movl 0x10(%rsp), %r10d
movl 0x18(%rsp), %eax
movl 0x14(%rsp), %edx
movb $0x1, %r14b
movq %rbp, %r13
movq 0x30(%rsp), %rbp
testl %r11d, %r11d
je 0x3543
testb %r14b, %r14b
je 0x34b4
cmpl %eax, %r11d
je 0x3543
cmpl %r10d, %r11d
je 0x3543
movq %rbx, %rdi
movq %r13, %rsi
movl %r11d, %edx
movl 0x8(%rsp), %ecx
callq 0x39c0
movl 0xc(%rsp), %r11d
movl 0x10(%rsp), %r10d
movl 0x18(%rsp), %eax
movl 0x14(%rsp), %edx
jmp 0x3543
movq 0x20(%rbx), %rax
movl 0x8cce(%rip), %ecx      # 0xc18c
imull %ebp, %ecx
addl %r15d, %ecx
movslq %ecx, %rcx
movl %r11d, (%rax,%rcx,4)
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x34eb
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %rbp
cmpl %r11d, (%rbp)
je 0x34ee
incl %ecx
cmpl %ecx, %eax
jne 0x34d7
movq %r13, %rbp
movq %rbp, %rdi
movl 0x8(%rsp), %r14d
movl %r14d, %esi
callq 0x585c
movq %rbp, %rdi
movl %r14d, %esi
callq 0x586c
movq %rbp, %rdi
movl %eax, %esi
callq 0x58a4
movq %rbx, %rdi
movq %rbp, %rsi
movl %r15d, %edx
movq 0x30(%rsp), %rcx
callq 0x388a
movl 0xc(%rsp), %r11d
movl 0x10(%rsp), %r10d
movl 0x18(%rsp), %eax
movl 0x14(%rsp), %edx
movb $0x1, %r14b
movq %rbp, %r13
movq 0x30(%rsp), %rbp
testl %edx, %edx
je 0x35ed
testb %r14b, %r14b
je 0x357b
cmpl %eax, %edx
je 0x35ed
cmpl %r10d, %edx
je 0x35ed
cmpl %r11d, %edx
je 0x35ed
movq %rbx, %rdi
movq %r13, %rsi
movl 0x8(%rsp), %ecx
callq 0x39c0
jmp 0x35ed
movq 0x20(%rbx), %rax
movl 0x8c07(%rip), %ecx      # 0xc18c
imull %ebp, %ecx
addl %r15d, %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x35b0
xorl %ecx, %ecx
movslq %ecx, %rsi
movq 0x28(%rbx,%rsi,8), %rbp
cmpl %edx, (%rbp)
je 0x35b3
incl %ecx
cmpl %ecx, %eax
jne 0x359d
movq %r13, %rbp
movq %rbp, %rdi
movl 0x8(%rsp), %r14d
movl %r14d, %esi
callq 0x585c
movq %rbp, %rdi
movl %r14d, %esi
callq 0x586c
movq %rbp, %rdi
movl %eax, %esi
callq 0x58a4
movq %rbx, %rdi
movq %rbp, %rsi
movl %r15d, %edx
movq 0x30(%rsp), %rbp
movl %ebp, %ecx
callq 0x388a
movq %r15, 0x18(%rsp)
movl $0x3, %edx
subl %r12d, %edx
movl 0x8b8c(%rip), %eax      # 0xc18c
movl %eax, %esi
imull %ebp, %esi
xorl %r13d, %r13d
movq 0x20(%rbx), %rcx
movl $0x0, %r15d
cmpl %edx, 0x28(%rsp)
jne 0x3625
movl 0x38(%rsp), %edi
addl %esi, %edi
movslq %edi, %rdi
movl (%rcx,%rdi,4), %r15d
movl $0x0, %ebp
cmpl %edx, 0x4(%rsp)
jne 0x363a
addl 0x3c(%rsp), %esi
movslq %esi, %rsi
movl (%rcx,%rsi,4), %ebp
movl $0x0, %r14d
cmpl %edx, 0x24(%rsp)
jne 0x3658
movl 0x40(%rsp), %esi
imull %eax, %esi
addl 0x18(%rsp), %esi
movslq %esi, %rsi
movl (%rcx,%rsi,4), %r14d
cmpl %edx, 0x2c(%rsp)
jne 0x366d
imull 0x44(%rsp), %eax
addl 0x18(%rsp), %eax
cltq
movl (%rcx,%rax,4), %r13d
testl %r15d, %r15d
je 0x36d0
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x3692
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %r12
cmpl %r15d, (%r12)
je 0x369f
incl %ecx
cmpl %ecx, %eax
jne 0x367e
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r12d, %r12d
jmp 0x36a3
movl %ecx, 0x4(%rsp)
movq %r12, %rdi
movl 0x8(%rsp), %esi
callq 0x586c
movq %r12, %rdi
movl %eax, %esi
callq 0x58a4
cmpl $0x0, 0xc(%r12)
jne 0x36d0
movq %rbx, %rdi
movq %r12, %rsi
movl 0x4(%rsp), %edx
callq 0x3ada
testl %ebp, %ebp
je 0x3737
cmpl %r15d, %ebp
je 0x3737
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x36f9
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %r12
cmpl %ebp, (%r12)
je 0x3706
incl %ecx
cmpl %ecx, %eax
jne 0x36e5
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r12d, %r12d
jmp 0x370a
movl %ecx, 0x4(%rsp)
movq %r12, %rdi
movl 0x8(%rsp), %esi
callq 0x586c
movq %r12, %rdi
movl %eax, %esi
callq 0x58a4
cmpl $0x0, 0xc(%r12)
jne 0x3737
movq %rbx, %rdi
movq %r12, %rsi
movl 0x4(%rsp), %edx
callq 0x3ada
testl %r14d, %r14d
je 0x37a4
cmpl %r15d, %r14d
je 0x37a4
cmpl %ebp, %r14d
je 0x37a4
movl 0x1028(%rbx), %eax
testl %eax, %eax
je 0x3766
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %r12
cmpl %r14d, (%r12)
je 0x3773
incl %ecx
cmpl %ecx, %eax
jne 0x3752
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r12d, %r12d
jmp 0x3777
movl %ecx, 0x4(%rsp)
movq %r12, %rdi
movl 0x8(%rsp), %esi
callq 0x586c
movq %r12, %rdi
movl %eax, %esi
callq 0x58a4
cmpl $0x0, 0xc(%r12)
jne 0x37a4
movq %rbx, %rdi
movq %r12, %rsi
movl 0x4(%rsp), %edx
callq 0x3ada
testl %r13d, %r13d
je 0x380f
cmpl %r15d, %r13d
je 0x380f
cmpl %ebp, %r13d
je 0x380f
cmpl %r14d, %r13d
je 0x380f
movl 0x1028(%rbx), %eax
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
testl %eax, %eax
je 0x37dd
xorl %ecx, %ecx
movslq %ecx, %rdx
movq 0x28(%rbx,%rdx,8), %r12
cmpl %r13d, (%r12)
je 0x37e2
incl %ecx
cmpl %ecx, %eax
jne 0x37c9
xorl %r12d, %r12d
jmp 0x37e4
movl %ecx, %ebp
movq %r12, %rdi
movl 0x8(%rsp), %esi
callq 0x586c
movq %r12, %rdi
movl %eax, %esi
callq 0x58a4
cmpl $0x0, 0xc(%r12)
jne 0x380f
movq %rbx, %rdi
movq %r12, %rsi
movl %ebp, %edx
callq 0x3ada
movq 0x30(%rsp), %rax
imull 0x8971(%rip), %eax      # 0xc18c
addl 0x18(%rsp), %eax
cltq
movq 0x20(%rbx), %rcx
movq 0x28(%rbx), %rsi
movl (%rcx,%rax,4), %eax
xorl %edx, %edx
cmpl %eax, (%rsi)
je 0x3847
movl $0x1, %edx
movslq %edx, %rdx
movq 0x28(%rbx,%rdx,8), %rsi
incl %edx
cmpl %eax, (%rsi)
jne 0x3837
decl %edx
cmpl $0x0, 0xc(%rsi)
je 0x385c
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3ada
movq %rax, %rbx
movl $0x610, %esi            # imm = 0x610
movq %r13, %rdi
callq 0x21c0
movq %rbx, %rdi
callq 0x22c0