Skip to content

Commit

Permalink
Update README with new game statistics and enhance decision-making lo…
Browse files Browse the repository at this point in the history
…gic for penalty situations
  • Loading branch information
naderzare committed Dec 1, 2024
1 parent fae71ac commit 9db14e2
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 23 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ there are many different ways to run the base code, in the next section, we will
| Summary Statistics

- **Game Count**: 100
- **Goals**: 234 : 143 (diff: 91)
- **Points**: 212 : 71 (diff: 141)
- **Average Goals**: 2.34 : 1.43 (diff: 0.91)
- **Average Points**: 2.12 : 0.71 (diff: 1.41)
- **Win**: 65, **Draw**: 17, **Lost**: 18
- **Win Rate**: 65.00%
- **Expected Win Rate**: 78.31%
- **Goals**: 223 : 78 (diff: 145)
- **Points**: 229 : 52 (diff: 177)
- **Average Goals**: 2.23 : 0.78 (diff: 1.45)
- **Average Points**: 2.29 : 0.52 (diff: 1.77)
- **Win**: 70, **Draw**: 19, **Lost**: 11
- **Win Rate**: 70.00%
- **Expected Win Rate**: 86.42%

| Goals Distribution

```mermaid
xychart-beta
title "Diff Goals Distribution"
x-axis [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
x-axis [-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8]
y-axis "Percentage"
bar [0,4,2,5,7,17,27,19,13,4,2]
line [0,4,2,5,7,17,27,19,13,4,2]
bar [0,0,0,0,1.00, 0.00, 2.00, 8.00, 19.00, 22.00, 25.00, 13.00, 5.00, 2.00, 2.00, 0.00, 1.00]
line [0,0,0,0,1.00, 0.00, 2.00, 8.00, 19.00, 22.00, 25.00, 13.00, 5.00, 2.00, 2.00, 0.00, 1.00]
```

## Quick start
Expand Down
10 changes: 6 additions & 4 deletions src/decision_makers/decision_maker.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from src.interfaces.IDecisionMaker import IDecisionMaker
from .play_on_decision_maker import PlayOnDecisionMaker
from .set_play_decision_maker import SetPlayDecisionMaker
from .penalty_decision_maker import PenaltyDecisionMaker
from src.interfaces.IAgent import IAgent
from service_pb2 import *

Expand All @@ -18,19 +19,20 @@ class DecisionMaker(IDecisionMaker):
Makes a decision for the given agent based on its role and the current game mode.
If the agent is a goalie, it adds a goalie action.
If the game mode is 'PlayOn', it delegates the decision to play_on_decision_maker.
If the game mode is a penalty kick, it adds a penalty action.
Otherwise, it adds a set play action.
If the game mode is a penalty kick, it adds a penalty action using penalty_decision_maker.
Otherwise, it adds a set play action using set_play_decision_maker.
"""
def __init__(self):
self.play_on_decision_maker = PlayOnDecisionMaker()
self.set_play_decision_maker = SetPlayDecisionMaker()
self.penalty_decision_maker = PenaltyDecisionMaker()

def make_decision(self, agent: IAgent):
if agent.wm.self.is_goalie:
agent.add_action(PlayerAction(helios_goalie=HeliosGoalie()))
elif agent.wm.game_mode_type == GameModeType.PlayOn:
self.play_on_decision_maker.make_decision(agent)
elif agent.wm.is_penalty_kick_mode:
agent.add_action(PlayerAction(helios_penalty=HeliosPenalty()))
self.penalty_decision_maker.make_decision(agent)
else:
agent.add_action(PlayerAction(helios_set_play=HeliosSetPlay()))
self.set_play_decision_maker.make_decision(agent)
11 changes: 11 additions & 0 deletions src/decision_makers/penalty_decision_maker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from src.interfaces.IDecisionMaker import IDecisionMaker
from src.interfaces.IAgent import IAgent
from service_pb2 import *


class PenaltyDecisionMaker(IDecisionMaker):
def __init__(self):
pass

def make_decision(self, agent: IAgent):
agent.add_action(PlayerAction(helios_penalty=HeliosPenalty()))
2 changes: 1 addition & 1 deletion src/decision_makers/set_play_decision_maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ class SetPlayDecisionMaker(IDecisionMaker):
def __init__(self):
pass

def make_decision(self, agent: IAgent, wm: WorldModel):
def make_decision(self, agent: IAgent):
agent.add_action(PlayerAction(helios_set_play=HeliosSetPlay()))
56 changes: 48 additions & 8 deletions src/strategy/formation_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,81 @@


class Situation(Enum):
"""
Enum class representing different game situations in a 2D soccer simulation.
Attributes:
OurSetPlay_Situation (int): Represents a situation where our team is executing a set play.
OppSetPlay_Situation (int): Represents a situation where the opposing team is executing a set play.
Defense_Situation (int): Represents a defensive situation for our team.
Offense_Situation (int): Represents an offensive situation for our team.
PenaltyKick_Situation (int): Represents a penalty kick situation.
"""
OurSetPlay_Situation = 0,
OppSetPlay_Situation = 1,
Defense_Situation = 2,
Offense_Situation = 3,
PenaltyKick_Situation = 4

class Formation:
"""
A class to manage different soccer formations for various game situations.
Attributes:
before_kick_off_formation (FormationFile): Formation used before the kick-off.
defense_formation (FormationFile): Formation used during defense.
offense_formation (FormationFile): Formation used during offense.
goalie_kick_opp_formation (FormationFile): Formation used when the opponent's goalie kicks.
goalie_kick_our_formation (FormationFile): Formation used when our goalie kicks.
kickin_our_formation (FormationFile): Formation used during our team's kick-in.
setplay_opp_formation (FormationFile): Formation used during the opponent's set play.
setplay_our_formation (FormationFile): Formation used during our team's set play.
Args:
path (str): The path to the directory containing the formation configuration files.
logger (logging.Logger): Logger instance for logging formation-related information.
"""
def __init__(self, path, logger: logging.Logger):
# Initialize formation files for different game situations
# before_kick_off_formation: Formation used before the kick-off
self.before_kick_off_formation: FormationFile = FormationFile(f'{path}/before-kick-off.conf', logger)
# defense_formation: Formation used during defense
self.defense_formation: FormationFile = FormationFile(f'{path}/defense-formation.conf', logger)
# offense_formation: Formation used during offense
self.offense_formation: FormationFile = FormationFile(f'{path}/offense-formation.conf', logger)
# goalie_kick_opp_formation: Formation used when the opponent's goalie kicks
self.goalie_kick_opp_formation: FormationFile = FormationFile(f'{path}/goalie-kick-opp-formation.conf', logger)
# goalie_kick_our_formation: Formation used when our goalie kicks
self.goalie_kick_our_formation: FormationFile = FormationFile(f'{path}/goalie-kick-our-formation.conf', logger)
# kickin_our_formation: Formation used during our team's kick-in
self.kickin_our_formation: FormationFile = FormationFile(f'{path}/kickin-our-formation.conf', logger)
# setplay_opp_formation: Formation used during the opponent's set play
self.setplay_opp_formation: FormationFile = FormationFile(f'{path}/setplay-opp-formation.conf', logger)
# setplay_our_formation: Formation used during our team's set play
self.setplay_our_formation: FormationFile = FormationFile(f'{path}/setplay-our-formation.conf', logger)

class FormationStrategy(IPositionStrategy):
def __init__(self, logger: logging.Logger):
self.logger = logger
self.formations: dict[str, Formation] = {}
self.formations['4-3-3'] = Formation('src/formations/4-3-3', logger)
self.formations['4-3-3-cyrus-base'] = Formation('src/formations/4-3-3-cyrus-base', logger)
self.formations['4-3-3-helios-base'] = Formation('src/formations/4-3-3-helios-base', logger)
self.selected_formation_name = '4-3-3' # '4-3-3' '4-3-3-cyrus-base' '4-3-3-helios-base'

self._read_formations()
self._set_formation(None)

self._poses: dict[int, Vector2D] = {(i, Vector2D(0, 0)) for i in range(11)}
self.current_situation = Situation.Offense_Situation
self.current_formation_file: FormationFile = self._get_current_formation().offense_formation

def _read_formations(self):
self.formations['4-3-3'] = Formation('src/formations/4-3-3', self.logger)
self.formations['4-3-3-cyrus-base'] = Formation('src/formations/4-3-3-cyrus-base', self.logger)
self.formations['4-3-3-helios-base'] = Formation('src/formations/4-3-3-helios-base', self.logger)

def _get_current_formation(self) -> Formation:
return self.formations[self.selected_formation_name]

def _set_formation(self, wm: WorldModel):
self.selected_formation_name = '4-3-3'
self.selected_formation_name = '4-3-3-cyrus-base' # '4-3-3' '4-3-3-cyrus-base' '4-3-3-helios-base'

def update(self, agent: IAgent):
logger = agent.logger
Expand Down Expand Up @@ -117,13 +157,13 @@ def update(self, agent: IAgent):
def get_position(self, uniform_number) -> Vector2D:
return self._poses[uniform_number]

def get_role_name(self, uniform_number) -> int:
def get_role_name(self, uniform_number) -> RoleName:
return self.current_formation_file.get_role(uniform_number).name

def get_role_type(self, uniform_number) -> int:
def get_role_type(self, uniform_number) -> RoleType:
return self.current_formation_file.get_role(uniform_number).type

def get_role_side(self, uniform_number) -> int:
def get_role_side(self, uniform_number) -> RoleSide:
return self.current_formation_file.get_role(uniform_number).side

def get_role_pair(self, uniform_number) -> int:
Expand Down

0 comments on commit 9db14e2

Please sign in to comment.