// File: /workspace/github_cpp_makefile_star2_O2/MichaelXanth[P]RPG_Game/Game/Game.cpp
// Function: Game::StartBattle()
void Game::StartBattle(void)
{
    vector<Monster *> monsters;
    short extraMonsters = rand() % 3;
    unsigned int lvlOfEM = 0;
    unsigned int generalLvlOfMon = 0;
    bool  battleOver  = false;
    short faints      = 0;
    bool  heroesWon   = false;
    bool  monstersWon = false;

    int  arrow     = 0;
    char selection = ' ';

    /* If the heroes are below level 5 then the number of monsters that appear 
     * is equal to the number of heroes. Over level 5 the number of monsters 
     * can be increased by 2 extra monsters.
     */
    if (heroes[0]->GetLevel() > 4)
        extraMonsters = rand() % 3;
    else
        extraMonsters = 0;

    for (short i = 0; i < heroes.size(); i++) {
        monsters.push_back(Battle::FindMonster(heroes[i]->GetLevel()));
        lvlOfEM += heroes[i]->GetLevel();
    }

    generalLvlOfMon += lvlOfEM;
    lvlOfEM = lvlOfEM / heroes.size(); /* calculates the average of the 3 heroes */

    for (short i = 0; i < extraMonsters; i++) {
        monsters.push_back(Battle::FindMonster(floor(lvlOfEM))); //creates a monster
        generalLvlOfMon += floor(lvlOfEM);
    }

    generalLvlOfMon = generalLvlOfMon / (extraMonsters + heroes.size()); //the average of all monsters

    unsigned int level = 0;

    while(battleOver == false) {
        bool res = true;

        for (short int j = 0; j < heroes.size(); j++) {
            if (res == true /*&& selection != 'c'*/) {
                cout << "\033[2J\033[1;1H";

                if (monsters.size() > heroes.size())
                    cout << "\033[" << ((monsters.size() - 1) * 31) / 2 + 7 << "C";
                else
                    cout << "\033[" << ((heroes.size() - 1) * 31) / 2 + 7 << "C";

                if (j == 0)
                    level++;

                cout << "---> Round " << level << " <---" << endl << endl;

                DisplayAllStats(monsters);
            }

            if (heroes[j]->Fainted() == false)
            {

                if (res == false && selection == 'c')
                    cout << "\033[3A";

                cout << "Press 'c' to skip this Hero" << endl;
                cout << "Hero " << j + 1 << ": \033[38;5;220m" << heroes[j]->GetName() << "\033[0m" << endl;
                cout << "\033[J" << endl;

                do {

                    if (res == false && selection == '\n') {
                        cout << "\033[6A";
                        cout << "\033[J";
                        cout << "Choose a new action: " << endl;
                    }

                    // Displays and handles the arrow menu
                    do {
                        DisplayActions(arrow);

                        selection = getch();

                        if (selection == 'w' && arrow)
                            arrow--;
                        else if (selection == 's' && arrow < 4)
                            arrow++;

                        if (selection != '\n')
                            cout << "\033[5A";

                        if (selection == 'c' && j == heroes.size() - 1)
                            cout << "\033[5B";

                    }while(selection != 'c' && selection != '\n');

                    if (selection == 'c')
                        break;

                } while((res = ChooseAction(*heroes[j],arrow + 1,monsters)) == false);

                if (selection == 'c') {
                    if (j < heroes.size() - 1) /* If a hero was skipped we disable the screen refresh */
                        res = false;          /* only if we are not at the last hero of the current round */
                    else
                        res = true;           /* We set the 'res' var to TRUE for enabling the screen refresh for the next round */

                    continue;
                }

                if (res == true)
                    cout << "\033[8A\033[J";

                // When the vector of monsters is empty then heroes won
                if (monsters.empty() == true) {
                    heroesWon = true;
                    monstersWon = false;
                    break;
                }
            
            } else {
                cout << "\033[35mWarning:\033[0m Hero \033[38;5;220m" << heroes[j]->GetName() << "\033[0m has fainted." << endl;
                usleep(1500000);
                cout << "\033[1A\033[K";
            }
        }

        for (short int j = 0 ; j < monsters.size() ; j++)
        {
            short chance = rand() % heroes.size();

            if (heroes[chance]->Fainted() == false) {
                Battle::MonsterAttack(*monsters[j], *heroes[chance]);//monster attacks a random hero

                if (heroes[chance]->Fainted() == true)
                    faints++;

                // If all heroes faint then monsters win
                if (faints == heroes.size()) {
                    monstersWon = true;
                    heroesWon = false;
                    break;
                }
            }
            else
                j--;
        }

        if (heroesWon == true && monstersWon == false) {
            battleOver = true;
            
            // When the heroes win then they gain experience and money
            for (int k = 0; k < heroes.size(); k++) {
                
                // If a hero faints the they are restored to half HP
                if (heroes[k]->Fainted() == true)
                    heroes[k]->RestoreToHalfHP();

                if (heroes[k]->GetLevel() < 100)
                    heroes[k]->GainXP(ceil((double)generalLvlOfMon * (extraMonsters + heroes.size()) / 10));
                heroes[k]->ChangeMoney(2 * generalLvlOfMon * (extraMonsters + heroes.size()));
            }
            break;
        
        } else if (heroesWon == false && monstersWon == true) {
            battleOver = true;
            
            // If the heroes lose then they lose half their money and are restore to half HP
            for (int k = 0; k < heroes.size(); k++) {
                heroes[k]->ChangeMoney(-(heroes[k]->GetMoney() / 2));
                heroes[k]->RestoreToHalfHP();
            }
            break;
        }

        // Heroes and monsters alike get back some of their HP
        for (int c = 0; c < heroes.size(); c++) {
            if (heroes[c]->Fainted() == false)
                heroes[c]->EndTurnRefill();
        }

        for (int c = 0; c < monsters.size(); c++)
            monsters[c]->EndRound();
    }

    // If monsters win then they are deleted since they are not needed anymore
    for (int i = monsters.size(); !monsters.empty(); i--) {
        delete monsters[i - 1];
        monsters.erase(monsters.begin() + i - 1);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdi, %r13
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
andq $0x0, 0x30(%rsp)
callq 0x3060
movq 0x10(%r13), %rax
movq (%rax), %rax
movq (%rax), %rdi
callq 0xcef2
xorl %ebx, %ebx
movl $0x0, %ebp
cmpl $0x5, %eax
jb 0x9d01
callq 0x3060
pushq $0x3
popq %rcx
cltd
idivl %ecx
movl %edx, %ebp
leaq 0x20(%rsp), %r14
leaq 0x68(%rsp), %r15
xorl %r12d, %r12d
movswq %r12w, %r12
movq 0x10(%r13), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r12, %rcx
jbe 0x9d60
movq (%rax,%r12,8), %rdi
callq 0xcef2
movl %eax, %edi
callq 0x912e
movq %rax, 0x68(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0xbdfe
movq 0x10(%r13), %rax
movq (%rax), %rax
movq (%rax,%r12,8), %rdi
callq 0xcef2
addl %eax, %ebx
incl %r12d
jmp 0x9d0e
movl %ebx, %eax
xorl %esi, %esi
xorl %edx, %edx
divq %rcx
movq %rax, %r14
testw %bp, %bp
movl %ebp, %r15d
cmovlel %esi, %r15d
leaq 0x68(%rsp), %r12
subw $0x1, %r15w
jb 0x9da1
movl %r14d, %edi
callq 0x912e
movq %rax, 0x68(%rsp)
leaq 0x20(%rsp), %rdi
movq %r12, %rsi
callq 0xbdfe
addl %r14d, %ebx
jmp 0x9d7b
movl %ebx, %eax
movswq %bp, %rdx
movq %r13, 0x10(%rsp)
movq 0x10(%r13), %rcx
movq 0x8(%rcx), %rsi
subq (%rcx), %rsi
sarq $0x3, %rsi
movq %rdx, 0x60(%rsp)
addq %rdx, %rsi
movq $0x0, 0x50(%rsp)
xorl %edx, %edx
divq %rsi
movq %rax, 0x58(%rsp)
movb $0x20, 0xf(%rsp)
movq 0x1d1e6(%rip), %r12     # 0x26fc8
leaq 0x68(%rsp), %r13
leaq 0x1163f(%rip), %r14     # 0x1b42d
movq $0x0, 0x48(%rsp)
xorl %r15d, %r15d
movl $0x0, 0x44(%rsp)
movb $0x1, 0x18(%rsp)
xorl %ebp, %ebp
movswq %bp, %rbx
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbx, %rcx
jbe 0xa1ad
testb $0x1, 0x18(%rsp)
je 0x9f23
movq %r12, %rdi
leaq 0x1158e(%rip), %rsi     # 0x1b3d0
callq 0x31d0
movq 0x28(%rsp), %rax
subq 0x20(%rsp), %rax
movq 0x10(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq 0x8(%rcx), %rdx
subq (%rcx), %rdx
cmpq %rdx, %rax
jbe 0x9e7c
movq %r12, %rdi
leaq 0x1156b(%rip), %rsi     # 0x1b3db
callq 0x31d0
leaq 0x20(%rsp), %rcx
jmp 0x9e94
movq %r12, %rdi
leaq 0x11555(%rip), %rsi     # 0x1b3db
callq 0x31d0
movq 0x10(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq 0x8(%rcx), %rdx
subq (%rcx), %rdx
sarq $0x3, %rdx
imulq $0x1f, %rdx, %rsi
addq $-0x1f, %rsi
shrq %rsi
addq $0x7, %rsi
movq %rax, %rdi
callq 0x3120
movq %rax, %rdi
leaq 0x14916(%rip), %rsi     # 0x1e7d6
callq 0x31d0
cmpw $0x1, %bp
adcl $0x0, 0x44(%rsp)
movq %r12, %rdi
leaq 0x11506(%rip), %rsi     # 0x1b3de
callq 0x31d0
movl 0x44(%rsp), %esi
movq %rax, %rdi
callq 0x3120
movq %rax, %rdi
leaq 0x114f7(%rip), %rsi     # 0x1b3ea
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movq %rax, %rdi
callq 0x30d0
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0xa50a
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rdi
callq 0xcecc
testb %al, %al
je 0x9fa2
movq %r12, %rdi
leaq 0x11505(%rip), %rsi     # 0x1b43f
callq 0x31d0
movq %rax, %rbp
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rsi
movq %r13, %rdi
callq 0xced6
movq %rbp, %rdi
movq %r13, %rsi
callq 0x3190
movq %rax, %rdi
leaq 0x114f3(%rip), %rsi     # 0x1b462
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movq %r13, %rdi
callq 0x30c0
movl $0x16e360, %edi         # imm = 0x16E360
callq 0x32a0
movq %r12, %rdi
leaq 0x14ff6(%rip), %rsi     # 0x1ef8e
callq 0x31d0
jmp 0xa19d
movb 0x18(%rsp), %cl
andb $0x1, %cl
movb 0xf(%rsp), %al
xorb $0x63, %al
movb %cl, 0x18(%rsp)
orb %cl, %al
jne 0x9fc6
movq %r12, %rdi
leaq 0x113d0(%rip), %rsi     # 0x1b391
callq 0x31d0
movq %r12, %rdi
leaq 0x11420(%rip), %rsi     # 0x1b3f0
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movq %r12, %rdi
leaq 0x11425(%rip), %rsi     # 0x1b40c
callq 0x31d0
leal 0x1(%rbx), %esi
movq %rax, %rdi
callq 0x3320
movq %rax, %rdi
leaq 0x1137a(%rip), %rsi     # 0x1b37b
callq 0x31d0
movq %rax, %rbp
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rsi
movq %r13, %rdi
callq 0xced6
movq %rbp, %rdi
movq %r13, %rsi
callq 0x3190
movq %rax, %rdi
leaq 0x13dae(%rip), %rsi     # 0x1dde4
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movq %r13, %rdi
callq 0x30c0
movq %r12, %rdi
leaq 0x1374e(%rip), %rsi     # 0x1d7a3
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movb 0xf(%rsp), %al
xorb $0xa, %al
orb %al, 0x18(%rsp)
sete %cl
testb $0x1, %cl
je 0xa0a9
movq %r12, %rdi
leaq 0x11394(%rip), %rsi     # 0x1b412
callq 0x31d0
movq %r12, %rdi
leaq 0x13716(%rip), %rsi     # 0x1d7a3
callq 0x31d0
movq %r12, %rdi
leaq 0x1137b(%rip), %rsi     # 0x1b417
callq 0x31d0
movq %rax, %rdi
callq 0x30d0
movl %r15d, 0x68(%rsp)
movq %r13, %rsi
xorl %edx, %edx
callq 0x9b2e
callq 0xcd74
movl %eax, %ebp
cmpb $0x77, %al
jne 0xa0cd
testl %r15d, %r15d
je 0xa0cd
decl %r15d
jmp 0xa0e9
cmpb $0x73, %bpl
sete %al
cmpl $0x4, %r15d
setl %cl
andb %al, %cl
movzbl %cl, %eax
addl %eax, %r15d
cmpb $0xa, %bpl
je 0xa0fc
movq %r12, %rdi
movq %r14, %rsi
callq 0x31d0
cmpb $0x63, %bpl
jne 0xa0a9
jmp 0xa14e
movq 0x10(%rsp), %rdi
movq 0x10(%rdi), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rsi
leal 0x1(%r15), %eax
movswl %ax, %edx
leaq 0x20(%rsp), %rcx
callq 0xa53a
movb $0x1, %cl
testb %al, %al
je 0xa06f
movq %r12, %rdi
leaq 0x11306(%rip), %rsi     # 0x1b437
callq 0x31d0
movq 0x20(%rsp), %rax
movb $0xa, 0xf(%rsp)
movb $0x1, 0x18(%rsp)
cmpq 0x28(%rsp), %rax
jne 0xa19d
jmp 0xa1a6
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rcx
movq 0x8(%rcx), %rax
subq (%rcx), %rax
sarq $0x3, %rax
decq %rax
cmpq %rbx, %rax
jne 0xa190
movq %r12, %rdi
leaq 0x112be(%rip), %rsi     # 0x1b432
callq 0x31d0
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rcx
movq 0x8(%rcx), %rax
subq (%rcx), %rax
sarq $0x3, %rax
decq %rax
cmpq %rbx, %rax
setbe 0x18(%rsp)
movb $0x63, 0xf(%rsp)
incl %ebx
movl %ebx, %ebp
jmp 0x9e09
movb $0x1, %al
movq %rax, 0x48(%rsp)
xorl %ebx, %ebx
movswq %bx, %rbp
movq 0x28(%rsp), %rax
subq 0x20(%rsp), %rax
sarq $0x3, %rax
cmpq %rbp, %rax
jbe 0xa275
movq %r13, %r12
movq %r14, %r13
callq 0x3060
cltq
movq 0x10(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq (%rcx), %rsi
movq 0x8(%rcx), %rcx
subq %rsi, %rcx
sarq $0x3, %rcx
xorl %edx, %edx
divq %rcx
movswq %dx, %r14
movq (%rsi,%r14,8), %rdi
callq 0xcecc
testb %al, %al
je 0xa208
decl %ebx
jmp 0xa261
movq 0x20(%rsp), %rax
movq (%rax,%rbp,8), %rdi
movq 0x10(%rsp), %rbp
movq 0x10(%rbp), %rax
movq (%rax), %rax
movq (%rax,%r14,8), %rsi
callq 0x967a
movq 0x10(%rbp), %rax
movq (%rax), %rax
movq (%rax,%r14,8), %rdi
callq 0xcecc
movzbl %al, %eax
movq 0x50(%rsp), %rcx
addl %eax, %ecx
movq %rcx, 0x50(%rsp)
movswq %cx, %rax
movq 0x10(%rbp), %rcx
movq 0x8(%rcx), %rdx
subq (%rcx), %rdx
sarq $0x3, %rdx
cmpq %rax, %rdx
je 0xa2ef
incl %ebx
movq %r13, %r14
movq %r12, %r13
movq 0x1cd58(%rip), %r12     # 0x26fc8
jmp 0xa1af
testb $0x1, 0x48(%rsp)
jne 0xa340
xorl %ebx, %ebx
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbx, %rcx
jbe 0xa2c5
movq (%rax,%rbx,8), %rdi
callq 0xcecc
testb %al, %al
jne 0xa2c0
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rdi
callq 0xd646
incq %rbx
jmp 0xa282
xorl %ebx, %ebx
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbx, %rcx
jbe 0x9e02
movq (%rax,%rbx,8), %rdi
callq 0x12956
incq %rbx
jmp 0xa2c7
xorl %ebx, %ebx
movq 0x10(%rsp), %r15
movq 0x10(%r15), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbx, %rcx
jbe 0xa433
movq (%rax,%rbx,8), %r14
movq %r14, %rdi
callq 0xd0a8
shrl %eax
negl %eax
movq %r14, %rdi
movl %eax, %esi
callq 0xd5d0
movq 0x10(%r15), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rdi
callq 0xd5a6
incq %rbx
jmp 0xa2f6
movq 0x58(%rsp), %r13
movl %r13d, %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, 0x18(%rsp)
addq %r13, %r13
xorl %ebx, %ebx
movq 0x10(%rsp), %r15
movq 0x60(%rsp), %r12
movq 0x10(%r15), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %rbx, %rcx
jbe 0xa433
movq (%rax,%rbx,8), %rdi
callq 0xcecc
testb %al, %al
je 0xa39a
movq 0x10(%r15), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rdi
callq 0xd5a6
movq 0x10(%r15), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rdi
callq 0xcef2
cmpl $0x63, %eax
ja 0xa409
movq 0x10(%r15), %rax
movq (%rax), %rcx
movq 0x8(%rax), %rax
movq (%rcx,%rbx,8), %r14
subq %rcx, %rax
sarq $0x3, %rax
addq %r12, %rax
movq %rax, %xmm1
punpckldq 0x10efb(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x10f03(%rip), %xmm1    # 0x1b2e0
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
mulsd 0x18(%rsp), %xmm0
divsd 0x10ef9(%rip), %xmm0    # 0x1b2f0
callq 0x3040
cvttsd2si %xmm0, %rsi
movq %r14, %rdi
callq 0xd5b4
movq 0x10(%r15), %rax
movq (%rax), %rcx
movq 0x8(%rax), %rsi
movq (%rcx,%rbx,8), %rdi
subq %rcx, %rsi
shrq $0x3, %rsi
addl %r12d, %esi
imull %r13d, %esi
callq 0xd5d0
incq %rbx
jmp 0xa362
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rdx
movq %rdx, %rcx
subq %rax, %rcx
shrq $0x3, %rcx
movslq %ecx, %rbx
shlq $0x3, %rbx
movq %rbx, %r14
negq %r14
cmpq %rdx, %rax
je 0xa4ac
movq -0x8(%rax,%rbx), %rdi
testq %rdi, %rdi
je 0xa473
movq (%rdi), %rax
callq *0x18(%rax)
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rdx
leaq (%rax,%rbx), %rsi
cmpq %rdx, %rsi
je 0xa499
leaq (%rax,%rbx), %rdi
addq $-0x8, %rdi
subq %rax, %rdx
addq %r14, %rdx
callq 0x32f0
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rdx
addq $-0x8, %rdx
movq %rdx, 0x28(%rsp)
addq $-0x8, %rbx
addq $0x8, %r14
jmp 0xa454
leaq 0x20(%rsp), %rdi
callq 0xbdca
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4e0
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x30c0
jmp 0xa4f8
jmp 0xa4f5
jmp 0xa4f5
jmp 0xa4f5
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0xbdca
movq %rbx, %rdi
callq 0x3330