# Thread: Help with combat algorithm

1. ## Help with combat algorithm

This is for a personal hobby project of mine, im working on a console based choose your own adventure with free movement between areas using grid coordinats IE [0,0,0] and im working on static monster encounters and the combat portion of it. I would like to do random dice rolls with dmg based on atk/defense of player and monster as well as hitrate, ive already got some starter code i worked on but there is still a fair bit im not able to grasp.

Several of my questions:

Can i use nested if else statements to continue the fight step by step until the monster or players hp is <= 0 and how do i return the value of the dmg done to a players global variable. I would like to pre-set the stats for each individual monster possible have a Combat() function which then loads a Monster function IE Monster001() or Zombie() Skeleton() etc.

How do i calaculate in hit %. I'm using rand() for the dice rolls but how to incorporate % chance the hit is successful.

How do i fetch the value of total dmg from each random dice to subtract it from player / monster hp.

Then after how do i assign pre-decided exp per monster to the player in the event of victory or return the player to a death message if he fails. I'm using nested switchs for the accual menu options in each area and using goto only for Actions and Error/default for the switch. As well as each area has an AREA### goto for certain moves between areas that are oposite the flow of the code.

At some point in the future id also like to assign equipment to an inventory system using strings and and equip feature which adds stats to players stats pre-combat as well.

Here is my current dmg algorith code.

Code:
```#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;
/*
These constants define our upper
and our lower bounds.
*/
int Test = 0;
int MonsterLevel = 1;
int MonsterHitPoints = 15;
int MonsterAttack = 8;
int MonsterDefense = 3;
int PlayerLevel = 1;
int PlayerHitPoints = 25;
int PlayerAttack = 10;
int PlayerDefense = 5;

int LowMonster = 2;
int HighMonster = MonsterAttack - PlayerDefense;
int LowPlayer = 2;
int HighPlayer = PlayerAttack - MonsterDefense;
int main()
{
/*
Variables to hold random values
for the first and the second die on
each roll.
*/
int first_die, sec_die;
/*
Declare variable to hold seconds on clock.
*/
time_t seconds;
/*
Get value from system clock and
place in seconds variable.
*/
time(&seconds);
/*
Convert seconds to a unsigned
integer.
*/
srand((unsigned int) seconds);
/*
Get first and second random numbers.
*/
if ( (MonsterHitPoints >= 1) && (PlayerHitPoints >= 1) )
{
cout << "Monsters & Player Can Fight HP ok.\n";
first_die = rand() % (HighPlayer - LowPlayer + 1) + LowPlayer;
sec_die = rand() % (HighPlayer - LowPlayer +1) + LowPlayer;

cout<< "Players attack is (" << first_die << ", "
<< sec_die << "}" << endl << endl;

first_die = rand() % (HighMonster - LowMonster + 1) + LowMonster;
sec_die = rand() % (HighMonster - LowMonster + 1) + LowMonster;

cout<< "Monsters attack is (" << first_die << ", "
<< sec_die << "}" << endl << endl;

}
else if ( (MonsterHitPoints <= 0) && (PlayerHitPoints <= 0) );
{
cout << "Unable to fight! Player or Monster HP are 0.\n";
cin >> Test;
}
return 0;
}```

2. Typically for this you would use a loop.
Code:
```while(monsterHP > 0 && playerHP > 0){
}//while```
Then you could write your handlers for what happened after that loop condition is false.
Code:
```if(monsterHP <= 0){
//Player won
}
if(playerHP <= 0){
//Monster won
}//if```
Of course this can become more complicated. Say the player attacks first and kills the monster, obviously the dead monster can't do damage on the player. So you could also write your loops this way
Code:
```while(true){
//Do player attack
if(monsterHP <= 0){
break;
}//if

//Do monster attack
if(playerHP <= 0){
break;
}//if
}//while```
All depends on how you want to handle it.

3. ## New code after several hours of work today

I think i have the bases covered in the event of a 1 hit kill blow, but ive yet to figure out how to deal with when the player kills the monster on his turn, its dual cycle so the monster is dead yet he finishes his blow before the loop ends. not sure use some kind of boolean check? any help would be appreciated. thx

Code:
```#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
using namespace std;

// Strings and extra variables
string PlayerName; // Player's name
string MonsterName = "Zombie";  // Monster name or type
char NextRound;  // Continue to next combat cycle

// MONSTER VARIABLES
int MonsterLevel = 1;
int MonsterHitPoints = 10;
int MonsterAttack = 8;
int MonsterDefense = 3;
int MonsterHitRate = 60;

// PLAYER VARIABLES
int PlayerLevel = 1;
int PlayerExperience = 0;
int PlayerGold = 100;
int PlayerHitPoints = 25;
int PlayerAttack = 10;
int PlayerDefense = 5;
int PlayerHitRate = 75;

// Monster damage variables using rand
// Also subtracts player defense from monsters damage
int LowMonster = 2;
int HighMonster = MonsterAttack - PlayerDefense;

// Player damage variables using rand
// Also subtraces monster defense from players damage
int LowPlayer = 2;
int HighPlayer = PlayerAttack - MonsterDefense;

// Variable to see if player or monster land a blow
int PlayerHitCheck = 0;
int MonsterHitCheck = 0;

// Player % chance to hit high and low
int PlayerHitLow = 1;
int PlayerHitHigh = 100;

// Monster % chance to hit high and low
int MonsterHitLow = 1;
int MonsterHitHigh = 100;

// Player & Monster damage results die 1 + die 2
int MonsterDamageResults = 0;
int PlayerDamageResults = 0;

int main()
{
/*
Variables to hold random values
for the first and the second die on
each roll.
*/
int first_die, sec_die;
/*
Declare variable to hold seconds on clock.
*/
time_t seconds;
/*
Get value from system clock and
place in seconds variable.
*/
time(&seconds);
/*
Convert seconds to a unsigned
integer.
*/
srand((unsigned int) seconds);
/*
Get first and second random numbers.
*/
/// COMBAT SCRIPT BELOW
cout << "You encounter a Level 1 Zombie. Prepare to fight!\n";
cout << "What is your name? <a-z>\n";
cin >> PlayerName;

while ( ( PlayerHitPoints >= 0 ) && ( MonsterHitPoints >= 0 ) )
{
if ( (MonsterHitPoints >= 1) && (PlayerHitPoints >= 1) )
{
cout << "Starting combat round between [" << PlayerName <<"] & [" << MonsterName <<"]!\n";
PlayerHitCheck = rand() % (PlayerHitHigh - PlayerHitLow +1) + PlayerHitLow;

if (PlayerHitCheck <= 25)
{
cout << "" << PlayerName <<" swing's at the " << MonsterName << " and misses!\n";
cout << "Press <c> and enter to continue to the next combat round.\n";
cin >> NextRound;
}
else
{
cout << "" << PlayerName <<" swing's at the " << MonsterName <<" and lands a blow!\n";
first_die = rand() % (HighPlayer - LowPlayer + 1) + LowPlayer;  // Calculate player damage of first dice roll
sec_die = rand() % (HighPlayer - LowPlayer +1) + LowPlayer;     // Calculate player damage of second dice roll
cout << "" << PlayerName <<"'s attack is (" << first_die << ", "
<< sec_die << "}\n\n";
PlayerDamageResults = sec_die + first_die; // Calculate total damage done by player
cout << "" << PlayerName << " hits " << MonsterName << " for " << PlayerDamageResults << " damage.\n";
MonsterHitPoints = MonsterHitPoints - PlayerDamageResults; // Subtract damage from monsters hitpoints
cout << "" << PlayerName <<"'s hitpoints are: " << PlayerHitPoints << ".\n";
cout << "" << MonsterName <<"'s hitpoints are: " << MonsterHitPoints << ".\n";
cout << "Press <c> and enter to continue to the next combat round.\n";
cin >> NextRound;

MonsterHitCheck = rand() % (MonsterHitHigh - MonsterHitLow +1) + MonsterHitLow; // Check to see if monster hits player
}
if (MonsterHitCheck <= 40)
{
cout << "" << MonsterName <<" swing's at " << PlayerName << " and misses!\n";
cout << "Press <c> and enter to continue to the next combat round.\n";
cin >> NextRound;
}
else
{
cout << "" << MonsterName <<" swing's at " << PlayerName <<" and lands a blow!\n";
first_die = rand() % (HighMonster - LowMonster + 1) + LowMonster; // Calculate monster damage of first dice roll
sec_die = rand() % (HighMonster - LowMonster + 1) + LowMonster;   // Calculate monster damage of second dice roll
cout << "" << MonsterName <<"'s attack is (" << first_die << ", "
<< sec_die << "}\n\n";
MonsterDamageResults = sec_die + first_die; // Calculate total damage done by monster
cout << "" << MonsterName <<" hits " << PlayerName <<" for " << MonsterDamageResults << " damage.\n";
PlayerHitPoints = PlayerHitPoints - MonsterDamageResults; // Subtract damage from players hitpoints
cout << "" << PlayerName <<"'s hitpoints are: " << PlayerHitPoints << ".\n";
cout << "" << MonsterName <<"'s hitpoints are: " << MonsterHitPoints << ".\n";
cout << "Press <c> and enter to continue to the next combat round.\n";
cin >> NextRound;
}
}
else
{   // If & Else statements in the event a 1 hit kill blow is scored
if ( (PlayerHitPoints <=0) && ( MonsterHitPoints >=1) )
{
cout << "" << PlayerName <<" has died! [GAME OVER]\n\n";
cout << "Do you wish to reload your saved game? (Currently Unsupported)\n\n";
cin >> NextRound;
}
else
{
cout << "" << MonsterName <<" has died! [VICTORY!]\n\n";
cout << "You find 8 gold pieces on the " << MonsterName <<"!\n";
cout << "You gain 10 experience points!\n";
PlayerGold = PlayerGold + 8;               // Award player gold
PlayerExperience = PlayerExperience + 10;  // Award player experience
cout << "Players Experience:" << PlayerExperience <<"\n";
cin >> NextRound;
}
}
}       // If & Else statements end of combat cycle
if ( (PlayerHitPoints <=0) && ( MonsterHitPoints >=1) )
{
cout << "" << PlayerName <<" has died! [GAME OVER]\n\n";
cout << "Do you wish to reload your saved game? (Currently Unsupported)\n\n";
cin >> NextRound;
}
else
{
cout << "" << MonsterName <<" has died! [VICTORY!]\n\n";
cout << "You find 8 gold pieces on the " << MonsterName <<"!\n";
cout << "You gain 10 experience points!\n";
PlayerGold = PlayerGold + 8;              // Award player gold
PlayerExperience = PlayerExperience + 10; // Award player experience
cout << "Players Experience:" << PlayerExperience <<"\n";
cin >> NextRound;

}
return 0;
}```

4. I've always found that algorithms like this are much easier to formulate and work with if you assume all values lie in range 0.0f to 1.0f. This makes all operations on the data much simpler since you know the min and the max values.

5. I'm pretty new to C++ and im only just starting to really get the hang of this. I don't see how a float would fix this bug then again ive yet to really work with floats due to the fact i havn't done conversions on variables yet.

6. I also have another problem im trying to create a function to level up the character which will be run after each battle to check and if needed update level,atk,defense,hitrate, exp to next level,

i can update almost every single stat long as its a set # per levelup but when it comes to updating the exp to next level from a list of const ints im stuck!

Code:
```int ExperienceCalculator()
{
// Variables that store the experience for next level
const int NextExperienceUp2 = 100;
const int NextExperienceUp3 = 225;
const int NextExperienceUp4 = 400;
const int NextExperienceUp5 = 925;
const int NextExperienceUp6 = 1400;
const int NextExperienceUp7 = 2425;
const int NextExperienceUp8 = 3650;
const int NextExperienceUp9 = 5675;
const int NextExperienceUp10 = 8150;

// Variables that store the total exp at next level
const int NextExperience2 = 100;
const int NextExperience3 = 325;
const int NextExperience4 = 725;
const int NextExperience5 = 1650;
const int NextExperience6 = 3025;
const int NextExperience7 = 5475;
const int NextExperience8 = 7900;
const int NextExperience9 = 11550;
const int NextExperience10 = 19700;

// Variable that store new hit points value for next level (Base 20 + 5 per level)
const int PlayerHitPointsUp = 5;

// Variable that store new attack value for next level (Base 12 + 2 per level)
const int PlayerAttackUp = 2;

// Variable that store new defense value for next level (Base 6 + 3 per level)
const int PlayerDefenseUp = 3;

// Variable that stores new hitrate value for next level (Base 50% + 1% per level)
const int PlayerHitRateUp = 1;

cout << "Checking players level & experience stats.\n";

if (PlayerExperience >= PlayerNextExperience)
{
cout << "Leveling up player.\n";
++PlayerLevel;
PlayerHitPoints = PlayerHitPoints + PlayerHitPointsUp;
PlayerAttack = PlayerAttack + PlayerAttackUp;
PlayerDefense = PlayerDefense + PlayerDefenseUp;
PlayerHitRate = PlayerHitRate + PlayerHitRateUp;
cout << "Done leveling up player.\n";
cout << "Updating experience to next level.\n";
}
else
{
cout << "Player does not need to be leveled up.\n";
cout << "Returning to game...\n";
}
return 0;
}```

7. Have you tried something similar to this?

Code:
```const int NextExperienceLevels[] = {-1, 0, 100, 325, 375, ...};
if (PlayerExperience >= PlayerNextExperience)
{
...
if (PlayerLevel < MaxLevel) PlayerNextExperience = NextExperienceLevel[PlayerLevel+1];
}```

8. I tried using an array and it didn't work but it wasn't written exactly like that. Also what is MaxLevel for since i don't have a variable by that name.

9. What I posted is what's called an example. It's intended to give you ideas on how to implement your program.

If you tried something that didn't work, you can post it and someone here will be more than willing to help you fix it.

10. This is what i have right now. At the moment im using a static 500xp per lvl but at some point i want to change it to an exp chart that starts out low and increases with each level.
Code:
```int ExperienceCalculator()
{
HANDLE hConsole; // Code for colored text
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Code for colored text
// Variables that store the experience for next level (Currently unused STATIC 500xp/level)
const int NextExperienceUp2 = 100;
const int NextExperienceUp3 = 225;
const int NextExperienceUp4 = 400;
const int NextExperienceUp5 = 925;
const int NextExperienceUp6 = 1400;
const int NextExperienceUp7 = 2425;
const int NextExperienceUp8 = 3650;
const int NextExperienceUp9 = 5675;
const int NextExperienceUp10 = 8150;

// Variables that store the total exp at next level (Currently unused STATIC 500xp/level)
const int NextExperience2 = 100;
const int NextExperience3 = 325;
const int NextExperience4 = 725;
const int NextExperience5 = 1650;
const int NextExperience6 = 3025;
const int NextExperience7 = 5475;
const int NextExperience8 = 7900;
const int NextExperience9 = 11550;
const int NextExperience10 = 19700;

// Variable that store new hit points value for next level (Base 20 + 5 per level)
const int PlayerHitPointsUp = 5;

// Variable that store new attack value for next level (Base 6 + 2 per level)
const int PlayerAttackUp = 2;

// Variable that store new defense value for next level (Base 3 + 3 per level)
const int PlayerDefenseUp = 3;

// Variable that stores new hitrate value for next level (Base 50% + 1% per level)
const int PlayerHitRateUp = 1;
{
SetConsoleTextAttribute(hConsole, 15); // Colored Text Red
}
cout << "\n[";
{
SetConsoleTextAttribute(hConsole, 12); // Colored Text Red
}
cout << " SYSTEM MESSAGE: ";
{
SetConsoleTextAttribute(hConsole, 15); // Colored Text Red
}
cout << "Experience Calculator ]\n";
cout << "\nChecking players level & experience stats.\n";

if (PlayerExperience >= PlayerNextExperience)
{
cout << "Leveling up player.\n";
++PlayerLevel;
PlayerHitPoints = PlayerHitPoints + PlayerHitPointsUp;
PlayerMaxHitPoints = PlayerLevel * 5 + 15;
PlayerAttack = PlayerAttack + PlayerAttackUp;
PlayerDefense = PlayerDefense + PlayerDefenseUp;
PlayerHitRate = PlayerHitRate + PlayerHitRateUp;
PlayerNextExperience = PlayerLevel * 500;
cout << "Done leveling up player.\n";
cout << "Returning to game...\n\n";
}
else
{
cout << "\nPlayer does not need to be leveled up.\n";
cout << "Returning to game...\n\n";
}
return 0;
}```

11. Is this what you were talking about? it appears to work, but not sure if there is any bugs could you check it over, also should i move the array over to globals? How will this effect saving as i now have save/load in my game.

Code:
```int ExperienceCalculator()
{
HANDLE hConsole; // Code for colored text
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Code for colored text
// Array that stores the exp needed for each level
const int NextExperienceLevels[] = {0, 100, 225, 400, 925, 1400, 2425, 3650, 5675, 8150};
// Variables that store the experience for next level (Currently Unused - Guide Only)
const int NextExperienceUp2 = 100;
const int NextExperienceUp3 = 225;
const int NextExperienceUp4 = 400;
const int NextExperienceUp5 = 925;
const int NextExperienceUp6 = 1400;
const int NextExperienceUp7 = 2425;
const int NextExperienceUp8 = 3650;
const int NextExperienceUp9 = 5675;
const int NextExperienceUp10 = 8150;

// Variables that store the total exp at next level (Currently Unused - Guide Only)
const int NextExperience2 = 100;
const int NextExperience3 = 325;
const int NextExperience4 = 725;
const int NextExperience5 = 1650;
const int NextExperience6 = 3025;
const int NextExperience7 = 5475;
const int NextExperience8 = 7900;
const int NextExperience9 = 11550;
const int NextExperience10 = 19700;

// Variable that store new hit points value for next level (Base 20 + 5 per level)
const int PlayerHitPointsUp = 5;

// Variable that store new attack value for next level (Base 6 + 2 per level)
const int PlayerAttackUp = 2;

// Variable that store new defense value for next level (Base 3 + 3 per level)
const int PlayerDefenseUp = 3;

// Variable that stores new hitrate value for next level (Base 50% + 1% per level)
const int PlayerHitRateUp = 1;
{
SetConsoleTextAttribute(hConsole, 15); // Colored Text Red
}
cout << "\n[";
{
SetConsoleTextAttribute(hConsole, 12); // Colored Text Red
}
cout << " SYSTEM MESSAGE: ";
{
SetConsoleTextAttribute(hConsole, 15); // Colored Text Red
}
cout << "Experience Calculator ]\n";
cout << "\nChecking players level & experience stats.\n";

while ( PlayerExperience >= PlayerNextExperience)
if (PlayerExperience >= PlayerNextExperience)
{
cout << "Leveling up player.\n";
if (PlayerLevel < PlayerMaxLevel) PlayerNextExperience = NextExperienceLevels[PlayerLevel+1];
++PlayerLevel;
PlayerHitPoints = PlayerHitPoints + PlayerHitPointsUp;
PlayerMaxHitPoints = PlayerLevel * 5 + 15;
PlayerAttack = PlayerAttack + PlayerAttackUp;
PlayerDefense = PlayerDefense + PlayerDefenseUp;
PlayerHitRate = PlayerHitRate + PlayerHitRateUp;
}
else
{
cout << "\nPlayer does not need to be leveled up.\n";
cout << "Returning to game...\n\n";
}
cout << "Done leveling up player.\n";
cout << "Returning to game...\n\n";
return 0;
}```