Reputation: 39
I'm working in a card game. where I want the cards to have generic upgrades that could be applied to any card.
My cards have a Play() function, and I would want upgrades like
When one of these upgrades is applied to a card that card play function should do something similar to this to the PlayFunction()
PlayFunction(){
formerPlayFunction()
millCard()
}
How could I achieve this??
I was trying to do it with a lambda function that could be modified by the upgrades but didnt seemed like the better option.
Upvotes: -2
Views: 104
Reputation: 31020
Invent a struct Effect
that embodies the result of playing the card:
class Effect {
virtual ~Effect() {}
virtual void apply(context * ctx, Card & card) = 0;
virtual std::string description() const { return ""; }
};
Have Card objects store a std::vector<unique_ptr<Effect>>
.
Initially, this effect is just a default scoring effect for the card:
class Card {
private:
std::vector<unique_ptr<Effect>> effects;
public:
Card() {
effects.push_back(make_unique<DefaultEffect>());
}
void play(context * ctx) {
for (auto& effect : effects) {
effect.apply(ctx, *this);
}
}
};
DefaultEffect
might look something like this:
class DefaultEffect : public Effect {
virtual void apply(context * ctx, Card & card) {
ctx->score += card.value;
}
};
Making effects objects instead of plain function pointers allows you to make stateful effects and allows you to document the additional effects to the player (with the description
method). For example, "every time this card is played its value goes up by one" or "this effect can only be used 5 times".
The for
loop I suggest above is just for getting started, you can make things as complex as you want by returning something meaningful from Effect::apply
(eg a token value that stops the processing the effects or actually restarts it)
Upvotes: 1