// File: /workspace/github_cpp_makefile_star2_O2/integeruser[P]GA3C-cpp/src/ga3c.cc
// Function: agent(unsigned int, std::shared_ptr<Environment>)
void agent(uint32_t id, std::shared_ptr<Environment> env)
{
    for (uint32_t episode = 1; true; ++episode) {
        const float t = (float)num_training_experiences / (MAX_NUM_TRAINING_EXPERIENCES-1);
        const float epsilon = (1-t)*EPSILON_START + t*EPSILON_END;

        // reset the environment starting a new episode
        observation_t curr_state, next_state;
        curr_state = env->reset();

        memory_t memory;
        float reward = 0.0f;
        float episode_reward = 0.0f;

        bool done = false;
        while (not done) {
            // stop training after reaching a fixed number of training experiences
            if (num_training_experiences >= MAX_NUM_TRAINING_EXPERIENCES) { return; }

            // predict policy and value
            std::vector<float> policy;
            float value;
            std::tie(policy, value) = shared_model->predict_policy_and_value(curr_state);

            // select and perform an action
            const auto action = select_action(env, epsilon, policy);
            std::tie(next_state, reward, done) = env->step(action);
            episode_reward += reward;

            experience_t experience = experience_t{curr_state, action, reward, next_state, done};
            memory.push_back(experience);

            // add experiences to the training queue when:
            // - enough of them are accumulated in memory and the n-step return can be computed
            // - the episode is over and the memory is not empty
            while ((memory.size() >= N_STEP_RETURN) or (done and not memory.empty())) {
                const auto training_experience = extract_accumulated_experience(memory, value);
                training_experiences_queue.push(training_experience);
            }

            curr_state = next_state;
        }

        if (episode % 10 == 0) {
            std::cout << "[" << std::setfill('0') << std::setw(2) << id << "] "
                      << "Ep. " << std::setfill('0') << std::setw(5) << episode << " "
                      << "reward: " << episode_reward << std::endl;
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rsi, %r15
movl %edi, %eax
movq %rax, 0x70(%rsp)
pushq $0x1
popq %rax
movl %eax, 0x10(%rsp)
leaq 0xd0(%rsp), %r13
leaq 0xb0(%rsp), %r12
leaq 0x120(%rsp), %rbx
leaq 0x88(%rsp), %rbp
movq %rsi, 0x20(%rsp)
movl 0x8b4f(%rip), %eax      # 0xb258
cvtsi2ss %rax, %xmm1
leaq 0x8a77(%rip), %rax      # 0xb18c
movl (%rax), %eax
decl %eax
cvtsi2ss %rax, %xmm0
divss %xmm0, %xmm1
movss %xmm1, 0xc(%rsp)
andq $0x0, 0xc0(%rsp)
mulss 0x3933(%rip), %xmm1     # 0x606c
movss %xmm1, 0x14(%rsp)
andq $0x0, 0x60(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0xb0(%rsp)
movaps %xmm0, 0x50(%rsp)
movq (%r15), %rsi
movq (%rsi), %rax
movq %r13, %rdi
callq *(%rax)
movq %r12, %rdi
movq %r13, %rsi
callq 0x4618
movq %r13, %rdi
callq 0x3d6e
movq %r13, %rdi
callq 0x3a16
movss 0x38e5(%rip), %xmm0     # 0x6068
subss 0xc(%rsp), %xmm0
andl $0x0, 0x18(%rsp)
addss 0x14(%rsp), %xmm0
movss %xmm0, 0x14(%rsp)
movb $0x0, 0xb(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0xc(%rsp)
xorl %r15d, %r15d
testb $0x1, %r15b
jne 0x2971
movl 0x8a9d(%rip), %eax      # 0xb258
leaq 0x89ca(%rip), %rcx      # 0xb18c
cmpl (%rcx), %eax
jae 0x2a38
andq $0x0, 0x40(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movq 0x89c1(%rip), %rsi      # 0xb1a0
movq (%rsi), %rax
movq %rbx, %rdi
movq %r12, %rdx
callq *0x8(%rax)
movq %r12, %r14
leaq 0x1c(%rsp), %rax
movq %rax, 0x88(%rsp)
leaq 0x30(%rsp), %r15
movq %r15, 0x90(%rsp)
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x3004
movq %rbx, %rdi
callq 0x3d6e
leaq 0x78(%rsp), %r15
movq %r15, %rdi
movq 0x20(%rsp), %r12
movq %r12, %rsi
callq 0x3c30
movq %r15, %rdi
movss 0x14(%rsp), %xmm0
leaq 0x30(%rsp), %rsi
callq 0x24bc
movq %rax, %r15
leaq 0x80(%rsp), %rdi
callq 0x3532
movq %r15, 0x28(%rsp)
movq (%r12), %rsi
movq (%rsi), %rax
movq %rbx, %rdi
leaq 0x28(%rsp), %rdx
callq *0x8(%rax)
leaq 0xb(%rsp), %r12
movq %r12, 0x88(%rsp)
leaq 0x18(%rsp), %r12
movq %r12, 0x90(%rsp)
leaq 0x50(%rsp), %r15
movq %r15, 0x98(%rsp)
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x302e
leaq 0x128(%rsp), %rdi
callq 0x3d6e
movss 0xc(%rsp), %xmm0
addss 0x18(%rsp), %xmm0
movss %xmm0, 0xc(%rsp)
movq %rbx, %rdi
movq %r14, %r12
movq %r14, %rsi
leaq 0x28(%rsp), %rdx
leaq 0x18(%rsp), %rcx
movq %r15, %r8
leaq 0xb(%rsp), %r9
callq 0x3c64
movq %r13, %rdi
movq %rbx, %r15
movq %rbx, %rsi
callq 0x3044
leaq 0x98(%rsp), %r14
leaq 0x88b8(%rip), %rbx      # 0xb1b0
movq %r13, %rdi
callq 0x2f7c
cmpq $0x7, %rax
ja 0x291f
cmpb $0x1, 0xb(%rsp)
jne 0x2945
movq 0x100(%rsp), %rax
cmpq 0xe0(%rsp), %rax
je 0x2945
movss 0x1c(%rsp), %xmm0
movq %rbp, %rdi
movq %r13, %rsi
callq 0x2555
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x306e
movq %r14, %rdi
callq 0x3d6e
jmp 0x28f8
movq %r12, %rdi
leaq 0x50(%rsp), %rsi
callq 0x30c8
movq %r15, %rbx
movq %r15, %rdi
callq 0x3192
leaq 0x30(%rsp), %rdi
callq 0x3d6e
movb 0xb(%rsp), %r15b
jmp 0x27ab
movl 0x10(%rsp), %eax
xorl %edx, %edx
pushq $0xa
popq %rcx
divl %ecx
testl %edx, %edx
jne 0x2a38
movq 0x864d(%rip), %rdi      # 0xafd8
leaq 0x374d(%rip), %rsi      # 0x60df
callq 0x21b0
movq %rax, %rdi
pushq $0x30
popq %rsi
callq 0x2250
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movq $0x2, 0x10(%rax,%rcx)
movq %rax, %rdi
movq 0x70(%rsp), %rsi
callq 0x2100
movq %rax, %rdi
leaq 0x3718(%rip), %rsi      # 0x60e1
callq 0x21b0
movq %rax, %rdi
leaq 0x370c(%rip), %rsi      # 0x60e4
callq 0x21b0
movq %rax, %rdi
pushq $0x30
popq %rsi
callq 0x2250
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movq $0x5, 0x10(%rax,%rcx)
movl 0x10(%rsp), %esi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
leaq 0x36d9(%rip), %rsi      # 0x60e7
callq 0x21b0
movq %rax, %rdi
leaq 0x36cc(%rip), %rsi      # 0x60e9
callq 0x21b0
movq %rax, %rdi
movss 0xc(%rsp), %xmm0
callq 0x2130
movq %rax, %rdi
callq 0x20a0
movq %r13, %rdi
callq 0x31ac
leaq 0x50(%rsp), %rdi
callq 0x3d6e
movq %r12, %rdi
callq 0x3d6e
incl 0x10(%rsp)
testb $0x1, %r15b
movq 0x20(%rsp), %r15
jne 0x2703
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2a79
movq %rax, %rbx
jmp 0x2ad4
movq %rax, %rbx
jmp 0x2ac7
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x3532
jmp 0x2abd
jmp 0x2a99
jmp 0x2a99
movq %rax, %rbx
jmp 0x2abd
jmp 0x2aad
movq %rax, %rbx
movq %r14, %rdi
callq 0x3d6e
jmp 0x2ab0
movq %rax, %rbx
leaq 0x120(%rsp), %rdi
callq 0x3192
leaq 0x30(%rsp), %rdi
callq 0x3d6e
leaq 0xd0(%rsp), %rdi
callq 0x31ac
leaq 0x50(%rsp), %rdi
callq 0x3d6e
leaq 0xb0(%rsp), %rdi
callq 0x3d6e
movq %rbx, %rdi
callq 0x22b0