mirror of
https://gitee.com/sui-feng-cb/AzurLaneAutoScript1
synced 2026-06-03 15:30:14 +08:00
Merge pull request #117 from LmeSzinc/dev
Opt: Different grid.cost for different fleet
This commit is contained in:
@@ -49,7 +49,7 @@ class Campaign(CampaignBase, HardEquipment):
|
|||||||
# logger.info('Grids: %s' % grids)
|
# logger.info('Grids: %s' % grids)
|
||||||
if grids:
|
if grids:
|
||||||
logger.hr('Clear BOSS')
|
logger.hr('Clear BOSS')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grids: %s' % str(grids))
|
logger.info('Grids: %s' % str(grids))
|
||||||
self._goto(grids[0], expected='boss')
|
self._goto(grids[0], expected='boss')
|
||||||
raise CampaignEnd('BOSS Clear.')
|
raise CampaignEnd('BOSS Clear.')
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ A7, B7, C7, D7, E7, F7, G7, H7, I7, \
|
|||||||
class Config:
|
class Config:
|
||||||
SUBMARINE = 0
|
SUBMARINE = 0
|
||||||
|
|
||||||
POOR_MAP_DATA = True
|
# POOR_MAP_DATA = True
|
||||||
MAP_HAS_AMBUSH = False
|
MAP_HAS_AMBUSH = False
|
||||||
MAP_HAS_FLEET_STEP = True
|
MAP_HAS_FLEET_STEP = True
|
||||||
MAP_HAS_MOVABLE_ENEMY = True
|
MAP_HAS_MOVABLE_ENEMY = True
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ A8, B8, C8, D8, E8, F8, G8, H8, I8, \
|
|||||||
class Config:
|
class Config:
|
||||||
SUBMARINE = 0
|
SUBMARINE = 0
|
||||||
|
|
||||||
POOR_MAP_DATA = True
|
# POOR_MAP_DATA = True
|
||||||
MAP_HAS_AMBUSH = False
|
MAP_HAS_AMBUSH = False
|
||||||
MAP_HAS_FLEET_STEP = True
|
MAP_HAS_FLEET_STEP = True
|
||||||
MAP_HAS_MOVABLE_ENEMY = True
|
MAP_HAS_MOVABLE_ENEMY = True
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ A7, B7, C7, D7, E7, F7, G7, H7, I7, \
|
|||||||
class Config:
|
class Config:
|
||||||
SUBMARINE = 0
|
SUBMARINE = 0
|
||||||
|
|
||||||
POOR_MAP_DATA = True
|
# POOR_MAP_DATA = True
|
||||||
MAP_HAS_AMBUSH = False
|
MAP_HAS_AMBUSH = False
|
||||||
MAP_HAS_FLEET_STEP = True
|
MAP_HAS_FLEET_STEP = True
|
||||||
MAP_HAS_MOVABLE_ENEMY = True
|
MAP_HAS_MOVABLE_ENEMY = True
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ A8, B8, C8, D8, E8, F8, G8, H8, I8, \
|
|||||||
class Config:
|
class Config:
|
||||||
SUBMARINE = 0
|
SUBMARINE = 0
|
||||||
|
|
||||||
POOR_MAP_DATA = True
|
# POOR_MAP_DATA = True
|
||||||
MAP_HAS_AMBUSH = False
|
MAP_HAS_AMBUSH = False
|
||||||
MAP_HAS_FLEET_STEP = True
|
MAP_HAS_FLEET_STEP = True
|
||||||
MAP_HAS_MOVABLE_ENEMY = True
|
MAP_HAS_MOVABLE_ENEMY = True
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ A10, B10, C10, D10, E10, F10, G10, H10, I10, J10, K10, L10, M10, \
|
|||||||
class Config:
|
class Config:
|
||||||
SUBMARINE = 0
|
SUBMARINE = 0
|
||||||
|
|
||||||
POOR_MAP_DATA = True
|
# POOR_MAP_DATA = True
|
||||||
MAP_HAS_AMBUSH = False
|
MAP_HAS_AMBUSH = False
|
||||||
MAP_HAS_FLEET_STEP = True
|
MAP_HAS_FLEET_STEP = True
|
||||||
MAP_HAS_MOVABLE_ENEMY = True
|
MAP_HAS_MOVABLE_ENEMY = True
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from module.base.button import Button
|
from module.base.button import Button
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.exception import CampaignEnd
|
from module.exception import CampaignEnd, ScriptError, MapEnemyMoved
|
||||||
from module.exception import ScriptError
|
|
||||||
from module.map.map import Map
|
from module.map.map import Map
|
||||||
from module.map.map_base import CampaignMap
|
from module.map.map_base import CampaignMap
|
||||||
from module.base.decorator import Config
|
from module.base.decorator import Config
|
||||||
@@ -27,9 +26,8 @@ class CampaignBase(Map):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@Config.when(POOR_MAP_DATA=True, MAP_CLEAR_ALL_THIS_TIME=False)
|
@Config.when(POOR_MAP_DATA=True, MAP_CLEAR_ALL_THIS_TIME=False)
|
||||||
def execute_a_battle(self):
|
def battle_function(self):
|
||||||
logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2)
|
logger.info('Using function: battle_with_poor_map_data')
|
||||||
logger.info('Running with poor map data.')
|
|
||||||
if self.fleet_2_break_siren_caught():
|
if self.fleet_2_break_siren_caught():
|
||||||
return True
|
return True
|
||||||
self.clear_all_mystery()
|
self.clear_all_mystery()
|
||||||
@@ -45,12 +43,10 @@ class CampaignBase(Map):
|
|||||||
return True
|
return True
|
||||||
return self.clear_enemy()
|
return self.clear_enemy()
|
||||||
|
|
||||||
logger.warning('No battle executed.')
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@Config.when(MAP_CLEAR_ALL_THIS_TIME=True)
|
@Config.when(MAP_CLEAR_ALL_THIS_TIME=True)
|
||||||
def execute_a_battle(self):
|
def battle_function(self):
|
||||||
logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2)
|
|
||||||
logger.info('Using function: clear_all')
|
logger.info('Using function: clear_all')
|
||||||
if self.fleet_2_break_siren_caught():
|
if self.fleet_2_break_siren_caught():
|
||||||
return True
|
return True
|
||||||
@@ -60,7 +56,7 @@ class CampaignBase(Map):
|
|||||||
self.pick_up_ammo()
|
self.pick_up_ammo()
|
||||||
|
|
||||||
remain = self.map.select(is_enemy=True, is_boss=False)
|
remain = self.map.select(is_enemy=True, is_boss=False)
|
||||||
logger.info('Enemy remain: {}')
|
logger.info(f'Enemy remain: {remain}')
|
||||||
if remain.count > 0:
|
if remain.count > 0:
|
||||||
if self.clear_siren():
|
if self.clear_siren():
|
||||||
return True
|
return True
|
||||||
@@ -74,18 +70,35 @@ class CampaignBase(Map):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
@Config.when(MAP_CLEAR_ALL_THIS_TIME=False, POOR_MAP_DATA=False)
|
@Config.when(MAP_CLEAR_ALL_THIS_TIME=False, POOR_MAP_DATA=False)
|
||||||
def execute_a_battle(self):
|
def battle_function(self):
|
||||||
func = self.FUNCTION_NAME_BASE + 'default'
|
func = self.FUNCTION_NAME_BASE + 'default'
|
||||||
for extra_battle in range(10):
|
for extra_battle in range(10):
|
||||||
if hasattr(self, self.FUNCTION_NAME_BASE + str(self.battle_count - extra_battle)):
|
if hasattr(self, self.FUNCTION_NAME_BASE + str(self.battle_count - extra_battle)):
|
||||||
func = self.FUNCTION_NAME_BASE + str(self.battle_count - extra_battle)
|
func = self.FUNCTION_NAME_BASE + str(self.battle_count - extra_battle)
|
||||||
break
|
break
|
||||||
|
|
||||||
logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2)
|
|
||||||
logger.info(f'Using function: {func}')
|
logger.info(f'Using function: {func}')
|
||||||
func = self.__getattribute__(func)
|
func = self.__getattribute__(func)
|
||||||
|
|
||||||
result = func()
|
result = func()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def execute_a_battle(self):
|
||||||
|
logger.hr(f'{self.FUNCTION_NAME_BASE}{self.battle_count}', level=2)
|
||||||
|
prev = self.battle_count
|
||||||
|
result = False
|
||||||
|
for _ in range(10):
|
||||||
|
try:
|
||||||
|
result = self.battle_function()
|
||||||
|
break
|
||||||
|
except MapEnemyMoved:
|
||||||
|
if self.battle_count > prev:
|
||||||
|
result = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
logger.warning('ScriptError, No combat executed.')
|
logger.warning('ScriptError, No combat executed.')
|
||||||
if self.config.ENABLE_EXCEPTION:
|
if self.config.ENABLE_EXCEPTION:
|
||||||
@@ -105,7 +118,7 @@ class CampaignBase(Map):
|
|||||||
self.handle_fleet_reverse()
|
self.handle_fleet_reverse()
|
||||||
self.map_init(self.MAP)
|
self.map_init(self.MAP)
|
||||||
|
|
||||||
for _ in range(50):
|
for _ in range(20):
|
||||||
try:
|
try:
|
||||||
self.execute_a_battle()
|
self.execute_a_battle()
|
||||||
except CampaignEnd:
|
except CampaignEnd:
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ class AzurLaneConfig:
|
|||||||
|
|
||||||
USING_SPARE_FLEET = False
|
USING_SPARE_FLEET = False
|
||||||
|
|
||||||
|
MOVABLE_ENEMY_FLEET_STEP = 2
|
||||||
|
MOVABLE_ENEMY_TURN = 2
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def FLEET_1(self):
|
def FLEET_1(self):
|
||||||
return self.FLEET_3 if self.USING_SPARE_FLEET else self._FLEET_1
|
return self.FLEET_3 if self.USING_SPARE_FLEET else self._FLEET_1
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from retrying import retry
|
|||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.base.utils import *
|
from module.base.utils import *
|
||||||
from module.device.connection import Connection
|
from module.device.connection import Connection
|
||||||
from module.exception import ScriptError
|
from module.exception import GameTooManyClickError
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class Control(Connection):
|
|||||||
if sum([1 if str(prev) == str(button) else 0 for prev in self.click_record]) >= 12:
|
if sum([1 if str(prev) == str(button) else 0 for prev in self.click_record]) >= 12:
|
||||||
logger.warning(f'Too many click for a button: {button}')
|
logger.warning(f'Too many click for a button: {button}')
|
||||||
logger.info(f'History click: {[str(prev) for prev in self.click_record]}')
|
logger.info(f'History click: {[str(prev) for prev in self.click_record]}')
|
||||||
raise ScriptError(f'Too many click for a button: {button}')
|
raise GameTooManyClickError(f'Too many click for a button: {button}')
|
||||||
else:
|
else:
|
||||||
self.click_record.append(str(button))
|
self.click_record.append(str(button))
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ class MapWalkError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MapEnemyMoved(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CampaignNameError(Exception):
|
class CampaignNameError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -26,5 +30,9 @@ class GameStuckError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GameTooManyClickError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class GameNotRunningError(Exception):
|
class GameNotRunningError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ class InfoHandler(ModuleBase):
|
|||||||
if self.story_popup_timout.started() and not self.story_popup_timout.reached():
|
if self.story_popup_timout.started() and not self.story_popup_timout.reached():
|
||||||
if self.handle_popup_confirm('STORY_SKIP'):
|
if self.handle_popup_confirm('STORY_SKIP'):
|
||||||
self.story_popup_timout = Timer(10)
|
self.story_popup_timout = Timer(10)
|
||||||
|
self.interval_reset(STORY_SKIP)
|
||||||
|
self.interval_reset(STORY_LETTERS_ONLY)
|
||||||
return True
|
return True
|
||||||
if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
|
if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
|
||||||
self.story_popup_timout.reset()
|
self.story_popup_timout.reset()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.combat.combat import Combat
|
from module.combat.combat import Combat
|
||||||
|
from module.exception import GameTooManyClickError, ScriptError
|
||||||
from module.handler.assets import *
|
from module.handler.assets import *
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.map.assets import *
|
from module.map.assets import *
|
||||||
@@ -10,7 +11,12 @@ from module.ui.ui import MAIN_CHECK
|
|||||||
|
|
||||||
|
|
||||||
class LoginHandler(Combat):
|
class LoginHandler(Combat):
|
||||||
def handle_app_login(self):
|
def _handle_app_login(self):
|
||||||
|
"""
|
||||||
|
Pages:
|
||||||
|
in: Any page
|
||||||
|
out: page_main
|
||||||
|
"""
|
||||||
logger.hr('App login')
|
logger.hr('App login')
|
||||||
|
|
||||||
confirm_timer = Timer(1.5, count=4).start()
|
confirm_timer = Timer(1.5, count=4).start()
|
||||||
@@ -54,6 +60,27 @@ class LoginHandler(Combat):
|
|||||||
self.config.start_time = datetime.now()
|
self.config.start_time = datetime.now()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def handle_app_login(self):
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
bool: If login success
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ScriptError: If login failed more than 3
|
||||||
|
"""
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
self._handle_app_login()
|
||||||
|
return True
|
||||||
|
except GameTooManyClickError as e:
|
||||||
|
logger.warning(e)
|
||||||
|
self.device.app_stop()
|
||||||
|
self.device.app_start()
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.warning('Login failed more than 3')
|
||||||
|
raise ScriptError('Login failed more than 3')
|
||||||
|
|
||||||
def app_restart(self):
|
def app_restart(self):
|
||||||
logger.hr('App restart')
|
logger.hr('App restart')
|
||||||
self.device.app_stop()
|
self.device.app_stop()
|
||||||
|
|||||||
@@ -190,27 +190,32 @@ class Camera(InfoHandler):
|
|||||||
if np.all(np.abs(vector) <= 0):
|
if np.all(np.abs(vector) <= 0):
|
||||||
break
|
break
|
||||||
|
|
||||||
def full_scan(self, battle_count=0, mystery_count=0, siren_count=0, carrier_count=0, mode='normal'):
|
|
||||||
"""Scan the hole map.
|
def full_scan(self, queue=None, must_scan=None, battle_count=0, mystery_count=0, siren_count=0, carrier_count=0,
|
||||||
|
mode='normal'):
|
||||||
|
"""Scan the whole map.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
queue (SelectedGrids): Grids to focus on. If none, use map.camera_data
|
||||||
|
must_scan (SelectedGrids): Must scan these grids
|
||||||
battle_count:
|
battle_count:
|
||||||
mystery_count:
|
mystery_count:
|
||||||
siren_count:
|
siren_count:
|
||||||
carrier_count:
|
carrier_count:
|
||||||
mode (str): Scan mode, such as 'normal', 'carrier', 'move'
|
mode (str): Scan mode, such as 'normal', 'carrier', 'movable'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
logger.info('Full scan start')
|
logger.info('Full scan start')
|
||||||
self.map.reset_fleet()
|
self.map.reset_fleet()
|
||||||
|
|
||||||
queue = self.map.camera_data
|
queue = queue if queue else self.map.camera_data
|
||||||
if battle_count == 0:
|
if must_scan:
|
||||||
queue = queue.add(self.map.camera_data_spawn_point)
|
queue = queue.add(must_scan)
|
||||||
|
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
if self.map.missing_is_none(battle_count, mystery_count, siren_count, carrier_count):
|
if self.map.missing_is_none(battle_count, mystery_count, siren_count, carrier_count):
|
||||||
if battle_count == 0 and queue.count != queue.delete(self.map.camera_data_spawn_point).count:
|
if must_scan and queue.count != queue.delete(must_scan).count:
|
||||||
logger.info('Continue scanning spawn points.')
|
logger.info('Continue scanning.')
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.info('All spawn found, Early stopped.')
|
logger.info('All spawn found, Early stopped.')
|
||||||
@@ -226,8 +231,8 @@ class Camera(InfoHandler):
|
|||||||
|
|
||||||
queue = queue[1:]
|
queue = queue[1:]
|
||||||
|
|
||||||
if battle_count is not None:
|
self.map.missing_predict(battle_count, mystery_count, siren_count, carrier_count)
|
||||||
self.map.missing_predict(battle_count, mystery_count, siren_count, carrier_count)
|
|
||||||
|
|
||||||
self.map.show()
|
self.map.show()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import itertools
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.exception import MapWalkError
|
from module.exception import MapWalkError, MapEnemyMoved
|
||||||
from module.handler.ambush import AmbushHandler
|
from module.handler.ambush import AmbushHandler
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.map.camera import Camera
|
from module.map.camera import Camera
|
||||||
@@ -85,6 +85,71 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
def switch_to(self):
|
def switch_to(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
round = 0
|
||||||
|
enemy_round = {}
|
||||||
|
|
||||||
|
def round_next(self):
|
||||||
|
"""
|
||||||
|
Call this method after fleet arrived.
|
||||||
|
"""
|
||||||
|
if not self.config.MAP_HAS_MOVABLE_ENEMY:
|
||||||
|
return False
|
||||||
|
self.round += 1
|
||||||
|
logger.info(f'Round: {self.round}, enemy_round: {self.enemy_round}')
|
||||||
|
|
||||||
|
def round_battle(self):
|
||||||
|
"""
|
||||||
|
Call this method after cleared an enemy.
|
||||||
|
"""
|
||||||
|
if not self.config.MAP_HAS_MOVABLE_ENEMY:
|
||||||
|
return False
|
||||||
|
if not self.map.select(is_siren=True):
|
||||||
|
self.enemy_round = {}
|
||||||
|
try:
|
||||||
|
data = self.map.spawn_data[self.battle_count]
|
||||||
|
except IndexError:
|
||||||
|
data = {}
|
||||||
|
enemy = data.get('siren', 0)
|
||||||
|
if enemy > 0:
|
||||||
|
r = self.round % self.config.MOVABLE_ENEMY_TURN
|
||||||
|
self.enemy_round[r] = self.enemy_round.get(r, 0) + enemy
|
||||||
|
|
||||||
|
def round_reset(self):
|
||||||
|
"""
|
||||||
|
Call this method after entering map.
|
||||||
|
"""
|
||||||
|
self.round = 0
|
||||||
|
self.enemy_round = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def round_is_new(self):
|
||||||
|
"""
|
||||||
|
Usually, MOVABLE_ENEMY_TURN = 2.
|
||||||
|
So a walk round is `player - player - enemy`, player moves twice, enemy moves once.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: If it's a new walk round, which means enemies have moved.
|
||||||
|
"""
|
||||||
|
if not self.config.MAP_HAS_MOVABLE_ENEMY:
|
||||||
|
return False
|
||||||
|
r = self.round % self.config.MOVABLE_ENEMY_TURN
|
||||||
|
if r in self.enemy_round:
|
||||||
|
logger.info('Enemy moved')
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def round_wait(self):
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
float: Seconds to wait enemies moving.
|
||||||
|
"""
|
||||||
|
if not self.config.MAP_HAS_MOVABLE_ENEMY:
|
||||||
|
return 0
|
||||||
|
r = (self.round + 1) % self.config.MOVABLE_ENEMY_TURN
|
||||||
|
return self.enemy_round.get(r, 0) * self.config.MAP_SIREN_MOVE_WAIT
|
||||||
|
|
||||||
def _goto(self, location, expected=''):
|
def _goto(self, location, expected=''):
|
||||||
"""Goto a grid directly and handle ambush, air raid, mystery picked up, combat.
|
"""Goto a grid directly and handle ambush, air raid, mystery picked up, combat.
|
||||||
|
|
||||||
@@ -92,7 +157,6 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
location (tuple, str, GridInfo): Destination.
|
location (tuple, str, GridInfo): Destination.
|
||||||
"""
|
"""
|
||||||
location = location_ensure(location)
|
location = location_ensure(location)
|
||||||
siren_count = self.map.select(is_siren=True).count
|
|
||||||
result_mystery = ''
|
result_mystery = ''
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
@@ -108,10 +172,8 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
self.device.click(grid)
|
self.device.click(grid)
|
||||||
arrived = False
|
arrived = False
|
||||||
# Wait to confirm fleet arrived. It does't appear immediately if fleet in combat .
|
# Wait to confirm fleet arrived. It does't appear immediately if fleet in combat .
|
||||||
add = self.config.MAP_SIREN_MOVE_WAIT * min(self.config.MAP_SIREN_COUNT, siren_count) \
|
arrive_timer = Timer(0.5 + self.round_wait, count=2)
|
||||||
if self.config.MAP_HAS_MOVABLE_ENEMY and not self.config.ENABLE_FAST_FORWARD else 0
|
arrive_unexpected_timer = Timer(1.5 + self.round_wait, count=6)
|
||||||
arrive_timer = Timer(0.5 + add, count=2)
|
|
||||||
arrive_unexpected_timer = Timer(1.5 + add, count=6)
|
|
||||||
# Wait after ambushed.
|
# Wait after ambushed.
|
||||||
ambushed_retry = Timer(0.5)
|
ambushed_retry = Timer(0.5)
|
||||||
# If nothing happens, click again.
|
# If nothing happens, click again.
|
||||||
@@ -125,6 +187,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
# Ambush
|
# Ambush
|
||||||
if self.handle_ambush():
|
if self.handle_ambush():
|
||||||
ambushed_retry.start()
|
ambushed_retry.start()
|
||||||
|
walk_timeout.reset()
|
||||||
|
|
||||||
# Mystery
|
# Mystery
|
||||||
mystery = self.handle_mystery(button=grid)
|
mystery = self.handle_mystery(button=grid)
|
||||||
@@ -149,7 +212,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
result = 'combat'
|
result = 'combat'
|
||||||
self.battle_count += 1
|
self.battle_count += 1
|
||||||
self.fleet_ammo -= 1
|
self.fleet_ammo -= 1
|
||||||
if 'siren' in expected:
|
if 'siren' in expected or (self.config.MAP_HAS_MOVABLE_ENEMY and not expected):
|
||||||
self.siren_count += 1
|
self.siren_count += 1
|
||||||
elif self.map[location].may_enemy:
|
elif self.map[location].may_enemy:
|
||||||
self.map[location].is_cleared = True
|
self.map[location].is_cleared = True
|
||||||
@@ -205,7 +268,14 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
self.map[location].is_fleet = True
|
self.map[location].is_fleet = True
|
||||||
self.__setattr__('fleet_%s_location' % self.fleet_current_index, location)
|
self.__setattr__('fleet_%s_location' % self.fleet_current_index, location)
|
||||||
if result_mystery == 'get_carrier':
|
if result_mystery == 'get_carrier':
|
||||||
self.full_scan(mode='carrier')
|
self.full_scan_carrier()
|
||||||
|
if result == 'combat':
|
||||||
|
self.round_battle()
|
||||||
|
self.round_next()
|
||||||
|
if self.round_is_new:
|
||||||
|
self.full_scan_movable()
|
||||||
|
self.find_path_initial()
|
||||||
|
raise MapEnemyMoved
|
||||||
self.find_path_initial()
|
self.find_path_initial()
|
||||||
|
|
||||||
def goto(self, location, optimize=True, expected=''):
|
def goto(self, location, optimize=True, expected=''):
|
||||||
@@ -225,20 +295,20 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
else:
|
else:
|
||||||
self._goto(location, expected=expected)
|
self._goto(location, expected=expected)
|
||||||
|
|
||||||
def find_path_initial(self, grid=None):
|
def find_path_initial(self):
|
||||||
"""
|
"""
|
||||||
Args:
|
Call this method after fleet moved or entered map.
|
||||||
grid (tuple, GridInfo): Current fleet grid
|
|
||||||
"""
|
"""
|
||||||
if grid is None:
|
|
||||||
grid = self.fleet_current
|
|
||||||
else:
|
|
||||||
grid = location_ensure(grid)
|
|
||||||
if self.fleet_1_location:
|
if self.fleet_1_location:
|
||||||
self.map[self.fleet_1_location].is_fleet = True
|
self.map[self.fleet_1_location].is_fleet = True
|
||||||
if self.fleet_2_location:
|
if self.fleet_2_location:
|
||||||
self.map[self.fleet_2_location].is_fleet = True
|
self.map[self.fleet_2_location].is_fleet = True
|
||||||
self.map.find_path_initial(grid, has_ambush=self.config.MAP_HAS_AMBUSH)
|
location_dict = {}
|
||||||
|
if self.config.FLEET_2:
|
||||||
|
location_dict[2] = self.fleet_2_location
|
||||||
|
location_dict[1] = self.fleet_1_location
|
||||||
|
self.map.find_path_initial_multi_fleet(
|
||||||
|
location_dict, current=self.fleet_current, has_ambush=self.config.MAP_HAS_AMBUSH)
|
||||||
|
|
||||||
def show_fleet(self):
|
def show_fleet(self):
|
||||||
fleets = []
|
fleets = []
|
||||||
@@ -251,15 +321,10 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
fleets.append(text)
|
fleets.append(text)
|
||||||
logger.info(' '.join(fleets))
|
logger.info(' '.join(fleets))
|
||||||
|
|
||||||
def full_scan(self, mode='normal'):
|
def full_scan(self, queue=None, must_scan=None, mode='normal'):
|
||||||
prev_enemy = self.map.select(is_enemy=True)
|
super().full_scan(
|
||||||
super().full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count,
|
queue=queue, must_scan=must_scan, battle_count=self.battle_count, mystery_count=self.mystery_count,
|
||||||
siren_count=self.siren_count, carrier_count=self.carrier_count,
|
siren_count=self.siren_count, carrier_count=self.carrier_count, mode=mode)
|
||||||
mode=mode)
|
|
||||||
|
|
||||||
if mode == 'carrier':
|
|
||||||
diff = self.map.select(is_enemy=True).delete(prev_enemy)
|
|
||||||
logger.info(f'Carrier spawn: {diff}')
|
|
||||||
|
|
||||||
if self.config.FLEET_2 and not self.fleet_2_location:
|
if self.config.FLEET_2 and not self.fleet_2_location:
|
||||||
fleets = self.map.select(is_fleet=True, is_current_fleet=False)
|
fleets = self.map.select(is_fleet=True, is_current_fleet=False)
|
||||||
@@ -276,6 +341,19 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
else:
|
else:
|
||||||
self.map[loca].wipe_out()
|
self.map[loca].wipe_out()
|
||||||
|
|
||||||
|
def full_scan_carrier(self):
|
||||||
|
prev = self.map.select(is_enemy=True)
|
||||||
|
self.full_scan(mode='carrier')
|
||||||
|
diff = self.map.select(is_enemy=True).delete(prev)
|
||||||
|
logger.info(f'Carrier spawn: {diff}')
|
||||||
|
|
||||||
|
def full_scan_movable(self):
|
||||||
|
prev = self.map.select(is_siren=True)
|
||||||
|
for grid in prev:
|
||||||
|
grid.wipe_out()
|
||||||
|
self.full_scan(queue=prev, must_scan=prev, mode='movable')
|
||||||
|
# after = self.map.select(is_siren=True)
|
||||||
|
|
||||||
def find_all_fleets(self):
|
def find_all_fleets(self):
|
||||||
logger.hr('Find all fleets')
|
logger.hr('Find all fleets')
|
||||||
queue = self.map.select(is_spawn_point=True)
|
queue = self.map.select(is_spawn_point=True)
|
||||||
@@ -373,20 +451,23 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
self.hp_init()
|
self.hp_init()
|
||||||
self.handle_strategy(index=self.fleet_current_index)
|
self.handle_strategy(index=self.fleet_current_index)
|
||||||
self.ensure_edge_insight(preset=self.map.in_map_swipe_preset_data)
|
self.ensure_edge_insight(preset=self.map.in_map_swipe_preset_data)
|
||||||
self.full_scan()
|
self.full_scan(must_scan=self.map.camera_data_spawn_point)
|
||||||
self.find_current_fleet()
|
self.find_current_fleet()
|
||||||
self.find_path_initial()
|
self.find_path_initial()
|
||||||
self.map.show_cost()
|
self.map.show_cost()
|
||||||
|
self.round_reset()
|
||||||
|
self.round_battle()
|
||||||
|
|
||||||
def handle_map_green_config_cover(self):
|
def handle_map_green_config_cover(self):
|
||||||
if not self.is_map_green:
|
if not self.is_map_green:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info('Map is green sea.')
|
logger.info('Map is green sea.')
|
||||||
self.config.MAP_HAS_FLEET_STEP = False
|
|
||||||
self.config.MAP_HAS_MOVABLE_ENEMY = False
|
|
||||||
if self.config.ENABLE_FAST_FORWARD:
|
if self.config.ENABLE_FAST_FORWARD:
|
||||||
self.config.MAP_HAS_AMBUSH = False
|
self.config.MAP_HAS_AMBUSH = False
|
||||||
|
self.config.MAP_HAS_FLEET_STEP = False
|
||||||
|
self.config.MAP_HAS_MOVABLE_ENEMY = False
|
||||||
else:
|
else:
|
||||||
# When disable fast forward, MAP_HAS_AMBUSH depends on map settings.
|
# When disable fast forward, MAP_HAS_AMBUSH depends on map settings.
|
||||||
# self.config.MAP_HAS_AMBUSH = True
|
# self.config.MAP_HAS_AMBUSH = True
|
||||||
@@ -397,7 +478,7 @@ class Fleet(Camera, MapOperation, AmbushHandler):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _expected_combat_end(self, expected):
|
def _expected_combat_end(self, expected):
|
||||||
for data in self.map._spawn_data_backup:
|
for data in self.map.spawn_data:
|
||||||
if data.get('battle') == self.battle_count and 'boss' in expected:
|
if data.get('battle') == self.battle_count and 'boss' in expected:
|
||||||
return 'in_stage'
|
return 'in_stage'
|
||||||
if data.get('battle') == self.battle_count + 1:
|
if data.get('battle') == self.battle_count + 1:
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ class GridInfo:
|
|||||||
is_ambush_save = False
|
is_ambush_save = False
|
||||||
is_caught_by_siren = False
|
is_caught_by_siren = False
|
||||||
cost = 9999
|
cost = 9999
|
||||||
|
cost_1 = 9999
|
||||||
|
cost_2 = 9999
|
||||||
connection = None
|
connection = None
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
@@ -128,6 +130,14 @@ class GridInfo:
|
|||||||
def is_accessible(self):
|
def is_accessible(self):
|
||||||
return self.cost < 9999
|
return self.cost < 9999
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_accessible_1(self):
|
||||||
|
return self.cost_1 < 9999
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_accessible_2(self):
|
||||||
|
return self.cost_2 < 9999
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_nearby(self):
|
def is_nearby(self):
|
||||||
return self.cost < 20
|
return self.cost < 20
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class Map(Fleet):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def select_grids(grids, nearby=False, is_accessible=True, scale=(), genre=(), strongest=False, weakest=False,
|
def select_grids(grids, nearby=False, is_accessible=True, scale=(), genre=(), strongest=False, weakest=False,
|
||||||
cost=True, weight=True, ignore=None):
|
sort=('weight', 'cost'), ignore=None):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
grids (SelectedGrids):
|
grids (SelectedGrids):
|
||||||
@@ -70,8 +70,7 @@ class Map(Fleet):
|
|||||||
genre (tuple[str], list[str]): light, main, carrier, treasure. (Case insensitive).
|
genre (tuple[str], list[str]): light, main, carrier, treasure. (Case insensitive).
|
||||||
strongest (bool):
|
strongest (bool):
|
||||||
weakest (bool):
|
weakest (bool):
|
||||||
cost (bool):
|
sort (tuple(str)):
|
||||||
weight (bool):
|
|
||||||
ignore (SelectedGrids):
|
ignore (SelectedGrids):
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -111,7 +110,7 @@ class Map(Fleet):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if grids:
|
if grids:
|
||||||
grids = grids.sort(cost=cost, weight=weight)
|
grids = grids.sort(*sort)
|
||||||
|
|
||||||
return grids
|
return grids
|
||||||
|
|
||||||
@@ -247,7 +246,7 @@ class Map(Fleet):
|
|||||||
|
|
||||||
if grids:
|
if grids:
|
||||||
logger.hr('Clear BOSS')
|
logger.hr('Clear BOSS')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grids: %s' % str(grids))
|
logger.info('Grids: %s' % str(grids))
|
||||||
self.clear_chosen_enemy(grids[0])
|
self.clear_chosen_enemy(grids[0])
|
||||||
|
|
||||||
@@ -274,7 +273,7 @@ class Map(Fleet):
|
|||||||
|
|
||||||
if grids:
|
if grids:
|
||||||
logger.hr('Clear BOSS')
|
logger.hr('Clear BOSS')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grids: %s' % str(grids))
|
logger.info('Grids: %s' % str(grids))
|
||||||
self.clear_chosen_enemy(grids[0])
|
self.clear_chosen_enemy(grids[0])
|
||||||
|
|
||||||
@@ -291,7 +290,7 @@ class Map(Fleet):
|
|||||||
|
|
||||||
for grid in grids:
|
for grid in grids:
|
||||||
logger.hr('Clear potential BOSS')
|
logger.hr('Clear potential BOSS')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grid: %s' % str(grid))
|
logger.info('Grid: %s' % str(grid))
|
||||||
self.clear_chosen_enemy(grid)
|
self.clear_chosen_enemy(grid)
|
||||||
if self.battle_count > battle_count:
|
if self.battle_count > battle_count:
|
||||||
@@ -316,7 +315,7 @@ class Map(Fleet):
|
|||||||
if self.brute_fleet_meet():
|
if self.brute_fleet_meet():
|
||||||
return True
|
return True
|
||||||
logger.info('Brute clear BOSS roadblocks')
|
logger.info('Brute clear BOSS roadblocks')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grids: %s' % str(grids))
|
logger.info('Grids: %s' % str(grids))
|
||||||
self.clear_chosen_enemy(grids[0])
|
self.clear_chosen_enemy(grids[0])
|
||||||
return True
|
return True
|
||||||
@@ -339,7 +338,7 @@ class Map(Fleet):
|
|||||||
grids = self.brute_find_roadblocks(self.map[self.fleet_2_location], fleet=1)
|
grids = self.brute_find_roadblocks(self.map[self.fleet_2_location], fleet=1)
|
||||||
if grids:
|
if grids:
|
||||||
logger.info('Brute clear roadblocks between fleets.')
|
logger.info('Brute clear roadblocks between fleets.')
|
||||||
grids = grids.sort(cost=True, weight=True)
|
grids = grids.sort('weight', 'cost')
|
||||||
logger.info('Grids: %s' % str(grids))
|
logger.info('Grids: %s' % str(grids))
|
||||||
self.clear_chosen_enemy(grids[0])
|
self.clear_chosen_enemy(grids[0])
|
||||||
return True
|
return True
|
||||||
@@ -354,20 +353,9 @@ class Map(Fleet):
|
|||||||
if not self.config.MAP_HAS_SIREN:
|
if not self.config.MAP_HAS_SIREN:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info('May siren: %s' % self.map.select(may_siren=True))
|
if self.config.FLEET_2:
|
||||||
logger.info('May siren and is enemy: %s' % self.map.select(may_siren=True, is_enemy=True))
|
kwargs['sort'] = ('weight', 'cost_2')
|
||||||
grids = self.map.select(may_siren=True, is_enemy=True)
|
grids = self.map.select(is_siren=True)
|
||||||
|
|
||||||
logger.info('Is siren: %s' % self.map.select(is_siren=True))
|
|
||||||
grids = grids.add(self.map.select(is_siren=True))
|
|
||||||
|
|
||||||
if self.config.POOR_MAP_DATA or not self.is_map_green:
|
|
||||||
logger.info('Is 0 scale enemy: %s' % self.map.select(is_enemy=True, enemy_scale=0))
|
|
||||||
grids = grids.add(self.map.select(is_enemy=True, enemy_scale=0))
|
|
||||||
|
|
||||||
logger.info('Delete is boss: %s' % self.map.select(is_boss=True))
|
|
||||||
grids = grids.delete(self.map.select(is_boss=True))
|
|
||||||
|
|
||||||
grids = self.select_grids(grids, **kwargs)
|
grids = self.select_grids(grids, **kwargs)
|
||||||
|
|
||||||
if grids:
|
if grids:
|
||||||
@@ -453,15 +441,13 @@ class Map(Fleet):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info('Fleet_2 push forward')
|
logger.info('Fleet_2 push forward')
|
||||||
grids = self.map.select(is_land=False).sort(cost=True, weight=True)
|
grids = self.map.select(is_land=False).sort('weight', 'cost')
|
||||||
if self.map[self.fleet_2_location].weight <= grids[0].weight:
|
if self.map[self.fleet_2_location].weight <= grids[0].weight:
|
||||||
logger.info('Fleet_2 pushed to destination')
|
logger.info('Fleet_2 pushed to destination')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.find_path_initial(self.fleet_2_location)
|
|
||||||
fleets = SelectedGrids([self.map[self.fleet_1_location], self.map[self.fleet_2_location]])
|
fleets = SelectedGrids([self.map[self.fleet_1_location], self.map[self.fleet_2_location]])
|
||||||
grids = grids.select(is_accessible=True, is_sea=True).delete(fleets)
|
grids = grids.select(is_accessible_2=True, is_sea=True).delete(fleets)
|
||||||
self.find_path_initial()
|
|
||||||
if not grids:
|
if not grids:
|
||||||
logger.info('Fleet_2 has no where to push')
|
logger.info('Fleet_2 has no where to push')
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class CampaignMap:
|
|||||||
self._wall_data = ''
|
self._wall_data = ''
|
||||||
self._block_data = []
|
self._block_data = []
|
||||||
self._spawn_data = []
|
self._spawn_data = []
|
||||||
self._spawn_data_backup = []
|
self._spawn_data_stack = []
|
||||||
self._camera_data = []
|
self._camera_data = []
|
||||||
self._camera_data_spawn_point = []
|
self._camera_data_spawn_point = []
|
||||||
self.in_map_swipe_preset_data = None
|
self.in_map_swipe_preset_data = None
|
||||||
@@ -177,7 +177,7 @@ class CampaignMap:
|
|||||||
Args:
|
Args:
|
||||||
grids:
|
grids:
|
||||||
camera (tuple):
|
camera (tuple):
|
||||||
mode (str): Scan mode, such as 'normal', 'carrier', 'move'
|
mode (str): Scan mode, such as 'normal', 'carrier', 'movable'
|
||||||
"""
|
"""
|
||||||
offset = np.array(camera) - np.array(grids.center_loca)
|
offset = np.array(camera) - np.array(grids.center_loca)
|
||||||
grids.show()
|
grids.show()
|
||||||
@@ -247,7 +247,7 @@ class CampaignMap:
|
|||||||
|
|
||||||
@spawn_data.setter
|
@spawn_data.setter
|
||||||
def spawn_data(self, data_list):
|
def spawn_data(self, data_list):
|
||||||
self._spawn_data_backup = data_list
|
self._spawn_data = data_list
|
||||||
spawn = {'battle': 0, 'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0}
|
spawn = {'battle': 0, 'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0}
|
||||||
for data in data_list:
|
for data in data_list:
|
||||||
spawn['battle'] = data['battle']
|
spawn['battle'] = data['battle']
|
||||||
@@ -255,7 +255,11 @@ class CampaignMap:
|
|||||||
spawn['mystery'] += data.get('mystery', 0)
|
spawn['mystery'] += data.get('mystery', 0)
|
||||||
spawn['siren'] += data.get('siren', 0)
|
spawn['siren'] += data.get('siren', 0)
|
||||||
spawn['boss'] += data.get('boss', 0)
|
spawn['boss'] += data.get('boss', 0)
|
||||||
self._spawn_data.append(spawn.copy())
|
self._spawn_data_stack.append(spawn.copy())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def spawn_data_stack(self):
|
||||||
|
return self._spawn_data_stack
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def weight_data(self):
|
def weight_data(self):
|
||||||
@@ -271,7 +275,7 @@ class CampaignMap:
|
|||||||
def is_map_data_poor(self):
|
def is_map_data_poor(self):
|
||||||
if not self.select(may_enemy=True) or not self.select(may_boss=True) or not self.select(is_spawn_point=True):
|
if not self.select(may_enemy=True) or not self.select(may_boss=True) or not self.select(is_spawn_point=True):
|
||||||
return False
|
return False
|
||||||
if not len(self._spawn_data_backup):
|
if not len(self.spawn_data):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -291,8 +295,12 @@ class CampaignMap:
|
|||||||
logger.info(text)
|
logger.info(text)
|
||||||
|
|
||||||
def find_path_initial(self, location, has_ambush=True):
|
def find_path_initial(self, location, has_ambush=True):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
location (tuple(int)): Grid location
|
||||||
|
has_ambush (bool): MAP_HAS_AMBUSH
|
||||||
|
"""
|
||||||
location = location_ensure(location)
|
location = location_ensure(location)
|
||||||
|
|
||||||
ambush_cost = 10 if has_ambush else 1
|
ambush_cost = 10 if has_ambush else 1
|
||||||
for grid in self:
|
for grid in self:
|
||||||
grid.cost = 9999
|
grid.cost = 9999
|
||||||
@@ -326,9 +334,22 @@ class CampaignMap:
|
|||||||
# self.show_cost()
|
# self.show_cost()
|
||||||
# self.show_connection()
|
# self.show_connection()
|
||||||
|
|
||||||
|
def find_path_initial_multi_fleet(self, location_dict, current, has_ambush):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
location_dict (dict): Key: int, fleet index. Value: tuple(int), grid location.
|
||||||
|
current (tuple): Current location.
|
||||||
|
has_ambush (bool): MAP_HAS_AMBUSH
|
||||||
|
"""
|
||||||
|
location_dict = sorted(location_dict.items(), key=lambda kv: (int(kv[1] == current),))
|
||||||
|
for fleet, location in location_dict:
|
||||||
|
self.find_path_initial(location, has_ambush=has_ambush)
|
||||||
|
attr = f'cost_{fleet}'
|
||||||
|
for grid in self:
|
||||||
|
grid.__setattr__(attr, grid.cost)
|
||||||
|
|
||||||
def _find_path(self, location):
|
def _find_path(self, location):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
location (tuple):
|
location (tuple):
|
||||||
|
|
||||||
@@ -364,7 +385,6 @@ class CampaignMap:
|
|||||||
|
|
||||||
def _find_route_node(self, route, step=0):
|
def _find_route_node(self, route, step=0):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
route (list[tuple]): list of grids.
|
route (list[tuple]): list of grids.
|
||||||
step (int): Fleet step in event map. Default to 0.
|
step (int): Fleet step in event map. Default to 0.
|
||||||
@@ -443,9 +463,9 @@ class CampaignMap:
|
|||||||
|
|
||||||
def missing_get(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
|
def missing_get(self, battle_count, mystery_count=0, siren_count=0, carrier_count=0):
|
||||||
try:
|
try:
|
||||||
missing = self.spawn_data[battle_count].copy()
|
missing = self.spawn_data_stack[battle_count].copy()
|
||||||
except IndexError:
|
except IndexError:
|
||||||
missing = self.spawn_data[-1].copy()
|
missing = self.spawn_data_stack[-1].copy()
|
||||||
may = {'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0, 'carrier': 0}
|
may = {'enemy': 0, 'mystery': 0, 'siren': 0, 'boss': 0, 'carrier': 0}
|
||||||
missing['enemy'] -= battle_count - siren_count
|
missing['enemy'] -= battle_count - siren_count
|
||||||
missing['mystery'] -= mystery_count
|
missing['mystery'] -= mystery_count
|
||||||
@@ -453,7 +473,7 @@ class CampaignMap:
|
|||||||
missing['carrier'] = carrier_count - self.select(is_enemy=True, may_enemy=False).count
|
missing['carrier'] = carrier_count - self.select(is_enemy=True, may_enemy=False).count
|
||||||
for grid in self:
|
for grid in self:
|
||||||
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
for attr in ['enemy', 'mystery', 'siren', 'boss']:
|
||||||
if grid.__getattribute__('is_' + attr) and grid.__getattribute__('may_' + attr):
|
if grid.__getattribute__('is_' + attr):
|
||||||
missing[attr] -= 1
|
missing[attr] -= 1
|
||||||
|
|
||||||
for grid in self:
|
for grid in self:
|
||||||
@@ -521,7 +541,6 @@ class CampaignMap:
|
|||||||
|
|
||||||
def flatten(self):
|
def flatten(self):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[GridInfo]:
|
list[GridInfo]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -105,23 +105,16 @@ class SelectedGrids:
|
|||||||
g = [grid for grid in self.grids if grid not in grids]
|
g = [grid for grid in self.grids if grid not in grids]
|
||||||
return SelectedGrids(g)
|
return SelectedGrids(g)
|
||||||
|
|
||||||
def sort(self, cost=True, weight=True):
|
def sort(self, *args):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
cost (bool):
|
args (str): Attribute name to sort.
|
||||||
weight (bool):
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
SelectedGrids:
|
||||||
"""
|
"""
|
||||||
attr = []
|
if len(args):
|
||||||
if weight:
|
grids = sorted(self.grids, key=operator.attrgetter(*args))
|
||||||
attr.append('weight')
|
|
||||||
if cost:
|
|
||||||
attr.append('cost')
|
|
||||||
if len(attr):
|
|
||||||
grids = sorted(self.grids, key=operator.attrgetter(*attr))
|
|
||||||
return SelectedGrids(grids)
|
return SelectedGrids(grids)
|
||||||
else:
|
else:
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class GridInfo:
|
|||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
info (GridInfo):
|
info (GridInfo):
|
||||||
mode (str): Scan mode, such as 'normal', 'carrier', 'move'
|
mode (str): Scan mode, such as 'normal', 'carrier', 'movable'
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: If success.
|
bool: If success.
|
||||||
@@ -166,6 +166,11 @@ class GridInfo:
|
|||||||
self.enemy_scale = 0
|
self.enemy_scale = 0
|
||||||
self.enemy_genre = info.enemy_genre
|
self.enemy_genre = info.enemy_genre
|
||||||
return True
|
return True
|
||||||
|
elif mode == 'movable' and not self.is_land:
|
||||||
|
self.is_siren = True
|
||||||
|
self.enemy_scale = 0
|
||||||
|
self.enemy_genre = info.enemy_genre
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
if info.is_enemy:
|
if info.is_enemy:
|
||||||
@@ -173,7 +178,8 @@ class GridInfo:
|
|||||||
self.is_enemy = True
|
self.is_enemy = True
|
||||||
if info.enemy_scale:
|
if info.enemy_scale:
|
||||||
self.enemy_scale = info.enemy_scale
|
self.enemy_scale = info.enemy_scale
|
||||||
if info.enemy_genre != 'Enemy':
|
if info.enemy_genre:
|
||||||
|
|
||||||
self.enemy_genre = info.enemy_genre
|
self.enemy_genre = info.enemy_genre
|
||||||
return True
|
return True
|
||||||
elif mode == 'carrier' and not self.is_land and self.may_carrier:
|
elif mode == 'carrier' and not self.is_land and self.may_carrier:
|
||||||
@@ -181,7 +187,7 @@ class GridInfo:
|
|||||||
self.is_carrier = True
|
self.is_carrier = True
|
||||||
if info.enemy_scale:
|
if info.enemy_scale:
|
||||||
self.enemy_scale = info.enemy_scale
|
self.enemy_scale = info.enemy_scale
|
||||||
if info.enemy_genre != 'Enemy':
|
if info.enemy_genre:
|
||||||
self.enemy_genre = info.enemy_genre
|
self.enemy_genre = info.enemy_genre
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -196,11 +196,19 @@ class ResearchSelector(UI):
|
|||||||
out.append(index)
|
out.append(index)
|
||||||
continue
|
continue
|
||||||
proj = self.projects[index]
|
proj = self.projects[index]
|
||||||
|
if not proj.valid:
|
||||||
|
continue
|
||||||
if (not self.config.RESEARCH_USE_CUBE and proj.need_cube) \
|
if (not self.config.RESEARCH_USE_CUBE and proj.need_cube) \
|
||||||
or (not self.config.RESEARCH_USE_COIN and proj.need_coin) \
|
or (not self.config.RESEARCH_USE_COIN and proj.need_coin) \
|
||||||
or (not self.config.RESEARCH_USE_PART and proj.need_part) \
|
or (not self.config.RESEARCH_USE_PART and proj.need_part):
|
||||||
or not proj.valid \
|
continue
|
||||||
or proj.genre.upper() in ['B', 'E']:
|
# Reasons to ignore B series and E-2:
|
||||||
|
# - Can't guarantee research condition satisfied.
|
||||||
|
# You may get nothing after a day of running, because you didn't complete the precondition.
|
||||||
|
# - Low income from B series research.
|
||||||
|
# Gold B-4 basically equivalent to C-12, but needs a lot of oil.
|
||||||
|
if (proj.genre.upper() == 'B') \
|
||||||
|
or (proj.genre.upper() == 'E' and str(proj.duration) != '6'):
|
||||||
continue
|
continue
|
||||||
out.append(index)
|
out.append(index)
|
||||||
return out
|
return out
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ class RewardResearch(ResearchSelector):
|
|||||||
if skip_first_screenshot:
|
if skip_first_screenshot:
|
||||||
skip_first_screenshot = False
|
skip_first_screenshot = False
|
||||||
else:
|
else:
|
||||||
|
self.device.sleep(2)
|
||||||
self.device.screenshot()
|
self.device.screenshot()
|
||||||
|
|
||||||
if self.appear(RESEARCH_CHECK, interval=10):
|
if self.appear(RESEARCH_CHECK, interval=10):
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ class Reward(RewardCommission, RewardTacticalClass, RewardResearch, LoginHandler
|
|||||||
|
|
||||||
_enable_daily_reward = False
|
_enable_daily_reward = False
|
||||||
_fleet_auto_mode = ('combat_auto', 'combat_auto', 'combat_auto')
|
_fleet_auto_mode = ('combat_auto', 'combat_auto', 'combat_auto')
|
||||||
|
_enable_map_fleet_lock = False
|
||||||
|
|
||||||
def reward_backup_daily_reward_settings(self):
|
def reward_backup_daily_reward_settings(self):
|
||||||
"""
|
"""
|
||||||
@@ -229,7 +230,10 @@ class Reward(RewardCommission, RewardTacticalClass, RewardResearch, LoginHandler
|
|||||||
self.config.ENABLE_DAILY_REWARD = False
|
self.config.ENABLE_DAILY_REWARD = False
|
||||||
self._fleet_auto_mode = self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE
|
self._fleet_auto_mode = self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE
|
||||||
self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE = ('combat_auto', 'combat_auto', 'combat_auto')
|
self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE = ('combat_auto', 'combat_auto', 'combat_auto')
|
||||||
|
self._enable_map_fleet_lock = self.config.ENABLE_MAP_FLEET_LOCK
|
||||||
|
self.config.ENABLE_MAP_FLEET_LOCK = True
|
||||||
|
|
||||||
def reward_recover_daily_reward_settings(self):
|
def reward_recover_daily_reward_settings(self):
|
||||||
self.config.ENABLE_DAILY_REWARD = self._enable_daily_reward
|
self.config.ENABLE_DAILY_REWARD = self._enable_daily_reward
|
||||||
self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE = self._fleet_auto_mode
|
self.config.FLEET_1_AUTO_MODE, self.config.FLEET_2_AUTO_MODE, self.config.FLEET_3_AUTO_MODE = self._fleet_auto_mode
|
||||||
|
self.config.ENABLE_MAP_FLEET_LOCK = self._enable_map_fleet_lock
|
||||||
|
|||||||
Reference in New Issue
Block a user