/******************************************************************************
Online C++ Compiler.
Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <iostream>
#include <string>
#include <random>
#include <algorithm>
#include <vector>
#include <functional>
#include <cassert>
// make a six-sided die
auto rng = std::mt19937( std::random_device{}() );
auto dist = std::uniform_int_distribution<int>( 1,6 );
auto d6 = std::bind( dist,std::ref( rng ) );
struct EngageResult
{
int attackCasualties;
int defendCasualties;
std::vector<int> attackRolls;
std::vector<int> defendRolls;
};
EngageResult Engage( int attackerArmies,int defenderArmies )
{
assert( attackerArmies <= 3 && attackerArmies > 0 );
assert( defenderArmies <= 2 && defenderArmies > 0 );
std::vector<int> attackRolls( attackerArmies );
std::vector<int> defendRolls( defenderArmies );
// roll those dice
std::generate( attackRolls.begin(),attackRolls.end(),d6 );
std::generate( defendRolls.begin(),defendRolls.end(),d6 );
// sort *descending*
std::sort( attackRolls.begin(),attackRolls.end(),std::greater<int>{} );
std::sort( defendRolls.begin(),defendRolls.end(),std::greater<int>{} );
// count the casualties
EngageResult res = { 0,0 };
const int nSkirmishes = std::min( attackerArmies,defenderArmies );
for( int i = 0; i < nSkirmishes; i++ )
{
if( attackRolls[i] > defendRolls[i] )
{
res.defendCasualties++;
}
else
{
res.attackCasualties++;
}
}
// move the rolls into result so they can also be displayed
res.attackRolls = std::move( attackRolls );
res.defendRolls = std::move( defendRolls );
return res;
}
int main()
{
int attackTotalArmies;
int defendTotalArmies;
std::cout << "Enter # of armies in attackers territory: ";
std::cin >> attackTotalArmies;
std::cout << "Enter # of armies in defender's territory: ";
std::cin >> defendTotalArmies;
if( attackTotalArmies < 1 || defendTotalArmies < 1 )
{
std::cout << "Error: impossible to have less than 1 army in territory!\n";
return 0;
}
while( true )
{
if( attackTotalArmies <= 1 )
{
std::cout << "Attacker lacks sufficient armies to mount assault. Aborting battle.\n";
break;
}
int attackArmies;
std::cout << "How many armies to attack with? ";
std::cin >> attackArmies;
if( attackArmies > attackTotalArmies - 1 || attackArmies < 1 || attackArmies > 3 )
{
std::cout << "You cannot attack with that number of armies\n";
continue;
}
int defendArmies;
std::cout << "How many armies to defend with? ";
std::cin >> defendArmies;
if( defendArmies > defendTotalArmies || defendArmies < 1 || defendArmies > 2 )
{
std::cout << "You cannot defend with that number of armies\n";
continue;
}
const auto result = Engage( attackArmies,defendArmies );
attackTotalArmies -= result.attackCasualties;
defendTotalArmies -= result.defendCasualties;
std::cout << "Rolling...\nAttacker: ";
for( int r : result.attackRolls ) { std::cout << r << " ";}
std::cout << "\nDefender: ";
for( int r : result.defendRolls ) { std::cout << r << " ";}
std::cout << "\nAttacker's losses: " << result.attackCasualties << std::endl;
std::cout << "Defender's losses: " << result.defendCasualties << std::endl;
std::cout << "[Remaining armies] Attacker: " << attackTotalArmies <<
" Defender: " << defendTotalArmies << std::endl;
if( defendTotalArmies == 0 )
{
std::cout << "Defending forces crushed! Attacker moves " <<
attackArmies - result.attackCasualties << " armies into defender's territory.\n";
break;
}
char yn;
std::cout << "Does attacker continue (y/n)? ";
std::cin >> yn;
if( yn == 'n' )
{
std::cout << "Aborting attack.\n";
break;
}
}
return 0;
}