2
\$\begingroup\$

I want to write somewhat randomized object activation effects, like when you step on a trap, you can be tepelorted, damaged, cursed and so on. I applied strategy pattern for this: damage/healing managed by class ChangeHealth, teleportation by class SetPosition etc.

I want to know how can I manage creation of objects in code from data, so, for example I want to be able to set that there will be trap which will damage player and there will be shrine which should teleport you upon activation from, for example, string or bit stream.

I'm working in C#, but interested in overall approach to this problem.

\$\endgroup\$
1
\$\begingroup\$

Fundamentally you're looking at creating a mapping from some piece of data (the "key") to some instance of your effect classes (ChangeHealth, SetPosition, et cetera). A straightforward way to accomplish this is to use

  • some kind of delegate (Func<...> in C#, for example) to manage the generic creation of effect instances and
  • some kind of associative array (Dictionary<K, V> in C#) to map from effect to delegate.

To do this you'd decide on a data representation for your traps. For simplicity's sake, I'll suggest you start with something text-based because it's easy to author, consume, and reason about. More complex ("binary") formats for your data may be an option you want to look at in the future, but aren't directly relevant to the mechanics of the technique I'm suggesting.

So, let's say each trap type is just a simple text file with a list of the effects it will apply, one per line. The effect name (a string like "teleport" or "poison" for example) becomes your dictionary's key.

Your dictionary's value is a Func<T>. T is the base class or interface shared by all your effect strategy classes. So your dictionary might look like:

Dictionary<string, Func<IEffect>> m_effectCreators;

When you define new effects in code, you can register them with this dictionary, supplying a delegate that creates a new instance of the appropriate effect:

m_effectCreators.Add("teleport", () => new SetPosition());
m_effectCreators.Add("poison", () => new ChangeHealth(-100));
m_effectCreators.Add("heal", () => new ChangeHealth(100));

Then, when you parse the trap, you read the trap's effect strings and, for each one, look it up in the dictionary to invoke the function to create the appropriate effect instance.

foreach(var effectName in trapData) {
  var creator = m_effectCreators[effectName];
  var effect = creator();
  actualTrap.AddEffect(effect); // ...or however you store the instances.
}

Hopefully you can see how you could even extend this to allow the trap text data to supply parameters. For example, instead of hard-coding the damage of a heal or poison trap as I did above, you could write "heal(30)" and have your code parse the "parameters" between the ( and ) and supply them so that the delegate can in turn pass them to the constructors of the effects.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.