![]() |
RoboCup2D Tutorial
|
Nessa seção é descrito o sistema de formação SBSP (Situation Based Strategic Positioning ou em português algo como Posicionamento Estratégico Baseado na Situação). Nesse SBSP, cada player agent não é considerado no movimento dos outros jogadores e para a posição-alvo do movimento é considerada como entrada somente a posição da bola. Isto é feito para apenas parecer que não é um posicionamento cooperativo, e sim como em uma coordenação aparentemente individual. O comportamento de posicionamento descrito nesta seção é algo próximo às habilidades individuais de cada player agent. No entanto, uma vez que são necessários ajustes em consideração ao equilíbrio de toda a equipe na implementação da operação, o que se segue aqui é uma parte da seção Desenvolvimento da Equipe.
A marcação próxima a um adversário específico é necessária quando o time está em seu campo de defesa. Obviamente, essa operação pode ser feita em outras situações, mas isso pode acarretar em um uso excessivo de stamina do jogador. Porém, isto necessariamente não leva à uma situação perigosa de jogo que poderia atrapalhar a formação do time. Estando no campo adversário e sem bola, uma marcação à distância já é suficiente. Com a posse de bola, uma marcação no campo de defesa pode trazer problemas ao tentar receber a bola em um passe; porém, no seu campo de ataque e estando sem a bola, isto será o objetivo principal desse comportamento. Para conseguir isto, mais do que marcar o adversário desejado é necessário mover-se próximo à posição da bola. Antes de decidir a posição-alvo do movimento de marcação, primeiro é necessário determinar qual jogador adversário será marcado. No código a seguir, decide-se qual jogador adversário será o candidato:
O código acima determina a posição para onde o player agent deve realizar o movimento de marcação sobre o adversário que, consequentemente, torna-se o jogador-alvo (target player).
Obtendo-se um ponteiro para o PlayerObject do adversário no método getMarkTarget, uma última modificação na coordenada Y é necessária para retroceder sem precisar de nenhuma rotação extra. Aqui, utiliza-se o valor da posição Y do próprio agent player, mas você pode utilizar um valor fixo.
No trecho de código acima, o objetivo é marcar o adversário próximo à home position do player agent. Numa visão mais abrangente onde se deseja um equilíbrio entre a função de cada jogador, a formação do time e os outros companheiros de equipe, seria necessária uma marcação mais complexa. Porém, em se tratando apenas de elaboração de regras, marcar o adversário parecer ser um tanto quanto difícil, particularmente, quando informações para identificação de outros jogadores são insuficientes. Portanto, para conseguir um comportamento de marcação mais confiável, compartilhar informações através de comunicação entre os jogadores é essencial.
Bloquear a linha de passe é uma importante tática defensiva pois reduz-se as opções do time adversário. Porém, como o jogador que está com a bola toma a iniciativa da jogada, o path behaviour não permite que o path course seja bem bloqueado mesmo se um player agent com características bem balanceadas for utilizado para tentar o bloqueio. Além disso, como a bola se move rapidamente, nem sempre é necessário tentar bloquear a linha de passe pois será difícil acompanhar o movimento da bola. Consequentemente, semelhante ao comportamento de marcação, é melhor tentar bloquear a linha de passe em situações defensivas onde o time está em seu campo de defesa.
O código a seguir mostra como bloquear a linha de passe da frente do gol até a direção do escanteio.
No exemplo acima, o player agent foi designado a mover-se em uma linha reta estabelecida entre uma posição fixa na frente do centro do gol e a posição da bola. Á 10m da bola, a distância mínima do eixo Y é 15m da coordenada Y da posição de bloqueio (block_point). Note que a role do jogador deve adotar outras regras quando o valor da coordenada Y da posição da bola é 15m ou menos. A coordenada X pode ser calculada a partir da equação da reta e o valor da coordenada Y. Essa implementação não pode ser considerada ótima pois nela é usado um número mágico, assim como em implementações similares a esta.
Se você deseja bloquear a linha de passe de jogadores adversários em particular, o player agent deve se mover na linha reta que conecta o adversário e a bola. Porém, a posição-alvo do movimento irá mudar durante os ciclos considerando que a bola e o adversário irão se mover. Durante o bloqueio, determinar se a posição do movimento é boa de uma forma fixa trará mais resultados do que apenas tentar bloquear uma linha reta qualquer do passe.
Imagine uma situação onde o jogador adversário inica um drible. Você não pode simplesmente correr atrás dele e tentar roubar a bola executando um behaviour para interceptar o drible. Nesse caso, é necessário que haja uma marcação na frente do adversário.
Segue o código:
Você deve estar imaginando que o código acima para obter a posição-alvo é bem simples. De fato, é bem simples. Contudo, a intenção não é ir exatamente no ponto onde previu-se o movimento do jogador adversário. Além do mais, o código acima pode resultar em rotações desnecessárias quando elaborado apenas para um ponto. Para resolver isto, basta atribuir um valor de erro maior no método BodyGoToPoint. Como resultado, é possível reduzir as rotações desnecessárias apenas mudando um pouco a direção da posição-alvo.
Prever o comportamento do adversário pode ser mais eficaz quando executado pelos jogadores ofensivos.
Existem vários métodos para calcular o campo potencial como uma forma de mudar a posição do movimento. O código a seguir obtém a densidade do jogador em uma certa posição.
No exemplo acima, é obtida a densidade de congestão dos jogadores adversários em um ponto específico (target_point). A posição que o valor da congestão possui é minimizado de acordo com o cálculo de várias coordenadas de posições medidas a partir do target_point.
Tudo parece ótimo nessa algoritmo, mas não funciona nesse caso. O campo de visão do player agent é limitado e desde que cada jogador está se movendo, as posições-alvo (target position) dos jogadores adversários estão constantemente mudando. Nesse caso, operações de rotaçãoes incluíram vários movimentos do player agent e isto não seria nada eficiente.
Uma solução para isto é registrar a intenção de movimento do tempo limite em uma forma que continue a realizar operações de movimentação para a posição, assim em um certo período de tempo você pode decidir qual target position será escolhida de acordo com o tempo considerado.
No entanto, mesmo reduzindo movimentos utilizando intention, mudanças dinâmicas da posição-alvo que está em movimento parece não surtir muito efeito. Se você deseja um efeito mais confiável, é melhor usar um método que incorpore regras estáticas que serão descritos abaixo.
Você também pode realizar a operação para cancelar a marcação através de regras de posicionamento fixo. Desta forma, é possível determinar a posição fixa do target point. Para ser mais preciso, isto não é um posicionamento dinâmico, isto é um posicionamento tático para uma situação local, como será explicado na mais detalhadamente na próxima seção. Por exemplo, no caso da role ForwardSide, o que você deve fazer é passar para a frente do gol para marcar o adversário de frente como mostrado no código a seguir.
A melhor ideia durante o jogo é ajustar a orientação do corpo mesmo quando não há ação a ser feita, em particular, quando o jogador já atingiu a posição final do seu movimento. Para um jogador ofensivo, é suficiente apenas rodar o corpo para a direção da linha de gol adversário. Isso pode ser facilmente obtido com o código a seguir:
Além disso, é útil ajustar a posição através do rear dash sem precisar mudar a orientação do corpo quando um jogador com role de marcação mais agressiva tiver que se mover continuamente para a target position.
Para um jogador com role defensiva, é necessário elaborar quase que um "comportamento racional" de interceptação. Por exemplo, no caso de uma role que faz uma linha defensiva a interceptação, considerando que é necessário o movimento que interfira o curso de movimento do jogador adversário de lado a lado, é mostrado no código a seguir:
Além disso, você precisará armazenar a direção perpendicular do corpo do player agent em relação à bola de modo que ficar fácil de lidar caso ela seja chutada de repente:
Porém, você deve verificar a posição da bola em qualquer caso. Assim, a operação para ajustar a orientação do corpo deve ser executada somente quando for possível confirmar a posição da bola.