def os_meowfficer_farming(self, hazard_level=5, daily=False):
        """
        Args:
            hazard_level (int): 1 to 6. Recommend 3 or 5 for higher meowfficer searching point per action points ratio.
            daily (bool): If false, loop until AP lower than OS_ACTION_POINT_PRESERVE.
                If True, loop until run out of AP (not including boxes).
                If True and ENABLE_OS_ASH_ATTACK, loop until ash beacon fully collected today,
                    then loop until run out of AP (not including boxes).
        """
        logger.hr(f'OS meowfficer farming, hazard_level={hazard_level}',
                  level=1)
        while 1:
            if daily:
                if self.config.ENABLE_OS_ASH_ATTACK:
                    if self._ash_fully_collected:
                        self.config.OS_ACTION_POINT_BOX_USE = False
                else:
                    self.config.OS_ACTION_POINT_BOX_USE = False

            # (1252, 1012) is the coordinate of zone 134 (the center zone) in os_globe_map.png
            zones = self.zone_select(hazard_level=hazard_level) \
                .delete(SelectedGrids([self.zone])) \
                .delete(SelectedGrids(self.zones.select(is_port=True))) \
                .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location)

            self.globe_goto(zones[0])
            self.run_auto_search()
            self.handle_fleet_repair(revert=False)
    def battle_0(self):
        if self.config.C72_BOSS_FLEET_STEP_ON_A3:
            if self.fleet_2_step_on(FLEET_2_STEP_ON, roadblocks=[ROAD_MAIN]):
                return True

            ignore = None
            if self.fleet_at(A3, fleet=2) and A1.enemy_scale != 3 and not self.fleet_at(A1, fleet=1):
                ignore = SelectedGrids([A2])
            if self.fleet_at(G3, fleet=2):
                ignore = SelectedGrids([H3])

            self.clear_all_mystery(nearby=False, ignore=ignore)
        else:
            self.clear_all_mystery(nearby=False)

        if self.clear_roadblocks([ROAD_MAIN], strongest=True):
            return True
        if self.clear_potential_roadblocks([ROAD_MAIN], strongest=True):
            return True

        if self.clear_enemy(scale=(3,)):
            return True

        if self.clear_grids_for_faster(GRIDS_FOR_FASTER, scale=(2,)):
            return True
        if self.clear_enemy(scale=(2,)):
            return True
        if self.clear_grids_for_faster(GRIDS_FOR_FASTER):
            return True

        return self.battle_default()
Esempio n. 3
0
    def clear_potential_roadblocks(self, roads, **kwargs):
        """Avoid roadblock that only has one grid empty.

        Args:
            roads(list[RoadGrids]):

        Returns:
            bool: True if clear an enemy.
        """
        grids = SelectedGrids([])
        for road in roads:
            grids = grids.add(road.potential_roadblocks())

        target = self.config.EnemyPriority_EnemyScaleBalanceWeight
        if target == 'S3_enemy_first':
            grids = self.select_grids(grids, strongest=True, **kwargs)
        elif target == 'S1_enemy_first':
            grids = self.select_grids(grids, weakest=True, **kwargs)
        else:
            grids = self.select_grids(grids, **kwargs)

        if grids:
            logger.hr('Avoid potential roadblock')
            self.show_select_grids(grids, **kwargs)
            self.clear_chosen_enemy(grids[0])
            return True

        return False
Esempio n. 4
0
    def clear_all_objects(self, grid=None):
        """Method to clear all objects around specific grid.

        Args:
            grid (GridInfo):

        Returns:
            int: Cleared count
        """
        if grid is not None:
            logger.hr(f'clear_all_objects: {grid}', level=2)
        for count in range(0, 10):
            grids = self.map.select(is_resource=True) \
                .add(self.map.select(is_enemy=True)) \
                .add(self.map.select(is_meowfficer=True)) \
                .add(self.map.select(is_exclamation=True)).delete(self.map.select(is_interactive_only=True))
            if grid is not None:
                grids = SelectedGrids([
                    g for g in grids if self.grid_is_in_sight(g, camera=grid)
                ])

            if not grids:
                logger.info(f'OS object cleared: {count}')
                return count

            grids = grids.sort_by_camera_distance(self.fleet_current)
            logger.hr('Clear all resource')
            logger.info(f'Grids: {grids}')
            logger.info(f'Clear object {grids[0]}')
            self.goto(grids[0], expected=self._get_goto_expected(grids[0]))
            self.handle_meowfficer_searching()

        logger.warning('Too many objects to clear, stopped')
        return 10
Esempio n. 5
0
    def os_meowfficer_farming(self):
        """
        Recommend 3 or 5 for higher meowfficer searching point per action points ratio.
        """
        logger.hr(
            f'OS meowfficer farming, hazard_level={self.config.OpsiMeowfficerFarming_HazardLevel}',
            level=1)
        self.action_point_limit_override()
        while 1:
            self.config.OS_ACTION_POINT_PRESERVE = self.config.OpsiMeowfficerFarming_ActionPointPreserve
            if self.config.OpsiAshBeacon_AshAttack \
                    and not self._ash_fully_collected \
                    and self.config.OpsiAshBeacon_EnsureFullyCollected:
                logger.info(
                    'Ash beacon not fully collected, ignore action point limit temporarily'
                )
                self.config.OS_ACTION_POINT_PRESERVE = 0
            logger.attr('OS_ACTION_POINT_PRESERVE',
                        self.config.OS_ACTION_POINT_PRESERVE)

            # (1252, 1012) is the coordinate of zone 134 (the center zone) in os_globe_map.png
            if self.config.OpsiMeowfficerFarming_TargetZone != 0:
                try:
                    zone = self.name_to_zone(
                        self.config.OpsiMeowfficerFarming_TargetZone)
                except ScriptError:
                    logger.warning(
                        f'wrong zone_id input:{self.config.OpsiMeowfficerFarming_TargetZone}'
                    )
                    self.config.task_stop(message=f'wrong input, task stopped')
                else:
                    logger.hr(f'OS meowfficer farming, zone_id={zone.zone_id}',
                              level=1)
                    self.globe_goto(zone)
                    self.fleet_set(self.config.OpsiFleet_Fleet)
                    self.os_order_execute(
                        recon_scan=False,
                        submarine_call=self.config.OpsiFleet_Submarine)
                    self.run_auto_search()
                    if not self.handle_after_auto_search():
                        self.globe_goto(self.zone_nearest_azur_port(zone=zone))
                    self.config.check_task_switch()
            else:
                zones = self.zone_select(hazard_level=self.config.OpsiMeowfficerFarming_HazardLevel) \
                    .delete(SelectedGrids([self.zone])) \
                    .delete(SelectedGrids(self.zones.select(is_port=True))) \
                    .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location)

                logger.hr(f'OS meowfficer farming, zone_id={zones[0].zone_id}',
                          level=1)
                self.globe_goto(zones[0])
                self.fleet_set(self.config.OpsiFleet_Fleet)
                self.os_order_execute(
                    recon_scan=False,
                    submarine_call=self.config.OpsiFleet_Submarine)
                self.run_auto_search()
                self.handle_after_auto_search()
                self.config.check_task_switch()
Esempio n. 6
0
    def _commission_choose(self, daily, urgent):
        """
        Args:
            daily (SelectedGrids):
            urgent (SelectedGrids):

        Returns:
            SelectedGrids, SelectedGrids: Chosen daily commission, Chosen urgent commission
        """
        # Count Commission
        total = daily.add_by_eq(urgent)
        self.max_commission = 4
        for comm in total:
            if comm.genre == 'event_daily':
                self.max_commission = 5
        running_count = int(np.sum([1 for c in total
                                    if c.status == 'running']))
        logger.attr('Running', f'{running_count}/{self.max_commission}')
        if running_count >= self.max_commission:
            return SelectedGrids([]), SelectedGrids([])

        # Filter
        COMMISSION_FILTER.load(self.config.Commission_CommissionFilter)
        run = COMMISSION_FILTER.apply(total.grids, func=self._commission_check)
        logger.attr('Filter_sort', ' > '.join([str(c) for c in run]))
        run = SelectedGrids(run)

        # Add shortest
        no_shortest = run.delete(SelectedGrids(['shortest']))
        if no_shortest.count + running_count < self.max_commission:
            if no_shortest.count < run.count:
                logger.info(
                    'Not enough commissions to run, add shortest daily commissions'
                )
                COMMISSION_FILTER.load(SHORTEST_FILTER)
                shortest = COMMISSION_FILTER.apply(daily,
                                                   func=self._commission_check)
                run = no_shortest.add_by_eq(SelectedGrids(shortest))
                logger.attr('Filter_sort', ' > '.join([str(c) for c in run]))
            else:
                logger.info('Not enough commissions to run')

        # Separate daily and urgent
        run = run[:self.max_commission - running_count]
        daily_choose = run.intersect_by_eq(daily)
        urgent_choose = run.intersect_by_eq(urgent)
        if daily_choose:
            logger.info('Choose daily commission')
            for comm in daily_choose:
                logger.info(comm)
        if urgent_choose:
            logger.info('Choose urgent commission')
            for comm in urgent_choose:
                logger.info(comm)

        return daily_choose, urgent_choose
    def _commission_scan_list(self):
        """
        Returns:
            SelectedGrids: SelectedGrids containing Commission objects
        """
        commission = SelectedGrids([])
        for _ in range(15):
            new = self._commission_detect(self.device.image)
            commission = commission.add_by_eq(new)

            # End
            if not self._commission_swipe():
                break

        return commission
Esempio n. 8
0
    def list_device(self):
        """
        Returns:
            SelectedGrids[AdbDeviceWithStatus]:
        """
        class AdbDeviceWithStatus(AdbDevice):
            def __init__(self, client: AdbClient, serial: str, status: str):
                self.status = status
                super().__init__(client, serial)

            def __str__(self):
                return f'AdbDevice({self.serial}, {self.status})'

            __repr__ = __str__

            def __bool__(self):
                return True

        devices = []
        with self.adb_client._connect() as c:
            c.send_command("host:devices")
            c.check_okay()
            output = c.read_string_block()
            for line in output.splitlines():
                parts = line.strip().split("\t")
                if len(parts) != 2:
                    continue
                device = AdbDeviceWithStatus(self.adb_client, parts[0],
                                             parts[1])
                devices.append(device)
        return SelectedGrids(devices)
Esempio n. 9
0
    def nearest_object(self, camera_sight=(-4, -3, 3, 3)):
        """
        Args:
            camera_sight:

        Returns:
            RadarGrid: Or None if no objects
        """
        objects = []
        for grid in self:
            if grid.is_port:
                continue
            if grid.is_enemy or grid.is_resource or grid.is_meowfficer \
                    or grid.is_exclamation or grid.is_question or grid.is_archive:
                objects.append(grid)
        objects = SelectedGrids(objects).sort_by_camera_distance((0, 0))
        if not objects:
            return None

        nearest = objects[0]
        limited = point_limit(nearest.location, area=camera_sight)
        if nearest.location == limited:
            return nearest
        else:
            return self[limited]
    def _tactical_books_filter_exp(self):
        """
        Complex filter to remove specific grade
        books from self.books based on current
        progress of the tactical skill.
        """
        # Shorthand referencing
        first, last = self.books[0], self.books[-1]

        # Read 'current' and 'remain' will be inaccurate
        # since first exp_value is factored into it
        current, remain, total = SKILL_EXP.ocr(self.device.image)

        # Max level in progress; so selective books
        # should be removed to prevent waste
        if total == 5800:
            if current == 0:
                # Lvl 9+1, using first will reach max level
                # Swap to last and re-OCR
                self._tactical_book_select(last)
                current, remain, total = SKILL_EXP.ocr(self.device.image)
                if current == 0:
                    # Still Lvl 9+1 even with last
                    # Must re-calculate to accurately gauge
                    current = total - last.exp_value
                    remain = last.exp_value
                else:
                    # Lvl 9, so can calculate normally
                    # but use last
                    current -= last.exp_value
                    remain += last.exp_value
            else:
                # Lvl 9, so can calculate normally
                current -= first.exp_value
                remain += first.exp_value
            logger.info('About to reach level 10; will remove '
                        'detected books based on actual '
                        f'progress: {current}/{total}; {remain}')

            def filter_exp_func(book):
                # Retain at least non-T1 bonus books if nothing else
                if book.exp_value == 100:
                    return True

                # Acquire 'overflow' for respective tier book if enabled
                overflow = 0
                if self.config.ControlExpOverflow_Enable:
                    overflow = getattr(
                        self.config, f'ControlExpOverflow_T{book.tier}Allow')

                # Remove book if sum to be gained exceeds total (+ overflow)
                if (current + book.exp_value) > (total + overflow):
                    return False
                return True

            before = self.books.count
            self.books = SelectedGrids(
                [book for book in self.books if filter_exp_func(book)])
            logger.attr('Filtered', before - self.books.count)
            logger.attr('Books', str(self.books))
Esempio n. 11
0
 def map_covered(self, nodes):
     """
     Args:
         nodes (list): Contains str.
     """
     self._map_covered = SelectedGrids(
         [self[node2location(node)] for node in nodes])
Esempio n. 12
0
 def camera_data_spawn_point(self, nodes):
     """
     Args:
         nodes (list): Contains str.
     """
     self._camera_data_spawn_point = SelectedGrids(
         [self[node2location(node)] for node in nodes])
Esempio n. 13
0
    def fleet_2_push_forward(self):
        """Move fleet 2 to the grid with lower grid.weight
        This will reduce the possibility of Boss fleet get stuck by enemies, especially for those one-way-road map
        from chapter 7 to chapter 9.

        Know more (in Chinese simplified):
        9章道中战最小化路线规划 (Route Planning for battle minimization in chapter 9)
        https://wiki.biligame.com/blhx/9%E7%AB%A0%E9%81%93%E4%B8%AD%E6%88%98%E6%9C%80%E5%B0%8F%E5%8C%96%E8%B7%AF%E7%BA%BF%E8%A7%84%E5%88%92

        Returns:
            bool: If pushed forward.
        """
        if not self.config.FLEET_2:
            return False

        logger.info('Fleet_2 push forward')
        grids = self.map.select(is_land=False).sort('weight', 'cost')
        if self.map[self.fleet_2_location].weight <= grids[0].weight:
            logger.info('Fleet_2 pushed to destination')
            return False

        fleets = SelectedGrids([self.map[self.fleet_1_location], self.map[self.fleet_2_location]])
        grids = grids.select(is_accessible_2=True, is_sea=True).delete(fleets)
        if not grids:
            logger.info('Fleet_2 has no where to push')
            return False
        if self.map[self.fleet_2_location].weight <= grids[0].weight:
            logger.info('Fleet_2 pushed to closest grid')
            return False

        logger.info(f'Grids: {grids}')
        logger.info(f'Push forward: {grids[0]}')
        self.fleet_2.goto(grids[0])
        self.fleet_1.switch_to()
        return True
    def _commission_detect(self, image):
        """
        Get all commissions from an image.

        Args:
            image: Pillow image

        Returns:
            SelectedGrids:
        """
        commission = []
        # Find white lines under each commission to locate them.
        # (597, 0, 619, 720) is somewhere with white lines only.
        color_height = np.mean(image.crop((597, 0, 619, 720)).convert('L'),
                               axis=1)
        parameters = {'height': 200, 'distance': 100}
        peaks, _ = signal.find_peaks(color_height, **parameters)
        # 67 is the height of commission list header
        # 117 is the height of one commission card.
        peaks = [y for y in peaks if y > 67 + 117]

        # Add commission to list
        for y in peaks:
            comm = Commission(image, y=y, config=self.config)
            logger.attr('Commission', comm)
            repeat = len([c for c in commission if c == comm])
            comm.repeat_count += repeat
            commission.append(comm)

        return SelectedGrids(commission)
Esempio n. 15
0
 def zones(self):
     """
     Returns:
         SelectedGrids:
     """
     return SelectedGrids(
         [Zone(zone_id, info) for zone_id, info in DIC_OS_MAP.items()])
Esempio n. 16
0
 def __init__(self, name=None):
     self.name = name
     self.grids = {}
     self._shape = (0, 0)
     self._map_data = ''
     self._map_data_loop = ''
     self._weight_data = ''
     self._wall_data = ''
     self._portal_data = []
     self._land_based_data = []
     self._maze_data = []
     self.maze_round = 9
     self._fortress_data = [(), ()]
     self._bouncing_enemy_data = []
     self._spawn_data = []
     self._spawn_data_stack = []
     self._spawn_data_loop = []
     self._spawn_data_use_loop = False
     self._camera_data = []
     self._camera_data_spawn_point = []
     self._map_covered = SelectedGrids([])
     self._ignore_prediction = []
     self.in_map_swipe_preset_data = None
     self.poor_map_data = False
     self.camera_sight = (-3, -1, 3, 2)
     self.grid_connection = {}
Esempio n. 17
0
    def _commission_scan_list(self):
        """
        Returns:
            SelectedGrids: SelectedGrids containing Commission objects
        """
        self.device.click_record_clear()
        commission = SelectedGrids([])
        for _ in range(15):
            new = self.commission_detect(trial=2)
            commission = commission.add_by_eq(new)

            # End
            if not self._commission_swipe():
                break

        self.device.click_record_clear()
        return commission
Esempio n. 18
0
    def battle_5(self):
        ignore = None
        if self.fleet_at(A3, fleet=2):
            ignore = SelectedGrids([A2])
        if self.fleet_at(G3, fleet=2):
            ignore = SelectedGrids([H3])
        self.clear_all_mystery(nearby=False, ignore=ignore)

        if self.clear_roadblocks([ROAD_MAIN]):
            return True

        if self.fleet_at(A3, fleet=2) and A2.is_mystery:
            self.fleet_2.clear_chosen_mystery(A2)
        if self.fleet_at(G3, fleet=2) and H3.is_mystery:
            self.fleet_2.clear_chosen_mystery(H3)

        return self.fleet_2.clear_boss()
    def _tactical_books_get(self, skip_first_screenshot=True):
        """
        Get books. Handle loadings, wait 10 times at max.
        When TACTICAL_CLASS_START appears, game may stuck in loading, wait and retry detection.
        If loading still exists, raise ScriptError.

        Returns:
            BookGroup:

        Pages:
            in: TACTICAL_CLASS_START
            out: TACTICAL_CLASS_START
        """
        prev = SelectedGrids([])
        for n in range(1, 16):
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            self.handle_info_bar(
            )  # info_bar appears when get ship in Launch Ceremony commissions
            if not self.appear(TACTICAL_CLASS_START, offset=(30, 30)):
                logger.info('Not in TACTICAL_CLASS_START anymore, exit')
                return False

            books = SelectedGrids([
                Book(self.device.image, button)
                for button in BOOKS_GRID.buttons
            ]).select(valid=True)
            self.books = books
            logger.attr('Book_count', books.count)
            logger.attr('Books', str(books))

            # End
            if books and books.count == prev.count:
                return books
            else:
                prev = books
                if n % 3 == 0:
                    self.device.sleep(3)
                continue

        logger.warning('No book found.')
        raise ScriptError('No book found, after 15 attempts.')
Esempio n. 20
0
    def to_selected(self, grids):
        """
        Args:
            grids (list):

        Returns:
            SelectedGrids:
        """
        return SelectedGrids([self[location_ensure(loca)] for loca in grids])
Esempio n. 21
0
 def map_covered(self):
     """
     Returns:
         SelectedGrids:
     """
     covered = []
     for grid in self:
         covered += self.grid_covered(grid).grids
     return SelectedGrids(covered).add(self._map_covered)
Esempio n. 22
0
    def _clear_os_world(self):
        for hazard_level in range(self.config.OS_WORLD_MIN_LEVEL,
                                  (self.config.OS_WORLD_MAX_LEVEL + 1)):
            zones = self.zone_select(hazard_level=hazard_level) \
                .delete(SelectedGrids(self.zones.select(is_port=True))) \
                .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location)

            for zone in zones:
                if not self.globe_goto(zone, stop_if_safe=True):
                    continue
                self.run_auto_search()
                self.handle_fleet_repair(revert=False)
Esempio n. 23
0
    def clear_first_roadblocks(self, roads, **kwargs):
        """Ensure every roadblocks have one grid with is_cleared=True.

        Args:
            roads(list[RoadGrids]):

        Returns:
            bool: True if clear an enemy.
        """
        grids = SelectedGrids([])
        for road in roads:
            grids = grids.add(road.first_roadblocks())

        grids = self.select_grids(grids, **kwargs)

        if grids:
            logger.hr('Clear first roadblock')
            self.show_select_grids(grids, **kwargs)
            self.clear_chosen_enemy(grids[0])
            return True

        return False
Esempio n. 24
0
    def clear_potential_roadblocks(self, roads, **kwargs):
        """Avoid roadblock that only has one grid empty.

        Args:
            roads(list[RoadGrids]):

        Returns:
            bool: True if clear an enemy.
        """
        grids = SelectedGrids([])
        for road in roads:
            grids = grids.add(road.potential_roadblocks())

        grids = self.select_grids(grids, **kwargs)

        if grids:
            logger.hr('Avoid potential roadblock')
            self.show_select_grids(grids, **kwargs)
            self.clear_chosen_enemy(grids[0])
            return True

        return False
Esempio n. 25
0
    def clear_roadblocks(self, roads, **kwargs):
        """Clear roadblocks.

        Args:
            roads(list[RoadGrids]):

        Returns:
            bool: True if clear an enemy.
        """
        grids = SelectedGrids([])
        for road in roads:
            grids = grids.add(road.roadblocks())

        grids = self.select_grids(grids, **kwargs)

        if grids:
            logger.hr('Clear roadblock')
            self.show_select_grids(grids, **kwargs)
            self.clear_chosen_enemy(grids[0])
            return True

        return False
Esempio n. 26
0
    def get_boss_leave_button(self):
        for grid in self.view:
            if grid.predict_current_fleet():
                return None

        grids = [grid for grid in self.view if grid.predict_caught_by_siren()]
        if len(grids) == 1:
            center = grids[0]
        elif len(grids) > 1:
            logger.warning(
                f'Found multiple fleets in boss ({grids}), use the center one')
            center = SelectedGrids(grids).sort_by_camera_distance(
                self.view.center_loca)[0]
        else:
            logger.warning('No fleet in boss, use camera center instead')
            center = self.view[self.view.center_loca]

        logger.info(f'Fleet in boss: {center}')
        # The left half grid next to the center grid.
        area = corner2inner(
            center.grid2screen(area2corner((1, 0.25, 1.5, 0.75))))
        button = Button(area=area, color=(), button=area, name='BOSS_LEAVE')
        return button
    def battle_3(self):
        if self.config.C72MysteryFarming_StepOnA3:
            ignore = None
            if self.fleet_at(A3, fleet=2):
                ignore = SelectedGrids([A2])
            if self.fleet_at(G3, fleet=2):
                ignore = SelectedGrids([H3])
            self.clear_all_mystery(nearby=False, ignore=ignore)

            if self.fleet_at(A3, fleet=2) and A2.is_mystery:
                self.fleet_2.clear_chosen_mystery(A2)
            if self.fleet_at(G3, fleet=2) and H3.is_mystery:
                self.fleet_2.clear_chosen_mystery(H3)
        else:
            self.clear_all_mystery(nearby=False)

        if self.map.select(is_mystery=True, is_accessible=False):
            logger.info('Roadblock blocks mystery.')
            if self.fleet_1.clear_roadblocks([ROAD_MAIN]):
                return True

        if not self.map.select(is_mystery=True):
            self.withdraw()
    def battle_0(self):
        if self.fleet_2_step_on(FLEET_2_STEP_ON, roadblocks=[ROAD_MAIN]):
            return True

        ignore = None
        if self.fleet_at(A3, fleet=2):
            ignore = SelectedGrids([A2])
        if self.fleet_at(G3, fleet=2):
            ignore = SelectedGrids([H3])
        self.clear_all_mystery(nearby=False, ignore=ignore)

        if self.clear_roadblocks([ROAD_MAIN], strongest=True):
            return True

        if self.clear_enemy(scale=(3, )):
            return True
        if self.clear_potential_roadblocks([ROAD_MAIN], strongest=True):
            return True

        if self.clear_enemy(strongest=True, weight=True):
            return True

        return self.battle_default()
Esempio n. 29
0
    def commission_detect(self,
                          trial=1,
                          area=None,
                          skip_first_screenshot=True):
        """
        Args:
            trial (int): Retry if has one invalid commission,
                         usually because info_bar didn't disappear completely.
            area (tuple):
            skip_first_screenshot (bool):

        Returns:
            SelectedGrids:
        """
        commissions = SelectedGrids([])
        for _ in range(trial):
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            image = self.device.image
            if area is not None:
                image = crop(image, area)
            commissions = self._commission_detect(image)

            if commissions.count >= 2 and commissions.select(
                    valid=False).count == 1:
                logger.info(
                    'Found 1 invalid commission, retry commission detect')
                continue
            else:
                return commissions

        logger.info('trials of commission detect exhausted, stop')
        return commissions
Esempio n. 30
0
    def grid_covered(self, grid, location=None):
        """
        Args:
            grid (GridInfo)
            location (list[tuple[int]]): Relative coordinate of the covered grid.

        Returns:
            SelectedGrids:
        """
        if location is None:
            covered = [tuple(np.array(grid.location) + upper) for upper in grid.covered_grid()]
        else:
            covered = [tuple(np.array(grid.location) + upper) for upper in location]
        covered = [self[upper] for upper in covered if upper in self]
        return SelectedGrids(covered)