Eric111
Eric111

Reputation: 39

Replace function with another one at runtime C++

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

Answers (1)

Botje
Botje

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

Related Questions