// File: Leeingnyo[P]newPuyoC/./board.h
// Function: Board::ChainingUpdate()
void ChainingUpdate() {
        bool chaining = false;
        static std::vector<std::vector<Pair>> chain_list;
        static std::vector<Pair> removed_obstacles;
        static const int CHAIN_BONUS[] = {0, 8, 16, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480, 512};
        static const int MAX_REMOVE_BONUS[] = {0, 2, 3, 4, 5, 6, 7};
        // FIXME: move this to static member variables (without cpp file, I want)
        // but it caused link error
        
        if (chaining_t > CHAINING_FRAME) {
            int removed_puyo_number = 0;
            int max_removed_bonus = 0;
            for (auto &chain : chain_list) {
                int chain_size = chain.size();
                removed_puyo_number += chain_size;
                max_removed_bonus += chain_size < 4 ? 0 : chain_size > 10 ? 10 : MAX_REMOVE_BONUS[chain_size - 4];
                // FIXME: I want to this logic to function 
                for (auto &pair : chain) {
                    map[pair.y][pair.x] = Puyo();
                }
            }
            // http://kayezero.blogspot.kr/2009/08/blog-post_8347.html 점수 계산법
            int gained_score = removed_puyo_number * (CHAIN_BONUS[chain_number - 1] + max_removed_bonus/* + 12*/ + 1);
            gain_score += gained_score;
            obstacle_number_to_send += std::ceil(gained_score / 7.0);
            while (obstacle_number_taken > 0 && obstacle_number_to_send > 0) {
                obstacle_number_taken -= 1;
                obstacle_number_to_send -= 1;
            }
            // TODO: 에잇 받아라 아이스스톰 등 effect 발행
            for (auto &pair : removed_obstacles) {
                map[pair.y][pair.x] = Puyo();
            }
            chain_list.clear();
            removed_obstacles.clear();
            chaining_t = 0;
            state = State::DROP;
            return;
        }
        else if (chaining_t > CHAINING_FRAME * 2 / 3) {
            chaining_t++;
            return;
        }
        else if (chaining_t > 0) {
            Puyo effect = Puyo(chaining_t / 4 % 2 ? PuyoKind::EXPLOSION : PuyoKind::BLANK);
            for (auto &chain : chain_list) {
                for (auto &pair : chain) {
                    map[pair.y][pair.x] = effect;
                }
            }
            for (auto &pair : removed_obstacles) {
                map[pair.y][pair.x] = effect;
            }
            chaining_t++;
            return;
        }
        
        // 맵 끝에서 끝까지 
        bool check[MAP_HEIGHT][MAP_WIDTH] = { false, };
        for (int y = 0; y < MAP_HEIGHT; y++) {
            for (int x = 0; x < MAP_WIDTH; x++) {
                if (map[y][x].IsBlank()) continue;
                if (map[y][x].IsObstacle()) continue;
                
                std::vector<Pair> chain;
                std::vector<Pair> nearby_obstacles;
                Chaining(check, chain, nearby_obstacles, x, y);
                if (chain.size() >= 4) { // FIXME make 4 constant. extract it
                    chaining = true;
                    chain_list.push_back(chain);
                    removed_obstacles.insert(removed_obstacles.end(), nearby_obstacles.begin(), nearby_obstacles.end());
                }
                else {
                    for (auto& obstacles : nearby_obstacles) {
                        check[obstacles.y][obstacles.x] = false;
                    }
                }
            }
        }
        
        if (chaining) {
            chaining_t = 1;
            chain_number++;
        }
        else {
            chain_number = 0;
            if (map[1][2].IsBlank()) state = State::DROP_OBSTACLE;
            else state = State::GAMEOVER;
        }
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movb $0x0, -0x9(%rbp)
cmpb $0x0, 0x1c7d3(%rip)     # 0x28338
jne 0xbbaa
leaq 0x1c7ca(%rip), %rdi     # 0x28338
callq 0x4510
cmpl $0x0, %eax
je 0xbbaa
leaq 0x1c7a1(%rip), %rdi     # 0x28320
callq 0xcad0
leaq 0xf65(%rip), %rdi       # 0xcaf0
leaq 0x1c78e(%rip), %rsi     # 0x28320
leaq 0x1c71f(%rip), %rdx     # 0x282b8
callq 0x4270
leaq 0x1c793(%rip), %rdi     # 0x28338
callq 0x4200
cmpb $0x0, 0x1c7a7(%rip)     # 0x28358
jne 0xbbf6
leaq 0x1c79e(%rip), %rdi     # 0x28358
callq 0x4510
cmpl $0x0, %eax
je 0xbbf6
leaq 0x1c775(%rip), %rdi     # 0x28340
callq 0xcb50
leaq 0xf99(%rip), %rdi       # 0xcb70
leaq 0x1c762(%rip), %rsi     # 0x28340
leaq 0x1c6d3(%rip), %rdx     # 0x282b8
callq 0x4270
leaq 0x1c767(%rip), %rdi     # 0x28358
callq 0x4200
movq -0x1d8(%rbp), %rcx
movl 0xb0(%rcx), %eax
cmpl 0xac(%rcx), %eax
jle 0xbed5
movl $0x0, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
leaq 0x1c6fc(%rip), %rax     # 0x28320
movq %rax, -0x20(%rbp)
leaq 0x1c6f1(%rip), %rdi     # 0x28320
callq 0xcbd0
movq %rax, -0x28(%rbp)
leaq 0x1c6e1(%rip), %rdi     # 0x28320
callq 0xcc00
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xcc30
testb $0x1, %al
jne 0xbc5e
jmp 0xbd5d
leaq -0x28(%rbp), %rdi
callq 0xcc70
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0xcc90
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
cmpl $0x4, -0x3c(%rbp)
jge 0xbc90
xorl %eax, %eax
movl %eax, -0x1dc(%rbp)
jmp 0xbcc8
cmpl $0xa, -0x3c(%rbp)
jle 0xbca3
movl $0xa, %eax
movl %eax, -0x1e0(%rbp)
jmp 0xbcbc
movl -0x3c(%rbp), %eax
subl $0x4, %eax
movslq %eax, %rcx
leaq 0xeb3d(%rip), %rax      # 0x1a7f0
movl (%rax,%rcx,4), %eax
movl %eax, -0x1e0(%rbp)
movl -0x1e0(%rbp), %eax
movl %eax, -0x1dc(%rbp)
movl -0x1dc(%rbp), %eax
addl -0x14(%rbp), %eax
movl %eax, -0x14(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
callq 0xccb0
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rdi
callq 0xcce0
movq %rax, -0x58(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0xcd10
testb $0x1, %al
jne 0xbd09
jmp 0xbd4d
leaq -0x50(%rbp), %rdi
callq 0xcd50
movq %rax, -0x60(%rbp)
leaq -0x61(%rbp), %rdi
callq 0xcab0
movq -0x1d8(%rbp), %rax
movq -0x60(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x6, %rcx, %rcx
addq %rcx, %rax
movq -0x60(%rbp), %rcx
movslq (%rcx), %rcx
movb -0x61(%rbp), %dl
movb %dl, (%rax,%rcx)
leaq -0x50(%rbp), %rdi
callq 0xcd70
jmp 0xbcf6
jmp 0xbd4f
leaq -0x28(%rbp), %rdi
callq 0xcd90
jmp 0xbc48
movq -0x1d8(%rbp), %rax
movl -0x10(%rbp), %ecx
movl 0x70(%rax), %edx
subl $0x1, %edx
movslq %edx, %rsi
leaq 0xea29(%rip), %rdx      # 0x1a7a0
movl (%rdx,%rsi,4), %edx
addl -0x14(%rbp), %edx
addl $0x1, %edx
imull %edx, %ecx
movl %ecx, -0x68(%rbp)
movl -0x68(%rbp), %ecx
addl 0x6c(%rax), %ecx
movl %ecx, 0x6c(%rax)
cvtsi2sdl -0x68(%rbp), %xmm0
movsd 0xe33c(%rip), %xmm1     # 0x1a0d8
divsd %xmm1, %xmm0
callq 0x4080
movq -0x1d8(%rbp), %rax
movaps %xmm0, %xmm1
cvtsi2sdl 0x78(%rax), %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x78(%rax)
movq -0x1d8(%rbp), %rcx
xorl %eax, %eax
cmpl $0x0, 0x74(%rcx)
movb %al, -0x1e1(%rbp)
jle 0xbde8
movq -0x1d8(%rbp), %rax
cmpl $0x0, 0x78(%rax)
setg %al
movb %al, -0x1e1(%rbp)
movb -0x1e1(%rbp), %al
testb $0x1, %al
jne 0xbdf4
jmp 0xbe0f
movq -0x1d8(%rbp), %rax
movl 0x74(%rax), %ecx
subl $0x1, %ecx
movl %ecx, 0x74(%rax)
movl 0x78(%rax), %ecx
subl $0x1, %ecx
movl %ecx, 0x78(%rax)
jmp 0xbdbf
leaq 0x1c52a(%rip), %rax     # 0x28340
movq %rax, -0x70(%rbp)
leaq 0x1c51f(%rip), %rdi     # 0x28340
callq 0xccb0
movq %rax, -0x78(%rbp)
leaq 0x1c50f(%rip), %rdi     # 0x28340
callq 0xcce0
movq %rax, -0x80(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0xcd10
testb $0x1, %al
jne 0xbe4d
jmp 0xbea0
leaq -0x78(%rbp), %rdi
callq 0xcd50
movq %rax, -0x88(%rbp)
leaq -0x89(%rbp), %rdi
callq 0xcab0
movq -0x1d8(%rbp), %rax
movq -0x88(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x6, %rcx, %rcx
addq %rcx, %rax
movq -0x88(%rbp), %rcx
movslq (%rcx), %rcx
movb -0x89(%rbp), %dl
movb %dl, (%rax,%rcx)
leaq -0x78(%rbp), %rdi
callq 0xcd70
jmp 0xbe3a
leaq 0x1c479(%rip), %rdi     # 0x28320
callq 0xcdb0
leaq 0x1c48d(%rip), %rdi     # 0x28340
callq 0xcdd0
movq -0x1d8(%rbp), %rax
movl $0x0, 0xb0(%rax)
movl $0x1, 0x68(%rax)
jmp 0xc47c
movq -0x1d8(%rbp), %rax
movl 0xb0(%rax), %ecx
movl %ecx, -0x1e8(%rbp)
movl 0xac(%rax), %eax
shll %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x1e8(%rbp), %eax
cmpl %ecx, %eax
jle 0xbf1f
movq -0x1d8(%rbp), %rax
movl 0xb0(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xb0(%rax)
jmp 0xc47c
movq -0x1d8(%rbp), %rax
cmpl $0x0, 0xb0(%rax)
jle 0xc151
movq -0x1d8(%rbp), %rax
movl 0xb0(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl $0x2, %ecx
cltd
idivl %ecx
movb $0x6, %al
xorl %ecx, %ecx
movb %cl, -0x1ea(%rbp)
cmpl $0x0, %edx
movb %al, -0x1e9(%rbp)
jne 0xbf71
movb -0x1ea(%rbp), %al
movb %al, -0x1e9(%rbp)
movb -0x1e9(%rbp), %al
leaq -0x8a(%rbp), %rdi
movsbl %al, %esi
callq 0xb560
leaq 0x1c393(%rip), %rax     # 0x28320
movq %rax, -0x98(%rbp)
leaq 0x1c385(%rip), %rdi     # 0x28320
callq 0xcbd0
movq %rax, -0xa0(%rbp)
leaq 0x1c372(%rip), %rdi     # 0x28320
callq 0xcc00
movq %rax, -0xa8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0xcc30
testb $0x1, %al
jne 0xbfd6
jmp 0xc099
leaq -0xa0(%rbp), %rdi
callq 0xcc70
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
callq 0xccb0
movq %rax, -0xc0(%rbp)
movq -0xb8(%rbp), %rdi
callq 0xcce0
movq %rax, -0xc8(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0xcd10
testb $0x1, %al
jne 0xc036
jmp 0xc086
leaq -0xc0(%rbp), %rdi
callq 0xcd50
movq %rax, %rcx
movq -0x1d8(%rbp), %rax
movq %rcx, -0xd0(%rbp)
movq -0xd0(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x6, %rcx, %rcx
addq %rcx, %rax
movq -0xd0(%rbp), %rcx
movslq (%rcx), %rcx
movb -0x8a(%rbp), %dl
movb %dl, (%rax,%rcx)
leaq -0xc0(%rbp), %rdi
callq 0xcd70
jmp 0xc01d
jmp 0xc088
leaq -0xa0(%rbp), %rdi
callq 0xcd90
jmp 0xbfba
leaq 0x1c2a0(%rip), %rax     # 0x28340
movq %rax, -0xd8(%rbp)
leaq 0x1c292(%rip), %rdi     # 0x28340
callq 0xccb0
movq %rax, -0xe0(%rbp)
leaq 0x1c27f(%rip), %rdi     # 0x28340
callq 0xcce0
movq %rax, -0xe8(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0xcd10
testb $0x1, %al
jne 0xc0e6
jmp 0xc136
leaq -0xe0(%rbp), %rdi
callq 0xcd50
movq %rax, %rcx
movq -0x1d8(%rbp), %rax
movq %rcx, -0xf0(%rbp)
movq -0xf0(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x6, %rcx, %rcx
addq %rcx, %rax
movq -0xf0(%rbp), %rcx
movslq (%rcx), %rcx
movb -0x8a(%rbp), %dl
movb %dl, (%rax,%rcx)
leaq -0xe0(%rbp), %rdi
callq 0xcd70
jmp 0xc0cd
movq -0x1d8(%rbp), %rax
movl 0xb0(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xb0(%rax)
jmp 0xc47c
jmp 0xc153
jmp 0xc155
leaq -0x140(%rbp), %rdi
xorl %esi, %esi
movl $0x4e, %edx
callq 0x41b0
movl $0x0, -0x144(%rbp)
cmpl $0xd, -0x144(%rbp)
jge 0xc419
movl $0x0, -0x148(%rbp)
cmpl $0x6, -0x148(%rbp)
jge 0xc403
movq -0x1d8(%rbp), %rdi
movslq -0x144(%rbp), %rax
imulq $0x6, %rax, %rax
addq %rax, %rdi
movslq -0x148(%rbp), %rax
addq %rax, %rdi
callq 0xb7a0
testb $0x1, %al
jne 0xc1c0
jmp 0xc1c5
jmp 0xc3ef
movq -0x1d8(%rbp), %rdi
movslq -0x144(%rbp), %rax
imulq $0x6, %rax, %rax
addq %rax, %rdi
movslq -0x148(%rbp), %rax
addq %rax, %rdi
callq 0xcdf0
testb $0x1, %al
jne 0xc1ef
jmp 0xc1f4
jmp 0xc3ef
leaq -0x160(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0xcb50
leaq -0x178(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0xcb50
movq -0x1d8(%rbp), %rdi
movq -0x200(%rbp), %rdx
movq -0x1f8(%rbp), %rcx
movl -0x148(%rbp), %r8d
movl -0x144(%rbp), %r9d
leaq -0x140(%rbp), %rsi
callq 0xce10
jmp 0xc24b
leaq -0x160(%rbp), %rdi
callq 0xcc90
cmpq $0x4, %rax
jb 0xc340
movb $0x1, -0x9(%rbp)
leaq 0x1c0b4(%rip), %rdi     # 0x28320
leaq -0x160(%rbp), %rsi
callq 0xd100
jmp 0xc27a
leaq 0x1c0bf(%rip), %rdi     # 0x28340
movq %rdi, -0x210(%rbp)
callq 0xcce0
movq %rax, -0x198(%rbp)
leaq -0x190(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0xd220
leaq -0x178(%rbp), %rdi
movq %rdi, -0x218(%rbp)
callq 0xccb0
movq -0x218(%rbp), %rdi
movq %rax, -0x1a0(%rbp)
callq 0xcce0
movq -0x210(%rbp), %rdi
movq %rax, -0x1a8(%rbp)
movq -0x190(%rbp), %rsi
movq -0x1a0(%rbp), %rdx
movq -0x1a8(%rbp), %rcx
callq 0xd170
movq %rax, -0x208(%rbp)
jmp 0xc2fe
movq -0x208(%rbp), %rax
movq %rax, -0x1b0(%rbp)
jmp 0xc3d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x180(%rbp)
movl %eax, -0x184(%rbp)
leaq -0x178(%rbp), %rdi
callq 0xcb70
leaq -0x160(%rbp), %rdi
callq 0xcb70
jmp 0xc485
leaq -0x178(%rbp), %rax
movq %rax, -0x1b8(%rbp)
movq -0x1b8(%rbp), %rdi
callq 0xccb0
movq %rax, -0x1c0(%rbp)
movq -0x1b8(%rbp), %rdi
callq 0xcce0
movq %rax, -0x1c8(%rbp)
leaq -0x1c0(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0xcd10
testb $0x1, %al
jne 0xc38d
jmp 0xc3d5
leaq -0x1c0(%rbp), %rdi
callq 0xcd50
movq %rax, -0x1d0(%rbp)
movq -0x1d0(%rbp), %rax
movslq 0x4(%rax), %rcx
leaq -0x140(%rbp), %rax
imulq $0x6, %rcx, %rcx
addq %rcx, %rax
movq -0x1d0(%rbp), %rcx
movslq (%rcx), %rcx
movb $0x0, (%rax,%rcx)
leaq -0x1c0(%rbp), %rdi
callq 0xcd70
jmp 0xc374
jmp 0xc3d7
leaq -0x178(%rbp), %rdi
callq 0xcb70
leaq -0x160(%rbp), %rdi
callq 0xcb70
movl -0x148(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x148(%rbp)
jmp 0xc189
jmp 0xc405
movl -0x144(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x144(%rbp)
jmp 0xc172
testb $0x1, -0x9(%rbp)
je 0xc43b
movq -0x1d8(%rbp), %rax
movl $0x1, 0xb0(%rax)
movl 0x70(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x70(%rax)
jmp 0xc47c
movq -0x1d8(%rbp), %rdi
movl $0x0, 0x70(%rdi)
addq $0x6, %rdi
addq $0x2, %rdi
callq 0xb7a0
testb $0x1, %al
jne 0xc45c
jmp 0xc46c
movq -0x1d8(%rbp), %rax
movl $0x3, 0x68(%rax)
jmp 0xc47a
movq -0x1d8(%rbp), %rax
movl $0x6, 0x68(%rax)
jmp 0xc47c
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
movq -0x180(%rbp), %rdi
callq 0x44f0
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)