mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-22 16:40:28 +00:00
Add: Logic fleet_2_rescue, Logic for chapter 3
- Fix camera outside map caused by info bar - Fix mis-detection of is_caught_by_siren - Fix grid attribute is_caught_by_siren will be kept to next attack - Fix find_current_fleet when ammo icon of another fleet is covered by the green arrow of current fleet - Fix fleet_boss_index - Fix can not predict when boss appear on fleet's face
This commit is contained in:
parent
6548677c80
commit
81f9b61ea5
Binary file not shown.
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 4.9 KiB |
@ -14,9 +14,9 @@ MAP.map_data = '''
|
||||
'''
|
||||
MAP.weight_data = '''
|
||||
30 30 30 20 10 10 10
|
||||
30 30 30 20 10 10 10
|
||||
40 40 40 20 10 10 10
|
||||
30 30 30 20 10 09 10
|
||||
40 40 40 20 10 10 10
|
||||
40 40 40 20 20 10 10
|
||||
'''
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 2, 'mystery': 1},
|
||||
@ -36,6 +36,9 @@ class Config:
|
||||
FLEET_BOSS = 1
|
||||
|
||||
MAP_MYSTERY_HAS_CARRIER = True
|
||||
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
||||
'height': (120, 255 - 40),
|
||||
'width': (1.5, 10),
|
||||
@ -54,6 +57,11 @@ class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
self.fleet_2_push_forward()
|
||||
|
||||
if self.fleet_2_rescue(G2):
|
||||
return True
|
||||
|
||||
self.clear_all_mystery()
|
||||
|
||||
return self.battle_default()
|
||||
@ -64,4 +72,4 @@ class Campaign(CampaignBase):
|
||||
if not self.check_accessibility(G2, fleet='boss'):
|
||||
return self.fleet_boss.battle_default()
|
||||
|
||||
return self.clear_boss()
|
||||
return self.fleet_boss.clear_boss()
|
||||
|
@ -15,10 +15,10 @@ MAP.map_data = '''
|
||||
SP ME -- -- ME MM -- ++
|
||||
'''
|
||||
MAP.weight_data = '''
|
||||
50 50 50 30 30 20 10 10
|
||||
50 50 50 30 30 20 10 09
|
||||
50 50 40 40 30 20 10 10
|
||||
50 50 50 40 40 20 20 20
|
||||
50 50 50 50 35 30 30 30
|
||||
50 50 50 40 40 50 20 20
|
||||
50 50 50 50 35 50 50 50
|
||||
'''
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 2, 'mystery': 1},
|
||||
@ -38,11 +38,17 @@ class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
self.fleet_2_push_forward()
|
||||
|
||||
if self.fleet_2_rescue(H1):
|
||||
return True
|
||||
|
||||
self.clear_all_mystery()
|
||||
|
||||
return self.battle_default()
|
||||
|
||||
def battle_3(self):
|
||||
# print(H1.__dict__)
|
||||
self.clear_all_mystery()
|
||||
|
||||
if not self.check_accessibility(H1, fleet='boss'):
|
||||
|
@ -18,8 +18,8 @@ MAP.weight_data = '''
|
||||
50 50 30 30 50 50
|
||||
50 50 30 30 50 50
|
||||
50 50 20 30 50 50
|
||||
10 10 10 20 50 50
|
||||
10 10 10 50 50 50
|
||||
09 10 11 20 50 50
|
||||
10 10 11 50 50 50
|
||||
'''
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 2, 'mystery': 1},
|
||||
@ -40,6 +40,11 @@ class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
self.fleet_2_push_forward()
|
||||
|
||||
if self.fleet_2_rescue(A4):
|
||||
return True
|
||||
|
||||
self.clear_all_mystery()
|
||||
|
||||
return self.battle_default()
|
||||
|
@ -18,8 +18,8 @@ MAP.map_data = '''
|
||||
MAP.weight_data = '''
|
||||
40 40 40 40 40 40 40 40
|
||||
40 40 40 30 30 30 30 30
|
||||
40 40 30 30 20 10 10 10
|
||||
40 40 30 20 20 10 10 10
|
||||
40 40 30 30 20 10 10 09
|
||||
40 40 30 20 20 10 10 09
|
||||
'''
|
||||
MAP.spawn_data = [
|
||||
{'battle': 0, 'enemy': 2},
|
||||
@ -38,15 +38,16 @@ A4, B4, C4, D4, E4, F4, G4, H4, \
|
||||
class Config(Config31):
|
||||
MAP_MYSTERY_HAS_CARRIER = False
|
||||
|
||||
# Map 3-4 is relatively small for the density of enemies.
|
||||
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
|
||||
|
||||
|
||||
class Campaign(CampaignBase):
|
||||
MAP = MAP
|
||||
|
||||
def battle_0(self):
|
||||
self.fleet_2_push_forward()
|
||||
|
||||
if self.fleet_2_rescue(H3):
|
||||
return True
|
||||
|
||||
return self.battle_default()
|
||||
|
||||
def battle_3(self):
|
||||
|
@ -111,7 +111,15 @@ class Camera(InfoHandler):
|
||||
self.grids.update(image=self.device.image)
|
||||
return True
|
||||
|
||||
self.grids = Grids(self.device.image, config=self.config)
|
||||
try:
|
||||
self.grids = Grids(self.device.image, config=self.config)
|
||||
except PerspectiveError as e:
|
||||
if self.info_bar_count():
|
||||
logger.info('Perspective error cause by info bar. Waiting.')
|
||||
self.handle_info_bar()
|
||||
return self.update(camera=camera)
|
||||
else:
|
||||
raise e
|
||||
|
||||
# Catch perspective error
|
||||
known_exception = self.info_bar_count()
|
||||
|
@ -1,5 +1,6 @@
|
||||
import itertools
|
||||
|
||||
|
||||
from module.base.timer import Timer
|
||||
from module.exception import MapWalkError
|
||||
from module.handler.ambush import AmbushHandler
|
||||
@ -58,7 +59,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
||||
@property
|
||||
def fleet_boss_index(self):
|
||||
if self.config.FLEET_BOSS == 2 or self.config.FLEET_2:
|
||||
return 1
|
||||
return 2
|
||||
else:
|
||||
return 1
|
||||
|
||||
@ -265,7 +266,12 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
||||
|
||||
for loca in [self.fleet_1_location, self.fleet_2_location]:
|
||||
if len(loca) and loca in self.map:
|
||||
self.map[loca].wipe_out()
|
||||
grid = self.map[loca]
|
||||
if grid.may_boss and grid.is_caught_by_siren:
|
||||
# Only boss appears on fleet's face
|
||||
pass
|
||||
else:
|
||||
self.map[loca].wipe_out()
|
||||
|
||||
def find_all_fleets(self):
|
||||
logger.hr('Find all fleets')
|
||||
@ -306,7 +312,12 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
||||
self.fleet_1 = another.location
|
||||
self.fleet_2 = fleets[0].location
|
||||
else:
|
||||
self.find_all_fleets()
|
||||
cover = self.map.grid_covered(fleets[0], location=[(0, -1)])
|
||||
if fleets[0].is_current_fleet and len(cover) and cover[0].is_spawn_point:
|
||||
self.fleet_1 = fleets[0].location
|
||||
self.fleet_2 = cover[0].location
|
||||
else:
|
||||
self.find_all_fleets()
|
||||
elif count == 2:
|
||||
current = self.map.select(is_current_fleet=True)
|
||||
if current.count == 1:
|
||||
|
@ -139,11 +139,17 @@ class GridInfo:
|
||||
ignore_may (bool): Ignore map_data, force update.
|
||||
ignore_cleared (bool): Ignore is_cleared property.
|
||||
"""
|
||||
if info.is_caught_by_siren:
|
||||
self.is_caught_by_siren = True
|
||||
|
||||
for item in ['boss', 'siren']:
|
||||
if info.enemy_scale or self.enemy_scale:
|
||||
break
|
||||
if info.__getattribute__('is_' + item):
|
||||
flag = not info.is_fleet and not self.is_fleet
|
||||
if item == 'boss':
|
||||
flag = not info.is_fleet
|
||||
else:
|
||||
flag = not info.is_fleet and not self.is_fleet
|
||||
if not ignore_may:
|
||||
flag &= self.__getattribute__('may_' + item)
|
||||
if not ignore_cleared:
|
||||
@ -186,8 +192,6 @@ class GridInfo:
|
||||
self.is_fleet = info.is_fleet
|
||||
if info.is_current_fleet:
|
||||
self.is_current_fleet = True
|
||||
if info.is_caught_by_siren:
|
||||
self.is_caught_by_siren = True
|
||||
return False
|
||||
|
||||
def wipe_out(self):
|
||||
@ -201,6 +205,7 @@ class GridInfo:
|
||||
self.is_boss = False
|
||||
self.is_ammo = False
|
||||
self.is_siren = False
|
||||
self.is_caught_by_siren = False
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
|
@ -267,4 +267,3 @@ class GridPredictor:
|
||||
return name
|
||||
|
||||
return None
|
||||
|
||||
|
@ -237,7 +237,8 @@ class Map(Fleet):
|
||||
bool:
|
||||
"""
|
||||
grids = self.map.select(is_boss=True, is_accessible=True)
|
||||
logger.info('Is boss: %s' % self.map.select(is_boss=True))
|
||||
grids = grids.add(self.map.select(may_boss=True, is_caught_by_siren=True))
|
||||
logger.info('Is boss: %s' % grids)
|
||||
if not grids.count:
|
||||
grids = grids.add(self.map.select(may_boss=True, is_enemy=True, is_accessible=True))
|
||||
logger.warning('Boss not detected, using may_boss grids.')
|
||||
@ -277,6 +278,7 @@ class Map(Fleet):
|
||||
def brute_clear_boss(self):
|
||||
"""
|
||||
Method to clear boss, using brute-force to find roadblocks.
|
||||
Note: This method will use 2 fleets.
|
||||
"""
|
||||
boss = self.map.select(is_boss=True)
|
||||
if boss:
|
||||
@ -296,7 +298,7 @@ class Map(Fleet):
|
||||
elif self.map.select(may_boss=True, is_caught_by_siren=True):
|
||||
logger.info('BOSS appear on fleet grid')
|
||||
self.fleet_2.switch_to()
|
||||
self.clear_chosen_enemy(self.map.select(may_boss=True, is_caught_by_siren=True)[0])
|
||||
return self.clear_chosen_enemy(self.map.select(may_boss=True, is_caught_by_siren=True)[0])
|
||||
else:
|
||||
logger.warning('BOSS not detected, trying all boss spawn point.')
|
||||
return self.clear_potential_boss()
|
||||
@ -442,3 +444,26 @@ class Map(Fleet):
|
||||
self.fleet_2.goto(grids[0])
|
||||
self.fleet_1.switch_to()
|
||||
return True
|
||||
|
||||
def fleet_2_rescue(self, grid):
|
||||
"""Use mob fleet to rescue boss fleet.
|
||||
|
||||
Args:
|
||||
grid (GridInfo): Destination. Usually to be boss spawn grid.
|
||||
|
||||
Returns:
|
||||
bool: If clear an enemy.
|
||||
"""
|
||||
if not self.config.FLEET_2:
|
||||
return False
|
||||
|
||||
grids = self.brute_find_roadblocks(grid, fleet=2)
|
||||
if not grids:
|
||||
return False
|
||||
logger.info('Fleet_2 rescue')
|
||||
grids = self.select_grids(grids)
|
||||
if not grids:
|
||||
return False
|
||||
|
||||
self.clear_chosen_enemy(grids[0])
|
||||
return True
|
||||
|
@ -392,6 +392,22 @@ class CampaignMap:
|
||||
|
||||
return path
|
||||
|
||||
def grid_covered(self, grid, location=None):
|
||||
"""
|
||||
Args:
|
||||
grid (GridInfo)
|
||||
location (list[tuple[int]]): Relative coordinate of the covered grid.
|
||||
|
||||
Returns:
|
||||
list[GridInfo]:
|
||||
"""
|
||||
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 covered
|
||||
|
||||
def missing_get(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
|
||||
try:
|
||||
missing = self.spawn_data[battle_count].copy()
|
||||
@ -408,15 +424,12 @@ class CampaignMap:
|
||||
missing[attr] -= 1
|
||||
|
||||
for grid in self:
|
||||
for upper in grid.covered_grid():
|
||||
upper = tuple(np.array(grid.location) + upper)
|
||||
if upper in self:
|
||||
upper = self[upper]
|
||||
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
||||
if upper.__getattribute__('may_' + attr) and not upper.__getattribute__('is_' + attr):
|
||||
may[attr] += 1
|
||||
if upper.may_carrier:
|
||||
may['carrier'] += 1
|
||||
for upper in self.grid_covered(grid):
|
||||
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
||||
if upper.__getattribute__('may_' + attr) and not upper.__getattribute__('is_' + attr):
|
||||
may[attr] += 1
|
||||
if upper.may_carrier:
|
||||
may['carrier'] += 1
|
||||
|
||||
logger.attr('enemy_missing',
|
||||
', '.join([f'{k[:2].upper()}:{str(v).rjust(2)}' for k, v in missing.items() if k != 'battle']))
|
||||
@ -444,18 +457,15 @@ class CampaignMap:
|
||||
|
||||
# predict
|
||||
for grid in self:
|
||||
for upper in grid.covered_grid():
|
||||
upper = tuple(np.array(grid.location) + upper)
|
||||
if upper in self:
|
||||
upper = self[upper]
|
||||
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
||||
if upper.__getattribute__('may_' + attr) and missing[attr] > 0 and missing[attr] == may[attr]:
|
||||
logger.info('Predict %s to be %s' % (location2node(upper.location), attr))
|
||||
upper.__setattr__('is_' + attr, True)
|
||||
if carrier_count:
|
||||
if upper.may_carrier and missing['carrier'] > 0 and missing['carrier'] == may['carrier']:
|
||||
logger.info('Predict %s to be enemy' % location2node(upper.location))
|
||||
upper.__setattr__('is_enemy', True)
|
||||
for upper in self.grid_covered(grid):
|
||||
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
||||
if upper.__getattribute__('may_' + attr) and missing[attr] > 0 and missing[attr] == may[attr]:
|
||||
logger.info('Predict %s to be %s' % (location2node(upper.location), attr))
|
||||
upper.__setattr__('is_' + attr, True)
|
||||
if carrier_count:
|
||||
if upper.may_carrier and missing['carrier'] > 0 and missing['carrier'] == may['carrier']:
|
||||
logger.info('Predict %s to be enemy' % location2node(upper.location))
|
||||
upper.__setattr__('is_enemy', True)
|
||||
|
||||
def select(self, **kwargs):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user