// File: /workspace/github_c_makefile_star2_O2/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 $0x128, %rsp            # imm = 0x128
movl %edi, %r14d
andl $0x0, 0x1c(%rsp)
movl 0x6e844(%rip), %eax     # 0x7c0ec
movl %eax, 0x4(%rsp)
movl 0x6e83e(%rip), %eax     # 0x7c0f0
movl %eax, (%rsp)
movl 0x6e839(%rip), %eax     # 0x7c0f4
movl %eax, 0x18(%rsp)
callq 0x13d00
movl %eax, 0x8(%rsp)
callq 0x12f75
movq %rax, %r15
leaq 0xe6e4(%rip), %rsi      # 0x1bfbb
movq %rax, %rdi
callq 0x8220
testl %eax, %eax
je 0xd8fa
leaq 0xd70d(%rip), %rsi      # 0x1aff7
movq %r15, %rdi
callq 0x8220
testl %eax, %eax
jne 0xddc9
movsd 0x6e7fe(%rip), %xmm0    # 0x7c100
movsd %xmm0, 0x10(%rsp)
callq 0x13640
movq %rax, %rbx
callq 0x13664
movq %rax, %r13
callq 0x1372b
movl %eax, %r12d
movsbl %al, %r15d
leaq 0xe62e(%rip), %rsi      # 0x1bf59
leaq 0xe694(%rip), %rdx      # 0x1bfc6
xorl %ebp, %ebp
pushq $0x2
popq %rdi
movq %rbx, %rcx
movq %r13, %r8
movl %r15d, %r9d
xorl %eax, %eax
callq 0x1920b
leaq 0x6e7ba(%rip), %rdi     # 0x7c108
addq $-0x400, %rbp           # imm = 0xFC00
cmpq $-0x20400, %rbp         # imm = 0xFFFDFC00
je 0xda88
leaq 0x400(%rdi), %rbx
movq %r13, %rsi
callq 0x8360
movq %rbx, %rdi
testq %rax, %rax
je 0xd94e
leaq 0x6e768(%rip), %r13     # 0x7c0e8
subq %rbp, %r13
addq $-0x3e0, %r13           # imm = 0xFC20
leaq 0xd7bd(%rip), %rdx      # 0x1b14e
pushq $0x1
popq %rsi
movq %r13, %rdi
callq 0xed9c
testq %rax, %rax
je 0xd9c1
leaq 0xd71d(%rip), %rsi      # 0x1b0c5
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %ebx, %ebx
cmpl $0x1, %eax
setne %bl
jmp 0xd9c3
xorl %ebx, %ebx
leaq 0xd784(%rip), %rdx      # 0x1b14e
pushq $0x2
popq %rsi
movq %r13, %rdi
callq 0xed9c
testq %rax, %rax
je 0xd9f8
leaq 0xd6e4(%rip), %rsi      # 0x1b0c5
movq %rsp, %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %ecx, %ecx
cmpl $0x1, %eax
setne %cl
orl %ecx, %ebx
leaq 0xd74f(%rip), %rdx      # 0x1b14e
pushq $0x3
popq %rsi
movq %r13, %rdi
callq 0xed9c
testq %rax, %rax
je 0xda2f
leaq 0xe68a(%rip), %rsi      # 0x1c0a0
leaq 0x10(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
xorl %ecx, %ecx
cmpl $0x1, %eax
setne %cl
orl %ecx, %ebx
addb $-0x41, %r12b
cmpb $0x19, %r12b
ja 0xda80
testl %ebx, %ebx
jne 0xda80
addl $-0x3d, %r15d
leaq 0xd706(%rip), %rdx      # 0x1b14e
movq %r13, %rdi
movl %r15d, %esi
callq 0xed9c
testq %rax, %rax
je 0xda88
leaq 0xd666(%rip), %rsi      # 0x1b0c5
leaq 0x1c(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %eax
jne 0xddc9
movl 0x1c(%rsp), %eax
addl %eax, (%rsp)
jmp 0xda88
testl %ebx, %ebx
jne 0xddc9
leaq 0xd01c(%rip), %rdi      # 0x1aaab
xorl %esi, %esi
callq 0x17172
testq %rax, %rax
jne 0xdb15
movsd 0x10(%rsp), %xmm0
leaq 0xe4b1(%rip), %rsi      # 0x1bf59
leaq 0xe546(%rip), %rdx      # 0x1bff5
pushq $0x2
popq %rdi
movb $0x1, %al
callq 0x1920b
movsd 0x10(%rsp), %xmm0
leaq 0xe5da(%rip), %rdx      # 0x1c0a0
leaq 0x20(%rsp), %rbx
movl $0x100, %esi            # imm = 0x100
movq %rbx, %rdi
movb $0x1, %al
callq 0x8190
leaq 0xcfbd(%rip), %rdi      # 0x1aa9e
movq %rbx, %rsi
callq 0x12464
cmpb $0x0, 0x92a24(%rip)     # 0xa0514
je 0xdb15
movsd 0x10(%rsp), %xmm0
mulsd 0xcbd8(%rip), %xmm0     # 0x1a6d8
leaq 0xe50b(%rip), %rdi      # 0x1c012
leaq 0x92a06(%rip), %rsi     # 0xa0514
movb $0x1, %al
callq 0x125a8
leaq 0xcf49(%rip), %rdi      # 0x1aa65
xorl %ebx, %ebx
xorl %esi, %esi
callq 0x17172
testq %rax, %rax
je 0xdc44
movl 0x1bf8c(%rip), %ecx     # 0x29ac0
cmpl $-0x1, %ecx
setne %al
testl %r14d, %r14d
sete %dl
testb %al, %dl
jne 0xdb6d
leaq 0xe59c(%rip), %rdi      # 0x1c0e7
callq 0x12469
leaq 0xe596(%rip), %rsi      # 0x1c0ed
movq %rax, %rdi
callq 0x83c0
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
movl %ecx, 0x1bf53(%rip)     # 0x29ac0
testl %ecx, %ecx
je 0xdca8
leaq 0xcebf(%rip), %rdi      # 0x1aa3b
callq 0x12469
leaq 0xd53d(%rip), %rbx      # 0x1b0c5
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x82d0
movl %eax, %r14d
leaq 0xcea6(%rip), %rdi      # 0x1aa4a
callq 0x12469
movq %rsp, %rdx
movq %rax, %rdi
movq %rbx, %rsi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %r14d
jne 0xddc9
cmpl $0x1, %eax
jne 0xddc9
movl 0x4(%rsp), %edx
movl (%rsp), %esi
cmpl %esi, %edx
je 0xddc9
movl 0x8(%rsp), %edi
movl 0x18(%rsp), %ecx
callq 0xe18f
movl %eax, %ebx
leaq 0xd4d4(%rip), %rdx      # 0x1b0c5
leaq 0x20(%rsp), %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
movl %eax, %ecx
xorl %eax, %eax
callq 0x8190
leaq 0xce4b(%rip), %rdi      # 0x1aa59
movq %r14, %rsi
callq 0x12464
movl 0x4(%rsp), %ecx
movl (%rsp), %r8d
movsd 0x10(%rsp), %xmm0
leaq 0xe32e(%rip), %rsi      # 0x1bf59
leaq 0xe41e(%rip), %rdx      # 0x1c050
pushq $0x2
popq %rdi
movl %ebx, %r9d
movb $0x1, %al
callq 0x1920b
jmp 0xdd9d
movl 0x4(%rsp), %ecx
movl (%rsp), %r8d
leaq 0xe306(%rip), %rsi      # 0x1bf59
leaq 0xe3cd(%rip), %rdx      # 0x1c027
pushq $0x2
popq %rdi
xorl %eax, %eax
callq 0x1920b
andl $0x0, 0xc(%rsp)
leaq 0x92498(%rip), %rdi     # 0xa0108
leaq 0xd4d7(%rip), %rdx      # 0x1b14e
movl 0x8(%rsp), %esi
callq 0xed9c
testq %rax, %rax
je 0xdcd8
leaq 0xd439(%rip), %rsi      # 0x1b0c5
xorl %ebx, %ebx
leaq 0xc(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x82d0
cmpl $0x1, %eax
jne 0xdcd3
movl 0xc(%rsp), %ebx
jmp 0xdcd8
movl 0x4(%rsp), %ecx
movl (%rsp), %r8d
movsd 0x10(%rsp), %xmm0
leaq 0xe29c(%rip), %rsi      # 0x1bf59
leaq 0xe3e0(%rip), %rdx      # 0x1c0a4
pushq $0x2
popq %rdi
movb $0x1, %al
callq 0x1920b
jmp 0xddc9
andl $0x0, 0xc(%rsp)
movl 0x4(%rsp), %ecx
addl %ebx, %ecx
addl (%rsp), %ebx
addl 0x6e3fd(%rip), %ebx     # 0x7c0e4
movl 0x6e40b(%rip), %eax     # 0x7c0f8
cmpl %eax, %ebx
cmovgel %eax, %ebx
movl %ebx, (%rsp)
addl 0x6e3e5(%rip), %ecx     # 0x7c0e0
movl %ecx, 0x4(%rsp)
jg 0xdd0c
pushq $0x1
popq %rcx
movl $0x1, 0x4(%rsp)
cmpl %ebx, %ecx
jle 0xdd13
movl %ecx, (%rsp)
leaq 0xd3ab(%rip), %r15      # 0x1b0c5
leaq 0x20(%rsp), %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
movq %r15, %rdx
xorl %eax, %eax
callq 0x8190
leaq 0xcd03(%rip), %rdi      # 0x1aa3b
movq %r14, %rsi
callq 0x12464
movl (%rsp), %ecx
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
movq %r15, %rdx
xorl %eax, %eax
callq 0x8190
leaq 0xccee(%rip), %rdi      # 0x1aa4a
movq %r14, %rsi
callq 0x12464
movl (%rsp), %esi
movl 0x4(%rsp), %edx
movl 0x8(%rsp), %edi
movl 0x18(%rsp), %ecx
callq 0xe18f
movl %eax, %ebx
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
movq %r15, %rdx
movl %eax, %ecx
xorl %eax, %eax
callq 0x8190
leaq 0xccc4(%rip), %rdi      # 0x1aa59
movq %r14, %rsi
callq 0x12464
cmpb $0x0, 0x92770(%rip)     # 0xa0514
je 0xddc9
movl 0x4(%rsp), %edx
addl %edx, %edx
movl (%rsp), %ecx
addl %ecx, %ecx
leaq 0xe284(%rip), %rdi      # 0x1c03c
leaq 0x92755(%rip), %rsi     # 0xa0514
movl %ebx, %r8d
xorl %eax, %eax
callq 0x125a8
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq