obi
formerly david stone
I made a damage calculator in C++ for DP. I did it partly to learn C++, but also because it seems like none of the other calculators out there get it exactly right (often they are off just a bit due to rounding). To the best of my knowledge, this will always output the correct number.
This is what I have yet to add:
Unaware
Simple
2v2 support
In the two supported ambiguous cases (the order of Me First vs. Tinted Lens and the order of DeepSeaScale vs. Rock-type in Sandstorm Special Defense bonus), my calculator does the multiplication in the same order as Shoddybattle.
I also don't yet have a way to auto-calculate the power of variable power moves (coming eventually, but that's after the next step).
I plan to give it a way to automatically enter a lot of this data just by saying who the defender is, what the attack is, etc.
There is currently no real interface. It's just a command-line prompt. If you enter stupid data ("What is the attackers level?" "df!") you'll cause some sort of strange error. Creating a nice interface is the last of my goals. However, it is a goal, as it's something I'd like to learn.
This is partly a learning thing for me, so here is the source code for it. If you see a way to improve it / spot an error, please let me know.
So, want to help me beta test it? I don't anticipate any errors, but whatever.
I know the structure is a bit funny (as in the order it asks about everything), but expect that to be improved next version (likely some time tomorrow?).
This is what I have yet to add:
Unaware
Simple
2v2 support
In the two supported ambiguous cases (the order of Me First vs. Tinted Lens and the order of DeepSeaScale vs. Rock-type in Sandstorm Special Defense bonus), my calculator does the multiplication in the same order as Shoddybattle.
I also don't yet have a way to auto-calculate the power of variable power moves (coming eventually, but that's after the next step).
I plan to give it a way to automatically enter a lot of this data just by saying who the defender is, what the attack is, etc.
There is currently no real interface. It's just a command-line prompt. If you enter stupid data ("What is the attackers level?" "df!") you'll cause some sort of strange error. Creating a nice interface is the last of my goals. However, it is a goal, as it's something I'd like to learn.
This is partly a learning thing for me, so here is the source code for it. If you see a way to improve it / spot an error, please let me know.
Code:
// Pokemon DP Damage Calculator, Beta release 1, 2008-Jan-25 23:06 EST
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
inline string lcase(const string str) // convert strings to lowercase
{
char *const pstr = _strlwr(_strdup(str.c_str()));
const string ret = pstr;
free(pstr);
return ret;
}
int main ()
{
calculate: // goto anchor
double level; // Attacker's level
double power; // Move's base power
double HH = 1; // Helping Hand
double BPAIM = 1; // Base Power Attacker Item Modifier (Muscle Band, Wise Glasses, Type-boosting items)
double Charge = 1; // Charge
double sport = 1; // Mud Sport / Water Sport
double BPAAM = 1; // Base Power Attacker Ability Modifier (Blaze, Iron Fist, Overgrow, Reckless, Rivalry, Swarm, Technician, Torrent)
double BPDAM = 1; // Base Power Defender Ability Modifier (Dry Skin, Heatproof, Thick Fat)
double atk; // Attacking stat
double ASM = 0; // Attacking Stat Modifier
double AAM = 1; // Attack Ability Modifier (Flower Gift (on the attacker), Guts, Huge Power, Hustle, Pure Power, Slow Start, Solar Power)
double AIM = 1; // Attack Item Modifier (Choice Band, Choice Specs, DeepSeaTooth, Light Ball, Thick Club)
double def; // Defending stat
double DSM = 0; // Defending Stat Modifier
double DAM = 1; // Defense Ability Modifier (Flower Gift (on the defender), Marvel Scale)
double DIM = 1; // Defense Item Modifier (DeepSeaScale, Metal Powder, Soul Dew)
double SS = 1; // Sandstorm Special Defense bonus to Rocks
double boom = 1; // Explosion / Selfdestuct Defense modifier
double BRN = 1; // Burn
double RL = 1; // Reflect / Light Screen
double weather = 1; // Sunny Day / Rain Dance
double FF = 1; // Flash Fire
double CH = 1; // Critical Hit
double item = 1; // Life Orb, Metronome
double TL = 1; // Tinted Lens
double MF = 1; // Me First
double STAB = 1; // Same Type Attack Bonus (STAB)
string spectrum; // Whether the move is physical or special
string type; // What type the move is
double Type1 = 1; // Effectiveness on the defender's first type
double Type2 = 1; // Effectiveness on the defender's second type
double AEM = 1; // Ability Effectiveness Multiplier (Solid Rock, Filter)
double EB = 1; // Expert Belt
double RB = 1; // Resistance berries
double HP = 1; // HP
int maxDamage = 0;
int minDamage = 0;
int midDamage = 0; // Temporary variable to find chance to OHKO
double R; // The Random number
double probability = 0; // Chance to OHKO
double probabilityPercent;
double maxPercent;
double minPercent;
string recalculate;
cout << "How effective is the attack on the defender's first type? (0 for No Effect, .5 for Not Very Effective, 1 for neutral, 2 for Super Effective) ";
cin >> Type1;
if (Type1 != 0)
{
cout << "How effective is the attack on the defender's second type? (0 for No Effect, .5 for Not Very Effective, 1 for neutral, 2 for Super Effective) ";
cin >> Type2;
if (Type2 != 0)
{
cout << "What is the attacker's level? ";
cin >> level;
cout << "Is the move physical or special? ";
cin >> spectrum;
spectrum = lcase(spectrum);
cout << "What type is the move? ";
cin >> type;
type = lcase(type);
cout << "What is the base power of the move? ";
cin >> power;
if (power <= 60)
{
cout << "Does the attacker have Technician? (1.5 for yes, 1 for no) ";
cin >> BPAAM;
}
cout << "What is the attacking stat? ";
cin >> atk;
cout << "What is the attacking stat modifier? (-6 through 6) ";
cin >> ASM;
if (ASM >= 0) // Converts stages to multipliers
ASM = (2 + ASM) / 2;
else
ASM = 2 / (2 - ASM);
cout << "Does Pikachu have a Light Ball? (2 for yes, 1 for no) ";
cin >> AIM;
if (AIM == 1)
{
cout << "Is there a type-boosting item in play? (1.2 for yes, 1 for no) ";
cin >> BPAIM;
}
if (spectrum == "physical") // Physical attacks
{
if (BPAAM == 1)
{
cout << "Does the attacker have Pure Power / Huge Power? (2 for yes, 1 for no) ";
cin >> AAM;
if (AAM == 1)
{
cout << "Is Guts activated? (1.5 for yes, 1 for no) ";
cin >> AAM;
if (AAM == 1)
{
cout << "Is Hustle activated? (1.5 for yes, 1 for no) ";
cin >> AAM;
if (AAM == 1)
{
cout << "Is Slow Start active? (.5 for yes, 1 for no) ";
cin >> AAM;
if (AAM == 1)
{
cout << "Does the attacker have Flower Gift activated? (1.5 for yes, 1 for no) ";
cin >> AAM;
}
}
}
}
}
if ((AIM == 1) && (BPAIM == 1))
{
cout << "Is the attacker holding a Choice Band? (1.5 for yes, 1 for no) ";
cin >> AIM;
if (AIM == 1)
{
if (AIM == 1)
{
cout << "Does Cubone / Marowak have a Thick Club? (2 for yes, 1 for no) ";
cin >> AIM;
if (AIM == 1)
{
cout << "Is the attacker holding a Muscle Band? (1.1 for yes, 1 for no) ";
cin >> BPAIM;
}
}
}
}
}
else // Special attacks
{
cout << "Is Solar Power active? (1.5 for yes, 1 for no) ";
cin >> AAM;
cout << "Is the attacker holding Choice Specs? (1.5 for yes, 1 for no) ";
cin >> AIM;
if ((AIM == 1) && (BPAIM == 1))
{
cout << "Is the attacker holding Wise Glasses? (1.1 for yes, 1 for no) ";
cin >> BPAIM;
}
}
if ((AIM == 1) && (BPAIM == 1))
{
cout << "Is the attacker holding a Life Orb? (1.3 for yes, 1 for no) ";
cin >> item;
if (item == 1)
{
cout << "Is the attacker holding a Metronome? (2 for yes, 1 for no) ";
cin >> item;
if (item > 1)
{
cout << "How many times has the attack been used already? ";
cin >> item;
item = (item / 10) + 1;
if (item > 2)
item = 2;
}
}
}
cout << "What is the defending stat? ";
cin >> def;
cout << "What is the defending stat modifier? (-6 through 6)";
cin >> DSM;
if (DSM >= 0) // Converts stages to multipliers
DSM = (2 + DSM) / 2;
else
DSM = 2 / (2 - DSM);
if (spectrum == "physical")
{
cout << "Is Reflect in play? (2 for yes, 1 for no) ";
cin >> RL;
cout << "Is the attacker burned? (2 for yes, 1 for no) ";
cin >> BRN;
cout << "Is the attacker using Explosion or Selfdestruct? (2 for yes, 1 for no) ";
cin >> boom;
cout << "Does the defender have Marvel Scale activated? (1.5 for yes, 1 for no) ";
cin >> DAM;
cout << "Is Ditto holding Metal Powder? (1.5 for yes, 1 for no) ";
cin >> DIM;
if (BPAAM == 1)
{
cout << "Is Iron Fist activated? (1.2 for yes, 1 for no) ";
cin >> BPAAM;
if (BPAAM == 1)
{
cout << "Is Reckless activated? (1.2 for yes, 1 for no) ";
cin >> BPAAM;
}
}
}
else
{
cout << "Is Light Screen in play? (2 for yes, 1 for no) ";
cin >> RL;
cout << "Is the defender a Rock type during Sandstorm? (1.5 for yes, 1 for no) ";
cin >> SS;
cout << "Is Flower Gift activated on the target? (1.5 for yes, 1 for no) ";
cin >> DAM;
cout << "Is Latias or Latios holding Soul Dew? (1.5 for yes, 1 for no) ";
cin >> DIM;
if (DIM == 1)
{
cout << "Is Ditto holding Metal Powder? (1.5 for yes, 1 for no) ";
cin >> DIM;
if (DIM == 1)
{
cout << "Is Clamperl holding DeepSeaScale? (2 for yes, 1 for no) ";
cin >> DIM;
}
}
}
if (BPAAM == 1)
{
cout << "Is Rivalry activated? (1.25 for same gender, .75 for opposite gender, 1 for no) ";
cin >> BPAAM;
}
if ((type == "fire") || (type == "ice"))
{
cout << "Does the defender have Thick Fat? (.5 for yes, 1 for no) ";
cin >> BPDAM;
if (type == "fire")
{
if (BPDAM == 1)
{
cout << "Does the defender have Heatproof? (.5 for yes, 1 for no) ";
cin >> BPDAM;
if (BPDAM == 1)
{
cout << "Does the defender have Dry Skin? (1.25 for yes, 1 for no) ";
cin >> BPDAM;
}
}
cout << "Is Sunny Day in effect? (1.5 for yes, 1 for no) ";
cin >> weather;
if (weather == 1)
{
cout << "Is Rain Dance in effect? (.5 for yes, 1 for no) ";
cin >> weather;
}
cout << "Is Flash Fire activated? (1.5 for yes, 1 for no) ";
cin >> FF;
if (BPAAM == 1)
{
cout << "Is Blaze activated? (1.5 for yes, 1 for no) ";
cin >> BPAAM;
}
}
}
else if (type == "water")
{
cout << "Is Rain Dance in effect? (1.5 for yes, 1 for no) ";
cin >> weather;
if (weather == 1)
{
cout << "Is Sunny Day in effect? (.5 for yes, 1 for no) ";
cin >> weather;
}
if (BPAAM == 1)
{
cout << "Is Torrent activated? (1.5 for yes, 1 for no) ";
cin >> BPAAM;
}
}
else if (type == "electric")
{
cout << "Was Charge used on the previous turn? (2 for yes, 1 for no) ";
cin >> Charge;
}
else if (type == "grass")
{
if (BPAAM == 1)
{
cout << "Is Overgrow activated? (1.5 for yes, 1 for no) ";
cin >> BPAAM;
}
}
else if (type == "bug")
{
if (BPAAM == 1)
{
cout << "Is Swarm activated? (1.5 for yes, 1 for no) ";
cin >> BPAAM;
}
}
cout << "Is the attacker using the move Me First? (1.5 for yes, 1 for no) ";
cin >> MF;
cout << "Is the attack of the same type as the attacker (STAB)? (1.5 for yes, 1 for no) ";
cin >> STAB;
if (Type1 * Type2 > 1)
{
cout << "Does the defender have Filter / Solid Rock? (.75 for yes, 1 for no) ";
cin >> AEM;
if ((AIM == 1) && (BPAIM) && (item = 1))
{
cout << "Is the attacker holding an Expert Belt? (1.2 for yes, 1 for no) ";
cin >> EB;
}
}
else if ((Type1 * Type2 < 1) && (Type1 * Type2 != 0))
{
cout << "Does the attacker have the ability Tinted Lens? (2 for yes, 1 for no) ";
cin >> TL;
}
if (Type1 * Type2 >= 1)
{
if (type != "normal")
{
cout << "Is the defender holding a resistance berry that will activate? (2 for yes, 1 for no) ";
cin >> RB;
}
else if (Type1 * Type2 > 1)
{
cout << "Is the defender holding a Chilan Berry? (2 for yes, 1 for no) ";
cin >> RB;
}
}
cout << "Is the attacker's ally using Helping Hand? (1.5 for yes, 1 for no) ";
cin >> HH;
cout << "Is the move a critical hit? (2 for yes, 1 for no, 3 for Sniper) ";
cin >> CH;
if (CH != 1)
{
if (ASM < 1)
ASM = 1;
if (DSM > 1)
DSM = 1;
RL = 1;
}
cout << "What is the defender's HP? ";
cin >> HP;
power = floor(floor(floor(floor(floor(floor(power * HH) * BPAIM) * Charge) * sport) * BPAAM) * BPDAM);
if (power == 0)
power = 1;
atk = floor(floor(floor(atk * ASM) * AAM) * AIM);
if (atk == 0)
atk = 1;
def = floor(floor(floor(floor(floor(def * DSM) * DAM) * DIM) * SS) / boom);
if (def == 0)
def = 1;
maxDamage = floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(level * 2 / 5 + 2) * power * atk / 50) / def) / BRN) / RL) * weather) * FF + 2) * CH * item) * TL * MF) * STAB) * Type1) * Type2) * AEM) * EB) / RB);
minDamage = floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(level * 2 / 5 + 2) * power * atk / 50) / def) / BRN) / RL) * weather) * FF + 2) * CH * item) * TL * MF) * .85) * STAB) * Type1) * Type2) * AEM) * EB) / RB);
maxPercent = 100 * maxDamage / HP;
minPercent = 100 * minDamage / HP;
}
}
if (maxDamage >= HP)
{
R = 217;
while ((R <= 255) && (midDamage < HP)) // Cycles through all possible values for R until it finds the lowest R that grants a OHKO, only if such a value is possible
{
midDamage = floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(floor(level * 2 / 5 + 2) * power * atk / 50) / def) / BRN) / RL) * weather) * FF + 2) * CH * item) * TL * MF) * floor(R * 100 / 255)) / 100) * STAB) * Type1) * Type2) * AEM) * EB) / RB);
R = R + 1;
}
probability = (256 - R);
probabilityPercent = (probability / 39) * 100;
cout << "There is a " << probability << "/39 chance to OHKO, or " << probabilityPercent << "%\n";
cout << "Damage is " << minDamage << "-" << HP << ", or " << minPercent << "%-100%\n";
}
else
cout << "Damage is " << minDamage << "-" << maxDamage << ", or " << minPercent << "%-" << maxPercent << "%" << '\n';
cout << "Would you like to calculate again? (1 for yes, 0 for no)";
cin >> recalculate;
if (recalculate != "0")
goto calculate; // Brings you back to the start to recalculate
return 0;
}
I know the structure is a bit funny (as in the order it asks about everything), but expect that to be improved next version (likely some time tomorrow?).
Attachments
-
9.2 KB Views: 412