Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: natural bunker placement #124

Merged
merged 1 commit into from
Mar 31, 2024
Merged
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
65 changes: 59 additions & 6 deletions src/ares/managers/placement_manager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import time
from itertools import product
from typing import TYPE_CHECKING, Any, Callable, Coroutine, DefaultDict, Optional, Union

import numpy as np
Expand All @@ -8,6 +9,7 @@
cy_find_building_locations,
cy_get_bounding_box,
cy_pylon_matrix_covers,
cy_towards,
)
from loguru import logger
from sc2.constants import ALL_GAS
Expand Down Expand Up @@ -364,6 +366,16 @@ def request_building_placement(
k, self.ai.main_base_ramp.top_center
),
)
elif structure_type == UnitID.BUNKER:
if _available := [
a
for a in available
if self.placements_dict[location][building_size][a]["bunker"]
]:
final_placement = min(
_available,
key=lambda k: cy_distance_to_squared(k, base_location),
)
# prioritize production pylons if they exist
elif structure_type == UnitID.PYLON:
if available := [
Expand Down Expand Up @@ -577,10 +589,15 @@ def _solve_terran_building_formation(self):
pathing_grid: np.ndarray = self.manager_mediator.get_ground_grid.astype(
np.uint8
).T
self._solve_natural_bunker()
for el in self.ai.expansion_locations_list:
self.placements_dict[el] = {}
self.placements_dict[el][BuildingSize.TWO_BY_TWO] = {}
self.placements_dict[el][BuildingSize.THREE_BY_THREE] = {}
if el not in self.placements_dict:
self.placements_dict[el] = {}
if BuildingSize.TWO_BY_TWO not in self.placements_dict[el]:
self.placements_dict[el][BuildingSize.TWO_BY_TWO] = {}
if BuildingSize.THREE_BY_THREE not in self.placements_dict[el]:
self.placements_dict[el][BuildingSize.THREE_BY_THREE] = {}

# avoid building 3x3 within 9 distance of el
start_x: int = int(el.x - 4.5)
start_y: int = int(el.y - 4.5)
Expand Down Expand Up @@ -815,6 +832,7 @@ def _add_placement_position(
position: Point2,
production_pylon: bool = False,
wall: bool = False,
bunker: bool = False,
) -> None:
"""Add calculated position to placements dict."""
self.placements_dict[expansion_location][building_size][position] = {
Expand All @@ -825,6 +843,7 @@ def _add_placement_position(
"worker_on_route": False,
"time_requested": 0.0,
"production_pylon": production_pylon,
"bunker": bunker,
}

def _calculate_main_ramp_placements(self, el: Point2) -> None:
Expand Down Expand Up @@ -891,11 +910,15 @@ async def _draw_building_placements(self):
self.ai.draw_text_on_world(position, f"{placement}")
pos_min = Point3((placement.x - 1.5, placement.y - 1.5, z))
pos_max = Point3((placement.x + 1.5, placement.y + 1.5, z + 2))
self.ai.client.debug_box_out(pos_min, pos_max, Point3((255, 0, 0)))
if self.ai.race == Race.Terran:
if info["bunker"]:
colour = Point3((0, 255, 0))
else:
colour = Point3((0, 0, 255))
self.ai.client.debug_box_out(pos_min, pos_max, colour)
if self.ai.race == Race.Terran and not info["bunker"]:
pos_min = Point3((placement.x + 1.5, placement.y + 0.5, z))
pos_max = Point3((placement.x + 3.5, placement.y - 1.5, z + 1))
self.ai.client.debug_box_out(pos_min, pos_max, Point3((0, 255, 0)))
self.ai.client.debug_box_out(pos_min, pos_max, Point3((0, 0, 255)))

for placement in two_by_two:
info = self.placements_dict[location][BuildingSize.TWO_BY_TWO][
Expand Down Expand Up @@ -952,3 +975,33 @@ def _track_requested_placements(self) -> None:

for loc in loc_to_remove:
self.worker_on_route_tracker.pop(loc)

def _solve_natural_bunker(self):
nat_location: Point2 = self.manager_mediator.get_own_nat
start_x: int = int(nat_location.x - 4.5)
start_y: int = int(nat_location.y - 4.5)
self.points_to_avoid_grid[start_y : start_y + 9, start_x : start_x + 9] = 1
self.placements_dict[nat_location] = {}
self.placements_dict[nat_location][BuildingSize.THREE_BY_THREE] = {}

size: BuildingSize = STRUCTURE_TO_BUILDING_SIZE[UnitID.BUNKER]

towards_ramp: tuple[float, float] = cy_towards(
nat_location, self.ai.main_base_ramp.bottom_center, 4.0
)
towards_center: tuple[float, float] = cy_towards(
towards_ramp, self.ai.game_info.map_center, 6.0
)
goal_x: int = int(towards_center[0])
goal_y: int = int(towards_center[1])

for x, y in product(range(-2, 2), range(-2, 2)):
pos: Point2 = Point2((goal_x + x, goal_y + y))
if self.can_place_structure(pos, UnitID.BUNKER):
self._add_placement_position(size, nat_location, pos, bunker=True)
avoid_x = int(pos.x - 1.5)
avoid_y = int(pos.y - 1.5)
self.points_to_avoid_grid[
avoid_y : avoid_y + 3, avoid_x : avoid_x + 3
] = 1
break
Loading