after refactor v2

mail@pastecode.io avatar
unknown
ruby
3 years ago
6.2 kB
1
Indexable
Never
#include <iostream>
#include <unordered_map>
#include <vector>

using namespace std;

enum class Class {
    Barbarian,
    Magician
};

enum class PrimaryWeapon {
    Sword, 
    Axe,
    Bow,
    MagicBook
};

enum class SecondaryWeapon {
    ShortSword,
    Shield,
    Arrows,
    None
};

enum class Tools {
    Lockpick,
    Bandages,
    Adrenaline, 
    ManaPotion
};

unordered_map<PrimaryWeapon, string> primaryWeaponContainer {
    {PrimaryWeapon::Sword, "Sword"},
    {PrimaryWeapon::Axe, "Axe"},
    {PrimaryWeapon::Bow, "Bow"},
    {PrimaryWeapon::MagicBook, "MagicBook"}
};

unordered_map<SecondaryWeapon, string> secondaryWeaponContainer {
    {SecondaryWeapon::ShortSword, "Short sword"},
    {SecondaryWeapon::Shield, "Shield"},
    {SecondaryWeapon::Arrows, "Arrows"},
    {SecondaryWeapon::None, "None"}
};

unordered_map<Tools, string> toolsContainer {
    {Tools::Lockpick, "Lockpick"},
    {Tools::Bandages, "Bandages"},
    {Tools::Adrenaline, "Adrenaline"},
    {Tools::ManaPotion, "ManaPotion"}
};

struct StartingEquipment {
    PrimaryWeapon primaryWeapon;
    SecondaryWeapon secondaryWeapon;
    Tools tools;
};

struct Equipment {
    vector<PrimaryWeapon> primaryWeapon;
    vector<SecondaryWeapon> secondaryWeapon;
    vector<Tools> tools;
};

class Stats {
  public:
    virtual void create() = 0;
    virtual Stats* copy() = 0;  /// prototype pattern
    
    void setStrength(int a_strength) { strength = a_strength; }
    int getStrength() const { return strength; }
    
    void setDefence(int a_defence) { defence = a_defence; }
    int getDefence() const { return defence; }
    
    void setSpeed(int a_speed) { speed = a_speed; }
    int getSpeed() const { return speed; }
    
    void setIntelligence(int a_intelligence) { intelligence = a_intelligence; }
    int getIntelligence() const { return intelligence; }
    
  private:
    int strength;
    int defence;
    int speed;
    int intelligence;
};

class BarbarianStats : public Stats {
  public:
    void create() {
        setStrength(10);
        setDefence(5);
        setSpeed(3);
        setIntelligence(1);
    }
    Stats* copy() { return new BarbarianStats(*this); }
};

class MagicianStats : public Stats {
  public:
    void create() {
        setStrength(1);
        setDefence(3);
        setSpeed(5);
        setIntelligence(10);
    }
    Stats* copy() { return new MagicianStats(*this); }
};

class Character {
  public:
    virtual Stats* inputStats() = 0;   /// factory method
    
    void create() { 
        stats = inputStats(); 
        stats->create();
        setStartingEquipment();
        printStats();
    }
    
    void reborn() {
        stats = stats->copy();    
        setStartingEquipment();
    }
    
    void levelUp() {
        stats->setStrength(stats->getStrength() + 1);
        stats->setDefence(stats->getDefence() + 1);
        stats->setSpeed(stats->getSpeed() + 2);
        stats->setIntelligence(stats->getIntelligence() + 3);
    }
    
    void printStats() {
        cout << "--------Stats---------";
        cout << "\nStrength: " << stats->getStrength();
        cout << "\nDefence: " << stats->getDefence();
        cout << "\nSpeed: " << stats->getSpeed();
        cout << "\nIntelligence: " << stats->getIntelligence();
        cout << "\n-------Equipment------";
        cout << "\nPrimary weapon: "; //<< primaryWeaponContainer[getStartingEquipment().primaryWeapon];
        for(auto primaryWeapon : getStartingEquipment().primaryWeapon) {
            cout << "\n  " << primaryWeaponContainer[primaryWeapon];
        }
        cout << "\nSecondary weapon: ";
        for(auto secondaryWeapon : getStartingEquipment().secondaryWeapon) {
            cout << "\n  " << secondaryWeaponContainer[secondaryWeapon];
        }
        cout << "\nTools: ";
        for(auto tools : getStartingEquipment().tools) {
            cout << "\n  " << toolsContainer[tools];
        }
        // cout << "\nSecondary weapon: " << secondaryWeaponContainer[getStartingEquipment().secondaryWeapon];
        // cout << "\nTools: " << toolsContainer[getStartingEquipment().tools];
        cout << "\n\n\n";
    }
    
    virtual void setStartingEquipment() = 0;
    void addItemToEquipment() { equipment.tools.push_back(Tools::ManaPotion); };
    Equipment getStartingEquipment() const { return equipment; };
  
  protected:
    Equipment equipment;
  private:
    Stats* stats;
    int experience;
    int level;
};

class BarbarianCharacter : public Character {
  public:
    Stats* inputStats() {
        return new BarbarianStats();
    }
    void setStartingEquipment() { 
        equipment.primaryWeapon.clear();
        equipment.secondaryWeapon.clear();
        equipment.tools.clear();
        equipment.primaryWeapon.push_back(PrimaryWeapon::Axe);
        equipment.secondaryWeapon.push_back(SecondaryWeapon::None);
        equipment.tools.push_back(Tools::ManaPotion);
    }
};

class MagicianCharacter : public Character {
  public:
    Stats* inputStats() {
        return new MagicianStats();
    }
    void setStartingEquipment() {
      equipment.primaryWeapon.clear();
      equipment.secondaryWeapon.clear();
      equipment.tools.clear();
      equipment.primaryWeapon.push_back(PrimaryWeapon::MagicBook);
      equipment.secondaryWeapon.push_back(SecondaryWeapon::None);
      equipment.tools.push_back(Tools::Bandages);
    }
};

class CharacterCreator {
  public:
    Character* chooseClass(Class characterClass) {
        if(characterClass == Class::Magician) {
            return new MagicianCharacter();
        } else if(characterClass == Class::Barbarian) {
            return new BarbarianCharacter();
        } else {
            return nullptr;
        }
    }
    Character* create(Class characterClass) {
        character = chooseClass(characterClass);
        character->create();
        return character;
    }
  private:
    Character* character;
};

int main()
{
    CharacterCreator creator;
    Character* character = creator.create(Class::Magician);
    character->levelUp();
    character->addItemToEquipment();
    character->printStats();
    character->reborn();
    character->printStats();
    
    return 0;
}