Gotchas
Selecting a worker¶
If you're using the Mining behavior
and need to select workers
to perform tasks, then you should request ares
to release workers from mining.
Problem¶
Behind the scenes, Ares designates workers to UnitRole.GATHERING
and automatically assigns
specific resources to each worker. If you try to steal these workers without informing ares
the Mining
task will send the worker back to mining again.
Solution¶
Opting to
select a worker through the mediator
is recommended.
This not only simplifies internal bookkeeping by removing the worker from mining and assigned resource
but also prioritizes a worker
that isn't currently involved in mining or holding resources. The selection process even extends to workers at
distant mineral patches whenever possible.
Additionally, it's worth considering assigning a fresh role to the worker to preempt potential
reassignment by the Mining task. Here's an example:
from ares.consts import UnitRole
if worker := self.mediator.select_worker(
target_position=self.start_location
):
self.mediator.assign_role(tag=worker.tag, role=UnitRole.DEFENDING)
DEFENDING
role: from sc2.ids.unit_typeid import UnitTypeId
from sc2.units import Units
defending_workers: Units = self.mediator.get_units_from_role(
role=UnitRole.DEFENDING, unit_type=UnitTypeId.SCV
)
Mixing python-sc2
and ares-sc2
¶
If starting with a blank ares bot, all python-sc2
logic will work as intended.
However, you may start working with ares
behaviors or methods that may interfere with common python-sc2
convenience methods or functions.
Mining behavior¶
If you're using the ares
Mining behavior,
then this breaks the functionality of the following python-sc2
convenience methods.
-
self.build()
Problem
Since theMining
behavior takes control of all spare workers by default it does not relinquish control of the worker this method is trying to select.
Solution
There are two solutions:- Avoid
python-sc2
methods and useares-sc2
build structure functionalities. See:
BuildStructure
behavior and
self.mediator.build_with_specific_worker
Additionally the build runner usesares
build functionality if you're using that. - If you want to stay with
python-sc2
for now, theself.build()
accepts abuild_worker
argument, we can askares
to select a worker and then pass that into the method:# building_pos is the area you want to build in building_pos: Point2 = self.start_location if worker := self.mediator.select_worker(target_position=building_pos): # ares has given us a worker, assign it a role so ares doesn't # steal it for mining self.mediator.assign_role(tag=worker.tag, role=UnitRole.BUILDING) # now we are free to use this worker with `self.build()) await self.build( building=UnitTypeId.BARRACKS, near=building_pos, build_worker=worker )
- Avoid
-
self.expand_now()
Problem
Same scenario asself.build()
but we do not have the same option to pass the worker into theexpand_now()
as we did withself.build()
.
Solution
However, we can combinepython-sc2
andares-sc2
alternative convenience methods for a similar effect. Example:
Note, you could use this solution for other buildings too, if you already calculated exactly where you will place the structure.# Use `python-sc2` get_next_expansion to get a new base location if next_expand_loc := await self.get_next_expansion(): # ask ares for a worker if worker := self.mediator.select_worker( target_position=next_expand_loc, force_close=True, ): # use ares build_with_specific_worker worker to build base # this will assign worker a new role # additionally by using this method, you get some extra functionality! # Such as replacing dead building workers and pathing control or worker self.mediator.build_with_specific_worker( worker=worker, structure_type=UnitTypeId.NEXUS, pos=next_expand_loc, )
-
self.distribute_workers()
- This one is obviously broken if you're usingMining
behavior but added for completion’s sake! -
self.select_build_worker()
Problem
Similar to previous problems,python-sc2
will not be able to select a worker withoutares-sc2
trying to steal it back.
Solution
Askares
for a worker
Building structures¶
This section covers breaking python-sc2
functionality if you interact with ares
custom build
tracker in any way. You're maybe using the building tracker if you use the following ares
features:
-
BuildStructure
macro behavior -
self.mediator.request_building_placement()
-
Using the
ares
BuildRunner
system in your bot
self.already_pending()
breaks for pending structures¶
Problem¶
Due to the custom tracking of workers that are currently on route to construct structures, the
already_pending()
method in python-sc2
has no knowledge of these pending structures.
Solution¶
ares
has an alternative function for pending structures:
# checks workers on route and in progress structures
num_pending_barracks: int = self.structure_pending(UnitTypeId.BARRACKS)
structure_pending
as worker is always present.
For Protoss or Zerg this will only count workers on route.
# checks workers on route, doesn't include gateways in construction
num_on_route_to_build_gateways: int = self.mediator.get_building_counter[UnitTypeId.GATEWAY]
Mixing ares-sc2
and python-sc2
build methods¶
There are no known breakages here, but a word of warning that mixing building structures via
ares
building methods and python-sc2
find placement queries could have
unintended consequences.
If possible try to stick with one system or the other, or limit mixing.
ares
in the background will check if position is available before building so mixing may
be fine in most cases.
Example ares-sc2
functions and methods that may interfere with python-sc2
convenience methods:
BuildStructure
behaviorself.mediator.request_building_placement()
- Using
ares
BuildRunner
system in your bot
These could interfere with following python-sc2
methods:
self.build()
self.find_placement()
- Your own calculated placements
Selecting a unit already assigned to a UnitSquad
¶
If you are using ares-sc2
unit squad system,
and you want to select a unit already assigned to a squad then you should take care to remove the unit to ensure
accurate squad calculations. You can do so by making the following mediator request:
from sc2.unit import Unit
# pretend this unit is already assigned to a unit squad
unit: Unit = self.units[0]
self.mediator.remove_tag_from_squads(tag=unit.tag)
Note if you're using the ares
role system, when assigning a unit a new role,
units are removed from squads automatically. So this should work too:
from ares.consts import UnitRole
from sc2.unit import Unit
# pretend this unit is already assigned to a unit squad
unit: Unit = self.units[0]
# switches unit to new role, and removes from any squad
self.mediator.assign_role(tag=unit.tag, role=UnitRole.DEFENDING)
Other gotchas?¶
Found something not listed here? Please feel free to contribute to the docs or raise an issue
in the ares-sc2
github repo.