示例#1
0
def main():
    # Config is a wrapper for a socket, and a channel (for now)
    _config = config.Config(socketutils.connect_to_config(cf), cf.CHANNEL)

    # This is to determine whether we log information or not
    if cf.DO_LOG:
        print("Doing logging.")
        logging.set_logfile_func(cf.get_log_filename)
    if not cf.DO_STDOUT:
        logging.set_print_function(logging.no_print)
    else:
        print("Doing printing.")
    log = logging.log
    log_all = False

    # API takes an object with socket and channel members
    _api = ut.API(_config)
    _manager = EventManager(_api)
    # _manager.add_event(EveryLoopEvent(_callable=None, _api=_api, _manager=_manager, runs_till_event=30,
    #                                   extra_event=functools.partial(_api.send, "There have been 10 loops!")))

    can_make_commanders = [
        'dfolder'
    ]  # This could be loaded from a configuration file & saved back to there
    commanders = ['dfolder']

    log('Starting bot. Information:\n\tSocket:', str(_api.socket),
        '\n\tChannel:', _api.channel)
    while True:
        do_events(_api, _manager)
        full_response = _api.resp()
        _api.extend_resp_list(full_response)
        while full_response is not None and len(full_response) > 0:
            response = full_response.pop(0)
            did_something = False
            # We got a response from the server!
            # First, let's clean it up if we're in full mode.
            # This means that the response looks really ugly & includes a bunch of unnecessary information at the start.
            if _api.full_mode:
                try:
                    full_information = re.search(
                        r'^@badges=[\w/0-9,]*;color=[\w/0-9,]*;display-name=(\w*);.*?user-type=[\w/0-9,]* (.*)',
                        response)
                    log('[FULL RESPONSE]', full_information.strip('\r\n'))
                except TypeError:
                    full_information = None
                    log("Got erroneous response: ")
                    log(str(response))
                if full_information is not None:
                    log('[SENDER]', full_information.group(1))
                    response = full_information.group(2)
            log('[RESPONSE]', response.strip('\r\n'))
            command = re.search(
                r':(\w*)!\1@\1\.tmi\.twitch\.tv PRIVMSG #\w* : *~(.+)$',
                response)
            if command is not None:
                _command = command.group(2).strip('\r\n ')
                _caller = command.group(1)
                _args = None if len(_command.split(
                    ' ', 1)) <= 1 else _command.split(' ', 1)[1]
                _command = _command.split(' ')[0].lower()

                if _caller in can_make_commanders:
                    if log_all:
                        log('[2] Executing command: ' + _command +
                            ' with args: ' + str(_args))
                    if _command == 'conscript':
                        commanders.append(_args.lower())
                        did_something = True
                    elif _command == 'decommission':
                        commanders.remove(_args.lower())
                        did_something = True

                if _caller in commanders:
                    # This should be improved later, but we're going to just check the command here
                    if log_all:
                        log('[1] Executing command: ' + _command +
                            ' with args: ' + str(_args))
                    if _command == 'stop':
                        _manager.add_event_t(
                            SendMessageEvent,
                            message="Why don't you love me...",
                            after_run=functools.partial(
                                ut.safe_exit, _config, 0))
                    elif _command == 'print_full_debug':
                        log_all = True
                        log("Enabled full debugging mode.")
                    elif _command == 'no_full_debug':
                        log_all = False
                    elif _command == 'debug':
                        log("Attempting to print debug messages:")
                        log("Manager debug:")
                        log(_manager.dump_debug())
                        log("Command arguments:")
                        log(str(_args))
                        log("Current commanders:")
                        log(str(commanders))
                        # _manager.add_event_t(GetNoticesEvent)
                    elif _command == 'say' and _args is not None:
                        _manager.add_event_t(SendMessageEvent, message=_args)
                    elif _command == 'cap_req' and _args is not None:
                        _manager.add_event_t(SendCapReqEvent, message=_args)
                    elif _command == 'send_exact' or _command == 'say_exact' and _args is not None:
                        _manager.add_event_t(SendExactEvent, message=_args)
                    elif _command == 'enable_full':
                        _manager.add_event(
                            Event(_event=ut.enable_full,
                                  _api=_api,
                                  _manager=_manager))
                    elif _command == 'flush_log':
                        log("Flushing log.")
                        logging.flush()
                elif not did_something:
                    # We didn't set moderator privileges and we don't have command use
                    if log_all:
                        log('The user ' + _caller + ' attempted to use ' +
                            _command + ' with args: ' + str(_args))
                    _manager.add_event_t(
                        SendMessageEvent,
                        message="Please stop trying to abuse me, " + _caller +
                        ".")

        # This is to avoid making Twitch angry
        time.sleep(0.75)
示例#2
0
class TapiocaBot(sc2.BotAI):
    def __init__(self, verbose=False, visual_debug=False):
        self.verbose = verbose
        self.visual_debug = visual_debug

        ipdb.launch_ipdb_on_exception()

        # Control Stuff
        self.researched_warpgate = False  # Remove me later

        # Managers and controllers
        self.worker_controller = WorkerController(bot=self,
                                                  verbose=self.verbose)
        self.army_controller = ArmyController(bot=self, verbose=self.verbose)
        self.scouting_controller = ScoutingController(bot=self,
                                                      verbose=self.verbose)
        self.upgrades_controller = UpgradesController(bot=self,
                                                      verbose=self.verbose)
        self.robotics_facility_controller = RoboticsFacilitiyController(
            bot=self,
            verbose=self.verbose,
        )
        self.gateway_controller = GatewayController(
            bot=self, verbose=self.verbose, auto_morph_to_warpgate=True)
        self.building_controller = BuildingController(bot=self,
                                                      verbose=self.verbose)
        self.event_manager = EventManager()
        self.build_order_controller = BuildOrderController(
            verbose=self.verbose, bot=self)
        self.coordinator = Coordinator(bot=self,
                                       verbose=self.verbose,
                                       build_order='three_gate_blink_all_in')

        self.order_queue = []

    def on_start(self):
        self.army_controller.init()

        self.event_manager.add_event(self.worker_controller.step,
                                     0.1,
                                     jitter=0)
        self.event_manager.add_event(
            self.building_controller.update_nexus_list, 2.5)
        self.event_manager.add_event(self.build_order_controller.step, 0.5)
        self.event_manager.add_event(self.army_controller.step, 0.1, jitter=0)
        self.event_manager.add_event(self.coordinator.step, 1)

        self.coordinator.on_start()

    async def on_step(self, iteration):
        if iteration == 0:  # Do nothing on the first iteration to avoid
            # everything being done at the same time
            if self.verbose:
                print('\n------------------------\n')
                print('%8.2f %3d Rise and Shine' %
                      (self.time, self.supply_used))

            await self.chat_send(
                "Cry 'havoc', and let slip the Tapiocas of war!")

            return

        events = self.event_manager.get_current_events(self.time)
        for event in events:
            await event()

        await self.debug()

        await self.execute_order_queue()

        if self.verbose:
            sys.stdout.flush()

    async def do(self, action):
        self.order_queue.append(action)

    async def execute_order_queue(self):
        await self._client.actions(self.order_queue, game_data=self._game_data)
        self.order_queue = []

    async def debug(self):
        if not self.visual_debug:
            return

        # Setup and info

        font_size = 14

        total_units = 0
        for unit_type in self.army_controller.units_available_for_attack.keys(
        ):
            total_units += self.units(unit_type).idle.amount

        # Text

        messages = [
            '       n_workers: %3d' % self.units(UnitTypeId.PROBE).amount,
            '      n_stalkers: %3d' % self.units(UnitTypeId.STALKER).amount,
            '    militia_size: %3d' %
            len(self.worker_controller.militia_controller.militia), '',
            'ememy_structures_nearby: %3d' %
            len(self.worker_controller.militia_controller.
                nearby_enemy_structures_found),
            '   ememy_workers_nearby: %3d' %
            len(self.worker_controller.militia_controller.
                nearby_enemy_workers_found),
            '     ememy_units_nearby: %3d' %
            len(self.worker_controller.militia_controller.
                nearby_enemy_units_found), '',
            '  know_enemy_structures: %3d' % len(self.known_enemy_structures)
        ]

        y = 0
        inc = 0.018

        for message in messages:
            self._client.debug_text_screen(message,
                                           pos=(0.001, y),
                                           size=font_size)
            y += inc

        # 3D text

        debug_army_state = False

        if debug_army_state:
            for tag in self.army_controller.soldiers:
                unit = self.units.find_by_tag(tag)
                if unit is not None:
                    message = self.army_controller.soldiers[tag]['state']
                    self._client.debug_text_world(message,
                                                  pos=unit.position3d,
                                                  size=font_size)

        # Spheres

        debug_army_groups = False

        if debug_army_groups:
            leader_tag = self.army_controller.leader
            for soldier_tag in self.army_controller.soldiers:
                soldier_unit = self.units.find_by_tag(soldier_tag)

                if soldier_unit is not None:
                    if soldier_tag == leader_tag:
                        self._client.debug_sphere_out(soldier_unit,
                                                      r=1,
                                                      color=(255, 0, 0))
                    else:
                        self._client.debug_sphere_out(soldier_unit,
                                                      r=1,
                                                      color=(0, 0, 255))

        # Lines

        if debug_army_groups:
            if self.army_controller.army_size() > 0:
                leader_tag = self.army_controller.leader
                leader_unit = self.units.find_by_tag(leader_tag)

                for soldier_tag in self.army_controller.soldiers:
                    if soldier_tag == leader_tag:
                        continue

                    soldier_unit = self.units.find_by_tag(soldier_tag)
                    if soldier_unit is not None:
                        leader_tag = self.army_controller.leader
                        leader_unit = self.units.find_by_tag(leader_tag)
                        if leader_unit is not None:
                            self._client.debug_line_out(leader_unit,
                                                        soldier_unit,
                                                        color=(0, 255, 255))

        # Attack Lines
        debug_army_attack = False

        if debug_army_attack:
            if self.army_controller.army_size() > 0:
                for soldier_tag in self.army_controller.soldiers:
                    soldier_unit = self.units.find_by_tag(soldier_tag)

                    if soldier_unit is not None and \
                       self.army_controller.soldiers[soldier_tag]['state'] == 'attacking' and \
                       self.army_controller.attack_target is not None:
                        self._client.debug_line_out(
                            soldier_unit,
                            self.army_controller.attack_target,
                            color=(255, 127, 0))

        # Sens the debug info to the game
        await self._client.send_debug()

    def get_unit_info(self, unit, field="food_required"):
        assert isinstance(unit, (Unit, UnitTypeId))

        if isinstance(unit, Unit):
            unit = unit._type_data._proto
        else:
            unit = self._game_data.units[unit.value]._proto

        if hasattr(unit, field):
            return getattr(unit, field)
        else:
            return None