Skip to content

conceitos player playbook

Eduardo Makita edited this page Jul 21, 2023 · 2 revisions

O PlayerPlaybook é uma maneira alternativa para se criar uma estratégia, ele funciona como uma máquina de estados onde cada transição (chamada de trigger) pode ser ativada pelo estado do jogo (posições de robô e bola) e cada estado (chamado de PlayerPlay) é um comportamento utilizado em uma situação específica.

Um exemplo dessa implementacao pode ser vista no codigo do atacante principal usado na modalidade física para a ironcup 2023:

from controller.PID_control import PID_W_control, PID_control
from strategy.BaseStrategy import Strategy
from strategy.utils.player_playbook import PlayerPlay, PlayerPlaybook, OnInsideBox, OnNextTo, AndTransition


class MainPlay(PlayerPlay):
    ...


class WingPlay(PlayerPlay):
    ...


class CrossPlay(PlayerPlay):
    ...


class MainStriker(Strategy):
    def __init__(self, match, name="Main_Attacker"):
        super().__init__(match, name, controller=PID_W_control)

        self.playerbook = None

    def start(self, robot=None):
        super().start(robot=robot)

        # Criando Player Playbook: A maquina de estados do jogador
        self.playerbook = PlayerPlaybook(self.match.coach, self.robot)

        # Instância as plays definidas acima
        main = MainPlay(self.match, self.robot)
        main.start()
        wing = WingPlay(self.match, self.robot)
        wing.start()
        cross = CrossPlay(self.match, self.robot)
        cross.start()

        # Adiciona as plays ao playbook
        self.playerbook.add_play(main)
        self.playerbook.add_play(wing)
        self.playerbook.add_play(cross)

        # Criar os triggers
        on_wing = OnInsideBox(self.match, [0, 0.3, 1.5, 0.7], True)
        off_wing = OnInsideBox(self.match, [0, 0.3, 1.5, 0.7], False)
        
        on_cross_region = OnInsideBox(self.match, [1.4, 0, .15, 1.3])
        on_near_ball = OnNextTo(self.match.ball, self.robot, 0.1)
        able_to_cross = AndTransition([on_near_ball, on_cross_region, on_wing])

        # Conecta a play inicial, o trigger e a play final. Seguindo o modelo:
        # play_inicial.add_transition(trigger, play_final)
        main.add_transition(on_wing, wing)
        wing.add_transition(off_wing, main)
        wing.add_transition(able_to_cross, cross)
        cross.add_transition(off_wing, main)

        # Estado inicial
        self.playerbook.set_play(main)

    def decide(self):
        return self.playerbook.update()

Esse trecho é uma simplificação que omite tanto a lógica das plays, quanto as plays defensivas. O código na íntegra pode ser encontrado aqui.

Na estratégia acima (MainStriker), existem 3 PlayerPlay, que podem ser entendidas como miniestratégias convencionais. Cada uma possui o seu controle ideal e as suas lógicas que guiam o movimento do robô. Na estratégia, o PlayerPlaybook é criado. Ele recebe todas as plays e controla a partir das transições (Triggers) qual play será ativada em cada momento.

O playbook pode se representado pelo grafo acima, onde cada nó é uma play e cada aresta um trigger.

Vale ressaltar que aqui só foram utilizados triggers já existentes (disponíveis aqui), mas vocẽ tem a opção de criar novos dependendo das suas intenções.