2011 version
std::string
s, std::bind
s initializer lists, modern random number generators, auto
variable typing. Shucks, even a few oldies-but-goodies like classes and error checking the input.
#include <iostream>
#include <random>
#include <functional>
#include <map>
// prep random number generator to simulate a 100 sided die
std::default_random_engine engine; // not being fancy here. Just using default RNG
std::uniform_int_distribution<int> uniform(1,100);// random from 1 to 100
auto d100 = std::bind ( uniform, engine ); // Convenience wrapper
void upstat(int & stat, // stat to increase
int chance, // odds of increase
int inc, // amount to increase
const std::string & statname)
{
if (d100() <= chance)
{ //less than or equal because I decided to emulate a d100.
// if the range was 0 - 99, only < would be necessary.
// such is the cost of slavishly adhering to dice conventions.
// std::cout<< statname << " increased by " << inc << std::endl;
stat += inc;
}
}
class Character
{
public:
Character(const std::string & name,
int level,
int HP,
int str,
int skl,
int spd,
int lck,
int def,
int res):
mName(name), mLevel(level), mStr(str), mSkl(skl), mLck(lck),
mDef(def), mRes(res), mHP(HP), mSpd(spd)
{
}
void levelup()
{
upstat(mHP, 90, 1, "HP");
upstat(mStr, 40, 1, "Strength/Magic");
upstat(mSkl, 40, 1, "Skill");
upstat(mSpd, 30, 1, "Speed");
upstat(mLck, 35, 1, "Luck");
upstat(mDef, 20, 1, "Defense");
upstat(mRes, 15, 1, "Resistance");
mLevel++;
}
// a couple useful getters
const std::string & getName()
{
return mName;
}
unsigned int getLevel()
{
return mLevel;
}
// out stream operator
friend std::ostream & operator<<(std::ostream & out,
const Character & ch)
{
out << "Stats " << "HP/STR/SKL/SPD/LCK/DEF/RES " <<
ch.mHP << " " <<
ch.mStr << " " <<
ch.mSkl << " " <<
ch.mSpd << " " <<
ch.mLck << " " <<
ch.mDef << " " <<
ch.mRes << std::endl;
return out;
}
private:
std::string mName;
unsigned int mLevel;
int mStr;
int mSkl;
int mLck;
int mDef;
int mRes;
int mHP;
int mSpd;
};
// name-indexed list of characters. Currently only contains Dieck.
std::map<std::string, Character> charlist{{"Dieck",{"Dieck",1, 26, 9, 12, 10, 4, 6, 1}}};
int main()
{
unsigned int finalLevel;
std::string cha; // using a string rather than a char array. Much less error prone.
std::cout << "Which character?" <<std::endl;
std::cin >> cha;
auto found = charlist.find(cha); // look in charlist for selected character
if (found != charlist.end()) // find returns end of list if not found
{
std::cout << "You chose " << found->second.getName() << "." << std::endl <<
found->second << std::endl; //optional. Print stats
for ( ; ; ) // Stay a while. Stay FOREVER! Muhuhahahahaha!
{
std::cout << "What level do you want him/her to be?" << std::endl;
if (std::cin >> finalLevel)
{
while (found->second.getLevel() < finalLevel)
{ // keep calling characer's level up routine until desired level reached
// or do nothing if the character is already a higher level.
found->second.levelup();
}
std::cout << found->second << std::endl; //optional. Print new stats
break; // breaks the infinite loop if input was good
}
else
{ // bad user input. Call user names until they get it right.
std::cout << "Valid positive numbers only, please." << std::endl;
std::cin.clear();
std::cin.ignore(INT_MAX, '
');
}
}
}
else
{ // didn't find character. Do nothing.
// Should probably prompt to create new character here.
std::cout << "Character " << cha << " not found." << std::endl;
}
return 0;
}
2020 Rethink
Doesn't change much, but replaces std::bind
with a Lambda expression.
std::default_random_engine engine;
std::uniform_int_distribution<int> uniform(1,100);
auto d100 = std::bind ( uniform, engine );
is replaced with
auto d100 = [](){
// all bundled up inside the lambda. No globals leaking out
static std::mt19937 gen{std::random_device{}()};
// explicitly specified the generator. Fewer surprises.
// this can be expensive, so it might be worth exposing gen and sharing it with
// other die-rolling lamdas
static std::uniform_int_distribution<int> uniform(1,100); // random from 1 to 100
return uniform(gen); // return result
};