Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,93 @@ TODO

TODO

## Decision Making

```mermaid
flowchart TD
subgraph SamplePlayerAgent
SamplePlayerAgent_update_actions[update_actions]
end
subgraph FormationStrategy
FormationStrategy_update[update]
end
subgraph StarterStrategy
StarterStrategy_update[update]
end
subgraph DecisionMaker
DecisionMaker_make_decision[make_decision]
end
subgraph PlayOnDecisionMaker
PlayOnDecisionMaker_make_decision[make_decision]
end
subgraph SetPlayDecisionMaker
SetPlayDecisionMaker_make_decision[make_decision]
end
subgraph PenaltyDecisionMaker
PenaltyDecisionMaker_make_decision[make_decision]
end
subgraph GoalieDecisionMaker
GoalieDecisionMaker_make_decision[make_decision]
end
subgraph KickDecisionMaker
KickDecisionMaker_make_decision[make_decision]
end
subgraph MoveDecisionMaker
MoveDecisionMaker_make_decision[make_decision]
end
subgraph BhvKickPlanner
BhvKickPlanner_execute[execute]
end
subgraph BhvStarterKickPlanner
BhvStarterKickPlanner_execute[execute]
end
subgraph BhvSetPlay
BhvSetPlay_execute[execute]
end
subgraph BhvStarterSetPlay
BhvStarterSetPlay_execute[execute]
end
subgraph BhvPenalty
BhvPenalty_execute[execute]
end
subgraph BhvStarterPenalty
BhvStarterPenalty_execute[execute]
end
SamplePlayerAgent_update_actions --> A{is starter?}
A -->|yes| StarterStrategy_update
A -->|no| FormationStrategy_update
SamplePlayerAgent_update_actions --> DecisionMaker_make_decision
DecisionMaker_make_decision --> B{status?}
B --> PlayOnDecisionMaker_make_decision
B --> SetPlayDecisionMaker_make_decision
B --> PenaltyDecisionMaker_make_decision
B --> GoalieDecisionMaker_make_decision
PlayOnDecisionMaker_make_decision --> C{is kickable?}
C -->|yes| KickDecisionMaker_make_decision
C -->|no| MoveDecisionMaker_make_decision
KickDecisionMaker_make_decision --> D{is starter?}
D -->|yes| BhvStarterKickPlanner_execute
D -->|no| BhvKickPlanner_execute
SetPlayDecisionMaker_make_decision --> E{is starter?}
E -->|yes| BhvStarterSetPlay_execute
E -->|no| BhvSetPlay_execute
PenaltyDecisionMaker_make_decision --> F{is starter?}
F -->|yes| BhvStarterPenalty_execute
F -->|no| BhvPenalty_execute
```

## Citation

- [Cross Language Soccer Framework](https://arxiv.org/pdf/2406.05621)
Expand Down
7 changes: 7 additions & 0 deletions idl/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ message PenaltyKickState {
int32 our_score = 5;
int32 their_score = 6;
bool is_kick_taker = 7;
int32 cycle = 8;
}

/**
Expand Down Expand Up @@ -172,6 +173,7 @@ message Player {
int32 ball_reach_steps = 28; // How many cycles the player needs to reach the ball.
bool is_tackling = 29; // Whether the player is tackling or not.
int32 type_id = 30; // The type identifier of the player.
RpcVector2D inertia_final_point = 31;
}

/**
Expand Down Expand Up @@ -220,6 +222,7 @@ message Self {
CardType card = 39; // The card type of the agent. It can be NO_CARD, YELLOW, or RED.
int32 catch_time = 40; // The time when the last catch command is performed.
float effort = 41; // The effort of the agent. TODO more info
float get_safety_dash_power = 42;
}

/**
Expand Down Expand Up @@ -1296,6 +1299,8 @@ message bhv_doForceKick {}

message bhv_doHeardPassRecieve {}

message bhv_goalieFreeKick {}

message PlayerAction {
oneof action {
Dash dash = 1;
Expand Down Expand Up @@ -1366,6 +1371,7 @@ message PlayerAction {
bhv_doHeardPassRecieve bhv_do_heard_pass_recieve = 66;
HeliosBasicTackle helios_basic_tackle = 67;
Neck_OffensiveInterceptNeck neck_offensive_intercept_neck = 68;
bhv_goalieFreeKick bhv_goalie_free_kick = 69;
}
}

Expand Down Expand Up @@ -1668,6 +1674,7 @@ message ServerParam {
float goal_area_length = 224;
float center_circle_r = 225;
float goal_post_radius = 226;
float pitch_margin = 227;
}

message PlayerParam {
Expand Down
9 changes: 4 additions & 5 deletions src/behaviors/bhv_block.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

from typing import TYPE_CHECKING
from src.interfaces.IAgent import IAgent
from src.utils.convertor import Convertor
from pyrusgeom.geom_2d import *
from pyrusgeom.soccer_math import *
from service_pb2 import *
from src.interfaces.IBehavior import IBehavior

if TYPE_CHECKING:
from src.sample_player_agent import SamplePlayerAgent

class Bhv_Block(IBehavior):
"""
Expand All @@ -26,7 +28,7 @@ class Bhv_Block(IBehavior):
def __init__(self):
pass

def execute(self, agent: IAgent) -> bool:
def execute(self, agent: "SamplePlayerAgent") -> bool:
"""
Executes the block behavior for the agent. Predicts the future position of the ball and checks if the agent or any teammate can block it within a certain number of cycles.
Parameters:
Expand All @@ -38,9 +40,6 @@ def execute(self, agent: IAgent) -> bool:
- Calculate the first cycle that the agent or a teammate can block the ball.
- If the agent can block the ball, add a Body_GoToPoint action to the agent.
"""
from src.sample_player_agent import SamplePlayerAgent # Local import to avoid circular import
assert isinstance(agent, SamplePlayerAgent)

agent.logger.debug(f'------ Bhv_Block ------')
wm = agent.wm
sp = agent.server_params
Expand Down
7 changes: 4 additions & 3 deletions src/behaviors/bhv_kick_planner.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from typing import TYPE_CHECKING
from src.interfaces.IBehavior import IBehavior
from src.interfaces.IAgent import IAgent
from pyrusgeom.soccer_math import *
from pyrusgeom.geom_2d import *
from service_pb2 import *

if TYPE_CHECKING:
from src.sample_player_agent import SamplePlayerAgent

class BhvKickPlanner(IBehavior):
"""
Expand Down Expand Up @@ -33,10 +36,8 @@ class BhvKickPlanner(IBehavior):
def __init__(self):
pass

def execute(self, agent: IAgent):
def execute(self, agent: "SamplePlayerAgent"):
agent.logger.debug("--- WithBallDecisionMaker ---")
from src.sample_player_agent import SamplePlayerAgent # Local import to avoid circular import
assert isinstance(agent, SamplePlayerAgent)

agent.add_action(
PlayerAction(helios_offensive_planner=self._get_helios_offensive_planner(agent))
Expand Down
8 changes: 4 additions & 4 deletions src/behaviors/bhv_penalty.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

from typing import TYPE_CHECKING
from src.interfaces.IAgent import IAgent
from src.utils.convertor import Convertor
from pyrusgeom.geom_2d import *
from pyrusgeom.soccer_math import *
from service_pb2 import *
from src.interfaces.IBehavior import IBehavior

if TYPE_CHECKING:
from src.sample_player_agent import SamplePlayerAgent

class BhvPenalty(IBehavior):
def __init__(self):
pass

def execute(self, agent: IAgent) -> bool:
def execute(self, agent: "SamplePlayerAgent"):
agent.logger.debug("BhvPenalty.execute")
from src.sample_player_agent import SamplePlayerAgent # Local import to avoid circular import
assert isinstance(agent, SamplePlayerAgent)
agent.add_action(PlayerAction(helios_penalty=HeliosPenalty()))
8 changes: 4 additions & 4 deletions src/behaviors/bhv_setplay.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

from typing import TYPE_CHECKING
from src.interfaces.IAgent import IAgent
from src.utils.convertor import Convertor
from pyrusgeom.geom_2d import *
from pyrusgeom.soccer_math import *
from service_pb2 import *
from src.interfaces.IBehavior import IBehavior

if TYPE_CHECKING:
from src.sample_player_agent import SamplePlayerAgent

class BhvSetPlay(IBehavior):
def __init__(self):
pass

def execute(self, agent: IAgent) -> bool:
def execute(self, agent: "SamplePlayerAgent"):
agent.logger.debug("BhvSetPlay.execute")
from src.sample_player_agent import SamplePlayerAgent # Local import to avoid circular import
assert isinstance(agent, SamplePlayerAgent)
agent.add_action(PlayerAction(helios_set_play=HeliosSetPlay()))
39 changes: 39 additions & 0 deletions src/behaviors/bhv_starter_clearball.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from src.interfaces.IBehavior import IBehavior
from src.interfaces.IAgent import IAgent
from pyrusgeom.soccer_math import *
from pyrusgeom.geom_2d import *
from src.utils.tools import Tools
from pyrusgeom import vector_2d
from service_pb2 import *

class BhvStarterClearBall():

def __init__(self):
pass


def execute(agent: IAgent):
wm = agent.wm
ball_pos = Vector2D(wm.ball.position.x, wm.ball.position.y)
target = Vector2D(agent.server_params.pitch_half_length, 0.0)
if ball_pos.x() > -25.0 :
if ball_pos.dist(Vector2D(0.0, -agent.server_params.pitch_half_width)) < ball_pos.dist(Vector2D(0.0, agent.server_params.pitch_half_width)) :
target = Vector2D(0.0,-34.0)
else:
target = Vector2D(0.0,34.0)
else :
if abs(ball_pos.y()) < 10 and ball_pos.x() < -10.0 :
if ball_pos.y() > 0.0 :
target = Vector2D(-agent.server_params.pitch_half_length, 20.0)
else :
target = Vector2D(-agent.server_params.pitch_half_length, -20.0)
else:
if ball_pos.y() > 0.0 :
target = Vector2D(ball_pos.x(), 34.0)
else :
target = Vector2D(ball_pos.x(), -34.0)
return PlayerAction(body_smart_kick=Body_SmartKick(target_point=RpcVector2D(x=target.x(), y=target.y()),
first_speed=2.7,
first_speed_threshold=2.7,
max_steps=2))

33 changes: 33 additions & 0 deletions src/behaviors/bhv_starter_dribble.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from src.interfaces.IBehavior import IBehavior
from src.interfaces.IAgent import IAgent
from src.utils.tools import Tools
from pyrusgeom.vector_2d import Vector2D
from pyrusgeom.sector_2d import Sector2D
from service_pb2 import *


class BhvStarterDribble():

def __init__(self):
pass

def execute(agent: IAgent):
wm = agent.wm
ball_pos = Vector2D(wm.ball.position.x, wm.ball.position.y)
dribble_angle = (Vector2D(52.5, 0) - ball_pos).th().degree()
dribble_speed = 0.8
dribble_threshold = 0.7
dribble_sector = Sector2D(ball_pos, 0, 3, dribble_angle - 15, dribble_angle + 15)

if not Tools.ExistOpponentIn(agent , dribble_sector):
Target = Vector2D.polar2vector(3, dribble_angle) + ball_pos
return PlayerAction(body_smart_kick=Body_SmartKick(target_point=RpcVector2D(x=Target.x(), y=Target.y()),
first_speed=dribble_speed,
first_speed_threshold=dribble_threshold,
max_steps=2))
return





33 changes: 29 additions & 4 deletions src/behaviors/bhv_starter_kick_planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,39 @@
from pyrusgeom.soccer_math import *
from pyrusgeom.geom_2d import *
from service_pb2 import *

from src.behaviors.bhv_starter_clearball import BhvStarterClearBall
from src.behaviors.bhv_starter_pass import BhvStarterPass
from src.behaviors.bhv_starter_dribble import BhvStarterDribble
from src.behaviors.bhv_starter_shoot import BhvStarterShoot
from src.utils.tools import Tools

class BhvStarterKickPlanner(IBehavior):
def __init__(self):
pass
'''self.starter_shoot = BhvStarterShoot()
self.starter_clear_ball = BhvStarterClearBall()
self.starter_dribble = BhvStarterDribble()
self.starter_pass = BhvStarterPass()'''

def execute(self, agent: IAgent):
agent.logger.debug("BhvStarterKickPlanner.execute")
from src.sample_player_agent import SamplePlayerAgent # Local import to avoid circular import
assert isinstance(agent, SamplePlayerAgent)
raise NotImplementedError("BhvStarterKickPlanner.execute not implemented")
actions = []
actions += [shoot] if (shoot := BhvStarterShoot.execute(agent)) is not None else []
opps = Tools.OpponentsFromSelf(agent)
nearest_opp = opps[0] if opps else None
nearest_opp_dist = nearest_opp.dist_from_self if nearest_opp else 1000.0

if nearest_opp_dist < 10:
actions += [passing] if (passing := BhvStarterPass.execute(agent)) is not None else []

actions += [dribble] if (dribble := BhvStarterDribble.execute(agent)) is not None else []

if nearest_opp_dist > 2.5:
actions.append(PlayerAction(body_hold_ball=Body_HoldBall()))

actions.append(BhvStarterClearBall.execute(agent))

#Sending actions' queue
for i in actions:
if not i == []:
agent.add_action(i)
Loading