156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
"""
 | 
						|
This class is very experimental and probably not up to date and needs to be refurbished.
 | 
						|
If it works, you can watch replays with it.
 | 
						|
"""
 | 
						|
 | 
						|
# pylint: disable=W0201,W0212
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
from typing import TYPE_CHECKING, List, Union
 | 
						|
 | 
						|
from .bot_ai_internal import BotAIInternal
 | 
						|
from .data import Alert, Result
 | 
						|
from .game_data import GameData
 | 
						|
from .position import Point2
 | 
						|
from .unit import Unit
 | 
						|
from .units import Units
 | 
						|
 | 
						|
if TYPE_CHECKING:
 | 
						|
    from .client import Client
 | 
						|
    from .game_info import GameInfo
 | 
						|
 | 
						|
 | 
						|
class ObserverAI(BotAIInternal):
 | 
						|
    """Base class for bots."""
 | 
						|
 | 
						|
    @property
 | 
						|
    def time(self) -> float:
 | 
						|
        """ Returns time in seconds, assumes the game is played on 'faster' """
 | 
						|
        return self.state.game_loop / 22.4  # / (1/1.4) * (1/16)
 | 
						|
 | 
						|
    @property
 | 
						|
    def time_formatted(self) -> str:
 | 
						|
        """ Returns time as string in min:sec format """
 | 
						|
        t = self.time
 | 
						|
        return f"{int(t // 60):02}:{int(t % 60):02}"
 | 
						|
 | 
						|
    @property
 | 
						|
    def game_info(self) -> GameInfo:
 | 
						|
        """ See game_info.py """
 | 
						|
        return self._game_info
 | 
						|
 | 
						|
    @property
 | 
						|
    def game_data(self) -> GameData:
 | 
						|
        """ See game_data.py """
 | 
						|
        return self._game_data
 | 
						|
 | 
						|
    @property
 | 
						|
    def client(self) -> Client:
 | 
						|
        """ See client.py """
 | 
						|
        return self._client
 | 
						|
 | 
						|
    def alert(self, alert_code: Alert) -> bool:
 | 
						|
        """
 | 
						|
        Check if alert is triggered in the current step.
 | 
						|
        Possible alerts are listed here https://github.com/Blizzard/s2client-proto/blob/e38efed74c03bec90f74b330ea1adda9215e655f/s2clientprotocol/sc2api.proto#L679-L702
 | 
						|
 | 
						|
        Example use:
 | 
						|
 | 
						|
            from sc2.data import Alert
 | 
						|
            if self.alert(Alert.AddOnComplete):
 | 
						|
                print("Addon Complete")
 | 
						|
 | 
						|
        Alert codes::
 | 
						|
 | 
						|
            AlertError
 | 
						|
            AddOnComplete
 | 
						|
            BuildingComplete
 | 
						|
            BuildingUnderAttack
 | 
						|
            LarvaHatched
 | 
						|
            MergeComplete
 | 
						|
            MineralsExhausted
 | 
						|
            MorphComplete
 | 
						|
            MothershipComplete
 | 
						|
            MULEExpired
 | 
						|
            NuclearLaunchDetected
 | 
						|
            NukeComplete
 | 
						|
            NydusWormDetected
 | 
						|
            ResearchComplete
 | 
						|
            TrainError
 | 
						|
            TrainUnitComplete
 | 
						|
            TrainWorkerComplete
 | 
						|
            TransformationComplete
 | 
						|
            UnitUnderAttack
 | 
						|
            UpgradeComplete
 | 
						|
            VespeneExhausted
 | 
						|
            WarpInComplete
 | 
						|
 | 
						|
        :param alert_code:
 | 
						|
        """
 | 
						|
        assert isinstance(alert_code, Alert), f"alert_code {alert_code} is no Alert"
 | 
						|
        return alert_code.value in self.state.alerts
 | 
						|
 | 
						|
    @property
 | 
						|
    def start_location(self) -> Point2:
 | 
						|
        """
 | 
						|
        Returns the spawn location of the bot, using the position of the first created townhall.
 | 
						|
        This will be None if the bot is run on an arcade or custom map that does not feature townhalls at game start.
 | 
						|
        """
 | 
						|
        return self.game_info.player_start_location
 | 
						|
 | 
						|
    @property
 | 
						|
    def enemy_start_locations(self) -> List[Point2]:
 | 
						|
        """Possible start locations for enemies."""
 | 
						|
        return self.game_info.start_locations
 | 
						|
 | 
						|
    async def on_unit_destroyed(self, unit_tag: int):
 | 
						|
        """
 | 
						|
        Override this in your bot class.
 | 
						|
        This will event will be called when a unit (or structure, friendly or enemy) dies.
 | 
						|
        For enemy units, this only works if the enemy unit was in vision on death.
 | 
						|
 | 
						|
        :param unit_tag:
 | 
						|
        """
 | 
						|
 | 
						|
    async def on_unit_created(self, unit: Unit):
 | 
						|
        """Override this in your bot class. This function is called when a unit is created.
 | 
						|
 | 
						|
        :param unit:"""
 | 
						|
 | 
						|
    async def on_building_construction_started(self, unit: Unit):
 | 
						|
        """
 | 
						|
        Override this in your bot class.
 | 
						|
        This function is called when a building construction has started.
 | 
						|
 | 
						|
        :param unit:
 | 
						|
        """
 | 
						|
 | 
						|
    async def on_building_construction_complete(self, unit: Unit):
 | 
						|
        """
 | 
						|
        Override this in your bot class. This function is called when a building
 | 
						|
        construction is completed.
 | 
						|
 | 
						|
        :param unit:
 | 
						|
        """
 | 
						|
 | 
						|
    async def on_start(self):
 | 
						|
        """
 | 
						|
        Override this in your bot class. This function is called after "on_start".
 | 
						|
        At this point, game_data, game_info and the first iteration of game_state (self.state) are available.
 | 
						|
        """
 | 
						|
 | 
						|
    async def on_step(self, iteration: int):
 | 
						|
        """
 | 
						|
        You need to implement this function!
 | 
						|
        Override this in your bot class.
 | 
						|
        This function is called on every game step (looped in realtime mode).
 | 
						|
 | 
						|
        :param iteration:
 | 
						|
        """
 | 
						|
        raise NotImplementedError
 | 
						|
 | 
						|
    async def on_end(self, game_result: Result):
 | 
						|
        """Override this in your bot class. This function is called at the end of a game.
 | 
						|
 | 
						|
        :param game_result:"""
 |