// File: NathanWine[P]2048-AI-Solvers/src/MonteCarlo.cpp
// Function: monteCarloSimulateGame(int, int, Game)
std::pair<int, int> monteCarloSimulateGame(int runs, int display_level, Game game) {
    std::cout << "Attempting to solve a new game with Monte Carlo... " << std::flush;
    while (game.canContinue()) {
        if (display_level >= 2) {
            std::cout << std::endl << game;
        }
        int scores[4] = {0, 0, 0, 0};
        int counter[4] = {0, 0, 0, 0};

        for (int i = 0; i < runs; ++i) {
            std::pair<int, int> res = simulateOneRun(game);
            scores[res.first] += res.second;
            counter[res.first] += 1;
        }

        int best_avg_score = 0;
        int best_move = UP;
        for (int i = 0; i < 4; ++i) {
            int move = i;
            if (counter[move] != 0 && ((float) scores[move] / counter[move]) > best_avg_score) {
                best_avg_score = (float) scores[move] / counter[move];
                best_move = move;
            }
        }

        switch(best_move) {
            case UP:
                game.up(false);
                break;
            case DOWN:
                game.down(false);
                break;
            case LEFT:
                game.left(false);
                break;
            case RIGHT:
                game.right(false);
                break;
        }
    }
    if (display_level <= 1) {
        std::cout << "Done!" << (display_level == 0 ? "\n" : "");
    }
    if (display_level >= 1) {
        std::cout << std::endl << game << std::endl;
    }
    std::pair<int, int> ret(game.getHighestTile(), game.score);
    return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdx, -0x98(%rbp)
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq 0x1f425(%rip), %rdi     # 0x22fc8
leaq 0x1447a(%rip), %rsi     # 0x18024
callq 0x3260
movq %rax, %rdi
movq 0x1f417(%rip), %rsi     # 0x22fd0
callq 0x32a0
movq -0x98(%rbp), %rdi
callq 0xf4f0
testb $0x1, %al
jne 0x3bd3
jmp 0x3dcf
cmpl $0x2, -0x10(%rbp)
jl 0x3bfb
movq 0x1f3e8(%rip), %rdi     # 0x22fc8
movq 0x1f3c9(%rip), %rsi     # 0x22fb0
callq 0x32a0
movq -0x98(%rbp), %rsi
movq %rax, %rdi
callq 0x10f60
leaq -0x30(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x3110
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x3110
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0xc(%rbp), %eax
jge 0x3cb1
movq -0x98(%rbp), %rsi
leaq -0x70(%rbp), %rdi
movq %rdi, -0xa8(%rbp)
callq 0x3f70
movq -0xa8(%rbp), %rdi
callq 0x38b0
movq %rax, -0xa0(%rbp)
jmp 0x3c5a
movq -0xa0(%rbp), %rax
movq %rax, -0x4c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4460
movl -0x48(%rbp), %ecx
movslq -0x4c(%rbp), %rax
addl -0x30(%rbp,%rax,4), %ecx
movl %ecx, -0x30(%rbp,%rax,4)
movslq -0x4c(%rbp), %rax
movl -0x40(%rbp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, -0x40(%rbp,%rax,4)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x3c22
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4460
jmp 0x3e75
movl $0x0, -0x80(%rbp)
movl $0x0, -0x84(%rbp)
movl $0x0, -0x88(%rbp)
cmpl $0x4, -0x88(%rbp)
jge 0x3d62
movl -0x88(%rbp), %eax
movl %eax, -0x8c(%rbp)
movslq -0x8c(%rbp), %rax
cmpl $0x0, -0x40(%rbp,%rax,4)
je 0x3d4c
movslq -0x8c(%rbp), %rax
cvtsi2ssl -0x30(%rbp,%rax,4), %xmm0
movslq -0x8c(%rbp), %rax
cvtsi2ssl -0x40(%rbp,%rax,4), %xmm1
divss %xmm1, %xmm0
cvtsi2ssl -0x80(%rbp), %xmm1
ucomiss %xmm1, %xmm0
jbe 0x3d4c
movslq -0x8c(%rbp), %rax
cvtsi2ssl -0x30(%rbp,%rax,4), %xmm0
movslq -0x8c(%rbp), %rax
cvtsi2ssl -0x40(%rbp,%rax,4), %xmm1
divss %xmm1, %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x80(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, -0x84(%rbp)
jmp 0x3d4e
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x3ccc
movl -0x84(%rbp), %eax
movq %rax, -0xb0(%rbp)
subq $0x3, %rax
ja 0x3dca
movq -0xb0(%rbp), %rax
leaq 0x14291(%rip), %rcx     # 0x18014
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x98(%rbp), %rdi
xorl %esi, %esi
callq 0xfa10
jmp 0x3dca
movq -0x98(%rbp), %rdi
xorl %esi, %esi
callq 0xfac0
jmp 0x3dca
movq -0x98(%rbp), %rdi
xorl %esi, %esi
callq 0xfb10
jmp 0x3dca
movq -0x98(%rbp), %rdi
xorl %esi, %esi
callq 0xfb60
jmp 0x3bbe
cmpl $0x1, -0x10(%rbp)
jg 0x3e08
movq 0x1f1ec(%rip), %rdi     # 0x22fc8
leaq 0x14275(%rip), %rsi     # 0x18058
callq 0x3260
movq %rax, %rdi
movl -0x10(%rbp), %ecx
leaq 0x1426a(%rip), %rsi     # 0x1805f
leaq 0x14262(%rip), %rax     # 0x1805e
cmpl $0x0, %ecx
cmoveq %rax, %rsi
callq 0x3260
cmpl $0x1, -0x10(%rbp)
jl 0x3e3f
movq 0x1f1b3(%rip), %rdi     # 0x22fc8
movq 0x1f194(%rip), %rsi     # 0x22fb0
callq 0x32a0
movq -0x98(%rbp), %rsi
movq %rax, %rdi
callq 0x10f60
movq %rax, %rdi
movq 0x1f176(%rip), %rsi     # 0x22fb0
callq 0x32a0
movq -0x98(%rbp), %rdi
callq 0x10e40
movq -0x98(%rbp), %rdx
movl %eax, -0x90(%rbp)
leaq -0x8(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x4480
movq -0x8(%rbp), %rax
addq $0xb0, %rsp
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x33d0
nop