Una Máquinas de estado finitos (FSM, por sus siglas en inglés) es un modelo matemático compuesto por:
Las FSM pueden implementarse utilizando simples estructuras condicionales if-then-else (o switch/case) es lo que se conoce como “FSM implícita”. Este tipo de FSM funcionan para casos simples, pero no escala bien y puede volverse difícil de mantener, depurar o extender.
Los principales inconvenientes que plantea este enfoque son:
Existen otras formas más robustas, modulares y limpias de implementar las FSM, uno de las técnicas más usadas es la que utiliza el enfoque orientado a objetos donde cada estado es una clase, y las transiciones se manejan dentro de esas clases.
Las ventajas de este modelo es que cada estado encapsula su lógica lo que lo hace fácil de extender ya que añadir un nuevo estado solo requiere una nueva clase y evita grandes bloques de if/else que hacen el código ilegible.
Clase base para todos los estados del NPC. Cada estado define una interfaz común que define:
enter: qué hacer al entrar en el estado, execute (o update): qué hacer cuando se está en ese estadoexit: qué hacer al salir del estado.get_next_state_class: define el estado al que se pasa ante la llegada de un evento.def enter(self, npc): → Acción al entrar en el estado.
def execute(self, npc): → Acción principal que se ejecuta cada frame.
def exit(self, npc): → Acción al salir del estado.
def get_next_state_class(self, event): → Devuelve la clase del estado siguiente según el evento recibido.
Esta clase implementa la Máquina de estados que gestiona el estado actual de un NPC.
Para definir nuevos estados se define una nueva clase que hereda de State:
class TimidoPatrolState(State): """ Estado en el que el NPC tímido patrulla por el borde. """ ...
Las transiciones de un estado a otros se pueden definir en el método get_next_state_class(self, event) de cada estado.
Otras implementaciones definen las transiciones entre estados como un diccionario de pares “evento”:estado. Por ejemplo se puede definir para cada estado un diccionario denominado transitions con el evento que provoca una transición y a qué estado se mueve.
# Definir transiciones para NPCTimido TimidoPatrolState.transitions = {"player_seen": TimidoChaseState} TimidoChaseState.transitions = {"player_too_close": TimidoFleeState, "player_lost": TimidoPatrolState} ...
En esta imagen se muestra el comportamiento de tres NPCs distintos modelados usando FSM. Los estados se muestran en azul los eventos que provocan las transiciones entre estados aparecen sobre las flechas.
Su comportamiento cambia drásticamente dependiendo de si está en “misión de alerta” (buscando al guardia para reportar la posición del jugador):
tiene un comportamiento intermedio. Si no ve al jugador, actúa como un “investigador”: va a la última posición reportada del jugador si tiene esa información, o vuelve a patrullar si no.
Puedes ver y ejecutar el ejemplo en este script de python