1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#include <iostream>
#include <list>
enum Spell {SleepSpell, MagicMissile, CharmPerson, Light, Invisibility, Haste};
class Player {
private:
std::string name;
int hitPoints;
std::list<Spell> spellsCastOnPlayer;
public:
Player() = default;
Player (const std::string& newName, int hp): name (newName), hitPoints (hp) {}
virtual ~Player() = default;
virtual std::string Name() const {return name;}
virtual int HitPoints() const {return hitPoints;}
virtual const std::list<Spell>& SpellsCastOnPlayer() const {return spellsCastOnPlayer;}
virtual void SpellsCastOnPlayerEmplaceBack (Spell spell) {spellsCastOnPlayer.emplace_back (spell);}
virtual void action() = 0;
virtual void losesHitPoints (int num) {hitPoints -= num; display(); if (hitPoints <= 0) dies();}
void display() const {std::cout << name << "'s hit points = " << hitPoints << ".\n";}
private:
void dies() {std::cout << Name() << " dies!" << std::endl; delete this;}
};
struct Fighter: virtual public Player {
public:
Fighter() = default;
Fighter (const std::string& name, int hp): Player (name, hp) {}
virtual void action() override {std::cout << Name() << "'s action is normal.\n";}
};
class MagicUser: virtual public Player {
private:
int numSpells;
public:
MagicUser() = default;
MagicUser (const std::string& name, int hp, int spells): Player (name, hp), numSpells (spells) {}
virtual int NumSpells() const {return numSpells;}
virtual void castsSpell() {numSpells--; std::cout << Name() << " casts a spell, now has " << numSpells << " spells left.\n";}
virtual void action() override {std::cout << Name() << "'s action is normal.\n";}
};
template <class PlayerType, Spell...spells>
struct PlayerDecorator: virtual public PlayerType {
Player* playerType; // owning pointer ( use std::unique_ptr )
PlayerDecorator() = default;
explicit PlayerDecorator (Player* p): playerType(p) {}
~PlayerDecorator() {delete playerType;}
virtual void action() = 0;
virtual std::string Name() const override {return playerType->Name();}
virtual int HitPoints() const override {return playerType->HitPoints();}
virtual void losesHitPoints (int num) override {playerType->losesHitPoints (num);}
virtual const std::list<Spell>& SpellsCastOnPlayer() const override {return playerType->SpellsCastOnPlayer();}
virtual void SpellsCastOnPlayerEmplaceBack (Spell spell) override {playerType->SpellsCastOnPlayerEmplaceBack (spell);}
};
template <Spell...spells>
struct PlayerDecorator<MagicUser, spells...>: virtual public MagicUser {
MagicUser* magicUser;
PlayerDecorator() = default;
explicit PlayerDecorator (MagicUser* m): magicUser (m) {}
~PlayerDecorator() {delete magicUser;}
virtual void action() = 0;
virtual std::string Name() const override {return magicUser->Name();}
virtual int HitPoints() const override {return magicUser->HitPoints();}
virtual void losesHitPoints (int num) override {magicUser->losesHitPoints (num);}
virtual const std::list<Spell>& SpellsCastOnPlayer() const override {return magicUser->SpellsCastOnPlayer();}
virtual void SpellsCastOnPlayerEmplaceBack (Spell spell) override {magicUser->SpellsCastOnPlayerEmplaceBack (spell);}
virtual int NumSpells() const override {return magicUser->NumSpells();}
virtual void castsSpell() override {magicUser->castsSpell();}
};
template <class PlayerType, Spell...spells>
struct PlayerUnderSpell: virtual public PlayerDecorator<PlayerType, spells...>, virtual public PlayerType {
using PlayerDecorator<PlayerType, spells...>::PlayerDecorator;
virtual void action() override {
std::cout << PlayerDecorator<PlayerType, spells...>::Name() << " is now under the following spells:\n";
for (Spell x: {spells...})
PlayerDecorator<PlayerType, spells...>::SpellsCastOnPlayerEmplaceBack (x);
for (Spell x: PlayerDecorator<PlayerType, spells...>::SpellsCastOnPlayer())
std::cout << "Spell #" << x << " ";
std::cout << std::endl;
}
};
int main() {
Fighter* fighter = new Fighter ("Rex the Fighter", 8);
MagicUser* magicUser = new MagicUser ("Merlin the Magic User", 4, 5);
fighter->display(); magicUser->display();
fighter->action(); magicUser->action();
magicUser->castsSpell();
std::cout << "Haste spell cast on Fighter and Magic User!" << std::endl;
fighter = new PlayerUnderSpell<Fighter, Haste> (fighter);
magicUser = new PlayerUnderSpell<MagicUser, Haste> (magicUser);
fighter->action(); magicUser->action();
magicUser->castsSpell();
std::cout << fighter->Name() << " hit by monster! Loses 6 hit points!" << std::endl;
fighter->losesHitPoints (6);
std::cout << "Invisibility spell cast on Fighter and Magic User!" << std::endl;
fighter = new PlayerUnderSpell<Fighter, Invisibility> (fighter);
magicUser = new PlayerUnderSpell<MagicUser, Invisibility> (magicUser);
fighter->action(); magicUser->action();
magicUser->castsSpell();
std::cout << "Though invisible, " << magicUser->Name() << " is caught in a fireball blast! 10 hit points lost!" << std::endl;
magicUser->losesHitPoints (10); // magicUser deleted automatically, and no leaking because of PlayerDecorator's destructor
std::cin.get();
}
|