Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/Dentosal/python-sc2 into…
Browse files Browse the repository at this point in the history
… dev_mine
  • Loading branch information
Matuiss2 committed Feb 20, 2019
2 parents 1b8d7d0 + e559413 commit 993e655
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 24 deletions.
12 changes: 6 additions & 6 deletions sc2/bot_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def main_base_ramp(self) -> "Ramp":
""" Returns the Ramp instance of the closest main-ramp to start location. Look in game_info.py for more information """
if hasattr(self, "cached_main_base_ramp"):
return self.cached_main_base_ramp
""" The reason for len(ramp.upper) in {2, 5} is:
""" The reason for len(ramp.upper) in {2, 5} is:
ParaSite map has 5 upper points, and most other maps have 2 upper points at the main ramp. The map Acolyte has 4 upper points at the wrong ramp (which is closest to the start position) """
self.cached_main_base_ramp = min(
(ramp for ramp in self.game_info.map_ramps if len(ramp.upper) in {2, 5}),
Expand Down Expand Up @@ -158,10 +158,10 @@ async def expand_now(self, building: UnitTypeId=None, max_distance: Union[int, f

if not location:
location = await self.get_next_expansion()
else:
await self.build(
building, near=location, max_distance=max_distance, random_alternative=False, placement_step=1
)

await self.build(
building, near=location, max_distance=max_distance, random_alternative=False, placement_step=1
)

async def get_next_expansion(self) -> Optional[Point2]:
"""Find next expansion location."""
Expand Down Expand Up @@ -440,7 +440,7 @@ def already_pending(self, unit_type: Union[UpgradeId, UnitTypeId], all_units: bo

if isinstance(unit_type, UpgradeId):
return self.already_pending_upgrade(unit_type)

ability = self._game_data.units[unit_type.value].creation_ability

if all_units:
Expand Down
29 changes: 18 additions & 11 deletions sc2/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,26 @@ def inner(self):
def property_cache_once_per_frame(f):
""" This decorator caches the return value for one game loop, then clears it if it is accessed in a different game loop
Only works on properties of the bot object because it requires access to self.state.game_loop """
f.frame = -1
f.cache = None

@wraps(f)
def inner(self):
if f.cache is None or f.frame != self.state.game_loop:
f.cache = f(self)
f.frame = self.state.game_loop
if type(f.cache).__name__ == "Units":
return f.cache.copy()
if isinstance(f.cache, (list, set, dict, Counter)):
return f.cache.copy()
return f.cache
property_cache = "_cache_" + f.__name__
state_cache = "_frame_" + f.__name__
cache_updated = (
hasattr(self, property_cache) and
getattr(self, state_cache, None) == self.state.game_loop
)
if not cache_updated:
setattr(self, property_cache, f(self))
setattr(self, state_cache, self.state.game_loop)

cache = getattr(self, property_cache)
should_copy = (
type(cache).__name__ == "Units" or
isinstance(cache, (list, set, dict, Counter))
)
if should_copy:
return cache.copy()
return cache

return property(inner)

Expand Down
14 changes: 14 additions & 0 deletions sc2/game_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,17 @@ def __ne__(self, other) -> bool:

def __bool__(self) -> bool:
return self.minerals != 0 or self.vespene != 0

def __add__(self, other) -> "Cost":
if not other:
return self
if not self:
return other
if self.time is None:
time = other.time
elif other.time is None:
time = self.time
else:
time = self.time + other.time
return self.__class__(self.minerals + other.minerals, self.vespene + other.vespene, time=time)

4 changes: 2 additions & 2 deletions sc2/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ async def _host_game(

assert any(isinstance(p, (Human, Bot)) for p in players)

async with SC2Process(render=rgb_render_config is not None) as server:
async with SC2Process(fullscreen=players[0].fullscreen, render=rgb_render_config is not None) as server:
await server.ping()

client = await _setup_host_game(server, map_settings, players, realtime, random_seed)
Expand Down Expand Up @@ -304,7 +304,7 @@ def _host_game_iter(*args, **kwargs):


async def _join_game(players, realtime, portconfig, save_replay_as=None, step_time_limit=None, game_time_limit=None):
async with SC2Process() as server:
async with SC2Process(fullscreen=players[1].fullscreen) as server:
await server.ping()

client = Client(server._ws)
Expand Down
11 changes: 6 additions & 5 deletions sc2/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


class AbstractPlayer:
def __init__(self, p_type, race=None, name=None, difficulty=None):
def __init__(self, p_type, race=None, name=None, difficulty=None, fullscreen=False):
assert isinstance(p_type, PlayerType)
assert name is None or isinstance(name, str)

Expand All @@ -25,11 +25,12 @@ def __init__(self, p_type, race=None, name=None, difficulty=None):
self.race = race
if p_type == PlayerType.Computer:
self.difficulty = difficulty
self.fullscreen=fullscreen


class Human(AbstractPlayer):
def __init__(self, race, name=None):
super().__init__(PlayerType.Participant, race, name=name)
def __init__(self, race, name=None, fullscreen=False):
super().__init__(PlayerType.Participant, race, name=name, fullscreen=fullscreen)

def __str__(self):
if self.name is not None:
Expand All @@ -39,13 +40,13 @@ def __str__(self):


class Bot(AbstractPlayer):
def __init__(self, race, ai, name=None):
def __init__(self, race, ai, name=None, fullscreen=False):
"""
AI can be None if this player object is just used to inform the
server about player types.
"""
assert isinstance(ai, BotAI) or ai is None
super().__init__(PlayerType.Participant, race, name=name)
super().__init__(PlayerType.Participant, race, name=name, fullscreen=fullscreen)
self.ai = ai

def __str__(self):
Expand Down
7 changes: 7 additions & 0 deletions sc2/position.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ def _distance_squared(self, p2: "Point2") -> Union[int, float]:
""" Function used to not take the square root as the distances will stay proportionally the same. This is to speed up the sorting process. """
return (self[0] - p2[0]) ** 2 + (self[1] - p2[1]) ** 2

def is_closer_than(self, d: Union[int, float], p: Union["Unit", "Point2"]) -> bool:
""" Check if another point (or unit) is closer than the given distance. More efficient than
distance_to(p) < d.
"""
p = p.position
return self._distance_squared(p) < d ** 2

def sort_by_distance(self, ps: Union["Units", List["Point2"]]) -> List["Point2"]:
""" This returns the target points sorted as list. You should not pass a set or dict since those are not sortable.
If you want to sort your units towards a point, use 'units.sorted_by_distance_to(point)' instead. """
Expand Down

0 comments on commit 993e655

Please sign in to comment.