// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %rbx
movl %esi, %ebp
movl %edi, 0xc(%rsp)
movq 0xa643(%rip), %r14      # 0xcfd8
leaq 0x66e4(%rip), %rsi      # 0x9080
movl $0x33, %edx
movq %r14, %rdi
callq 0x21e0
movq %r14, %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x61ca
testb %al, %al
je 0x2af8
leaq 0x40(%rsp), %r12
leaq 0x8(%rbx), %r13
movl %ebp, 0x8(%rsp)
cmpl $0x2, %ebp
jl 0x2a0c
movq 0xa5fe(%rip), %r14      # 0xcfd8
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2180
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2110
movq %rax, %rdi
movq %rbx, %rsi
callq 0x70ca
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0x10(%rsp)
movl 0xc(%rsp), %eax
movl %eax, %r15d
testl %eax, %eax
jle 0x2a62
movl (%rbx), %eax
movl %eax, 0x38(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x2cc2
leaq 0x38(%rsp), %rdi
callq 0x277c
movq %rax, %rbp
movq %rax, %r14
shrq $0x20, %r14
movq %r12, %rdi
callq 0x2da2
movslq %ebp, %rax
addl %r14d, 0x20(%rsp,%rax,4)
incl 0x10(%rsp,%rax,4)
decl %r15d
jne 0x2a24
xorl %eax, %eax
xorl %ecx, %ecx
xorl %edx, %edx
movl 0x10(%rsp,%rax,4), %esi
testl %esi, %esi
je 0x2a96
xorps %xmm0, %xmm0
cvtsi2ssl 0x20(%rsp,%rax,4), %xmm0
xorps %xmm1, %xmm1
cvtsi2ss %esi, %xmm1
xorps %xmm2, %xmm2
cvtsi2ss %edx, %xmm2
divss %xmm1, %xmm0
ucomiss %xmm2, %xmm0
jbe 0x2a96
cvttss2si %xmm0, %edx
movl %eax, %ecx
incq %rax
cmpq $0x4, %rax
jne 0x2a68
cmpl $0x3, %ecx
movl 0x8(%rsp), %ebp
ja 0x2ae8
movl %ecx, %eax
leaq 0x65bf(%rip), %rcx      # 0x9070
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
xorl %esi, %esi
callq 0x6542
jmp 0x2ae8
movq %rbx, %rdi
xorl %esi, %esi
callq 0x65ea
jmp 0x2ae8
movq %rbx, %rdi
xorl %esi, %esi
callq 0x6612
jmp 0x2ae8
movq %rbx, %rdi
xorl %esi, %esi
callq 0x65c2
movq %rbx, %rdi
callq 0x61ca
testb %al, %al
jne 0x29ce
cmpl $0x1, %ebp
jg 0x2b3e
movq 0xa4d4(%rip), %r14      # 0xcfd8
leaq 0x65a9(%rip), %rsi      # 0x90b4
movl $0x5, %edx
movq %r14, %rdi
callq 0x21e0
xorl %edx, %edx
testl %ebp, %ebp
sete %dl
leaq 0x6594(%rip), %rax      # 0x90ba
leaq 0x658e(%rip), %rsi      # 0x90bb
cmoveq %rax, %rsi
movq %r14, %rdi
callq 0x21e0
cmpl $0x1, %ebp
jne 0x2ba1
movq 0xa493(%rip), %r14      # 0xcfd8
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2180
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2110
movq %rax, %rdi
movq %rbx, %rsi
callq 0x70ca
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2180
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x7018
movl (%rbx), %ecx
shlq $0x20, %rcx
movl %eax, %eax
orq %rcx, %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq %r12, %rdi
callq 0x2da2
movq %rbx, %rdi
callq 0x22b0