// File: /workspace/github_cpp_makefile_star2_O3/NathanWine[P]2048-AI-Solvers/src/Expectimax.cpp
// Function: expectimaxScore(int, Game, bool)
float expectimaxScore(int depth, Game game, bool is_max) {
    std::map<int, weightedmoves> possibilities = game.computePossibilities();    
    if (possibilities.size() == 0) {
        return 0.0;
    }
    else if (is_max) {
        if (depth == 0) {
            return Heuristics::get_h_score(game.state);
        }
        else {
            std::map<int, float> scores;
            for (auto const& entry : possibilities) {
                int move = entry.first;                             // Direction of move
                weightedmoves weighted_subset = entry.second;       // Vector of (prob, game)
                int len = (int) weighted_subset.size();
                if (len > 0) {
                    scores[move] = 0.0;
                    for (int j = 0; j < len; ++j) {
                        scores[move] += Heuristics::get_h_score(weighted_subset[j].second.state) * weighted_subset[j].first;
                    }
                }
            }

            float max_score = -std::numeric_limits<float>::max();
            int max_choice = UP;
            for (auto const& score : scores) {      // Determine best move choice based on tabulated scores
                if (score.second > max_score) {
                    max_score = score.second;
                    max_choice = score.first;
                }
            }

            switch (max_choice) {
                case UP:
                    game.up(false);
                    break;
                case DOWN:
                    game.down(false);
                    break;
                case LEFT: 
                    game.left(false);
                    break;
                case RIGHT:
                    game.right(false);
            }

            return expectimaxScore(depth - 1, game, false);
        }
    }
    else {
        std::map<int, float> scores;
        for (auto const& entry : possibilities) {
            int move = entry.first;                             // Direction of move
            weightedmoves weighted_subset = entry.second;       // Vector of (prob, game)
            int len = (int) weighted_subset.size();
            if (len > 0) {
                scores[move] = 0.0;
                for (int j = 0; j < len; ++j) {
                    scores[move] += expectimaxScore(depth, weighted_subset[j].second, true) * weighted_subset[j].first;
                }
            }
        }
        float sum = 0.0;
        for (auto const& score : scores) {
            sum += score.second;
        }
        return sum / scores.size();
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movl %edx, %ebp
movq %rsi, %r14
movl %edi, 0xc(%rsp)
leaq 0x68(%rsp), %r15
movq %r15, %rdi
callq 0x664a
cmpq $0x0, 0x28(%r15)
je 0x84c7
testb %bpl, %bpl
je 0x84cf
cmpl $0x0, 0xc(%rsp)
je 0x8687
leaq 0x40(%rsp), %rcx
movl $0x0, (%rcx)
xorl %eax, %eax
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
leaq 0x70(%rsp), %rax
movq 0x10(%rax), %r15
cmpq %rax, %r15
je 0x8477
movq %r14, 0x30(%rsp)
leaq 0x18(%rsp), %r12
leaq 0x38(%rsp), %r13
leaq 0x14(%rsp), %rbp
movl 0x20(%r15), %eax
movl %eax, 0x14(%rsp)
leaq 0x28(%r15), %rsi
movq %r12, %rdi
callq 0x8d00
movq 0x20(%rsp), %r14
subq 0x18(%rsp), %r14
sarq $0x3, %r14
movabsq $-0x3333333333333333, %rax # imm = 0xCCCCCCCCCCCCCCCD
imulq %rax, %r14
testl %r14d, %r14d
jle 0x83f7
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3da4
movl $0x0, (%rax)
andl $0x7fffffff, %r14d      # imm = 0x7FFFFFFF
movl $0x10, %ebx
movq 0x18(%rsp), %rdi
addq %rbx, %rdi
callq 0x8ea9
movss %xmm0, 0x8(%rsp)
movq 0x18(%rsp), %rax
movss -0x10(%rax,%rbx), %xmm0
movss %xmm0, 0x10(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3da4
movss 0x8(%rsp), %xmm0
mulss 0x10(%rsp), %xmm0
addss (%rax), %xmm0
movss %xmm0, (%rax)
addq $0x28, %rbx
decq %r14
jne 0x83ab
movq %r12, %rdi
callq 0x3eb2
movq %r15, %rdi
callq 0x2120
movq %rax, %r15
leaq 0x70(%rsp), %rax
cmpq %rax, %r15
jne 0x8359
movq 0x50(%rsp), %rax
leaq 0x40(%rsp), %r15
cmpq %r15, %rax
movq 0x30(%rsp), %r14
je 0x8477
xorl %ebx, %ebx
movss 0xcd2(%rip), %xmm0      # 0x9108
movss 0x24(%rax), %xmm1
ucomiss %xmm0, %xmm1
jbe 0x8443
movl 0x20(%rax), %ebx
maxss %xmm0, %xmm1
movss %xmm1, 0x8(%rsp)
movq %rax, %rdi
callq 0x2120
movss 0x8(%rsp), %xmm0
cmpq %r15, %rax
jne 0x8436
cmpl $0x3, %ebx
ja 0x8481
movl %ebx, %eax
leaq 0x11de(%rip), %rcx      # 0x964c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %r14, %rdi
xorl %esi, %esi
callq 0x6542
movl (%r14), %eax
leaq 0xc0(%rsp), %r15
movl %eax, -0x8(%r15)
addq $0x8, %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0x2cc2
movl 0xc(%rsp), %edi
decl %edi
leaq 0xb8(%rsp), %rsi
xorl %edx, %edx
callq 0x82d0
movss %xmm0, 0x8(%rsp)
movq %r15, %rdi
callq 0x2da2
jmp 0x867b
xorps %xmm0, %xmm0
jmp 0x8693
leaq 0x40(%rsp), %rcx
movl $0x0, (%rcx)
xorl %eax, %eax
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
leaq 0x70(%rsp), %rax
movq 0x10(%rax), %rcx
xorps %xmm1, %xmm1
cmpq %rax, %rcx
je 0x8645
leaq 0xa0(%rsp), %r14
leaq 0x18(%rsp), %rbx
leaq 0x38(%rsp), %r13
leaq 0x14(%rsp), %rbp
leaq 0x98(%rsp), %r12
movl 0x20(%rcx), %eax
movl %eax, 0x14(%rsp)
movq %rcx, 0x30(%rsp)
leaq 0x28(%rcx), %rsi
movq %rbx, %rdi
callq 0x8d00
movq 0x20(%rsp), %r15
subq 0x18(%rsp), %r15
sarq $0x3, %r15
movabsq $-0x3333333333333333, %rax # imm = 0xCCCCCCCCCCCCCCCD
imulq %rax, %r15
testl %r15d, %r15d
jle 0x85ed
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3da4
movl $0x0, (%rax)
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
movl $0x10, %ebx
movq 0x18(%rsp), %rsi
movl -0x8(%rsi,%rbx), %eax
addq %rbx, %rsi
movl %eax, 0x98(%rsp)
movq %r14, %rdi
callq 0x2cc2
movl 0xc(%rsp), %edi
movq %r12, %rsi
movl $0x1, %edx
callq 0x82d0
movss %xmm0, 0x8(%rsp)
movq 0x18(%rsp), %rax
movss -0x10(%rax,%rbx), %xmm0
movss %xmm0, 0x10(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3da4
movss 0x8(%rsp), %xmm0
mulss 0x10(%rsp), %xmm0
addss (%rax), %xmm0
movss %xmm0, (%rax)
movq %r14, %rdi
callq 0x2da2
addq $0x28, %rbx
decq %r15
jne 0x857a
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3eb2
movq 0x30(%rsp), %rdi
callq 0x2120
movq %rax, %rcx
leaq 0x70(%rsp), %rax
cmpq %rax, %rcx
jne 0x8520
movq 0x50(%rsp), %rax
leaq 0x40(%rsp), %rbx
cmpq %rbx, %rax
xorps %xmm1, %xmm1
je 0x8645
addss 0x24(%rax), %xmm1
movss %xmm1, 0x8(%rsp)
movq %rax, %rdi
callq 0x2120
movss 0x8(%rsp), %xmm1
cmpq %rbx, %rax
jne 0x8627
movq 0x60(%rsp), %rax
testq %rax, %rax
js 0x8659
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
jmp 0x8671
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
xorps %xmm0, %xmm0
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
divss %xmm0, %xmm1
movss %xmm1, 0x8(%rsp)
leaq 0x38(%rsp), %rdi
callq 0x3e0a
jmp 0x8699
addq $0x8, %r14
movq %r14, %rdi
callq 0x8ea9
movss %xmm0, 0x8(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x3e5a
movss 0x8(%rsp), %xmm0
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
xorl %esi, %esi
callq 0x65ea
jmp 0x8481
movq %r14, %rdi
xorl %esi, %esi
callq 0x6612
jmp 0x8481
movq %r14, %rdi
xorl %esi, %esi
callq 0x65c2
jmp 0x8481
movq %rax, %rbx
jmp 0x872d
movq %rax, %rbx
movq %r15, %rdi
callq 0x2da2
jmp 0x8723
jmp 0x8702
jmp 0x8709
jmp 0x8709
jmp 0x8702
movq %rax, %rbx
jmp 0x8723
jmp 0x8709
movq %rax, %rbx
jmp 0x8719
movq %rax, %rbx
movq %r14, %rdi
callq 0x2da2
leaq 0x18(%rsp), %rdi
callq 0x3eb2
leaq 0x38(%rsp), %rdi
callq 0x3e0a
leaq 0x68(%rsp), %rdi
callq 0x3e5a
movq %rbx, %rdi
callq 0x22b0