automat icon indicating copy to clipboard operation
automat copied to clipboard

Guidance on creating multiple similar outputs with variations in return value

Open cwaldbieser opened this issue 7 years ago • 0 comments

I was experimenting with automat to simulate a game. The game has a number of different phases, and different players may only be active in particular phases.

I modelled the phases as different states, and an input, advance_phase allows transitioning from one phase to the next in a linear fashion. I.e. in state "A", calling advance_phase() causes the machine to enter state "B". Calling it again causes the machine to enter state "C", etc.

I'd like to be able to query which players are active during a particular phase, but since there doesn't seem to be any way to map the machine state to other meaningful information in the game, I find I need to track the phases independently. So I end up with something like the following:

class Game(object):
    _machine = MethodicalMachine()

    # States
    @_machine.state()
    def have_players(self):
        """
        The game has players configured.
        """

    @_machine.state(initial=True)
    def dont_have_players(self):
        """
        The game doesn't have any players set.
        """

    @_machine.state()
    def phase_a(self):
        """
        Game phase "A"
        """

    @_machine.state()
    def phase_b(self):
        """
        Game phase "B"
        """

    @_machine.state()
    def phase_c(self):
        """
        Game phase "C"
        """

    # ...

    @_machine.state()
    def phase_z(self):
        """
        Game phase "Z"
        """

    # Inputs

    @_machine.input()
    def start_game(self):
        """
        Start the game.
        """

    @_machine.input()
    def advance_phase(self):
        """
        Advance to the next phase.
        """

    # Outputs

    @_machine.output()
    def _set_phase_a(self):
        self._game_phase = "a"

    @_machine.output()
    def _set_phase_b(self):
        self._game_phase = "b"

    # ...

    @_machine.output()
    def _set_phase_z(self):
        self._game_phase = "z"

    # Transitions

    dont_have_players.upon(add_players, enter=have_players, outputs=[_set_players])

    have_players.upon(start_game, enter=phase_a, outputs=[_set_phase_a])
    phase_a.upon(advance_phase, enter=phase_b, outputs=[_set_phase_b])
    phase_b.upon(advance_phase, enter=phase_c, outputs=[_set_phase_c])
    # ...
    phase_y.upon(advance_phase, enter=phase_d, outputs=[_set_phase_z])

I end up with lots of repetitive-looking states and outputs, and I was wondering if there is some guidance on the best way for implementing these multiple states or outputs, using some kind of looping perhaps.

cwaldbieser avatar Dec 31 '17 00:12 cwaldbieser