1
\$\begingroup\$

I am using a FSM for the player entity and it is working fine. Currently the entity has one state and only one (e.g. paralyzed). The entity's state process() method is called every turn.

It is necessary however, that each entity can have more than one state simultaneously (e.g. paralyzed and blinded). Each state affects the entity attributes e.g. paralyzed reduces the walking range to 10% and blindness reduces it to 50%. Vision range is not affected by paralyzed state, but by blindness (set to 0).

Now it is important in which order the states are processed. I either end up with a wrong walking range or a wrong vision range. I could do checks in every state's process() whether the entity has any other states and alter the code accordingly, but this gets very messy the more states I add.

Currently I think it's a better choice to attach only one state to the entity, but to create more states, some of them a combination of two states (e.g. a blindedAndParalyzed). This way I'll and up with a lot more states than I currently calculated with, because ever state has to be combined with other states. I'm wondering if that is the best solution?

A state is a Singleton with an enter, process and exit method. Process is called each turn. Currently process() for paralyzed looks like this: public void process(){ walkRange = 10% * walkRangeBase; visionRange = visionRangeBase; }

and process() for blinded looks like this public void process(){ walkRange = 50% * walkRangeBase; visionRange = 0; } At the moment the result is always fine becvause only the process() method of only one state is executed. If I switch to multiple states both get executed and the result is either walkRange = 50% and visionRange = 0 or walkRange = 10%. THe desired result would be a walkRange of 10% and a visionRange of 0, because the walkRange should be limited to the smallest one. I could do something like that: public void process(){ if(state != paralyzed) walkRange = 50% * walkRangeBase; visionRange = 0; } But i have around 20 different states, so I have to create a lot of if cases. Choosing the smallest value for e.g. walkRange doesn't work either because there are some states with positive effect on walkRange. So I am wondering if it is better to avoid a state machine with more than one concurrent state and live with a bigger amount of states (about 50), or if there si another solution to this problem.

\$\endgroup\$
  • \$\begingroup\$ This is really your choice. It's a design decision that doesn't have a correct answer. Can you add more details about the problem that make it less of a "which to choose" type question? \$\endgroup\$ – MichaelHouse Oct 24 '14 at 21:08
  • 1
    \$\begingroup\$ Why are you thinking in terms of states? Blinded, paralyzed, etc should be properties, "tags" if you prefer. \$\endgroup\$ – Emiliano Oct 24 '14 at 21:21
  • \$\begingroup\$ No matter if they are states or tags, the problem (more tags or more spaghetti code) would still exist. \$\endgroup\$ – twilightends.com Oct 24 '14 at 21:31
  • \$\begingroup\$ Is it FSM if it has more than one active state? I think not. And yes, that is FSM feature that you need state for each possible combination. \$\endgroup\$ – wondra Oct 25 '14 at 12:17
  • \$\begingroup\$ If the effects are stackable you could also try to find a way of making effects append-only (think the balance of a bank account) and write the operations in way that they aren't affected by precedence. For instance, if the initial walkRange was already set to walkRangeBase, then paralyzed could do walkRange = 50% * walkRange and blinded walkRange = 10% * walkRange. The result would be the same independently of the order of operations. When the effect wears off you could call effect.wearOff() which would do the opposite manipulations. \$\endgroup\$ – plalx Sep 1 '15 at 13:25
1
\$\begingroup\$

If you built an FSM for the player entity you should have at least 2 different states or more. With only one you lose the point to have a FSM. Also you'd better think to states as conditions/moods/actions that the entity is actually doing. With this I mean that a state is a collection of properties values, while blinded and paralyzed are simply boolean properties and vision range and walking range are float properties/attributes.

1) The easiest solution would be maintaining the 2 bool variable and making some IF...ELSE during update. But it's not scalable.

2) So if you see that, for your game, you are going to need an independent management of legs and eyes you'd better split the control over 2 independent FSM, one for the legs state and the other one for the eyes. (DIVIDE ET IMPERA). Each one of the FSM is only modifying attributes relatives to legs or to eyes and they both receive any meaningful message to them.

For example let's say the legs are in the state walking and they received the message player poisoned. The legs FSM switch to state reduced mobility and set the walking range properly. Then they received the message player blinded. The legs FSM switch to state paralyzed and set the walking range accordingly. If the order of the 2 messages is switched due to different events in your game you can simply decide to ignore the message player poisoned if you are in the state paralyzed and the walking range will not change maintaining the correct lowest value. You can do the same example for your eyes.

Resuming, you split the FSM and then send messages to both about what is occurring to your player and they will decide what to do to their relatives attributes.

EDIT: referring to your code you should change the attributes in the enter method and not on each process

\$\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.