From bea05d396e0979d9b0cd55e0976a5c477953473d Mon Sep 17 00:00:00 2001 From: LmeSzinc Date: Fri, 24 Apr 2020 15:26:11 +0800 Subject: [PATCH] =?UTF-8?q?Add:=20=E9=80=82=E9=85=8D=E5=A4=8D=E5=88=BB?= =?UTF-8?q?=E8=8B=8D=E7=BA=A2=E7=9A=84=E5=9B=9E=E5=93=8DAB=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 开荒模式移动至出击设置 - 增加开荒模式自动启用, 无脑开就完事了 - 将透视识别参数放到了config里, 这样就可以用地图config覆盖了 - 适配小地图模式, 参数抄A1就行了 - 修复了章节名OCR的识别位置 - 修复了开荒会把BOSS当作精英打问题 - 增加战斗中的剧情跳过 - 注释掉了截图和点击的retry - 增加了捕捉目标点超出移动范围 --- assets/handler/MAP_WALK_OUT_OF_STEP.png | Bin 0 -> 7935 bytes assets/{daemon => handler}/STORY_CHOOCE.png | Bin assets/{daemon => handler}/STORY_CHOOCE_2.png | Bin .../{daemon => handler}/STORY_SKIP.BUTTON.png | Bin assets/{daemon => handler}/STORY_SKIP.png | Bin assets/map/MAP_PREPARATION_CANCEL.png | Bin 0 -> 5815 bytes .../TEMPLATE_MAP_WALK_OUT_OF_STEP.png | Bin 0 -> 4813 bytes campaign/event_20200423_cn/a1.py | 59 ++++++++++ campaign/event_20200423_cn/a2.py | 21 ++++ campaign/event_20200423_cn/a3.py | 21 ++++ campaign/event_20200423_cn/b1.py | 58 ++++++++++ campaign/event_20200423_cn/b2.py | 25 +++++ campaign/event_20200423_cn/b3.py | 25 +++++ config/template.ini | 6 +- module/base/ocr.py | 2 +- module/campaign/campaign_base.py | 13 ++- module/campaign/campaign_ocr.py | 2 +- module/campaign/run.py | 2 +- module/combat/combat.py | 8 +- module/config/argparser.py | 12 +- module/config/config.py | 31 +++--- module/config/dictionary.py | 6 +- module/daemon/assets.py | 3 - module/daemon/daemon.py | 13 +-- module/device/control.py | 4 +- module/device/screenshot.py | 2 +- module/handler/ambush.py | 17 ++- module/handler/assets.py | 4 + module/handler/enemy_searching.py | 9 +- module/handler/fast_forward.py | 28 ++++- module/handler/story.py | 22 ++++ module/map/assets.py | 1 + module/map/camera.py | 40 +++++-- module/map/exception.py | 4 + module/map/fleet.py | 103 +++++++++++++----- module/map/grids.py | 3 + module/map/map.py | 19 ++-- module/map/map_base.py | 3 +- module/map/map_operation.py | 29 ++++- module/map/perspective.py | 21 ++-- module/reward/reward.py | 3 + module/template/assets.py | 1 + 42 files changed, 507 insertions(+), 113 deletions(-) create mode 100644 assets/handler/MAP_WALK_OUT_OF_STEP.png rename assets/{daemon => handler}/STORY_CHOOCE.png (100%) rename assets/{daemon => handler}/STORY_CHOOCE_2.png (100%) rename assets/{daemon => handler}/STORY_SKIP.BUTTON.png (100%) rename assets/{daemon => handler}/STORY_SKIP.png (100%) create mode 100644 assets/map/MAP_PREPARATION_CANCEL.png create mode 100644 assets/template/TEMPLATE_MAP_WALK_OUT_OF_STEP.png create mode 100644 campaign/event_20200423_cn/a1.py create mode 100644 campaign/event_20200423_cn/a2.py create mode 100644 campaign/event_20200423_cn/a3.py create mode 100644 campaign/event_20200423_cn/b1.py create mode 100644 campaign/event_20200423_cn/b2.py create mode 100644 campaign/event_20200423_cn/b3.py create mode 100644 module/handler/story.py diff --git a/assets/handler/MAP_WALK_OUT_OF_STEP.png b/assets/handler/MAP_WALK_OUT_OF_STEP.png new file mode 100644 index 0000000000000000000000000000000000000000..8af403340dd2827b69db474459b434ca7a6efc7f GIT binary patch literal 7935 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 Wdnv4{j-CH#yQ^b#yIjlu<^KVKEuQ}X literal 0 HcmV?d00001 diff --git a/assets/daemon/STORY_CHOOCE.png b/assets/handler/STORY_CHOOCE.png similarity index 100% rename from assets/daemon/STORY_CHOOCE.png rename to assets/handler/STORY_CHOOCE.png diff --git a/assets/daemon/STORY_CHOOCE_2.png b/assets/handler/STORY_CHOOCE_2.png similarity index 100% rename from assets/daemon/STORY_CHOOCE_2.png rename to assets/handler/STORY_CHOOCE_2.png diff --git a/assets/daemon/STORY_SKIP.BUTTON.png b/assets/handler/STORY_SKIP.BUTTON.png similarity index 100% rename from assets/daemon/STORY_SKIP.BUTTON.png rename to assets/handler/STORY_SKIP.BUTTON.png diff --git a/assets/daemon/STORY_SKIP.png b/assets/handler/STORY_SKIP.png similarity index 100% rename from assets/daemon/STORY_SKIP.png rename to assets/handler/STORY_SKIP.png diff --git a/assets/map/MAP_PREPARATION_CANCEL.png b/assets/map/MAP_PREPARATION_CANCEL.png new file mode 100644 index 0000000000000000000000000000000000000000..269bb33d1c85a95aabfe9d06bad12fe2a0b2d492 GIT binary patch literal 5815 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 literal 0 HcmV?d00001 diff --git a/assets/template/TEMPLATE_MAP_WALK_OUT_OF_STEP.png b/assets/template/TEMPLATE_MAP_WALK_OUT_OF_STEP.png new file mode 100644 index 0000000000000000000000000000000000000000..b9d6d2019a6d8b35fd82ba46ff09de503bf82ce6 GIT binary patch literal 4813 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 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.') diff --git a/module/campaign/campaign_ocr.py b/module/campaign/campaign_ocr.py index 9263c60e7..e5fa445b0 100644 --- a/module/campaign/campaign_ocr.py +++ b/module/campaign/campaign_ocr.py @@ -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])) diff --git a/module/campaign/run.py b/module/campaign/run.py index 1d74394f3..457d4f8a2 100644 --- a/module/campaign/run.py +++ b/module/campaign/run.py @@ -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(): diff --git a/module/combat/combat.py b/module/combat/combat.py index d6ae545ee..e2f56d2ad 100644 --- a/module/combat/combat.py +++ b/module/combat/combat.py @@ -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: diff --git a/module/config/argparser.py b/module/config/argparser.py index aa4d77028..9d642d211 100644 --- a/module/config/argparser.py +++ b/module/config/argparser.py @@ -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'], diff --git a/module/config/config.py b/module/config/config.py index bb8bb2bd0..a90b1f242 100644 --- a/module/config/config.py +++ b/module/config/config.py @@ -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']: diff --git a/module/config/dictionary.py b/module/config/dictionary.py index 4e2faab29..763da5b4f 100644 --- a/module/config/dictionary.py +++ b/module/config/dictionary.py @@ -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', diff --git a/module/daemon/assets.py b/module/daemon/assets.py index d4d275f55..3ce3c9bab 100644 --- a/module/daemon/assets.py +++ b/module/daemon/assets.py @@ -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') diff --git a/module/daemon/daemon.py b/module/daemon/daemon.py index 903d508c3..ca3694c27 100644 --- a/module/daemon/daemon.py +++ b/module/daemon/daemon.py @@ -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. diff --git a/module/device/control.py b/module/device/control.py index 665868c6a..d27822784 100644 --- a/module/device/control.py +++ b/module/device/control.py @@ -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) diff --git a/module/device/screenshot.py b/module/device/screenshot.py index 4b37e5817..197364ac1 100644 --- a/module/device/screenshot.py +++ b/module/device/screenshot.py @@ -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): """ diff --git a/module/handler/ambush.py b/module/handler/ambush.py index 734084f4e..3998f8a36 100644 --- a/module/handler/ambush.py +++ b/module/handler/ambush.py @@ -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 diff --git a/module/handler/assets.py b/module/handler/assets.py index f1ff4cec7..4c2f50149 100644 --- a/module/handler/assets.py +++ b/module/handler/assets.py @@ -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') diff --git a/module/handler/enemy_searching.py b/module/handler/enemy_searching.py index 0aa475faf..0cecf7fad 100644 --- a/module/handler/enemy_searching.py +++ b/module/handler/enemy_searching.py @@ -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) diff --git a/module/handler/fast_forward.py b/module/handler/fast_forward.py index d36ab536d..94c423311 100644 --- a/module/handler/fast_forward.py +++ b/module/handler/fast_forward.py @@ -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 diff --git a/module/handler/story.py b/module/handler/story.py new file mode 100644 index 000000000..72d9ee3a6 --- /dev/null +++ b/module/handler/story.py @@ -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() \ No newline at end of file diff --git a/module/map/assets.py b/module/map/assets.py index e2fd15de2..7d57a186c 100644 --- a/module/map/assets.py +++ b/module/map/assets.py @@ -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') diff --git a/module/map/camera.py b/module/map/camera.py index 58e98ddac..e8bc3385b 100644 --- a/module/map/camera.py +++ b/module/map/camera.py @@ -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]: diff --git a/module/map/exception.py b/module/map/exception.py index 81f73a238..2340cc5c1 100644 --- a/module/map/exception.py +++ b/module/map/exception.py @@ -6,6 +6,10 @@ class PerspectiveError(Exception): pass +class MapWalkError(Exception): + pass + + class ScriptError(Exception): pass diff --git a/module/map/fleet.py b/module/map/fleet.py index b658a30d7..68b011692 100644 --- a/module/map/fleet.py +++ b/module/map/fleet.py @@ -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 diff --git a/module/map/grids.py b/module/map/grids.py index 67118cc17..d64f5485e 100644 --- a/module/map/grids.py +++ b/module/map/grids.py @@ -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 diff --git a/module/map/map.py b/module/map/map.py index bcfe56b4d..333239923 100644 --- a/module/map/map.py +++ b/module/map/map.py @@ -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) diff --git a/module/map/map_base.py b/module/map/map_base.py index 2320ad92b..8e9d852e3 100644 --- a/module/map/map_base.py +++ b/module/map/map_base.py @@ -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: diff --git a/module/map/map_operation.py b/module/map/map_operation.py index 352ae7089..b39b49c9c 100644 --- a/module/map/map_operation.py +++ b/module/map/map_operation.py @@ -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. diff --git a/module/map/perspective.py b/module/map/perspective.py index 406431a10..b3ad08ead 100644 --- a/module/map/perspective.py +++ b/module/map/perspective.py @@ -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)] diff --git a/module/reward/reward.py b/module/reward/reward.py index ca8320ee6..1c2655066 100644 --- a/module/reward/reward.py +++ b/module/reward/reward.py @@ -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 diff --git a/module/template/assets.py b/module/template/assets.py index 4fbb536b4..411b9b842 100644 --- a/module/template/assets.py +++ b/module/template/assets.py @@ -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')