Add: 适配复刻苍红的回响AB图

- 开荒模式移动至出击设置
- 增加开荒模式自动启用, 无脑开就完事了
- 将透视识别参数放到了config里, 这样就可以用地图config覆盖了
- 适配小地图模式, 参数抄A1就行了
- 修复了章节名OCR的识别位置
- 修复了开荒会把BOSS当作精英打问题
- 增加战斗中的剧情跳过
- 注释掉了截图和点击的retry
- 增加了捕捉目标点超出移动范围
This commit is contained in:
LmeSzinc 2020-04-24 15:26:11 +08:00
parent b4054b579e
commit bea05d396e
42 changed files with 507 additions and 113 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,59 @@
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.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
-- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- --
-- -- -- ++ ++ -- ++ -- --
-- -- -- ++ ++ -- -- -- --
SP -- -- -- -- -- -- ++ --
SP SP -- -- -- -- -- ++ --
'''
class Config:
SUBMARINE = 0
FLEET_BOSS = 1
POOR_MAP_DATA = True
MAP_HAS_AMBUSH = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_SIREN = True
MAP_HAS_DYNAMIC_RED_BORDER = True
MAP_GRID_CENTER_TOLERANCE = 0.3
MAP_SIREN_COUNT = 2
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 50
EDGE_LINES_HOUGHLINES_THRESHOLD = 50
CAMERA_SWIPE_MULTIPLY_X = 200 * 0.7
CAMERA_SWIPE_MULTIPLY_Y = 140 * 0.7
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.
MID_DIFF_RANGE_H = (45, 70)
MID_DIFF_RANGE_V = (97 - 3, 97 + 3)
TRUST_EDGE_LINES = True
VANISH_POINT_RANGE = ((540, 740), (-4000, -2000))
DISTANCE_POINT_X_RANGE = ((-2000, -1000),)
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (80, 255 - 40),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
'wlen': 100,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 40, 255),
'prominence': 10,
'distance': 50,
'wlen': 1000
}
class Campaign(CampaignBase):
MAP = MAP

View File

@ -0,0 +1,21 @@
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.event_20200423_cn.a1 import Config
MAP = CampaignMap()
MAP.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
-- -- -- -- -- -- --
-- -- -- ++ ++ ++ --
-- -- -- -- -- -- --
-- -- ++ -- -- -- --
-- -- -- -- -- -- --
SP -- -- -- -- ++ --
SP SP -- -- -- ++ --
'''
class Campaign(CampaignBase):
MAP = MAP

View File

@ -0,0 +1,21 @@
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.event_20200423_cn.a1 import Config
MAP = CampaignMap()
MAP.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
SP SP -- -- -- -- -- -- --
SP -- -- -- ++ ++ ++ -- --
-- -- -- -- -- -- -- -- --
-- ++ -- -- -- -- -- -- --
-- ++ -- -- ++ ++ -- -- --
-- -- -- -- -- -- -- ++ ++
-- -- -- -- -- -- -- ++ ++
'''
class Campaign(CampaignBase):
MAP = MAP

View File

@ -0,0 +1,58 @@
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.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
-- -- -- -- -- -- -- -- --
-- ++ ++ -- -- -- -- ++ --
-- -- -- -- -- -- -- -- --
-- -- ++ ++ ++ -- -- -- --
-- -- -- -- -- -- -- -- --
++ ++ -- -- -- -- ++ -- --
++ ++ SP SP -- -- ++ -- --
'''
class Config:
SUBMARINE = 0
FLEET_BOSS = 1
POOR_MAP_DATA = True
MAP_HAS_AMBUSH = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_SIREN = True
MAP_GRID_CENTER_TOLERANCE = 0.3
MAP_SIREN_COUNT = 2
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 50
EDGE_LINES_HOUGHLINES_THRESHOLD = 50
CAMERA_SWIPE_MULTIPLY_X = 200 * 0.7
CAMERA_SWIPE_MULTIPLY_Y = 140 * 0.7
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 1.
MID_DIFF_RANGE_H = (45, 70)
MID_DIFF_RANGE_V = (97 - 3, 97 + 3)
TRUST_EDGE_LINES = True
VANISH_POINT_RANGE = ((540, 740), (-4000, -2000))
DISTANCE_POINT_X_RANGE = ((-2000, -1000),)
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (80, 255 - 40),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
'wlen': 100,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 40, 255),
'prominence': 10,
'distance': 50,
'wlen': 1000
}
class Campaign(CampaignBase):
MAP = MAP

View File

@ -0,0 +1,25 @@
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.event_20200423_cn.b1 import Config as ConfigBase
MAP = CampaignMap()
MAP.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
-- -- -- -- SP SP -- -- ++ ++
-- -- -- -- -- -- -- -- ++ ++
++ ++ ++ -- -- -- -- -- -- --
-- -- -- -- ++ ++ -- -- -- --
-- -- -- -- -- -- -- -- -- --
-- ++ -- -- -- -- ++ -- -- --
-- ++ -- -- -- -- -- -- -- --
'''
class Config(ConfigBase):
FLEET_BOSS = 2
class Campaign(CampaignBase):
MAP = MAP

View File

@ -0,0 +1,25 @@
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.event_20200423_cn.b1 import Config as ConfigBase
MAP = CampaignMap()
MAP.camera_sight = (-4, -2, 5, 3)
MAP.map_data = '''
-- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- ++ ++
++ ++ -- -- ++ ++ -- -- --
-- -- -- -- ++ ++ -- -- SP
++ ++ -- -- -- -- -- -- SP
-- -- -- -- -- -- -- ++ --
-- -- ++ ++ ++ -- -- -- --
'''
class Config(ConfigBase):
FLEET_BOSS = 2
class Campaign(CampaignBase):
MAP = MAP

View File

@ -47,6 +47,9 @@ retire_sr = no
retire_ssr = no
enable_drop_screenshot = no
drop_screenshot_folder =
enable_map_clear_mode = yes
clear_mode_stop_condition = map_green
map_star_clear_all = index_3
command = setting
[Reward]
@ -110,9 +113,6 @@ command = daily
[Main]
command = main
main_stage = 7-2
enable_map_clear_mode = no
clear_mode_stop_condition = map_green
map_star_clear_all = index_3
[Event]
command = event

View File

@ -48,7 +48,7 @@ class Ocr:
self.mid_process_height = mid_process_height
self.threshold = threshold
self.additional_preprocess = additional_preprocess
self.use_binary=use_binary
self.use_binary = use_binary
self.length = (length, length) if isinstance(length, int) else length
self.white_list = white_list
self.buttons = buttons if isinstance(buttons, list) else [buttons]

View File

@ -39,6 +39,8 @@ class CampaignBase(Map):
if self.brute_clear_boss():
return True
else:
if self.clear_siren():
return True
return self.clear_enemy()
logger.warning('No battle executed.')
@ -53,7 +55,11 @@ class CampaignBase(Map):
if self.battle_count >= 3:
self.pick_up_ammo()
if self.map.select(is_enemy=True, is_boss=False).count > 0:
remain = self.map.select(is_enemy=True, is_boss=False)
logger.info('Enemy remain: {}')
if remain.count > 0:
if self.clear_siren():
return True
return self.battle_default()
else:
return self.battle_boss()
@ -91,4 +97,7 @@ class CampaignBase(Map):
self.execute_a_battle()
except CampaignEnd:
logger.hr('Campaign end')
break
return True
logger.warning('Battle function exhausted.')
raise ScriptError('Battle function exhausted.')

View File

@ -72,7 +72,7 @@ class CampaignOcr:
digits.append(Button(area=area_offset(stage, point), color=stage_clear_color, button=button, name='stage'))
result = TEMPLATE_STAGE_PERCENT.match_multi(image, similarity=0.95)
name_offset = (50, 0)
name_offset = (48, 0)
for point in result:
point = point[::-1]
button = tuple(np.append(point, point + TEMPLATE_STAGE_PERCENT.image.shape[:2][::-1]))

View File

@ -115,7 +115,7 @@ class CampaignRun(CampaignUI, Reward, LoginHandler):
start_date = datetime.now().date()
while 1:
if datetime.now().date() != start_date:
start_date.replace(day=datetime.now().day)
start_date = datetime.now().date()
self.app_restart()
self.campaign.fleet_checked_reset()
if self.handle_reward():

View File

@ -10,16 +10,16 @@ from module.combat.hp_balancer import HPBalancer
from module.combat.submarine import SubmarineCall
from module.handler.enemy_searching import EnemySearchingHandler
from module.handler.low_emotion import LowEmotionHandler
from module.handler.story import StoryHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.logger import logger
from module.map.assets import MAP_OFFENSIVE
from module.map.exception import CampaignEnd
from module.retire.retirement import Retirement
from module.ui.assets import BACK_ARROW
class Combat(HPBalancer, UrgentCommissionHandler, EnemySearchingHandler, Retirement, SubmarineCall, LowEmotionHandler,
CombatAuto, CombatManual):
CombatAuto, CombatManual, StoryHandler):
_automation_set_timer = Timer(1)
_emotion: Emotion
battle_status_click_interval = 0
@ -189,6 +189,8 @@ class Combat(HPBalancer, UrgentCommissionHandler, EnemySearchingHandler, Retirem
if not confirm_timer.reached() and self.appear_then_click(AUTOMATION_CONFIRM, offset=True):
continue
if self.handle_story_skip():
continue
if self.handle_combat_auto():
continue
if self.handle_combat_manual():
@ -298,6 +300,8 @@ class Combat(HPBalancer, UrgentCommissionHandler, EnemySearchingHandler, Retirem
continue
if self.handle_urgent_commission(save_get_items=save_get_items):
continue
if self.handle_story_skip():
continue
# End
if expected_end is None:

View File

@ -163,6 +163,11 @@ def main(ini_name=''):
drop.add_argument('--启用掉落记录', default=default('--启用掉落记录'), choices=['', ''])
drop.add_argument('--掉落保存目录', default=default('--掉落保存目录'))
clear = setting_parser.add_argument_group('开荒模式', '未开荒地图会在完成后停止, 已开荒的地图会忽略选项, 无脑开就完事了')
clear.add_argument('--启用开荒', default=default('--启用开荒'), choices=['', ''])
clear.add_argument('--开荒停止条件', default=default('--开荒停止条件'), choices=['地图通关', '地图三星', '地图绿海'])
clear.add_argument('--地图全清星星', default=default('--地图全清星星'), choices=['第一个', '第二个', '第三个', '不使用'], help='第几颗星星是击破所有敌舰')
# ==========收菜设置==========
reward_parser = subs.add_parser('收菜设置')
reward_condition = reward_parser.add_argument_group('触发条件', '需要运行一次来保存选项, 运行时会执行一次收菜')
@ -264,17 +269,12 @@ def main(ini_name=''):
stage = main_parser.add_argument_group('选择关卡', '主线图出击, 目前仅支持前六章和7-2')
stage.add_argument('--主线地图出击', default=default('--主线地图出击'), help='例如 7-2')
clear = stage.add_argument_group('主线开荒', '')
clear.add_argument('--启用主线开荒', default=default('--启用主线开荒'), choices=['', ''])
clear.add_argument('--主线开荒停止条件', default=default('--主线开荒停止条件'), choices=['地图通关', '地图三星', '地图绿海'])
clear.add_argument('--主线全清星星', default=default('--主线全清星星'), choices=['第一个', '第二个', '第三个', '不使用'], help='第几颗星星是击破所有敌舰')
# ==========活动图==========
event_parser = subs.add_parser('活动图')
event = event_parser.add_argument_group('选择关卡', '')
event.add_argument('--活动地图', default=default('--活动地图'),
choices=['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3', 'd1', 'd2', 'd3'][::-1],
choices=['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3', 'd1', 'd2', 'd3'],
help='例如 d3')
event.add_argument('--sp地图', default=default('--sp地图'),
choices=['sp3', 'sp2', 'sp1'],

View File

@ -195,9 +195,18 @@ class AzurLaneConfig:
"""
MAP_HAS_AMBUSH = True
MAP_HAS_FLEET_STEP = False
MAP_HAS_MOVABLE_ENEMY = False
MAP_HAS_SIREN = False
MAP_HAS_DYNAMIC_RED_BORDER = False
MAP_SIREN_MOVE_WAIT = 1.8 # The enemy moving takes about 1.5 ~ 1.8s.
MAP_SIREN_COUNT = 0
MAP_MYSTERY_HAS_CARRIER = False
MAP_GRID_CENTER_TOLERANCE = 0.1
POOR_MAP_DATA = False
FLEET_BOSS = 2
CAMERA_SWIPE_MULTIPLY_X = 200
CAMERA_SWIPE_MULTIPLY_Y = 140
"""
module.retire
@ -246,20 +255,15 @@ class AzurLaneConfig:
# Parameters for lines pre-cleansing
HORIZONTAL_LINES_THETA_THRESHOLD = 0.005
VERTICAL_LINES_THETA_THRESHOLD = 18
TRUST_EDGE_LINES = True # For map fog in event_20200326_cn.
# Parameters for perspective calculating
VANISH_POINT_RANGE = ((540, 740), (-3000, -1000))
DISTANCE_POINT_X_RANGE = ((-3200, -1600),)
# Parameters for line cleansing
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 3
ERROR_LINES_TOLERANCE = (-10, 10)
MID_DIFF_RANGE = (129 - 3, 129 + 3)
COINCIDENT_POINT_RANGE = (
(
-abs(ERROR_LINES_TOLERANCE[0]) * MID_DIFF_RANGE[1],
# SCREEN_SIZE[0] + ERROR_LINES_TOLERANCE[1] * MID_DIFF_RANGE[1]
200
),
MID_DIFF_RANGE
)
MID_DIFF_RANGE_H = (129 - 3, 129 + 3)
MID_DIFF_RANGE_V = (129 - 3, 129 + 3)
"""
module.daemon
@ -405,6 +409,11 @@ class AzurLaneConfig:
self.RETIRE_MODE = option['retire_mode'].split('_')[1]
for r in ['n', 'r', 'sr', 'ssr']:
self.__setattr__(f'RETIRE_{r.upper()}', to_bool(option[f'retire_{r}']))
# Clear mode
self.ENABLE_MAP_CLEAR_MODE = to_bool(option['enable_map_clear_mode'])
self.CLEAR_MODE_STOP_CONDITION = option['clear_mode_stop_condition']
star = option['map_star_clear_all']
self.MAP_STAR_CLEAR_ALL = int(star.split('_')[1]) if star.startswith('index_') else 0
# Reward
option = config['Reward']
@ -418,10 +427,6 @@ class AzurLaneConfig:
option = config['Main']
self.CAMPAIGN_NAME = option['main_stage']
self.CAMPAIGN_NAME = 'campaign_' + self.CAMPAIGN_NAME.replace('-', '_')
self.ENABLE_MAP_CLEAR_MODE = to_bool(option['enable_map_clear_mode'])
self.CLEAR_MODE_STOP_CONDITION = option['clear_mode_stop_condition']
star = option['map_star_clear_all']
self.MAP_STAR_CLEAR_ALL = int(star.split('_')[1]) if star.startswith('index_') else 0
option = config['Daily']
for n in ['daily_mission', 'hard_campaign', 'exercise']:

View File

@ -81,6 +81,9 @@ dic_chi_to_eng = {
'退役金皮': 'retire_ssr',
'启用掉落记录': 'enable_drop_screenshot',
'掉落保存目录': 'drop_screenshot_folder',
'启用开荒': 'enable_map_clear_mode',
'开荒停止条件': 'clear_mode_stop_condition',
'地图全清星星': 'map_star_clear_all',
'启用收获': 'enable_reward',
'收菜间隔': 'reward_interval',
'启用石油收获': 'enable_oil_reward',
@ -131,9 +134,6 @@ dic_chi_to_eng = {
'演习低血量确认时长': 'exercise_low_hp_confirm',
'演习快速换装': 'exercise_equipment',
'主线地图出击': 'main_stage',
'启用主线开荒': 'enable_map_clear_mode',
'主线开荒停止条件': 'clear_mode_stop_condition',
'主线全清星星': 'map_star_clear_all',
'活动地图': 'event_stage',
'sp地图': 'sp_stage',
'活动名称': 'event_name',

View File

@ -10,7 +10,4 @@ FLEET_PREPARATION = Button(area=(981, 575, 1180, 636), color=(235, 185, 114), bu
GET_EMERGENCY_REPAIR = Button(area=(645, 352, 666, 360), color=(255, 255, 255), button=(645, 352, 666, 360), file='./assets/daemon/GET_EMERGENCY_REPAIR.png')
GET_ITEMS = Button(area=(538, 217, 741, 253), color=(160, 192, 248), button=(1120, 643, 1146, 666), file='./assets/daemon/GET_ITEMS.png')
MAP_PREPARATION = Button(area=(853, 488, 1053, 549), color=(235, 186, 114), button=(853, 488, 1053, 549), file='./assets/daemon/MAP_PREPARATION.png')
STORY_CHOOCE = Button(area=(902, 344, 959, 357), color=(98, 122, 156), button=(902, 344, 959, 357), file='./assets/daemon/STORY_CHOOCE.png')
STORY_CHOOCE_2 = Button(area=(903, 388, 959, 399), color=(98, 121, 156), button=(903, 388, 959, 399), file='./assets/daemon/STORY_CHOOCE_2.png')
STORY_SKIP = Button(area=(1216, 676, 1258, 708), color=(148, 159, 178), button=(1180, 30, 1256, 49), file='./assets/daemon/STORY_SKIP.png')
STRATEGY_OPEN = Button(area=(1102, 480, 1178, 482), color=(255, 223, 74), button=(1064, 405, 1093, 483), file='./assets/daemon/STRATEGY_OPEN.png')

View File

@ -2,13 +2,13 @@ from module.combat.combat import Combat
from module.daemon.assets import *
from module.handler.ambush import MAP_AMBUSH_EVADE
from module.handler.mystery import MysteryHandler
from module.handler.popup import PopupHandler
from module.handler.story import StoryHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.map.map_fleet_preparation import FleetPreparation
class AzurLaneDaemon(FleetPreparation, Combat, UrgentCommissionHandler, MysteryHandler,
PopupHandler):
StoryHandler):
def daemon(self):
while 1:
@ -54,14 +54,7 @@ class AzurLaneDaemon(FleetPreparation, Combat, UrgentCommissionHandler, MysteryH
# Story
if self.config.ENABLE_SEMI_STORY_SKIP:
if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
continue
if self.handle_popup_confirm():
continue
if self.appear_then_click(STORY_CHOOCE, offset=True, interval=2):
continue
if self.appear_then_click(STORY_CHOOCE_2, offset=True, interval=2):
continue
self.story_skip()
# End
# No end condition, stop it manually.

View File

@ -64,11 +64,11 @@ class Control(Connection):
self._click_uiautomator2(x, y)
self.sleep(self.config.SLEEP_AFTER_CLICK)
@retry()
# @retry()
def _click_uiautomator2(self, x, y):
self.device.click(x, y)
@retry()
# @retry()
def _click_adb(self, x, y):
self.adb_shell(['input', 'tap', str(x), str(y)], serial=self.serial)

View File

@ -47,7 +47,7 @@ class Screenshot(Connection):
screenshot = self.adb_shell(['screencap', '-p'], serial=self.serial)
return self._process_screenshot(screenshot)
@retry()
# @retry()
# @timer
def screenshot(self):
"""

View File

@ -5,7 +5,7 @@ from module.base.utils import red_overlay_transparency, get_color
from module.combat.combat import Combat
from module.handler.assets import *
from module.logger import logger
from module.template.assets import TEMPLATE_AMBUSH_EVADE_SUCCESS, TEMPLATE_AMBUSH_EVADE_FAILED
from module.template.assets import *
def ambush_letter_preprocess(image):
@ -26,6 +26,7 @@ def ambush_letter_preprocess(image):
TEMPLATE_AMBUSH_EVADE_SUCCESS.image = ambush_letter_preprocess(TEMPLATE_AMBUSH_EVADE_SUCCESS.image)
TEMPLATE_AMBUSH_EVADE_FAILED.image = ambush_letter_preprocess(TEMPLATE_AMBUSH_EVADE_FAILED.image)
TEMPLATE_MAP_WALK_OUT_OF_STEP.image = ambush_letter_preprocess(TEMPLATE_MAP_WALK_OUT_OF_STEP.image)
class AmbushHandler(Combat):
@ -98,3 +99,17 @@ class AmbushHandler(Combat):
self._handle_ambush()
return False
def handle_walk_out_of_step(self):
if not self.config.MAP_HAS_FLEET_STEP:
return False
if not self.appear(INFO_BAR_1):
return False
image = ambush_letter_preprocess(np.array(self.device.image.crop(MAP_WALK_OUT_OF_STEP.area)))
if TEMPLATE_MAP_WALK_OUT_OF_STEP.match(image):
logger.warning('Map walk out of step.')
self.handle_info_bar()
return True
return False

View File

@ -35,9 +35,13 @@ MAP_GREEN = Button(area=(195, 260, 349, 292), color=(125, 190, 84), button=(195,
MAP_STAR_1 = Button(area=(245, 377, 254, 384), color=(251, 233, 143), button=(245, 377, 254, 384), file='./assets/handler/MAP_STAR_1.png')
MAP_STAR_2 = Button(area=(532, 377, 540, 384), color=(251, 233, 144), button=(532, 377, 540, 384), file='./assets/handler/MAP_STAR_2.png')
MAP_STAR_3 = Button(area=(818, 377, 827, 384), color=(251, 233, 143), button=(818, 377, 827, 384), file='./assets/handler/MAP_STAR_3.png')
MAP_WALK_OUT_OF_STEP = Button(area=(654, 312, 704, 335), color=(109, 113, 120), button=(654, 312, 704, 335), file='./assets/handler/MAP_WALK_OUT_OF_STEP.png')
MYSTERY_ITEM = Button(area=(589, 294, 691, 427), color=(144, 127, 83), button=(589, 294, 691, 427), file='./assets/handler/MYSTERY_ITEM.png')
POPUP_CANCEL = Button(area=(404, 493, 576, 550), color=(166, 169, 172), button=(404, 493, 576, 550), file='./assets/handler/POPUP_CANCEL.png')
POPUP_CONFIRM = Button(area=(704, 493, 876, 550), color=(94, 144, 204), button=(704, 493, 876, 550), file='./assets/handler/POPUP_CONFIRM.png')
STORY_CHOOCE = Button(area=(902, 344, 959, 357), color=(98, 122, 156), button=(902, 344, 959, 357), file='./assets/handler/STORY_CHOOCE.png')
STORY_CHOOCE_2 = Button(area=(903, 388, 959, 399), color=(98, 121, 156), button=(903, 388, 959, 399), file='./assets/handler/STORY_CHOOCE_2.png')
STORY_SKIP = Button(area=(1216, 676, 1258, 708), color=(148, 159, 178), button=(1180, 30, 1256, 49), file='./assets/handler/STORY_SKIP.png')
STRATEGY_OPEN = Button(area=(1198, 411, 1269, 471), color=(81, 85, 101), button=(1198, 411, 1269, 471), file='./assets/handler/STRATEGY_OPEN.png')
STRATEGY_OPENED = Button(area=(1176, 366, 1275, 393), color=(128, 155, 218), button=(1060, 406, 1092, 485), file='./assets/handler/STRATEGY_OPENED.png')
SUBMARINE_HUNT_OFF = Button(area=(1200, 415, 1262, 477), color=(125, 127, 132), button=(1200, 415, 1262, 477), file='./assets/handler/SUBMARINE_HUNT_OFF.png')

View File

@ -22,14 +22,17 @@ class EnemySearchingHandler(InfoBarHandler):
self.device.sleep(1.2)
def handle_in_stage(self):
if self.appear(IN_STAGE_RED) or self.appear(IN_STAGE_BLUE):
if self.is_in_stage():
logger.info('In stage.')
# self.device.sleep(0.5)
self.ensure_no_info_bar(timeout=0.6)
raise CampaignEnd('In map.')
self.ensure_no_info_bar(timeout=1.2)
raise CampaignEnd('In stage.')
else:
return False
def is_in_stage(self):
return self.appear(IN_STAGE_RED) or self.appear(IN_STAGE_BLUE)
def is_in_map(self):
return self.appear(IN_MAP)

View File

@ -3,7 +3,6 @@ from module.base.switch import Switch
from module.base.utils import color_bar_percentage
from module.handler.assets import *
from module.logger import logger
from module.map.exception import ScriptEnd
fast_forward = Switch('Fast_Forward')
fast_forward.add_status('on', check_button=FAST_FORWARD_ON)
@ -14,6 +13,8 @@ fleet_lock.add_status('off', check_button=FLEET_UNLOCKED)
class FastForwardHandler(ModuleBase):
map_clear_record = None
def handle_fast_forward(self):
if not self.appear(MAP_STAR_1) or not self.appear(MAP_STAR_2) or not self.appear(MAP_STAR_3):
logger.info('Campaign is not 3-star cleared.')
@ -30,6 +31,7 @@ class FastForwardHandler(ModuleBase):
logger.info('Set fast forward.')
self.config.MAP_HAS_FLEET_STEP = False
self.config.MAP_HAS_MOVABLE_ENEMY = False
if self.config.ENABLE_FAST_FORWARD:
self.config.MAP_HAS_AMBUSH = False
status = 'on'
@ -51,7 +53,7 @@ class FastForwardHandler(ModuleBase):
changed = fleet_lock.set(status=status, main=self)
return changed
def handle_map_clear_mode_stop(self):
def triggered_map_clear_mode_stop(self):
if not self.config.ENABLE_MAP_CLEAR_MODE:
return False
@ -59,11 +61,11 @@ class FastForwardHandler(ModuleBase):
logger.attr('Map_clear', f'{int(percent * 100)}%')
if self.config.CLEAR_MODE_STOP_CONDITION == 'map_100':
if percent > 0.95:
raise ScriptEnd(f'Reach condition: {self.config.CLEAR_MODE_STOP_CONDITION}')
return True
if self.config.CLEAR_MODE_STOP_CONDITION == 'map_3_star':
if self.appear(MAP_STAR_1) and self.appear(MAP_STAR_2) and self.appear(MAP_STAR_3):
raise ScriptEnd(f'Reach condition: {self.config.CLEAR_MODE_STOP_CONDITION}')
if self.appear(MAP_STAR_1) and self.appear(MAP_STAR_2) and self.appear(MAP_STAR_3) and percent > 0.95:
return True
if self.config.CLEAR_MODE_STOP_CONDITION in ['map_3_star', 'map_green'] and self.config.MAP_STAR_CLEAR_ALL:
button = [MAP_STAR_1, MAP_STAR_2, MAP_STAR_3][self.config.MAP_STAR_CLEAR_ALL - 1]
@ -72,4 +74,18 @@ class FastForwardHandler(ModuleBase):
if self.config.CLEAR_MODE_STOP_CONDITION == 'map_green':
if self.appear(MAP_GREEN):
raise ScriptEnd(f'Reach condition: {self.config.CLEAR_MODE_STOP_CONDITION}')
return True
return False
def handle_map_clear_mode_stop(self):
if self.map_clear_record is True:
return False
flag = self.triggered_map_clear_mode_stop()
if self.map_clear_record is None:
self.map_clear_record = flag
elif self.map_clear_record is False and flag:
return True
return False

22
module/handler/story.py Normal file
View File

@ -0,0 +1,22 @@
from module.handler.assets import *
from module.handler.popup import PopupHandler
class StoryHandler(PopupHandler):
def story_skip(self):
if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
return True
if self.handle_popup_confirm():
return True
if self.appear_then_click(STORY_CHOOCE, offset=True, interval=2):
return True
if self.appear_then_click(STORY_CHOOCE_2, offset=True, interval=2):
return True
return False
def handle_story_skip(self):
if not self.config.ENABLE_MAP_CLEAR_MODE:
return False
return self.story_skip()

View File

@ -18,6 +18,7 @@ FLEET_PREPARATION_HARD_2 = Button(area=(201, 393, 1001, 394), color=(255, 219, 0
MAP_CAT_ATTACK = Button(area=(1241, 106, 1271, 115), color=(255, 231, 123), button=(1148, 653, 1262, 705), file='./assets/map/MAP_CAT_ATTACK.png')
MAP_OFFENSIVE = Button(area=(1148, 653, 1262, 705), color=(234, 180, 108), button=(1148, 653, 1262, 705), file='./assets/map/MAP_OFFENSIVE.png')
MAP_PREPARATION = Button(area=(854, 488, 1052, 548), color=(236, 186, 115), button=(854, 488, 1052, 548), file='./assets/map/MAP_PREPARATION.png')
MAP_PREPARATION_CANCEL = Button(area=(234, 12, 278, 47), color=(45, 46, 69), button=(234, 12, 278, 47), file='./assets/map/MAP_PREPARATION_CANCEL.png')
SUBMARINE_BAR = Button(area=(1015, 525, 1186, 602), color=(193, 177, 144), button=(1015, 525, 1186, 602), file='./assets/map/SUBMARINE_BAR.png')
SUBMARINE_CHOOSE = Button(area=(1026, 447, 1090, 505), color=(208, 164, 103), button=(1026, 447, 1090, 505), file='./assets/map/SUBMARINE_CHOOSE.png')
SUBMARINE_CLEAR = Button(area=(1108, 447, 1172, 505), color=(152, 153, 154), button=(1108, 447, 1172, 505), file='./assets/map/SUBMARINE_CLEAR.png')

View File

@ -47,10 +47,20 @@ class Camera(InfoBarHandler):
# Linear fit
# x = x * 200
# y = y * 140
# Function fit
x, y = swipe_multiply_2d(x, y)
if self.config.CAMERA_SWIPE_MULTIPLY_X is not None and self.config.CAMERA_SWIPE_MULTIPLY_Y is not None:
if callable(self.config.CAMERA_SWIPE_MULTIPLY_X):
x = self.config.CAMERA_SWIPE_MULTIPLY_X(x)
else:
x = x * self.config.CAMERA_SWIPE_MULTIPLY_X
if callable(self.config.CAMERA_SWIPE_MULTIPLY_Y):
y = self.config.CAMERA_SWIPE_MULTIPLY_X(y)
else:
y = y * self.config.CAMERA_SWIPE_MULTIPLY_Y
else:
# Function fit
x, y = swipe_multiply_2d(x, y)
vector = (-x, -y)
vector = (-int(x), -int(y))
self.device.swipe(vector)
self.device.sleep(0.3)
self.update()
@ -71,7 +81,10 @@ class Camera(InfoBarHandler):
vector = np.array(vector)
self.camera = tuple(vector + self.camera)
vector = np.array([0.5, 0.5]) - np.array(self.grids.center_offset) + vector
self._map_swipe(vector)
try:
self._map_swipe(vector)
except PerspectiveError as e:
self.handle_camera_outside_map(e)
def focus_to_grid_center(self):
"""
@ -80,7 +93,7 @@ class Camera(InfoBarHandler):
Returns:
bool: Map swiped.
"""
if np.any(np.abs(self.grids.center_offset - 0.5) > 0.1):
if np.any(np.abs(self.grids.center_offset - 0.5) > self.config.MAP_GRID_CENTER_TOLERANCE):
logger.info('Re-focus to grid center.')
self.map_swipe((0, 0))
return True
@ -176,10 +189,7 @@ class Camera(InfoBarHandler):
self.map_swipe((x, y))
except PerspectiveError as e:
msg = str(e).split(':')[1].strip()
logger.info(f'Camera outside map: {msg}')
dic = {'to the left': (2, 0), 'to the right': (-2, 0), 'to the lower': (0, 2), 'to the upper': (0, -2)}
self._map_swipe(dic[msg])
self.handle_camera_outside_map(e)
continue
record.append((x, y))
@ -196,6 +206,12 @@ class Camera(InfoBarHandler):
return record
def handle_camera_outside_map(self, e):
msg = str(e).split(':')[1].strip()
logger.info(f'Camera outside map: {msg}')
dic = {'to the left': (2, 0), 'to the right': (-2, 0), 'to the lower': (0, 2), 'to the upper': (0, -2)}
self._map_swipe(dic[msg])
def focus_to(self, location, swipe_limit=(3, 2)):
"""Focus camera on a grid
@ -248,15 +264,17 @@ class Camera(InfoBarHandler):
carrier_count=carrier_count)
self.map.show()
def in_sight(self, location, sight=(-3, -1, 3, 2)):
def in_sight(self, location, sight=None):
"""Make sure location in camera sight
Args:
location:
sight:
sight (tuple): Such as (-3, -1, 3, 2).
"""
location = location_ensure(location)
logger.info('In sight: %s' % location2node(location))
if sight is None:
sight = self.map.camera_sight
diff = np.array(location) - self.camera
if diff[1] > sight[3]:

View File

@ -6,6 +6,10 @@ class PerspectiveError(Exception):
pass
class MapWalkError(Exception):
pass
class ScriptError(Exception):
pass

View File

@ -1,9 +1,11 @@
import itertools
from module.base.timer import Timer
from module.handler.ambush import AmbushHandler
from module.logger import logger
from module.map.camera import Camera
import itertools
from module.map.exception import MapWalkError
from module.map.grids import Grids
from module.map.map_base import SelectedGrids
from module.map.map_base import location2node, location_ensure
from module.map.map_operation import MapOperation
@ -82,12 +84,14 @@ class Fleet(Camera, MapOperation, AmbushHandler):
location (tuple, str, GridInfo): Destination.
"""
location = location_ensure(location)
self.in_sight(location, sight=(-3, 0, 3, 2))
self.focus_to_grid_center()
grid = self.convert_map_to_grid(location)
result_mystery = ''
while 1:
sight = self.map.camera_sight
self.in_sight(location, sight=(sight[0], 0, sight[2], sight[3]))
self.focus_to_grid_center()
grid = self.convert_map_to_grid(location)
self.ambush_color_initial()
self.enemy_searching_color_initial()
grid.__str__ = location
@ -95,8 +99,10 @@ class Fleet(Camera, MapOperation, AmbushHandler):
self.device.click(grid)
arrived = False
# Wait to confirm fleet arrived. It does't appear immediately if fleet in combat .
arrive_timer = Timer(0.3)
arrive_unexpected_timer = Timer(1.5)
add = self.config.MAP_SIREN_MOVE_WAIT * self.config.MAP_SIREN_COUNT \
if not self.config.ENABLE_FAST_FORWARD else 0
arrive_timer = Timer(0.3 + add)
arrive_unexpected_timer = Timer(1.5 + add)
# Wait after ambushed.
ambushed_retry = Timer(0.5)
# If nothing happens, click again.
@ -124,7 +130,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
self.hp_get()
if self.hp_withdraw_triggered():
self.withdraw()
arrived = True
arrived = True if not self.config.MAP_HAS_MOVABLE_ENEMY else False
result = 'combat'
self.battle_count += 1
self.fleet_ammo -= 1
@ -141,6 +147,9 @@ class Fleet(Camera, MapOperation, AmbushHandler):
if self.handle_map_cat_attack():
continue
if self.handle_walk_out_of_step():
raise MapWalkError('walk_out_of_step')
# Arrive
if self.is_in_map() and grid.predict_fleet():
arrive_timer.start()
@ -176,19 +185,27 @@ class Fleet(Camera, MapOperation, AmbushHandler):
self.__setattr__('fleet_%s_location' % self.fleet_current_index, location)
if result_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)
self.full_scan(is_carrier_scan=True)
diff = self.map.select(is_enemy=True).delete(prev_enemy)
logger.info(f'Carrier spawn: {diff}')
elif self.config.POOR_MAP_DATA:
for grid in self.map:
grid.wipe_out()
self.full_scan()
self.find_path_initial()
def goto(self, location, optimize=True, expected=''):
# self.device.sleep(1000)
location = location_ensure(location)
if self.config.MAP_HAS_AMBUSH and optimize:
if (self.config.MAP_HAS_AMBUSH or self.config.MAP_HAS_FLEET_STEP) and optimize:
nodes = self.map.find_path(location, step=self.fleet_step)
for node in nodes:
self._goto(node, expected=expected if node == nodes[-1] else '')
try:
self._goto(node, expected=expected if node == nodes[-1] else '')
except MapWalkError:
nodes_ = self.map.find_path(node, step=1)
for node_ in nodes_:
self._goto(node_, expected=expected if node == nodes[-1] else '')
else:
self._goto(location, expected=expected)
@ -206,6 +223,16 @@ class Fleet(Camera, MapOperation, AmbushHandler):
fleets.append(text)
logger.info(' '.join(fleets))
def full_scan(self, is_carrier_scan=False):
super().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=is_carrier_scan)
if self.config.FLEET_2 and not self.fleet_2_location:
fleets = self.map.select(is_fleet=True, is_current_fleet=False)
if fleets.count:
logger.info(f'Predict fleet_2 to be {fleets[0]}')
self.fleet_2_location = fleets[0].location
def find_all_fleets(self):
logger.hr('Find all fleets')
queue = self.map.select(is_spawn_point=True)
@ -232,25 +259,36 @@ class Fleet(Camera, MapOperation, AmbushHandler):
self.fleet_1 = fleets[0].location
else:
logger.info('Fleet_2 not detected.')
self.find_all_fleets()
elif count == 2:
fleets = fleets.sort_by_camera_distance(self.camera)
self.in_sight(fleets[0], sight=(-1, 0, 1, 2))
if self.convert_map_to_grid(fleets[0]).predict_current_fleet():
self.fleet_1 = fleets[0].location
self.fleet_2 = fleets[1].location
else:
self.in_sight(fleets[1], sight=(-1, 0, 1, 2))
if self.convert_map_to_grid(fleets[1]).predict_current_fleet():
self.fleet_1 = fleets[1].location
self.fleet_2 = fleets[0].location
if self.config.POOR_MAP_DATA and self.map.select(is_spawn_point=True):
self.fleet_1 = fleets[0].location
else:
logger.warning('Current fleet not found')
self.find_all_fleets()
elif count == 2:
current = self.map.select(is_current_fleet=True)
if current.count == 1:
self.fleet_1 = current[0].location
self.fleet_2 = fleets.delete(current)[0].location
else:
fleets = fleets.sort_by_camera_distance(self.camera)
self.in_sight(fleets[0], sight=(-1, 0, 1, 2))
if self.convert_map_to_grid(fleets[0]).predict_current_fleet():
self.fleet_1 = fleets[0].location
self.fleet_2 = fleets[1].location
else:
self.in_sight(fleets[1], sight=(-1, 0, 1, 2))
if self.convert_map_to_grid(fleets[1]).predict_current_fleet():
self.fleet_1 = fleets[1].location
self.fleet_2 = fleets[0].location
else:
logger.warning('Current fleet not found')
self.fleet_1 = fleets[0].location
self.fleet_2 = fleets[1].location
else:
if count == 0:
logger.warning('No fleets detected.')
fleets = self.map.select(is_current_fleet=True)
if fleets.count:
self.fleet_1 = fleets[0].location
if count > 2:
logger.warning('Too many fleets: %s.' % str(fleets))
self.find_all_fleets()
@ -275,8 +313,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
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,
carrier_count=self.carrier_count)
self.full_scan()
self.find_current_fleet()
self.find_path_initial()
self.map.show_cost()
@ -386,6 +423,18 @@ class Fleet(Camera, MapOperation, AmbushHandler):
if data.get('battle') == self.battle_count and data.get('boss', 0):
appear = True
if self.config.POOR_MAP_DATA:
self.device.screenshot()
grids = Grids(self.device.image, config=self.config)
grids.predict()
grids.show()
for grid in grids:
if grid.is_boss:
appear = True
for grid in self.map:
grid.wipe_out()
break
if appear:
logger.info('Catch camera re-positioning after boss appear')
camera = self.camera

View File

@ -93,6 +93,9 @@ class Grids(Perspective):
def predict(self):
for grid in self:
grid.predict()
if not self.config.MAP_HAS_DYNAMIC_RED_BORDER:
for grid in self:
grid.is_siren = False
def update(self, image):
self.image = image

View File

@ -18,11 +18,9 @@ class Map(Fleet):
self.emotion.wait(fleet=self.fleet_current_index)
self.goto(grid, expected=expected)
if self.config.POOR_MAP_DATA:
self.ensure_edge_insight()
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()
if not self.config.POOR_MAP_DATA:
self.full_scan()
self.find_path_initial()
self.map.show_cost()
def clear_chosen_mystery(self, grid):
@ -287,7 +285,7 @@ class Map(Fleet):
"""
Method to clear roadblocks between fleets, using brute-force to find roadblocks.
"""
if not self.config.FLEET_2:
if not self.config.FLEET_2 or not self.fleet_2_location:
return False
grids = self.brute_find_roadblocks(self.map[self.fleet_2_location], fleet=1)
if grids:
@ -304,11 +302,18 @@ class Map(Fleet):
Returns:
bool: True if clear an enemy.
"""
if not self.config.MAP_HAS_SIREN:
return False
grids = self.map.select(may_siren=True, is_enemy=True)
grids = grids.add(self.map.select(may_siren=True, is_siren=True))
grids = grids.add(self.map.select(is_siren=True))
grids = grids.add(self.map.select(is_enemy=True, enemy_scale=0))
grids = grids.delete(self.map.select(is_boss=True))
logger.info('May siren: %s' % self.map.select(may_siren=True))
logger.info('May siren and is enemy: %s' % self.map.select(may_siren=True, is_enemy=True))
logger.info('Is siren: %s' % self.map.select(is_siren=True))
logger.info('Is 0 scale enemy: %s' % self.map.select(is_enemy=True, enemy_scale=0))
logger.info('Delete is boss: %s' % self.map.select(is_boss=True))
grids = self.select_grids(grids, **kwargs)

View File

@ -46,6 +46,7 @@ class CampaignMap:
self._camera_data = []
self.in_map_swipe_preset_data = None
self.poor_map_data = False
self.camera_sight = (-3, -1, 3, 2)
def __iter__(self):
return iter(self.grids.values())
@ -85,7 +86,7 @@ class CampaignMap:
self.grids[(x, y)] = grid
# camera_data can be generate automatically, but it's better to set it manually.
self.camera_data = [location2node(loca) for loca in camera_2d(self._shape, sight=(-3, -1, 3, 2))]
self.camera_data = [location2node(loca) for loca in camera_2d(self._shape, sight=self.camera_sight)]
# weight_data set to 10.
for grid in self:

View File

@ -2,16 +2,18 @@ from module.base.timer import Timer
from module.handler.fast_forward import FastForwardHandler
from module.handler.low_emotion import LowEmotionHandler
from module.handler.mystery import MysteryHandler
from module.handler.story import StoryHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.logger import logger
from module.map.assets import *
from module.map.exception import CampaignEnd
from module.map.exception import ScriptEnd
from module.map.map_fleet_preparation import FleetPreparation
from module.retire.retirement import Retirement
class MapOperation(UrgentCommissionHandler, MysteryHandler, FleetPreparation, Retirement, FastForwardHandler,
LowEmotionHandler):
LowEmotionHandler, StoryHandler):
def fleet_switch_click(self):
"""
Switch fleet.
@ -55,7 +57,9 @@ class MapOperation(UrgentCommissionHandler, MysteryHandler, FleetPreparation, Re
if map_timer.reached() and self.appear(MAP_PREPARATION):
self.device.sleep(0.3) # Wait for map information.
self.device.screenshot()
self.handle_map_clear_mode_stop()
if self.handle_map_clear_mode_stop():
self.enter_map_cancel()
raise ScriptEnd(f'Reach condition: {self.config.CLEAR_MODE_STOP_CONDITION}')
self.handle_fast_forward()
self.device.click(MAP_PREPARATION)
map_timer.reset()
@ -84,12 +88,33 @@ class MapOperation(UrgentCommissionHandler, MysteryHandler, FleetPreparation, Re
if self.handle_urgent_commission():
continue
# Story skip
if self.handle_story_skip():
continue
# End
if self.handle_in_map_with_enemy_searching():
break
return True
def enter_map_cancel(self, skip_first_screenshot=True):
logger.hr('Enter map cancel')
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(MAP_PREPARATION) or self.appear(FLEET_PREPARATION):
self.device.click(MAP_PREPARATION_CANCEL)
continue
if self.is_in_stage():
break
return True
def withdraw(self):
"""
Withdraw campaign.

View File

@ -69,8 +69,11 @@ class Perspective:
# edge_v = edge_v.group()
horizontal = inner_h.add(edge_h).group()
vertical = inner_v.add(edge_v).group()
edge_h = edge_h.group().delete(inner_h) # Experimental, reduce edge lines.
edge_v = edge_v.group().delete(inner_v)
edge_h = edge_h.group()
edge_v = edge_v.group()
if not self.config.TRUST_EDGE_LINES:
edge_h = edge_h.delete(inner_h) # Experimental, reduce edge lines.
edge_v = edge_v.delete(inner_v)
self.horizontal = horizontal
self.vertical = vertical
@ -261,6 +264,7 @@ class Perspective:
793.1379371 922.2605459 1051.38315469 1180.50576349 1309.62837229]
"""
right_distant_point = (self.vanish_point[0] * 2 - self.distant_point[0], self.distant_point[1])
encourage = self.config.COINCIDENT_POINT_ENCOURAGE_DISTANCE ** 2
def convert_to_x(ys):
return Points([[self.config.SCREEN_CENTER[0], y] for y in ys], config=self.config) \
@ -285,7 +289,7 @@ class Perspective:
# Activation function
# distance = 1 / (1 + np.exp(16 / distance - distance))
distance = 1 / (1 + np.exp(9 / distance) / distance)
distance = 1 / (1 + np.exp(encourage / distance) / distance)
distance = np.sum(distance)
return distance
@ -302,16 +306,18 @@ class Perspective:
# Fitting mid
coincident = Lines(np.vstack(lines), is_horizontal=False, config=self.config)
# print(np.round(np.sort(coincident.get_x(128))).astype(int))
coincident_point = optimize.brute(coincident_point_value, self.config.COINCIDENT_POINT_RANGE)
mid_diff_range = self.config.MID_DIFF_RANGE_H if is_horizontal else self.config.MID_DIFF_RANGE_V
coincident_point_range = ((-abs(self.config.ERROR_LINES_TOLERANCE[0]) * mid_diff_range[1], 200), mid_diff_range)
coincident_point = optimize.brute(coincident_point_value, coincident_point_range)
# print(coincident_point, is_horizontal)
diff = abs(coincident_point[1] - 129)
if diff > 3:
diff = np.max([mid_diff_range[0] - coincident_point[1], coincident_point[1] - mid_diff_range[1]])
if diff > 0:
self.correct = False
logger.info('%s coincident point unexpected: %s' % (
'Horizontal' if is_horizontal else 'Vertical',
str(coincident_point)))
if diff > 6:
if diff > 3:
self.save_error_image()
# The limits of detecting area
@ -329,6 +335,7 @@ class Perspective:
left, right = border
# print(mids)
# print(np.diff(mids))
# Filling mid
mids = np.arange(-25, 25) * coincident_point[1] + coincident_point[0]
mids = mids[(mids > left - threshold) & (mids < right + threshold)]

View File

@ -119,6 +119,7 @@ class Reward(RewardCommission):
for button in [GET_ITEMS_1, GET_ITEMS_2]:
if self.appear_then_click(button, offset=(30, 30), interval=1):
exit_timer.reset()
timeout.reset()
reward = True
continue
@ -128,12 +129,14 @@ class Reward(RewardCommission):
if self.appear_then_click(button, interval=1):
exit_timer.reset()
click_timer.reset()
timeout.reset()
continue
if not self.appear(MISSION_CHECK):
if self.appear_then_click(GET_SHIP, interval=1):
click_timer.reset()
exit_timer.reset()
timeout.reset()
continue
# End

View File

@ -14,5 +14,6 @@ TEMPLATE_FLEET_AMMO = Template(file='./assets/template/TEMPLATE_FLEET_AMMO.png')
TEMPLATE_FORMATION_1 = Template(file='./assets/template/TEMPLATE_FORMATION_1.png')
TEMPLATE_FORMATION_2 = Template(file='./assets/template/TEMPLATE_FORMATION_2.png')
TEMPLATE_FORMATION_3 = Template(file='./assets/template/TEMPLATE_FORMATION_3.png')
TEMPLATE_MAP_WALK_OUT_OF_STEP = Template(file='./assets/template/TEMPLATE_MAP_WALK_OUT_OF_STEP.png')
TEMPLATE_STAGE_CLEAR = Template(file='./assets/template/TEMPLATE_STAGE_CLEAR.png')
TEMPLATE_STAGE_PERCENT = Template(file='./assets/template/TEMPLATE_STAGE_PERCENT.png')