/**
* Name: _team1strategy
* Author: Julien
* Description: This model contains one of the 2 team strategy.
* This strategy is quite advanced, attributing role for each player, with a custom influence_area and a custom position_mark.
* Tags:
*/
model team1strategy
import "Soccer Base.gaml"
species player_intelligentTeam parent:base_player {
// READ ONLY ATTRIBUTES :
// position : can be "front" or "back".
// players : list of all the players of the team.
// game
//closest_player_to_ball
// called_player : the player called for a pass
// possess_ball : true or false
// player_with_ball : player currently with the ball
// READ AND WRITE ATTRIBUTES :
// position_mark
// status : the current status of the player (can be useful to build the model)
// influence_area : the area of interest of the player. By default, this area is a circle 15m diameter centered in the player location.
float position_mark <- 0.0 update: location.y - 20*number_of_ennemy_player_in_range + self.distance_to_closest_ennemy_player;
string role; // a value between "defense", "mid" and "attack".
string wing; // a value between "left", "center" and "right".
geometry influence_area <- circle(15,init_pos);
float defense_mid_pos <- 30.0; // the y percent chosed to separate the defense from the mid position.
float mid_attack_pos <- 60.0; // the y percent chosen to separate the mid from the attack position.
init {
// set the role of the player (between "defense", "mid" and "attack").
if ( init_pos_in_percent.y < defense_mid_pos ) {
role <- "defense";
}
else if ( (init_pos_in_percent.y > mid_attack_pos ) ) {
role <- "attack";
}
else {
role <- "mid";
}
// set the wing of the player (between "left", "center" and "right")
if ( init_pos_in_percent.x < 40 ) {
wing <- "left";
}
else if ( init_pos_in_percent.x > 60 ) {
wing <- "right";
}
else {
wing <- "center";
}
}
action update_influence_area {
status <- wing + " " + role;
float y_ratio;
if (role = "defense") { // defense position from 0% to 70% from the own goal, multiplied by the percentage of advancement of the ball
y_ratio <- 0.7 * ball_advancement;
}
if (role = "mid") { // mid position from 15% to 85% from the own goal, multiplied by the percentage of advancement of the ball
y_ratio <- 0.15 + 0.7 * ball_advancement;
}
if (role = "attack") { // attack position from 30% to 100% from the own goal, multiplied by the percentage of advancement of the ball
y_ratio <- 0.3 + 0.7 * ball_advancement;
}
float x_ratio;
if (wing = "center") {
x_ratio <- 0.5;
}
else if (wing = "left") {
x_ratio <- 0.5 - 0.3 * cos( (y_ratio-0.5)*120 ); // the "side" wings are more marked if the player is in the center of the field.
}
else {
x_ratio <- 0.5 + 0.3 * cos( (y_ratio-0.5)*120 );
}
influence_area <- circle(15,{getXPos(x_ratio),getYPos(y_ratio)});
}
action defensive_behavior {
do update_influence_area;
// advanced defensive behavior
// run to the ball if the player is the closest player from the ball.
if ((self = team.closest_player_to_ball) or (self distance_to ball < 5)) {
status <- getStatus("run to ball");
do run_to_ball;
}
else {
// if there is an ennemy player in the influence area, mark the player.
if ( length(self.ennemy_team.players where (each intersects influence_area)) != 0 ) {
base_player marked_player <- first(1 among (self.ennemy_team.players where (each intersects influence_area)));
status <- getStatus("mark player "+marked_player);
do mark_player( marked_player );
}
// if there is no ennemy player in the influence area, stay in influence area.
else {
status <- getStatus("run to influence area");
do run_to(influence_area.location);
}
}
}
action offensive_behavior {
do update_influence_area;
// advanced offensive behavior
if (possess_ball) {
// if the player has the ball and is close enough to the ennemy goal, shoot.
if (distance_to_goal < 35 and flip(1/(0.1+(self.distance_to_goal/10)^2))) {
status <- getStatus("shoot the ball");
do shoot;
}
// if the player has the ball and is in a safe position, run to the ennemy goal.
else if ( (position_mark = max( team.players collect (each.position_mark) )) or (distance_to_closest_ennemy_player > 2) )
{
status <- getStatus("run to ennemy goal");
do run_to_ennemy_goal;
}
// if the player has the ball but is in a dangerous situation, pass the ball to another player.
else {
base_player target_player <- first(team.players where (each.position_mark = max( team.players collect (each.position_mark)) ) );
status <- getStatus("pass the ball to "+target_player);
do pass_the_ball_ahead ( target_player,10.0 );
}
}
// if the player has not the ball but is the called player, run to the ball.
else if (self = team.called_player) {
status <- getStatus("run to ball");
do run_to_ball;
status <- "called player";
}
// else, run to influence area.
else {
status <- getStatus("run to influence area");
do run_to(influence_area.location);
}
}
string getStatus(string str) {
return wing + " " + role + "| action : " + str;
}
}
species intelligentTeam parent:base_team {
// READ ONLY ATTRIBUTES :
// position : can be "front" or "back".
// players : list of all the players of the team.
// game.
// closest_player_to_ball.
// called_player : the player called for a pass.
// possess_ball : true when a player of the team possess the ball.
// player_with_ball
// READ AND WRITE ATTRIBUTES :
// player_init_position
// initial position of the player in percentage : for each point,
// the first value corresponds to the percentage from left to right (0 for the point the most in the left side)
// the second value corresponds to the percentage from the goal position to the mid position (0 for the goal position)
list player_init_position <- [{20,20},{50,20},{80,20},{30,50},{70,50},{50,70},{30,90},{50,90},{70,90}];
}