// File: /workspace/github_cpp_makefile_star2_O2/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, %r14d
movq 0xa857(%rip), %rdi      # 0xcfd0
leaq 0x58d0(%rip), %rsi      # 0x8050
callq 0x21b0
movq %rax, %rdi
callq 0x2120
xorl %eax, %eax
testl %r14d, %r14d
cmovlel %eax, %r14d
movl %r14d, 0xc(%rsp)
leaq 0x40(%rsp), %r12
leaq 0x38(%rsp), %r13
movl %ebp, 0x8(%rsp)
movq %rbx, %rdi
callq 0x56a2
testb %al, %al
je 0x28b0
cmpl $0x2, %ebp
jl 0x27d5
movq 0xa80b(%rip), %rdi      # 0xcfd0
callq 0x20d0
movq %rax, %rdi
movq %rbx, %rsi
callq 0x625d
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0x10(%rsp)
movl 0xc(%rsp), %r14d
subl $0x1, %r14d
jb 0x281f
movq %r13, %rdi
movq %rbx, %rsi
callq 0x29e8
movq %r13, %rdi
callq 0x25ac
movq %rax, %r15
movq %rax, %rbp
shrq $0x20, %rbp
movq %r12, %rdi
callq 0x2abc
movslq %r15d, %rax
addl %ebp, 0x20(%rsp,%rax,4)
incl 0x10(%rsp,%rax,4)
jmp 0x27e7
xorl %eax, %eax
xorl %edx, %edx
xorl %ecx, %ecx
movl 0x8(%rsp), %ebp
cmpq $0x4, %rax
je 0x2859
movl 0x10(%rsp,%rax,4), %esi
testl %esi, %esi
je 0x2854
cvtsi2ssl 0x20(%rsp,%rax,4), %xmm0
cvtsi2ss %esi, %xmm1
cvtsi2ss %edx, %xmm2
divss %xmm1, %xmm0
ucomiss %xmm2, %xmm0
jbe 0x2854
cvttss2si %xmm0, %edx
movl %eax, %ecx
incq %rax
jmp 0x2829
cmpl $0x3, %ecx
ja 0x27a9
movl %ecx, %eax
leaq 0x57d5(%rip), %rcx      # 0x8040
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
xorl %esi, %esi
callq 0x5944
jmp 0x27a9
movq %rbx, %rdi
xorl %esi, %esi
callq 0x59e0
jmp 0x27a9
movq %rbx, %rdi
xorl %esi, %esi
callq 0x5a08
jmp 0x27a9
movq %rbx, %rdi
xorl %esi, %esi
callq 0x59b8
jmp 0x27a9
cmpl $0x1, %ebp
jg 0x28e9
movq 0xa714(%rip), %rdi      # 0xcfd0
leaq 0x57c1(%rip), %rsi      # 0x8084
callq 0x21b0
testl %ebp, %ebp
leaq 0x57b9(%rip), %rcx      # 0x808a
leaq 0x57b3(%rip), %rsi      # 0x808b
cmoveq %rcx, %rsi
movq %rax, %rdi
callq 0x21b0
cmpl $0x1, %ebp
jne 0x2908
movq 0xa6e0(%rip), %rdi      # 0xcfd0
callq 0x20d0
movq %rax, %rdi
movq %rbx, %rsi
callq 0x625d
movq %rax, %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x61f8
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 0x2abc
movq %rbx, %rdi
callq 0x22c0