|
|||||||
|
|
Thread Tools |
|
|
#1 |
|
Fast-moving, smart, sexy and alarming.
![]() ![]() ![]() ![]() ![]()
Join Date: Aug 2005
Posts: 5,152
|
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. 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?).
__________________
Previously obi. Technical Machine, a Pokemon AI. "Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat." - Sun Tzu Last edited by david stone; Jan 25th, 2008 at 11:11:55 PM. |
|
|
|
|
#2 |
![]() ![]() ![]() ![]() ![]()
Administrator
Join Date: Jul 2007
Posts: 1,051
|
I know it was I who suggested that lcase() function but it turns out that strlwr() is actually a Microsoft-extension and not part of the C standard library (it failed to compile in gcc). If anybody else is compiling it in gcc, I used this version of lcase():
Code:
#include <cctype>
#include <algorithm>
inline string lcase(string s) {
transform(s.begin(), s.end(), s.begin(), (int( *)(int))toupper);
return s;
}
Last edited by Cathy; Jan 25th, 2008 at 11:45:10 PM. |
|
|
|
|
#3 |
|
Join Date: Jun 2007
Posts: 543
|
It works fine and produces a decent result. A few suggestions.
~ What is the point of asking for the type of the attacking move? You already ask us for STAB and it doesn't autocalculate effectiveness. Same thing with Physical/Special ~ Why not amalgamate all the separate prompts for items into one (eg: 1 = Choice Specs 2 = Wise Glasses etc.) ~ The same for abilities ~ Could you get it to accept arguments on the command line as that makes it easier to create shortcuts to certain results. I have six on my desktop for each of my pokemon that all go something like Code:
ruby damagecalc7.rb ? 202 ? ? ? 3 3 - ~ When the attack could OHKO the pokemon the result is a bit confusing... Code:
Damage is 292-100, or 292%-100% Finally, you have errors on compile: I know nothing about C so I don't know whether they matter or not! Code:
tim@tim-laptop:~$ g++ ObiDamageCalc.c ObiDamageCalc.c: In function ‘int main()’: ObiDamageCalc.c:356: warning: converting to ‘int’ from ‘double’ ObiDamageCalc.c:357: warning: converting to ‘int’ from ‘double’ ObiDamageCalc.c:367: warning: converting to ‘int’ from ‘double’ Working Linux binaries are attached if anyone's interested... |
|
|
|
|
#4 |
|
np: Biffy Clyro - Shock Shock
![]() ![]()
Join Date: Feb 2006
Posts: 4,679
Malta
|
Replacing
Code:
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); Code:
maxDamage = (int) 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); You don't need to do the following, but it's better to do without goto. I'd put Code:
do Code:
calculate: Code:
while (recalculate != "0"); Code:
if (recalculate != "0") goto calculate; Code:
cout << "Damage is " << minDamage << "-" << HP << ", or " << minPercent << "%-100%\n"; Code:
if (minDamage > HP) cout << "Damage is " << HP << ", or 100%\n"; else cout << "Damage is " << minDamage << "-" << HP << ", or " << minPercent << "%-100%\n"; @timw06: The type is asked because of such things as Thick Fat. The physical versus special is for Reflect/Light Screen etc.
__________________
http://users.smogon.com/X-Act For all your Pokemon needs (and more!) including: the Defensive EVs applet, the Probabilities of Breeding IVs in Pokemon applet, and the Ratings of Pokemon Base Stats applet (now Version 2.0!). And also the IV to PID applet! |
|
|
|
|
#5 |
|
Join Date: Aug 2007
Posts: 4,991
|
Obi, the Damage Calculator that is attached doesn't work on Macs.
|
|
|
|
|
#6 |
|
Don't tell me what to do.
![]() ![]() ![]() ![]() ![]()
Super Moderator
Join Date: Aug 2007
Posts: 3,370
|
I downloaded it and extracted it. When I tried to run it, I got this:
"The application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem" I have Windows XP. |
|
|
|
|
#7 |
![]() Join Date: Jan 2007
Posts: 999
|
i'm getting the same error. some time back when i had installed anope on my computer, i got the exact same error, which was subsequently fixed by copying a .manifest file from the net. could that be the issue obi?
i tried compiling using mingw32, but it's a bulky 500k executable, or i would have posted a link here edit: colinjf, compile it using the g++ command and not gcc
__________________
Code:
* !!!!!!!IF YOU CHANGE TABS TO SPACES, YOU WILL BE KILLED!!!!!!! * !!!!!!!!!!!!!!DOING SO FUCKS THE BUILD PROCESS!!!!!!!!!!!!!!!! |
|
|
|
|
#8 |
![]() ![]() ![]() ![]() ![]()
Administrator
Join Date: Jul 2007
Posts: 1,051
|
I did use g++ to invoke gcc. As I said, that change is required because strlwr() is a Microsoft extension. My post was intended to help other people compiling using gcc in a POSIX environment.
Last edited by Cathy; Jan 26th, 2008 at 3:45:03 PM. |
|
|
|
|
#9 | |
|
Join Date: Mar 2006
Posts: 270
Sillhouettes! In the sky! Wings are carrying me through the night!
|
Quote:
__________________
avatar spliced by YoshiToshi |
|
|
|
|
|
#10 |
![]() Join Date: Jan 2007
Posts: 999
|
pear: good idea, man. stripped and UPX'ed down to 82 KB, zips to 81 kb, so did not bother to zip further. http://ryubahamut.googlepages.com/damcalc.exe but not sure whether this requires the mingw32 runtime or not. XP users may attempt running this.
ColinJF: perhaps i'm able to compile under msys because the mingw32 dll uses windows runtime? that might be the case. sorry!
__________________
Code:
* !!!!!!!IF YOU CHANGE TABS TO SPACES, YOU WILL BE KILLED!!!!!!! * !!!!!!!!!!!!!!DOING SO FUCKS THE BUILD PROCESS!!!!!!!!!!!!!!!! |
|
|
|
|
#11 |
![]() ![]() ![]() ![]()
Join Date: Jan 2005
Posts: 2,625
|
That is what you call a RTE (Run Time Error.) Most RTEs are the cause of bad/lazy programming. When you are developing an application and debugging/testing it, you need to think like a user. You want to make your application is as fool-proof as possible. If somebody tries to enter just a space or fake input, you need to have a way to validate the input. It is really easy to validate input with Regular Expressions. Since this is basically just checking for numbers mostly, I would recommend checking to see if the input is an integer with a simple while loop. Keep repeating the loop until the input is valid.
|
|
|
|
|
#12 |
|
Fast-moving, smart, sexy and alarming.
![]() ![]() ![]() ![]() ![]()
Join Date: Aug 2005
Posts: 5,152
|
Life Orb appears to do nothing. I don't know what the error is, as it was working in prior versions. Can anyone spot the error?
__________________
Previously obi. Technical Machine, a Pokemon AI. "Strategy without tactics is the slowest route to victory. Tactics without strategy is the noise before defeat." - Sun Tzu |
|
|
|
|
#13 |
|
np: Biffy Clyro - Shock Shock
![]() ![]()
Join Date: Feb 2006
Posts: 4,679
Malta
|
What's the latest version of the program? I can try to help.
__________________
http://users.smogon.com/X-Act For all your Pokemon needs (and more!) including: the Defensive EVs applet, the Probabilities of Breeding IVs in Pokemon applet, and the Ratings of Pokemon Base Stats applet (now Version 2.0!). And also the IV to PID applet! |
|
|
|
|
#14 |
|
Join Date: Sep 2007
Posts: 218
houma
|
the only "problem" i have is you enter waterfall's data (80 power/water type) and it asks if your using selfdestruct/explosion but other than that i really have no complaints
|
|
|
| Thread Tools | |
|
|