Reputation: 103
I've been writing this game to just type in the amount of humans and skeletons with a random attack chance. If you enter in the same amount when running the program over and over it generates the same amount. Why isn't the hitChance/random attack amount changing everytime the while loop restarts? When I print the attackChance(randGen) in the while loop it changes. Why isn't the randGen changing the output of the winner of the battle?
#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;
int getNumSkeletons();
int getNumHumans();
void finishedBattleStats(int numHumans, int startHumans, int numSkeletons, int startSkeletons);
void simulatedBattle(int &numSkeletons, int &numHumans, int &startHumans, int &startSkeletons);
int main() {
int startHumans;
int startSkeletons;
int numHumans;
int numSkeletons;
cout << "------------------------------------\nSkeletons V Humans\n\n";
//Gets Number of Humans
numHumans = getNumHumans();
startHumans = numHumans;
//Gets Number of Skeletons
numSkeletons = getNumHumans();
startSkeletons = numSkeletons;
//Simulates Battle
simulatedBattle(numSkeletons, numHumans, startHumans, startSkeletons);
//End Battle Stats
finishedBattleStats(numHumans, startHumans, numSkeletons, startSkeletons);
cin.get();
return 0;
}
int getNumHumans() {
int numHumans;
cout << "Enter number of Humans: \n";
cin >> numHumans;
return numHumans;
}
int getNumSkeletons() {
int numSkeletons;
cout << "Enter number of Skeletons: \n";
cin >> numSkeletons;
return numSkeletons;
}
void simulatedBattle(int &numSkeletons, int &numHumans, int &startHumans, int &startSkeletons) {
static mt19937 randGen(time(NULL));
uniform_real_distribution<float> attackChance(0.0f, 1.0f);
//HumanProperties
float humanDamage = 30.0f;
float humanHitChance = 0.6f;
float humanCritChance = 0.2f;
float humanHealth = 50.0f;
float startHumanHealth = humanHealth;
float currentHuman = startHumanHealth;
//Skeleton Properties
float skeletonDamage = 20.0f;
float skeletonHitChance = 0.7f;
float skeletonCritChance = 0.2f;
float skeletonHealth = 40.0f;
float startSkeletonHealth = skeletonHealth;
float currentSkeleton = startSkeletonHealth;
char turn = 'H';
float hitChance;
while (numSkeletons > 0 && numHumans > 0) {
hitChance = attackChance(randGen);
if (turn == 'H') {
if (hitChance > humanHitChance) {
currentSkeleton -= humanDamage;
turn = 'S';
if (currentSkeleton < 0) {
numHumans--;
currentSkeleton = startSkeletonHealth;
turn = 'S';
}
}
}
else {
if (hitChance > skeletonHitChance) {
currentHuman -= skeletonDamage;
turn = 'H';
}
if (currentHuman < 0) {
numSkeletons--;
currentHuman = startHumanHealth;
turn = 'H';
}
}
}
}
void finishedBattleStats(int numHumans, int startHumans, int numSkeletons, int startSkeletons) {
if (numHumans == 0) {
cout << "Skeletons won! \n\n";
cout << "Skeletons left: " << numSkeletons << endl;
cout << "Skeleton Casualties: " << startSkeletons - numSkeletons << endl;
cout << "All " << startHumans << " humans are dead! \n\n";
cout << "Game Over!";
cin.get();
}
else {
cout << "Humans Won! \n\n";
cout << "Humans left: " << numHumans << endl;
cout << "Human Casualties: " << startHumans - numHumans << endl;
cout << "All " << startSkeletons << " skeletons are dead! \n\n";
cout << "Game Over!";
cin.get();
}
}
Upvotes: 0
Views: 454
Reputation: 42909
IMHO opinion you have a flaw in the battle calculations. That is, when a human's healths goes < 0 you subtract a skeleton and not a human and vice versa. Below is the correction. With a demo. I tried the demo a number of times and gives different results (ENJOY):
void simulatedBattle(int &numSkeletons, int &numHumans, int &startHumans, int &startSkeletons) {
uniform_real_distribution<float> attackChance(0.0f, 1.0f);
static mt19937 randGen(time(NULL));
//HumanProperties
float humanDamage = 25.0f;
float humanHitChance = 0.2f;
float humanCritChance = 0.2f;
float humanHealth = 50.0f;
float startHumanHealth = humanHealth;
float currentHuman = startHumanHealth;
//Skeleton Properties
float skeletonDamage = 20.0f;
float skeletonHitChance = 0.8f;
float skeletonCritChance = 0.2f;
float skeletonHealth = 40.0f;
float startSkeletonHealth = skeletonHealth;
float currentSkeleton = startSkeletonHealth;
char turn = 'H';
float hitChance;
while (numSkeletons > 0 && numHumans > 0) {
hitChance = attackChance(randGen);
if (turn == 'H') {
if (hitChance > humanHitChance) {
currentSkeleton -= humanDamage;
if (currentSkeleton < 0) {
--numSkeletons;
currentSkeleton = startSkeletonHealth;
}
turn = 'S';
}
}
else {
if (hitChance > skeletonHitChance) currentHuman -= skeletonDamage;
if (currentHuman < 0) {
--numHumans;
currentHuman = startHumanHealth;
}
turn = 'H';
}
}
}
Upvotes: 2
Reputation: 1030
You have to seed
a mersenne twister before use, or you'll always have the same output.
It is common practice to seed it with the internal clock:
// obtain a seed from the timer
myclock::duration d = myclock::now() - beginning;
unsigned seed2 = d.count();
generator.seed (seed2);
ref: std::mersenne_twister_engine::seed
Upvotes: 0