How to write a state machine so that I don't have to duplicate states with 99% similar code?

I am making an city management game, where workers are completely controlled by state machines. I have an “issue” where I find my self re-writing a lot of states that are 99% similar. Usually the only difference in some of the states is which state it should go to when it is completed.

For example, the below state is used for delivering resources, this is something all professions do but I have a write a specific one for each profession, since they all lead to different states on complete.

public class BakerDeliverGrainState : BaseWorkerState, IState
{
    public void Enter()
    {
        //Go to storage
        SetDestination(storage.position);
    }

    public void Execute()
    {
        if (unit.ReachedDestination())
        {
            //Reached destination, state completed
            storage.Store(unit.TakeResource());
            unit.stateMachine.ChangeState(new BakerWorkState(unit)); //This is the line that seperates the states. For example a blacksmith will go to "BlacksmithWorkState", and so on.
        }
    }

    public void Exit()
    {
       
    }
}

Is there some way I can pass which state to change to in a constructor? Or some other way I can adjust my design that will not require me to re-write so much code.

Whoa, looking at line 15, this is using the Design Pattern version where each action is it’s own class? I think C++ solves it by using multiple inheritance (in this case, from abstract Deliver). After all, the book was written before anyone ever tried the inherit-from-1-class-and-virtual-interfaces-for-the-rest thing. In C#, maybe template classes (what C# calls generics, I think)?

Hi,

yeah each action is its own state, which means its own class. This has made it extremely easy to debug, since my testers always can click “show debug info” and the state name the unit broke in will show.

Tbh Im not sure what you are trying to say with ur answer :slight_smile: Maybe that I could use an abstract class to control the common behaviours and extend it to add custom behaviour? This isnt a bad idea, I’d still have to create a class for each action, but it’s prob better than my current solution.

You could either make a abstract DeliveryState that does everything shown above and only uses the abstract method to create the instance of the next state then you can make a BakeryDeliveryState that overrides the abstract method to create the specific next state for the Bakery.

Or option B would be to create the DeliveryState and “next state” at the same time and then pass the “next state” to the DeliveryState (maybe in the constructor, depends on your current design)

I was just amazed anyone was implementing a state machine that way. I always assumed “a class for every state” was an academic exercise, and for real everyone just used a state variable.

But I feel something like class Deliver<who, what> might be a start.

You could use composition for the difference between profession states.

class BakerCommonAction
class ButcherCommonAction

becomes

class CommonAction
     PostAction postActionProvider;

class BakerPostAction : PostAction
class ButcherPostAction : PostAction

PostAction is abstract. It could implement a single method GetNextState(). As a result, derivations from the PostAction parent class are tiny and boilerplate-free. Whatever CommonAction you have (MakeDelivery) it compositionally outsources what state is done next to the PostAction, which gives BakerWorkState, ButcherWorkState or whatever.

You feed in the PostAction into the CommonAction constructor or set its property.

Decided to make some abstract states to inherit from, each state is its own class with Enter, Execute, Exit. Still a lot of classes, baker alone has 9 classes, but whatever if thats the cost of easy debugging Ill take it. If anyone is interested here is a visualization: