// File: /workspace/github_c_makefile_star2_O3/schroeder-lvb[P]sissm/src/pidynbots.c
// Function: computeBotParams
static int _computeBotParams( int refresh )
{
    int minBots, maxBots, i;
    unsigned int currHuman, currBots, minHuman, maxHuman;
    double aiDifficulty;
    char *objName, *mapName, objLetter;
    char strBuf[256], *w, *v;
    int adjust = 0, errCode = 0, botBias, offsetIndex;

    // default parameters
    // 
    minBots      = pidynbotsConfig.MinimumEnemies;
    maxBots      = pidynbotsConfig.MaximumEnemies;
    minHuman     = 1;
    maxHuman     = pidynbotsConfig.MaxPlayersToScaleEnemyCount;
    currHuman    = rosterCount();

    // a wedge code to disable this plugin if non-Checkpoint mode is running
    //
    v = apiGetServerMode();
    if (! ((0==strcmp( v, "checkpoint" )) || (0==strcmp( v, "hardcore"))) )  return 0;

#if 0 
    // DEBUG tap for simulating humans joining and leaving - take out this block later
    static int currHuman_static = 1;
    int currHuman_tmp;
    if ( 0 == debugPoke( "delme.txt", &currHuman_tmp ) ) {
        currHuman_static = currHuman_tmp;
    }
    currHuman = currHuman_static;
    printf("\nDEBUG pidynbots: override to %d\n", currHuman );
    apiSay("pidynbots: override to %d humans", currHuman );
#endif

    aiDifficulty = pidynbotsConfig.AIDifficulty;

    // get current side, map, and objective
    //
    objName   = rosterGetObjective();                    // e.g., "OCCheckpoint_A"
    mapName   = rosterGetMapName();                      // e.g., "Farmhouse_Checkpoint_Security"
    objLetter = rosterGetCoopObjectiveLetter();          // e.g., 'A', 'B', 'C', ... ' '

    logPrintf( LOG_LEVEL_INFO, "pidynbots", "ObjName ::%s:: MapName ::%s:: objLetter ::%c::", 
        objName, mapName, objLetter );

    // search the table if override is found (look for matching map name)
    //
    for (i=0; i<PIDYN_MAXADJUSTERS; i++) {

        if ( NULL != strcasestr( pidynbotsConfig.Adjuster[i], mapName )) {

            // get min/max/dif values 
            //
            if ( NULL != (w = getWord( pidynbotsConfig.Adjuster[i], 1, " " ))) 
                errCode |= ( 1 != sscanf( w, "%d", &minBots ));
            if ( NULL != (w = getWord( pidynbotsConfig.Adjuster[i], 2, " " ))) 
                errCode |= ( 1 != sscanf( w, "%d", &maxBots ));
            if ( NULL != (w = getWord( pidynbotsConfig.Adjuster[i], 3, " " ))) 
                errCode |= ( 1 != sscanf( w, "%lf", &aiDifficulty ));

            // if override was found, look for per-objective adjustments
            //
            if (( !errCode  ) && ( (objLetter >= 'A') && (objLetter <= 'Z') )) {
                offsetIndex = objLetter - 'A';
                offsetIndex += 4;        
                if ( NULL != (w = getWord( pidynbotsConfig.Adjuster[i], offsetIndex, " " ))) {
                    errCode |= ( 1 != sscanf( w, "%d", &adjust ));
                    if ( !errCode ) maxBots += adjust;
                }
            }
            break;
        }
    }

    // poke the new values
    //
    if ( !errCode )  {

        // Update the bot difficulty if it was not overridden by the 
        // operator (picladmin)
        //
        if ( 0L == p2pGetL( "picladmin.p2p.botAdminControlDifficulty", 0L )) {  // check if in-game admin took control
            logPrintf( LOG_LEVEL_INFO, "pidynbots", "Adjusting bot difficulty %lf", aiDifficulty );
            snprintf( strBuf, 256, "%lf", aiDifficulty );
                 apiGameModePropertySet( "aidifficulty",   strBuf ) ;

            // if enabled in config, update the players by showing new params in-game
            //
            if ( 0 != strlen( pidynbotsConfig.showInGame ) ) {
                apiSay("%s Difficulty %6.3lf", pidynbotsConfig.showInGame, aiDifficulty*10.0 );
            }
        }
        
        // Update the bot count if it was not overridden by the 
        // operator (picladmin)
        //
        if ( 0L == p2pGetL( "picladmin.p2p.botAdminControl", 0L )) {  // check if in-game admin took control
            logPrintf( LOG_LEVEL_INFO, "pidynbots", "Adjusting bots %d:%d" , minBots, maxBots );

            // Apply BotBias - this changes min/maxenemies by a specified offset in function of 
            // number of human players are present
            //
            botBias = 0;
            if ( NULL != (w = getWord( pidynbotsConfig.BotBias, currHuman, " " ))) 
               if ( 1 != sscanf( w, "%d", &botBias )) botBias = 0;

            // validate to keep the server from crashing
            // 
            minBots += botBias;                           // offset from bias table
            maxBots += botBias;
            minBots += pidynMinimumOffset;                // offset from game mode table
            maxBots += pidynMmaximumOffset;

            if ( maxBots > pidynbotsConfig.MaxBotsCrashProtect )  
                maxBots = pidynbotsConfig.MaxBotsCrashProtect;
            if ( minBots < 1  )      minBots =  1;
            if ( minBots > maxBots ) maxBots = minBots; 

            snprintf( strBuf, 256, "%d", minBots );
                apiGameModePropertySet( "minimumenemies", strBuf );
            snprintf( strBuf, 256, "%d", maxBots );
                apiGameModePropertySet( "maximumenemies", strBuf );

            // for instant-respawn mode, it uses SoloPlayer set of parameters.  Compute
            // the scaled bots linearly here and poke in the value;
            //
            currBots =  _botScale( currHuman, maxBots, minBots, maxHuman, minHuman );
            snprintf( strBuf, 256, "%d", currBots );
                apiGameModePropertySet( "soloenemies", strBuf );

            // apiSay("Bias %d Bots %d:%d:%d Humans %d", botBias, minBots, maxBots, currBots, currHuman);
            // printf("\n****Bias %d Bots %d:%d:%d Humans %d***\n", botBias, minBots, maxBots, currBots, currHuman);

            // if enabled in config, update the players by showing new params in-game
            //
            if ( 0 != strlen( pidynbotsConfig.showInGame ) ) {
                apiSay("%s Count %d:%d [%d]", pidynbotsConfig.showInGame, minBots*2, maxBots*2, currBots );
            }

        }

        // Admin Bot override is "on", but still must process if instand respawn mode to emulate
        // dynamic bot changes
        //
        else {
           
            // If "respawnMode" AND "not fixed bot" then, recompute the dynamic scaling for this objective
            // Poke the resulting value to soloenemies
            //
            if ( _inRespawnCoopMode( refresh ) ) {

                 // read gamemodeproperty for minenemies and maximumenemies
                 // convert to integer for math
                 //
                 if ( 1 != sscanf( apiGameModePropertyGet( "minimumenemies" ), "%d", &minBots )) errCode = 1;
                 if ( 1 != sscanf( apiGameModePropertyGet( "maximumenemies" ), "%d", &maxBots )) errCode = 1;

                 if ( 0 == errCode ) {
                     // program currBots to soloenemies
                     // 
                     if ( minBots != maxBots )  {
                         currBots =  _botScale( currHuman, maxBots, minBots, maxHuman, minHuman );
                         snprintf( strBuf, 256, "%d", currBots );

                         apiGameModePropertySet( "soloenemies", strBuf );

                         logPrintf( LOG_LEVEL_INFO, "pidynbots", 
                             "Adjusting bots respawn mode with operator override params %d:%d [%d] difficulty %lf", 
                             minBots, maxBots, currBots, aiDifficulty );

                         // if enabled in config, update the players by showing new params in-game
                         //
                         if ( 0 != strlen( pidynbotsConfig.showInGame ) ) {
                             apiSay("%s Count %d:%d [%d]", pidynbotsConfig.showInGame, minBots*2, maxBots*2, currBots );
                         }
                     }
                 }
             }
             else {
                 logPrintf( LOG_LEVEL_INFO, "pidynbots", "Adjusting bots bypassed due to Admin override %d:%d difficulty %lf", 
                     minBots, maxBots, aiDifficulty );
             }
        }

    }
    return 0;  
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movl %edi, 0x2c(%rsp)
movl $0x0, 0x1c(%rsp)
movl 0x6df4c(%rip), %eax     # 0x7c0ec
movl %eax, 0x8(%rsp)
movl 0x6df46(%rip), %eax     # 0x7c0f0
movl %eax, 0x4(%rsp)
movl 0x6df40(%rip), %eax     # 0x7c0f4
movl %eax, 0x18(%rsp)
callq 0x14c64
movq %rax, 0x20(%rsp)
callq 0x13dc1
movq %rax, %r14
leaq 0xede2(%rip), %rsi      # 0x1cfb3
movq %rax, %rdi
callq 0x8220
testl %eax, %eax
je 0xe1f4
leaq 0xde13(%rip), %rsi      # 0x1bff7
movq %r14, %rdi
callq 0x8220
testl %eax, %eax
jne 0xe7c3
movsd 0x6df04(%rip), %xmm0    # 0x7c100
movsd %xmm0, 0x10(%rsp)
callq 0x1455b
movq %rax, %r12
callq 0x1457f
movq %rax, %r13
callq 0x1464a
movl %eax, %r15d
movsbl %al, %r14d
leaq 0xed2c(%rip), %rsi      # 0x1cf51
leaq 0xed92(%rip), %rdx      # 0x1cfbe
xorl %ebx, %ebx
movl $0x2, %edi
movq %r12, %rcx
movq %r13, %r8
movl %r14d, %r9d
xorl %eax, %eax
callq 0x1a3e3
leaq 0x6de9e(%rip), %rbp     # 0x7c0e8
leaq (%rbx,%rbp), %r12
addq $0x20, %r12
movq %r12, %rdi
movq %r13, %rsi
callq 0x8350
testq %rax, %rax
jne 0xe495
addq $0x400, %rbx            # imm = 0x400
cmpq $0x20000, %rbx          # imm = 0x20000
jne 0xe24a
leaq 0xd82e(%rip), %rdi      # 0x1baab
xorl %esi, %esi
callq 0x181e1
testq %rax, %rax
jne 0xe305
movsd 0x10(%rsp), %xmm0
leaq 0xecbb(%rip), %rsi      # 0x1cf51
leaq 0xed50(%rip), %rdx      # 0x1cfed
movl $0x2, %edi
movb $0x1, %al
callq 0x1a3e3
movsd 0x10(%rsp), %xmm0
leaq 0xede2(%rip), %rdx      # 0x1d098
leaq 0x30(%rsp), %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
movb $0x1, %al
callq 0x8190
leaq 0xd7cd(%rip), %rdi      # 0x1ba9e
movq %r14, %rsi
callq 0x131ed
cmpb $0x0, 0x92234(%rip)     # 0xa0514
je 0xe305
movsd 0x10(%rsp), %xmm0
mulsd 0xd3e8(%rip), %xmm0     # 0x1b6d8
leaq 0xed13(%rip), %rdi      # 0x1d00a
leaq 0x92216(%rip), %rsi     # 0xa0514
movb $0x1, %al
callq 0x13337
leaq 0xd759(%rip), %rdi      # 0x1ba65
xorl %r14d, %r14d
xorl %esi, %esi
callq 0x181e1
testq %rax, %rax
je 0xe4d4
movl 0x1b79b(%rip), %ecx     # 0x29ac0
cmpl $-0x1, %ecx
setne %al
cmpl $0x0, 0x2c(%rsp)
sete %dl
testb %al, %dl
jne 0xe360
leaq 0xeda1(%rip), %rdi      # 0x1d0df
callq 0x131f2
leaq 0xed9b(%rip), %rsi      # 0x1d0e5
movq %rax, %rdi
callq 0x83b0
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
movl %ecx, 0x1b760(%rip)     # 0x29ac0
testl %ecx, %ecx
je 0xe62b
leaq 0xd6cc(%rip), %rdi      # 0x1ba3b
callq 0x131f2
leaq 0xdd4a(%rip), %r14      # 0x1c0c5
leaq 0x8(%rsp), %rdx
movq %rax, %rdi
movq %r14, %rsi
xorl %eax, %eax
callq 0x82d0
movl %eax, %ebp
leaq 0xd6b4(%rip), %rdi      # 0x1ba4a
callq 0x131f2
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
movq %r14, %rsi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %ebp
jne 0xe7c3
cmpl $0x1, %eax
jne 0xe7c3
movl 0x8(%rsp), %eax
movl 0x4(%rsp), %ecx
cmpl %ecx, %eax
je 0xe7c3
seta %dl
movl 0x18(%rsp), %edi
cmpl $0x2, %edi
setb %sil
movl $0x1, %r14d
orb %dl, %sil
jne 0xe437
movq 0x20(%rsp), %rdx
cmpl $0x1, %edx
adcl $0x0, %edx
cmpl %edi, %edx
cmovael %edi, %edx
movl %ecx, %ecx
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
movl %eax, %eax
cvtsi2sd %rax, %xmm1
subsd %xmm1, %xmm0
movl %edi, %eax
cvtsi2sd %rax, %xmm2
addsd 0xe9fc(%rip), %xmm2     # 0x1ce18
divsd %xmm2, %xmm0
decl %edx
xorps %xmm2, %xmm2
cvtsi2sd %rdx, %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
cvttsd2si %xmm2, %r14
leaq 0xdc87(%rip), %rdx      # 0x1c0c5
leaq 0x30(%rsp), %rbx
movl $0x100, %esi            # imm = 0x100
movq %rbx, %rdi
movl %r14d, %ecx
xorl %eax, %eax
callq 0x8190
leaq 0xd5fd(%rip), %rdi      # 0x1ba59
movq %rbx, %rsi
callq 0x131ed
movl 0x8(%rsp), %ecx
movl 0x4(%rsp), %r8d
movsd 0x10(%rsp), %xmm0
leaq 0xead7(%rip), %rsi      # 0x1cf51
leaq 0xebc7(%rip), %rdx      # 0x1d048
movl $0x2, %edi
movl %r14d, %r9d
movb $0x1, %al
callq 0x1a3e3
jmp 0xe796
leaq 0xdcb2(%rip), %rdx      # 0x1c14e
movq %r12, %rdi
movl $0x1, %esi
callq 0xf82d
testq %rax, %rax
je 0xe54c
leaq 0xdc0c(%rip), %rsi      # 0x1c0c5
leaq 0x8(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %r13d, %r13d
cmpl $0x1, %eax
setne %r13b
jmp 0xe54f
movl 0x8(%rsp), %ecx
movl 0x4(%rsp), %r8d
leaq 0xea6d(%rip), %rsi      # 0x1cf51
leaq 0xeb34(%rip), %rdx      # 0x1d01f
movl $0x2, %edi
xorl %eax, %eax
callq 0x1a3e3
movl $0x0, 0xc(%rsp)
leaq 0x91c02(%rip), %rdi     # 0xa0108
leaq 0xdc41(%rip), %rdx      # 0x1c14e
movq 0x20(%rsp), %rsi
callq 0xf82d
testq %rax, %rax
je 0xe661
leaq 0xdb9e(%rip), %rsi      # 0x1c0c5
xorl %r14d, %r14d
leaq 0xc(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %eax
jne 0xe659
movl 0xc(%rsp), %r14d
jmp 0xe661
xorl %r13d, %r13d
leaq 0xdbf8(%rip), %rdx      # 0x1c14e
movq %r12, %rdi
movl $0x2, %esi
callq 0xf82d
testq %rax, %rax
je 0xe589
leaq 0xdb56(%rip), %rsi      # 0x1c0c5
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %ecx, %ecx
cmpl $0x1, %eax
setne %cl
orl %ecx, %r13d
leaq 0xdbbe(%rip), %rdx      # 0x1c14e
movq %r12, %rdi
movl $0x3, %esi
callq 0xf82d
testq %rax, %rax
je 0xe5c3
leaq 0xeaef(%rip), %rsi      # 0x1d098
leaq 0x10(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %ecx, %ecx
cmpl $0x1, %eax
setne %cl
orl %ecx, %r13d
addb $-0x41, %r15b
cmpb $0x19, %r15b
ja 0xe61d
testl %r13d, %r13d
jne 0xe61d
addl $-0x3d, %r14d
leaq 0xdb71(%rip), %rdx      # 0x1c14e
movq %r12, %rdi
movl %r14d, %esi
callq 0xf82d
testq %rax, %rax
je 0xe276
leaq 0xdacd(%rip), %rsi      # 0x1c0c5
leaq 0x1c(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %eax
jne 0xe7c3
movl 0x1c(%rsp), %eax
addl %eax, 0x4(%rsp)
jmp 0xe276
testl %r13d, %r13d
jne 0xe7c3
jmp 0xe276
movl 0x8(%rsp), %ecx
movl 0x4(%rsp), %r8d
movsd 0x10(%rsp), %xmm0
leaq 0xe910(%rip), %rsi      # 0x1cf51
leaq 0xea54(%rip), %rdx      # 0x1d09c
movl $0x2, %edi
movb $0x1, %al
callq 0x1a3e3
jmp 0xe7c3
movl $0x0, 0xc(%rsp)
movl 0x8(%rsp), %ecx
addl %r14d, %ecx
addl 0x4(%rsp), %r14d
addl 0x6da70(%rip), %r14d    # 0x7c0e4
movl 0x6da7e(%rip), %eax     # 0x7c0f8
cmpl %eax, %r14d
cmovgel %eax, %r14d
movl %r14d, 0x4(%rsp)
addl 0x6da54(%rip), %ecx     # 0x7c0e0
movl %ecx, 0x8(%rsp)
jg 0xe69f
movl $0x1, 0x8(%rsp)
movl $0x1, %ecx
cmpl %r14d, %ecx
jle 0xe6a8
movl %ecx, 0x4(%rsp)
leaq 0xda16(%rip), %r14      # 0x1c0c5
leaq 0x30(%rsp), %r15
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x8190
leaq 0xd36e(%rip), %rdi      # 0x1ba3b
movq %r15, %rsi
callq 0x131ed
movl 0x4(%rsp), %ecx
movl $0x100, %esi            # imm = 0x100
movq %r15, %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x8190
leaq 0xd358(%rip), %rdi      # 0x1ba4a
movq %r15, %rsi
callq 0x131ed
movl 0x4(%rsp), %ecx
movl 0x8(%rsp), %eax
cmpl %eax, %ecx
setb %dl
movl 0x18(%rsp), %edi
cmpl $0x2, %edi
setb %sil
movl $0x1, %r14d
orb %dl, %sil
jne 0xe769
movq 0x20(%rsp), %rdx
cmpl $0x1, %edx
adcl $0x0, %edx
cmpl %edi, %edx
cmovael %edi, %edx
movl %ecx, %ecx
cvtsi2sd %rcx, %xmm0
movl %eax, %eax
cvtsi2sd %rax, %xmm1
subsd %xmm1, %xmm0
movl %edi, %eax
cvtsi2sd %rax, %xmm2
addsd 0xe6ca(%rip), %xmm2     # 0x1ce18
divsd %xmm2, %xmm0
decl %edx
xorps %xmm2, %xmm2
cvtsi2sd %rdx, %xmm2
mulsd %xmm0, %xmm2
addsd %xmm1, %xmm2
cvttsd2si %xmm2, %r14
leaq 0xd955(%rip), %rdx      # 0x1c0c5
leaq 0x30(%rsp), %rbx
movl $0x100, %esi            # imm = 0x100
movq %rbx, %rdi
movl %r14d, %ecx
xorl %eax, %eax
callq 0x8190
leaq 0xd2cb(%rip), %rdi      # 0x1ba59
movq %rbx, %rsi
callq 0x131ed
cmpb $0x0, 0x91d77(%rip)     # 0xa0514
je 0xe7c3
movl 0x8(%rsp), %edx
addl %edx, %edx
movl 0x4(%rsp), %ecx
addl %ecx, %ecx
leaq 0xe882(%rip), %rdi      # 0x1d034
leaq 0x91d5b(%rip), %rsi     # 0xa0514
movl %r14d, %r8d
xorl %eax, %eax
callq 0x13337
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq