#include <string>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>

struct shooter
{
    std::string name ;
    double accuracy ;
    bool alive ;
};

void shoot(const shooter& source, shooter& target) ;
void resurrect(shooter[], unsigned) ;
unsigned duel(shooter[], unsigned) ;

int main()
{
    std::srand(static_cast<unsigned>(std::time(0))) ;
    const unsigned trials = 100000 ;

    // The order of shooters is important.  It determines the sequence of attempts at shooting.
    // lowest index goes first.
    shooter shooters[] =
    {
        // {"Sue", 0.20, true},
        {"Aaron", 0.33, true},
        {"Bob", 0.50, true},
        {"Charlie", 1.0, true}
    };

    const unsigned nShooters = sizeof(shooters) / sizeof(shooters[0]) ;

    unsigned wins[nShooters] = {} ;

    for ( unsigned i=0; i<trials; ++i )
    {
        resurrect(shooters, nShooters) ;
        ++wins[duel(shooters,nShooters)] ;
    }

    for ( unsigned i=0; i<nShooters; ++i )
    {
        std::cout << std::left << std::setw(10) << shooters[i].name
                  << std::right << std::setw(6) << wins[i] << " (" 
                  << std::fixed << std::setprecision(1) << std::setw(4) 
                  << (wins[i] / static_cast<double>(trials))*100 << "%)\n" ;
    }
}

void shoot(const shooter& source, shooter& target)
{
    if ( ((std::rand() % 100) * 0.01 ) < source.accuracy )
        target.alive = false ;
}

void resurrect(shooter shooters[], unsigned size)
{
    for ( unsigned i=0; i<size; ++i )
        shooters[i].alive = true ;
}

bool onlyOneAlive(shooter shooters[], unsigned size)
{
    unsigned alive = 0 ;
    for ( unsigned i=0; i<size; ++i )
        if ( shooters[i].alive )
            ++alive ;

    return alive == 1 ;
}

// PRE:  size is greater than 0.
//       At least two of shooters[i].alive are true.
unsigned findTarget(shooter shooters[], unsigned size, const shooter& source)
{
    unsigned index = 0 ;

    while ( !shooters[index].alive || shooters[index].name == source.name )
        ++index ;

    unsigned target = index ;

    while ( ++index < size )
    {
        if ( shooters[index].alive && shooters[index].name != source.name )
            if ( shooters[index].accuracy > shooters[target].accuracy )
                target = index ;
    }

    return target ;
}

// PRE:  size is greater than 0.
//       Exactly one of shooters[i].alive is true.
unsigned winner(shooter shooters[], unsigned size)
{
    for ( unsigned i=0; i<size; ++i )
        if ( shooters[i].alive )
            return i ;

    return size ; // to quell a compiler warning.
}

// PRE:  size is greater than 0.
//       At least one of shooters[i].alive is true.
unsigned nextAlive(shooter shooters[], unsigned size, unsigned index)
{
    do
    {
        index = (index+1) % size ;
    } while (!shooters[index].alive) ;
 
    return index ;
}

// PRE:  size is greater than 0.
//       At least one of shooters[i].alive is true.
unsigned duel(shooter shooters[], unsigned size)
{
    unsigned turn = 0 ;
    while (!onlyOneAlive(shooters,size))
    {
        unsigned targetIndex = findTarget(shooters, size, shooters[turn]) ;
        shoot(shooters[turn], shooters[targetIndex]) ;

        turn = nextAlive(shooters, size, turn) ;
    }

    return winner(shooters, size) ;
}