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:
LmeSzinc 2020-06-05 03:51:54 +08:00
parent 6548677c80
commit 81f9b61ea5
12 changed files with 123 additions and 45 deletions

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

View File

@ -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()

View File

@ -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'):

View File

@ -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()

View File

@ -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):

View File

@ -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()

View File

@ -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:

View File

@ -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):
"""

View File

@ -267,4 +267,3 @@ class GridPredictor:
return name
return None

View File

@ -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

View File

@ -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):
"""