Add: 适配第三章

- 增加处理踩问号是会刷物资船的情况
- 增加对物资船的缺失预测
- 收完菜后出击, 会重新检查舰队
  因为离开出击界面后, 出击舰队会重置为游戏默认的
- 修复了部分偏红的过场图, 会被认作索敌的问题
This commit is contained in:
LmeSzinc 2020-04-15 15:14:35 +08:00
parent 6a9e82d468
commit 8ce405f28a
15 changed files with 315 additions and 53 deletions

View File

@ -0,0 +1,67 @@
from module.campaign.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap()
MAP.shape = 'G4'
MAP.map_data = '''
SP -- ME -- ME MB --
-- ME -- ME -- ME MB
++ ++ ME -- ME -- --
++ ++ SP ME MM ++ ++
'''
MAP.weight_data = '''
30 30 30 20 10 10 10
30 30 30 20 10 10 10
40 40 40 20 10 10 10
40 40 40 20 10 10 10
'''
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'mystery': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 2, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, \
A2, B2, C2, D2, E2, F2, G2, \
A3, B3, C3, D3, E3, F3, G3, \
A4, B4, C4, D4, E4, F4, G4, \
= MAP.flatten()
class Config:
FLEET_2 = 0
SUBMARINE = 0
MAP_MYSTERY_HAS_CARRIER = True
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (120, 255 - 40),
'width': (1.5, 10),
'prominence': 10,
'distance': 35,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 40, 255),
'prominence': 10,
'distance': 50,
'wlen': 1000
}
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
self.clear_all_mystery()
return self.battle_default()
def battle_3(self):
self.clear_all_mystery()
if not self.check_accessibility(G2):
return self.battle_default()
return self.clear_boss()

View File

@ -0,0 +1,51 @@
from module.campaign.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from campaign.campaign_main.campaign_3_1 import Config
MAP = CampaignMap()
MAP.shape = 'H4'
MAP.camera_data= ['D2']
MAP.map_data = '''
SP -- -- ME -- ME ME MB
++ ++ ME -- ME ++ ++ ++
-- ++ -- ME -- MA ++ ++
SP ME -- -- ME MM -- ++
'''
MAP.weight_data = '''
50 50 50 30 30 20 10 10
50 50 40 40 30 20 10 10
50 50 50 40 40 20 20 20
50 50 50 50 35 30 30 30
'''
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'mystery': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 2, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
= MAP.flatten()
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
self.clear_all_mystery()
return self.battle_default()
def battle_3(self):
self.clear_all_mystery()
if not self.check_accessibility(H1):
return self.battle_default()
return self.clear_boss()

View File

@ -0,0 +1,53 @@
from module.campaign.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from campaign.campaign_main.campaign_3_1 import Config
MAP = CampaignMap()
MAP.shape = 'F5'
MAP.map_data = '''
++ ++ ME MM ++ ++
++ ++ -- ME -- SP
++ ++ ME -- ME --
MB ME -- ME -- --
-- ME ME SP ME SP
'''
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
'''
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'mystery': 1},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, \
A2, B2, C2, D2, E2, F2, \
A3, B3, C3, D3, E3, F3, \
A4, B4, C4, D4, E4, F4, \
A5, B5, C5, D5, E5, F5, \
= MAP.flatten()
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
self.clear_all_mystery()
return self.battle_default()
def battle_3(self):
self.clear_all_mystery()
if not self.check_accessibility(A4):
return self.battle_default()
return self.clear_boss()

View File

@ -0,0 +1,56 @@
from module.campaign.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from campaign.campaign_main.campaign_3_1 import Config as Config31
MAP = CampaignMap()
MAP.shape = 'H4'
# WIKI的图是错的: https://wiki.biligame.com/blhx/3-4
# A3有岛, 假图害人
MAP.map_data = '''
SP -- -- ME -- ++ ++ ++
SP ME -- ME -- MA ++ ++
++ -- ME __ ME ME -- MB
SP ME -- ME -- -- ME MB
'''
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
'''
MAP.spawn_data = [
{'battle': 0, 'enemy': 2},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
= MAP.flatten()
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):
return self.battle_default()
def battle_3(self):
if not self.check_accessibility(H3):
return self.battle_default()
return self.clear_boss()

View File

@ -111,7 +111,8 @@ class CampaignRun(CampaignUI, Reward):
self.load_campaign(name, folder=folder)
self.run_count = 0
while 1:
self.handle_reward()
if self.handle_reward():
self.campaign.config.FLEET_CHECKED = False
# End
if total and self.run_count == total:
@ -134,6 +135,7 @@ class CampaignRun(CampaignUI, Reward):
self.campaign.ENTRANCE = self.campaign_get_entrance(name=self.stage)
if self.commission_notice_show_at_campaign():
if self.reward():
self.campaign.config.FLEET_CHECKED = False
continue
# End

View File

@ -175,6 +175,7 @@ class AzurLaneConfig:
module.map.fleet
"""
MAP_HAS_AMBUSH = True
MAP_MYSTERY_HAS_CARRIER = False
"""
module.retire

View File

@ -1,14 +1,13 @@
from module.combat.combat import Combat
from module.daemon.assets import *
from module.handler.ambush import MAP_AMBUSH_EVADE
from module.handler.enemy_searching import EnemySearchingHandler
from module.handler.mystery import MysteryHandler
from module.handler.popup import PopupHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.map.map_fleet_preparation import FleetPreparation
class AzurLaneDaemon(FleetPreparation, Combat, UrgentCommissionHandler, EnemySearchingHandler, MysteryHandler,
class AzurLaneDaemon(FleetPreparation, Combat, UrgentCommissionHandler, MysteryHandler,
PopupHandler):
def daemon(self):

View File

@ -12,12 +12,12 @@ class EnemySearchingHandler(InfoBarHandler):
def _color_initial(self):
MAP_ENEMY_SEARCHING.load_color(self.device.image)
def _enemy_searching_appear(self):
def enemy_searching_appear(self):
return red_overlay_transparency(
MAP_ENEMY_SEARCHING.color, get_color(self.device.image, MAP_ENEMY_SEARCHING.area)
) > self.MAP_ENEMY_SEARCHING_OVERLAY_TRANSPARENCY_THRESHOLD
def _handle_enemy_flashing(self):
def handle_enemy_flashing(self):
self.device.sleep(1)
def handle_in_stage(self):
@ -40,11 +40,11 @@ class EnemySearchingHandler(InfoBarHandler):
appeared = False
while 1:
timeout.start()
if self._enemy_searching_appear():
if self.enemy_searching_appear():
appeared = True
else:
if appeared:
self._handle_enemy_flashing()
self.handle_enemy_flashing()
self.device.sleep(0.3)
logger.info('In map.')
break

View File

@ -1,12 +1,14 @@
from module.base.timer import Timer
from module.base.utils import area_in_area
from module.handler.assets import *
from module.handler.enemy_searching import EnemySearchingHandler
from module.handler.strategy import StrategyHandler
from module.logger import logger
class MysteryHandler(StrategyHandler):
class MysteryHandler(StrategyHandler, EnemySearchingHandler):
_get_ammo_log_timer = Timer(3)
carrier_count = 0
def handle_mystery(self, button=None):
"""
@ -24,18 +26,22 @@ class MysteryHandler(StrategyHandler):
self.device.sleep(0.5)
self.device.screenshot()
self.handle_opened_strategy_bar()
return True
return 'get_item'
if self.info_bar_count():
if self._get_ammo_log_timer.reached() and self.appear(GET_AMMO):
logger.attr('Mystery', 'Get ammo')
self._get_ammo_log_timer.reset()
self._save_mystery_image()
return 'get_ammo'
return True
# if self.handle_info_bar():
# return True
if self.config.MAP_MYSTERY_HAS_CARRIER:
if self.is_in_map() and self.enemy_searching_appear():
logger.attr('Mystery', 'Get carrier')
self.carrier_count += 1
self._save_mystery_image()
self.handle_in_map_with_enemy_searching()
return 'get_carrier'
return False

View File

@ -124,9 +124,9 @@ class Camera(InfoBarHandler):
self.camera = (x, y)
self.show_camera()
def predict(self):
def predict(self, is_carrier_scan=False):
self.grids.predict()
self.map.update(grids=self.grids, camera=self.camera)
self.map.update(grids=self.grids, camera=self.camera, is_carrier_scan=is_carrier_scan)
def show_camera(self):
logger.info(' Camera: %s' % location2node(self.camera))
@ -206,29 +206,32 @@ class Camera(InfoBarHandler):
if np.all(np.abs(vector) <= 0):
break
def full_scan(self, battle_count=None, mystery_count=0, siren_count=0):
def full_scan(self, battle_count=None, mystery_count=0, siren_count=0, carrier_count=0, is_carrier_scan=False):
"""Scan the hole map.
Args:
battle_count:
mystery_count:
siren_count:
carrier_count:
is_carrier_scan:
"""
logger.info('Full scan start')
self.map.reset_fleet()
queue = self.map.camera_data
while len(queue) > 0:
if self.map.missing_is_none(battle_count, mystery_count, siren_count):
if self.map.missing_is_none(battle_count, mystery_count, siren_count, carrier_count):
logger.info('All spawn found, Early stopped.')
break
queue = queue.sort_by_camera_distance(self.camera)
self.focus_to(queue[0])
self.predict()
self.predict(is_carrier_scan=is_carrier_scan)
queue = queue[1:]
if battle_count is not None:
self.map.missing_predict(battle_count=battle_count, mystery_count=mystery_count, siren_count=siren_count)
self.map.missing_predict(battle_count=battle_count, mystery_count=mystery_count, siren_count=siren_count,
carrier_count=carrier_count)
self.map.show()
def in_sight(self, location, sight=(-3, -1, 3, 2)):

View File

@ -1,13 +1,12 @@
from module.base.timer import Timer
from module.handler.ambush import AmbushHandler
from module.handler.mystery import MysteryHandler
from module.logger import logger
from module.map.camera import Camera
from module.map.map_base import location2node, location_ensure
from module.map.map_operation import MapOperation
class Fleet(Camera, AmbushHandler, MysteryHandler, MapOperation):
class Fleet(Camera, MapOperation, AmbushHandler):
fleet_1_location = ()
fleet_2_location = ()
fleet_current_index = 1
@ -94,8 +93,8 @@ class Fleet(Camera, AmbushHandler, MysteryHandler, MapOperation):
# arrived = grid.predict_fleet()
# 把break去掉就搞定了
# break
if self.handle_mystery(button=grid):
mystery = self.handle_mystery(button=grid)
if mystery:
# arrived = True
self.mystery_count += 1
result = 'mystery'
@ -151,7 +150,12 @@ class Fleet(Camera, AmbushHandler, MysteryHandler, MapOperation):
self.map[location].wipe_out()
self.map[location].is_fleet = True
self.__setattr__('fleet_%s_location' % self.fleet_current_index, location)
if mystery == 'get_carrier':
prev_enemy = self.map.select(is_enemy=True)
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count,
siren_count=self.siren_count, carrier_count=self.carrier_count, is_carrier_scan=True)
diff = self.map.select(is_enemy=True).delete(prev_enemy)
logger.info(f'Carrier spawn: {diff}')
self.find_path_initial()
def goto(self, location, optimize=True, expected=''):
@ -223,6 +227,7 @@ class Fleet(Camera, AmbushHandler, MysteryHandler, MapOperation):
logger.hr('Map init')
self.battle_count = 0
self.mystery_count = 0
self.carrier_count = 0
self.siren_count = 0
self.ammo_count = 3
self.map = map_
@ -230,7 +235,8 @@ class Fleet(Camera, AmbushHandler, MysteryHandler, MapOperation):
self.hp_init()
self.handle_strategy(index=self.fleet_current_index)
self.ensure_edge_insight(preset=self.map.in_map_swipe_preset_data)
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count, siren_count=self.siren_count)
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count, siren_count=self.siren_count,
carrier_count=self.carrier_count)
self.find_current_fleet()
self.find_path_initial()
self.map.show_cost()

View File

@ -112,6 +112,10 @@ class GridInfo:
def is_sea(self):
return False if self.is_land or self.is_enemy or self.is_mystery or self.is_boss else True
@property
def may_carrier(self):
return self.is_sea and not self.may_enemy
@property
def is_accessible(self):
return self.cost < 9999
@ -120,10 +124,11 @@ class GridInfo:
def is_nearby(self):
return self.cost < 20
def update(self, info):
def update(self, info, is_carrier_scan=False):
"""
Args:
info(GridInfo):
info (GridInfo):
is_carrier_scan (bool): Is a scan for mystery: enemy_searching, which ignore may_enemy spawn point.
"""
# failure = 0
for item in ['boss', 'siren']:
@ -136,14 +141,19 @@ class GridInfo:
logger.info(f'Wrong Prediction. Grid: {self}, Attr: {item}')
# failure += 1
if info.is_enemy and self.may_enemy and not self.is_cleared \
and not info.is_fleet and not self.is_fleet:
self.is_enemy = True
self.enemy_scale = info.enemy_scale
self.enemy_type = info.enemy_type
if self.may_siren:
self.is_siren = True
return True
if info.is_enemy:
flag = not info.is_fleet and not self.is_fleet
if not is_carrier_scan:
flag = flag and self.may_enemy and not self.is_cleared
if flag:
self.is_enemy = True
self.enemy_scale = info.enemy_scale
self.enemy_type = info.enemy_type
if self.may_siren:
self.is_siren = True
return True
else:
logger.info(f'Wrong Prediction. Grid: {self}, Attr: is_enemy')
for item in ['mystery', 'ammo']:
if info.__getattribute__('is_' + item):

View File

@ -19,7 +19,8 @@ class Map(Fleet):
self.emotion.wait(fleet=self.fleet_current_index)
self.goto(grid, expected=expected)
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count, siren_count=self.siren_count)
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count, siren_count=self.siren_count,
carrier_count=self.carrier_count)
self.find_path_initial()
self.map.show_cost()
@ -311,6 +312,7 @@ class Map(Fleet):
else:
logger.info('Fleet_2 step on %s got roadblocks.' % grid)
self.fleet_1.clear_roadblocks(roadblocks)
self.fleet_1.clear_all_mystery()
return True
return False

View File

@ -108,11 +108,12 @@ class CampaignMap:
[self[(x, y)].str if (x, y) in self else ' ' for x in range(self.shape[0] + 1)])
logger.info(text)
def update(self, grids, camera):
def update(self, grids, camera, is_carrier_scan=False):
"""
Args:
grids:
camera (tuple):
is_carrier_scan (bool):
"""
# failure = 0
offset = np.array(camera) - np.array(grids.center_grid)
@ -120,7 +121,7 @@ class CampaignMap:
for grid in grids.grids.values():
loca = tuple(offset + grid.location)
if loca in self.grids:
self.grids[loca].update(grid)
self.grids[loca].update(grid, is_carrier_scan=is_carrier_scan)
# flag, fail = self.grids[loca].update(grid)
# failure += fail
@ -307,18 +308,19 @@ class CampaignMap:
return path
def missing_get(self, battle_count, mystery_count=0, siren_count=0):
def missing_get(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
try:
missing = self.spawn_data[battle_count].copy()
except IndexError:
missing = self.spawn_data[-1].copy()
may = {'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0}
may = {'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0, 'carrier': 0}
missing['enemy'] -= battle_count
missing['mystery'] -= mystery_count
missing['siren'] -= siren_count
missing['carrier'] = carrier_count - self.select(is_enemy=True, may_enemy=False).count
for grid in self:
for attr in may.keys():
if grid.__getattribute__('is_' + attr):
for attr in ['enemy', 'mystery', 'siren', 'boss']:
if grid.__getattribute__('is_' + attr) and grid.__getattribute__('may_' + attr):
missing[attr] -= 1
for grid in self:
@ -333,16 +335,18 @@ class CampaignMap:
upper = tuple(np.array(grid.location) + upper)
if upper in self:
upper = self[upper]
for attr in may.keys():
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.info('missing: %s' % missing)
logger.info('may: %s' % may)
return may, missing
def missing_is_none(self, battle_count, mystery_count=0, siren_count=0):
may, missing = self.missing_get(battle_count, mystery_count, siren_count)
def missing_is_none(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
may, missing = self.missing_get(battle_count, mystery_count, siren_count, carrier_count)
for key in may.keys():
if missing[key] != 0:
@ -350,8 +354,8 @@ class CampaignMap:
return True
def missing_predict(self, battle_count, mystery_count=0, siren_count=0):
may, missing = self.missing_get(battle_count, mystery_count, siren_count)
def missing_predict(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
may, missing = self.missing_get(battle_count, mystery_count, siren_count, carrier_count)
# predict
for grid in self:
@ -366,10 +370,14 @@ class CampaignMap:
upper = tuple(np.array(grid.location) + upper)
if upper in self:
upper = self[upper]
for attr in may.keys():
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):
"""

View File

@ -1,9 +1,7 @@
from module.base.timer import Timer
from module.handler.enemy_searching import EnemySearchingHandler
from module.handler.fast_forward import FastForwardHandler
from module.handler.low_emotion import LowEmotionHandler
from module.handler.popup import PopupHandler
from module.handler.strategy import StrategyHandler
from module.handler.mystery import MysteryHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.logger import logger
from module.map.assets import *
@ -12,8 +10,8 @@ from module.map.map_fleet_preparation import FleetPreparation
from module.retire.retirement import Retirement
class MapOperation(UrgentCommissionHandler, EnemySearchingHandler, FleetPreparation, Retirement, FastForwardHandler,
StrategyHandler, LowEmotionHandler, PopupHandler):
class MapOperation(UrgentCommissionHandler, MysteryHandler, FleetPreparation, Retirement, FastForwardHandler,
LowEmotionHandler):
def fleet_switch_click(self):
"""
Switch fleet.