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
9 changes: 7 additions & 2 deletions src/proto/parameters.proto
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ message DefensePlayConfig
(bounds).min_double_value = 0.0,
(bounds).max_double_value = 10.0
];

// The max number of crease defender can be created at a moment
required uint32 max_num_crease_defenders = 6
[default = 1, (bounds).min_int_value = 1, (bounds).max_int_value = 3];
}

// The distance at which a threat is considered "immediate" if there is only 1
Expand Down Expand Up @@ -634,12 +638,13 @@ message NetworkConfig

message CreaseDefenderConfig
{
// Unique steal config for crease defenders
required DefenderStealConfig defender_steal_config = 1;

// The additional buffer length for each side of the goal
// to determine if crease defender chipping is "towards goal"
required double goal_post_offset_chipping = 4
[default = 0.5, (bounds).min_double_value = 0.0, (bounds).max_double_value = 2.0];
// Unique steal config for crease defenders
required DefenderStealConfig defender_steal_config = 1;
}

message PassDefenderConfig
Expand Down
13 changes: 10 additions & 3 deletions src/software/ai/hl/stp/play/defense/defense_play_fsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ void DefensePlayFSM::defendAgainstThreats(const Update& event)
event.common.world_ptr->field(), event.common.world_ptr->friendlyTeam(),
event.common.world_ptr->enemyTeam(), event.common.world_ptr->ball(), false);

auto defender_assignment_config =
ai_config.defense_play_config().defender_assignment_config();
auto assignments = getAllDefenderAssignments(
enemy_threats, event.common.world_ptr->field(), event.common.world_ptr->ball(),
ai_config.defense_play_config().defender_assignment_config());
defender_assignment_config);

if (assignments.size() == 0)
{
return;
}

unsigned int max_num_crease_defenders =
defender_assignment_config.max_num_crease_defenders();

// Choose which defender assignments to assign defenders to based on number
// of tactics available to set
std::vector<DefenderAssignment> crease_defender_assignments;
Expand All @@ -42,17 +47,19 @@ void DefensePlayFSM::defendAgainstThreats(const Update& event)
defender_assignment = assignments.front();
}

if (defender_assignment.type == CREASE_DEFENDER)
if (defender_assignment.type == CREASE_DEFENDER && max_num_crease_defenders > 0)
{
crease_defender_assignments.emplace_back(defender_assignment);
max_num_crease_defenders--;

// If we have at least two available defenders, two defenders should
// be assigned to the highest scoring crease defender assignment to better
// block the shot cone of the most threatening enemy
if (i == 0 && event.common.num_tactics >= 2)
if (i == 0 && event.common.num_tactics >= 2 && max_num_crease_defenders > 0)
{
crease_defender_assignments.emplace_back(defender_assignment);
i++;
max_num_crease_defenders--;
}
}
else
Expand Down
52 changes: 26 additions & 26 deletions src/software/ai/hl/stp/tactic/defender/defender_fsm_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,48 @@ bool DefenderFSMBase::ballNearbyWithoutThreat(
const TbotsProto::BallStealMode& ball_steal_mode,
const TbotsProto::DefenderStealConfig& defender_steal_config)
{
if (ball_steal_mode == TbotsProto::BallStealMode::IGNORE)
{
// Do nothing if stealing is disabled
return false;
}

Point robot_position = robot.position();
Point ball_position = world_ptr->ball().position();

std::optional<Robot> nearest_friendly_to_ball =
world_ptr->friendlyTeam().getNearestRobot(ball_position);
std::optional<Robot> nearest_enemy_to_ball =
world_ptr->enemyTeam().getNearestRobot(robot_position);
if (ball_steal_mode == TbotsProto::BallStealMode::IGNORE)
{
// Do nothing if stealing is disabled
return false;
}
else if (nearest_friendly_to_ball.has_value() &&
robot.id() != nearest_friendly_to_ball.value().id())

if (nearest_friendly_to_ball.has_value() &&
robot.id() != nearest_friendly_to_ball.value().id())
{
// Do nothing if this robot is not the closest to the ball. Resolves issue of
// multiple simultaneous steals
return false;
}
if (nearest_enemy_to_ball.has_value())
{
// Get the ball if ball is closer to robot than enemy threat by threshold ratio
// and within max range
double ball_distance_to_friendly = distance(robot_position, ball_position);
double ball_distance_to_enemy =
distance(nearest_enemy_to_ball.value().position(), ball_position);

bool ball_is_near_friendly =
ball_distance_to_friendly <
ball_distance_to_enemy *
(1.0 - defender_steal_config.max_get_ball_ratio_threshold());
bool ball_is_within_max_range =
ball_distance_to_friendly <= defender_steal_config.max_get_ball_radius_m();
bool ball_is_slow = world_ptr->ball().velocity().length() <=
defender_steal_config.max_ball_speed_to_get_m_per_s();

return ball_is_near_friendly && ball_is_within_max_range && ball_is_slow;
}
else
if (!nearest_enemy_to_ball.has_value())
{
return true;
}

// Get the ball if ball is closer to robot than enemy threat by threshold ratio
// and within max range
double ball_distance_to_friendly = distance(robot_position, ball_position);
double ball_distance_to_enemy =
distance(nearest_enemy_to_ball.value().position(), ball_position);

bool ball_is_near_friendly =
ball_distance_to_friendly <
ball_distance_to_enemy * defender_steal_config.max_get_ball_ratio_threshold();
bool ball_is_within_max_range =
ball_distance_to_friendly <= defender_steal_config.max_get_ball_radius_m();
bool ball_is_slow = world_ptr->ball().velocity().length() <=
defender_steal_config.max_ball_speed_to_get_m_per_s();

return ball_is_near_friendly && ball_is_within_max_range && ball_is_slow;
}

void DefenderFSMBase::prepareGetPossession(
Expand Down