   Grouping classes together
  I have a problem related to grouping classes together.A game related (hypothetical, the problem is with this kind of grouping in general) example:I have a buff spell that heals 2 hp / second, i also have another buff spell that heals 2 mp / second. Both these  have a common abstract baseclass "StatusChanger"(or something) that exposes an Update method. A gameobject contains a list of StatusChangers. Say i now want to add FysicalPoison and MentalPoison that works the opposite way of my two buffs. They work exactly the same way inheriting from StatusChanger. These two are stored in the same list as the buffs, and the gameobject does not know if they are positive or negative.The problem occurs when i need to know if they are positive or negative, say a "cureallpoison" spell. This means that i need to group my "StatusChangers" in some way. I could do this by having two empty abstract subclasses of StatusChanger, PositiveStatusChanger and NegativeStatusChanger. Although using empty classes for classification.. feels wrong. I could store them in different lists, but that makes it harder to extend with new types. I could have an abstract method string GetTypeOfStatusChanger, although strings open up the possibility of misspellings which could be very annoying.Are there any patterns for grouping classes together where they don't need a different interface, that makes it easy to add classes to groups or add new groups? Ideally i would like it to be possible to multiclass the objects, and also have deeper hierachies like "positive.Accuracy".I'm using C# if that makes a difference (i could use attributes)I hope it's possible to understand me :)   
  Why do you need all these classes in the first place? They could buy you something, but in your example I don't yet see what that something is. So surely you can create a single StatusChanger class whose instances contain the deltas added when the changer is applied?Then you don't need any type checking. If you want to find out if its effect is "negative" in some sense, query its healthDelta() and see if it's less than 0.If you really do have to go with all these derived classes (sounds like overkill to me at the moment, though), you'll probably want to look in to the visitor pattern.   ;  Have a StatisChange Class.  Have the statis change class have an Effect class member.  Have the effect class have a Name, Type, and Amount.  TaDa. That does everything you need to do.  Also it means that you can add effects by script or data files and not by code.Remember you make a class for cars, not for ever model of car.theTroll   ;  The_ebb, Well, i could do that, but that was not the point here. That solution only works in my original example, but i find this problem in many other situations. Say for example i have a list of behaviouralcomponents, where some components affect "shooting" behaviour, others affect movement behaviour, both are some kind of statemachines that gets a call to update every now and then. So they both inherit from some "behaviour component" baseclass, but i still want to be able to distinguish them from one another. I'm not really sure how the visitor pattern applies here.TheTroll: That could be a solution, although it would still be string comparisons, and no possibility to multiclass or have deeper hierachies.One solution that i'm thinking of is having an Is(string group) method in the baseclass which could be used as: if (StatusChange.Is(positive)) checks a protected list of strings by doing if x.startswith(group), and then let each class fill its list with for example: "positive.healthrejuvination" or "behaviouralcomponent.movingbehaviour.flying". Then i could easily query the objects for what type they are. But this is still doing string comparisons.It might be that you are both right, and this type of classification is never needed, and all examples i can come up with are due to design errors.   ;  One possible solution may be to drive the abstraction a step furthur. Instead of hard-coding the State class' variables, you can encapsulate them one-by-one (e.g. as NumericVariable) and collect them to define the State. You can use the mediator pattern and/or singular value updates followed by a collective "rework" invocation for the State. Advantages may be(1) less classes at the end,(2) easier structure if the state has to be expanded later on,(3) the effectors can be interrogated whether they affect a specific variable,(4) simpler inheritance tree,(5) better integration with scripting,(6) ...Here especially point (3) may be what you are looking after. Although there is no longer a need to define distinct HPStateEffector and MPStateEffector classes, the only needed VariableEffector class becomes an interrogatable (uhh, corrrect word?) semantic due its linking with the targeted Variable instance!Point (4) means that you get the possibility of a totally different inheritance tree without getting a 2nd dependency. E.g. you can derive a OneShotVariableEffector and a RateVariableEffector, i.e. derivatives that are distinct in their behaviour, but _without_ the need of a HPOneShotVariableEffector and a HPRateVariableEffector and a MPOneShotVariableEffector and a MPRateVariableEffector etc.   ;Quote:Original post by haegarryou can encapsulate them one-by-one (e.g. as NumericVariable) and collect them to define the StateMy knowledge of design patterns is a little rusty so please correct me if I'm wrong, but would that be more or less equivalent to:Quote:Original post by MartinMMI could store them in different lists...I believe he meant to say that each character would have a list data structure for each conceivable property for status changersQuote:Original post by haegarr(3) the effectors can be interrogated whether they affect a specific variable,Here especially point (3) may be what you are looking after. Although there is no longer a need to define distinct HPStateEffector and MPStateEffector classes, the only needed VariableEffector class becomes an interrogatable (uhh, corrrect word?) semantic due its linking with the targeted Variable instance!Yeah but I think MartinMM wants something that can query for, say, all "poison" type so and so, or all "positive" and "mp" (boolean queries) so and so.  These things are all really game-specific so he needs something that is easy to modify, possibly during run-time.I could really see no other way but to give each status changer a type (or mulitple types contained in some data structure, possibly a binary tree or hash map for fast lookup), either using enum or string. Or you could use a bitset too. You might want to use bitsets for boolean querying capabilities.If you're worried of misspellings when using strings, then have your program throw an error it if receives a query for a non-existing StatusChanger type. It should be fairly easy to hunt them down during debug or development and make sure no misspellings are remaining upon release.   ;Quote:Original post by MartinMMThe_ebb, Well, i could do that, but that was not the point here. That solution only works in my original example, but i find this problem in many other situations. Say for example i have a list of behaviouralcomponents, where some components affect "shooting" behaviour, others affect movement behaviour, both are some kind of statemachines that gets a call to update every now and then. So they both inherit from some "behaviour component" baseclass, but i still want to be able to distinguish them from one another. I'm not really sure how the visitor pattern applies here.This exactly the kind of situation in which visitor arises; remember it's about visiting types, not objects. So you can have one visitor that only acts on "shooters" and one that acts only on "movers". I don't want to push this pattern to hard, because it's rather complicated, but you should certainly consider it.   ;  The "name" member of effect is only for human visualization, not for comparing with the code.  I guess I should have explained that better.  Type is just a enum or int that holds all the possible effects.  That was you can just just basic if's and selects to test them.theTroll   ;Quote:Original post by anomalous_underdogQuote:Original post by haegarryou can encapsulate them one-by-one (e.g. as NumericVariable) and collect them to define the StateMy knowledge of design patterns is a little rusty so please correct me if I'm wrong, but would that be more or less equivalent to:Quote:Original post by MartinMMI could store them in different lists...I believe he meant to say that each character would have a list data structure for each conceivable property for status changersI'm speaking of assembling the State, a bit like the nowadays popular generic "game object" design. On the other hand, the citation speaks of managing different lists of effectors (as you've mentioned). That are 2 very different things (that can nevertheless co-exist very well). The latter one is a kind of filter "in advance" that allows to not need to run queries at runtime. As such it will presumbly suffer from the multitude of possibilities that may arise in the evolution of the game. (You already have noticed that, I know.) The mechanism I mentioned goes exactly the opposite way: It introduces are greater flexibility, because it doesn't rely on a specific "unrolled" State class structure. So it is less prone to game evolution.Quote:Original post by anomalous_underdogQuote:Original post by haegarr(3) the effectors can be interrogated whether they affect a specific variable,Here especially point (3) may be what you are looking after. Although there is no longer a need to define distinct HPStateEffector and MPStateEffector classes, the only needed VariableEffector class becomes an interrogatable (uhh, corrrect word?) semantic due its linking with the targeted Variable instance!Yeah but I think MartinMM wants something that can query for, say, all "poison" type so and so, or all "positive" and "mp" (boolean queries) so and so.  These things are all really game-specific so he needs something that is easy to modify, possibly during run-time.The mechanism I have proposed above allows not to differentiate between poison and, say, a disease, as long as it isn't extended accordingly. Certainly it is able to be queried for all negative effects on the HP, for example, or each effects that increase the MP by more than 10 units/second. If a finer granularity is required, an extra semantic tag can be added easily. In principle, all tagging system mentioned in this thread are workable.However, I definitely second that one should not try to encode the behaviour in a single tag, be it a string or enum or whatever. It works well for a small system, but may become as unhandy as inheritance does when the system grows. Using multiple data instead reduces the imminence of repeated reworking. The semantic to the targeted variable is a valid criteria in this sense, too. So, IMHO, using a reference to a Variable is just another sequential step on the way to a data described implementation.;  Haegarr (and Anomalous_underdog): Anomalous_underdog pretty much answered that (and then you answered him). I dont have much to add other than:Quote: The mechanism I have proposed above allows not to differentiate between poison and, say, a disease, as long as it isn't extended accordingly. Certainly it is able to be queried for all negative effects on the HP, for example, or each effects that increase the MP by more than 10 units/second. And thats what i want to do. I want groups of classes in some way or another, groups thats easily extended and dynamic. Querying for what an effect modifies could work nice, but what if i have an "convertHP2MP" class, it's negative for the HP, but in this particular game it could be seen as an positive effect.Quote:However, I definitely second that one should not try to encode the behaviour in a single tag, be it a string or enum or whatever. It works well for a small system, but may become as unhandy as inheritance does when the system grows. Thats my problem, but i really don't see another solution, or well, i see many solutions, but none that gives me all that i want. I probably have to just choose one and be happy with it.Quote:This exactly the kind of situation in which visitor arises; remember it's about visiting types, not objects. So you can have one visitor that only acts on "shooters" and one that acts only on "movers". I don't want to push this pattern to hard, because it's rather complicated, but you should certainly consider it. But the problem here is not acting on these types, the problem is knowing that the ShootOnSight and ShootRandomly are both shooters. To the computer the ShootOnSight has as much in common with MoveRandomly as with the ShootRandomly (they all inherit from the same baseclass). What i need is some way of making that classification of shooters/movers. And i don't think the visitor pattern helps me with that.The troll: Enum leaves me with the problem of extending with new groups/types from a script. Int could work, but it comes with pretty much the same problems as using an string ("what was the number for the poison group now again!").   