Add: Abyssal Refrain chapter AC

- Add: clear_bouncing_enemy()
- Opt: Retry faster if fleet was caught by a moving enemy
This commit is contained in:
LmeSzinc 2022-02-24 20:43:38 +08:00
parent 3503601ead
commit 49c9e0afd9
14 changed files with 689 additions and 5 deletions

View File

@ -0,0 +1,89 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('A1')
MAP.shape = 'J6'
MAP.camera_data = ['D2', 'D4', 'G2', 'G4']
MAP.camera_data_spawn_point = ['D2', 'D4']
MAP.map_data = """
++ Me Me ++ ++ ++ ME -- ME ++
-- -- -- ME -- -- -- -- -- ME
SP -- -- __ -- -- -- -- -- MB
SP -- -- ME -- -- -- -- -- MB
++ -- -- -- ++ -- ME -- ME --
++ Me Me ++ ++ ME -- ++ ++ ++
"""
MAP.map_data_loop = """
++ Me Me ++ ++ ++ ME -- ME ++
-- -- -- ME -- -- -- -- -- ME
SP -- -- __ -- MS -- MS -- MB
SP -- -- ME -- -- -- -- -- MB
++ -- -- ME ++ -- ME -- ME --
++ Me Me ++ ++ ME -- ++ ++ ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1, 'boss': 1},
{'battle': 4, 'enemy': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1, 'boss': 1},
{'battle': 4, 'enemy': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(C2, C3, C4), ]
MAP.fortress_data = [E3, (E2, F2, F3, E4, F4)]
class Config:
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_HAS_FORTRESS = True
MAP_HAS_BOUNCING_ENEMY = True
MAP_SWIPE_MULTIPLY = 1.698
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.642
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_3(self):
return self.clear_boss()

View File

@ -0,0 +1,103 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .a1 import Config as ConfigBase
MAP = CampaignMap('A2')
MAP.shape = 'H10'
MAP.camera_data = ['D2', 'E5', 'E7']
MAP.camera_data_spawn_point = ['D2']
MAP.map_data = """
++ -- SP SP -- -- ++ ++
-- Me -- -- -- Me ++ ++
Me -- -- -- -- -- Me --
++ ++ -- __ -- Me -- --
-- ++ -- -- -- ++ ++ ++
-- ME -- -- -- -- ME --
++ ME -- -- -- -- -- MB
-- ME -- ME -- -- ME --
-- ++ ME -- ME ME ++ ++
-- -- -- -- -- -- -- ++
"""
MAP.map_data_loop = """
++ -- SP SP -- -- ++ ++
-- Me -- -- -- Me ++ ++
Me -- -- MS -- -- Me --
++ ++ -- __ -- Me -- --
-- ++ -- MS -- ++ ++ ++
-- ME -- -- ME -- ME --
++ ME -- -- -- -- -- MB
-- ME -- ME -- -- ME --
-- ++ ME -- ME ME ++ ++
-- -- -- -- -- -- -- ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
A5, B5, C5, D5, E5, F5, G5, H5, \
A6, B6, C6, D6, E6, F6, G6, H6, \
A7, B7, C7, D7, E7, F7, G7, H7, \
A8, B8, C8, D8, E8, F8, G8, H8, \
A9, B9, C9, D9, E9, F9, G9, H9, \
A10, B10, C10, D10, E10, F10, G10, H10, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(B3, C3, D3, E3, F3), ]
MAP.fortress_data = [D5, (C5, E5, C6, D6, E6)]
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.859
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.797
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,100 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .a1 import Config as ConfigBase
MAP = CampaignMap('A3')
MAP.shape = 'I9'
MAP.camera_data = ['E3', 'E5', 'E7']
MAP.camera_data_spawn_point = ['E7']
MAP.map_data = """
++ ++ ++ -- MB -- ++ ++ ++
++ -- -- -- -- -- -- -- ++
-- ME -- ME ++ ME -- ME --
-- -- -- -- -- -- -- -- --
-- ME -- -- -- -- -- ME --
++ ++ -- -- -- -- -- ++ ++
++ ++ Me -- Me -- Me ++ ++
++ Me -- -- __ -- -- Me ++
++ -- -- SP -- SP -- -- ++
"""
MAP.map_data_loop = """
++ ++ ++ -- MB -- ++ ++ ++
++ -- -- -- -- -- -- -- ++
-- ME -- ME ++ ME -- ME --
-- -- -- -- -- -- -- -- --
-- ME -- ME -- ME -- ME --
++ ++ -- MS -- MS -- ++ ++
++ ++ Me -- Me -- Me ++ ++
++ Me -- -- __ -- -- Me ++
++ -- -- SP -- SP -- -- ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, \
A9, B9, C9, D9, E9, F9, G9, H9, I9, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(C4, D4, E4, F4, G4), ]
MAP.fortress_data = [(D6, F6), (C5, D5, E5, F5, G5, C6, E6, G6)]
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.518
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.468
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,89 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('C1')
MAP.shape = 'J6'
MAP.camera_data = ['D2', 'D4', 'G2', 'G4']
MAP.camera_data_spawn_point = ['D2', 'D4']
MAP.map_data = """
++ Me Me ++ ++ ++ ME -- ME ++
-- -- -- ME -- -- -- -- -- ME
SP -- -- __ -- -- -- -- -- MB
SP -- -- ME -- -- -- -- -- MB
++ -- -- -- ++ -- ME -- ME --
++ Me Me ++ ++ ME -- ++ ++ ++
"""
MAP.map_data_loop = """
++ Me Me ++ ++ ++ ME -- ME ++
-- -- -- ME -- -- -- -- -- ME
SP -- -- __ -- MS -- MS -- MB
SP -- -- ME -- -- -- -- -- MB
++ -- -- ME ++ -- ME -- ME --
++ Me Me ++ ++ ME -- ++ ++ ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(C2, C3, C4), (H1, H2, H3, H4, H5)]
MAP.fortress_data = [E3, (E2, F2, F3, E4, F4)]
class Config:
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_HAS_FORTRESS = True
MAP_HAS_BOUNCING_ENEMY = True
MAP_SWIPE_MULTIPLY = 1.698
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.642
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,104 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .c1 import Config as ConfigBase
MAP = CampaignMap('C2')
MAP.shape = 'H10'
MAP.camera_data = ['D2', 'E5', 'E7']
MAP.camera_data_spawn_point = ['D2']
MAP.map_data = """
++ -- SP SP -- -- ++ ++
-- Me -- -- -- Me ++ ++
Me -- -- -- -- -- Me --
++ ++ -- __ -- Me -- --
-- ++ -- -- -- ++ ++ ++
-- ME -- -- -- -- ME --
++ ME -- -- -- -- -- MB
-- ME -- ME -- -- ME --
-- ++ ME -- ME ME ++ ++
-- -- -- -- -- -- -- ++
"""
MAP.map_data_loop = """
++ -- SP SP -- -- ++ ++
-- Me -- -- -- Me ++ ++
Me -- -- MS -- -- Me --
++ ++ -- __ -- Me -- --
-- ++ -- MS -- ++ ++ ++
-- ME -- -- ME -- ME --
++ ME -- -- -- -- -- MB
-- ME -- ME -- -- ME --
-- ++ ME -- ME ME ++ ++
-- -- -- -- -- -- -- ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
A5, B5, C5, D5, E5, F5, G5, H5, \
A6, B6, C6, D6, E6, F6, G6, H6, \
A7, B7, C7, D7, E7, F7, G7, H7, \
A8, B8, C8, D8, E8, F8, G8, H8, \
A9, B9, C9, D9, E9, F9, G9, H9, \
A10, B10, C10, D10, E10, F10, G10, H10, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(B3, C3, D3, E3, F3), (F6, F7, F8)]
MAP.fortress_data = [D5, (C5, E5, C6, D6, E6)]
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.859
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.797
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,102 @@
from .campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .c1 import Config as ConfigBase
MAP = CampaignMap('C3')
MAP.shape = 'I9'
MAP.camera_data = ['E3', 'E5', 'E7']
MAP.camera_data_spawn_point = ['E7']
MAP.map_data = """
++ ++ ++ -- MB -- ++ ++ ++
++ -- -- -- -- -- -- -- ++
-- ME -- ME ++ ME -- ME --
-- -- -- -- -- -- -- -- --
-- ME -- -- -- -- -- ME --
++ ++ -- -- -- -- -- ++ ++
++ ++ Me -- Me -- Me ++ ++
++ Me -- -- __ -- -- Me ++
++ -- -- SP -- SP -- -- ++
"""
MAP.map_data_loop = """
++ ++ ++ -- MB -- ++ ++ ++
++ -- -- -- -- -- -- -- ++
-- ME -- ME ++ ME -- ME --
-- -- -- -- -- -- -- -- --
-- ME -- ME -- ME -- ME --
++ ++ -- MS -- MS -- ++ ++
++ ++ Me -- Me -- Me ++ ++
++ Me -- -- __ -- -- Me ++
++ -- -- SP -- SP -- -- ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 1},
{'battle': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5, 'boss': 1},
]
MAP.spawn_data_loop = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, \
A9, B9, C9, D9, E9, F9, G9, H9, I9, \
= MAP.flatten()
MAP.bouncing_enemy_data = [(C4, D4, E4, F4, G4), (C2, D2, E2, F2, G2)]
MAP.fortress_data = [(D6, F6), (C5, D5, E5, F5, G5, C6, E6, G6)]
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.518
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.468
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,8 @@
from module.campaign.campaign_base import CampaignBase as CampaignBase_
class CampaignBase(CampaignBase_):
def handle_clear_mode_config_cover(self):
if super().handle_clear_mode_config_cover():
self.config.MAP_SIREN_TEMPLATE = ['SS']
self.config.MAP_HAS_SIREN = True

View File

@ -66,6 +66,8 @@ class CampaignBase(CampaignUI, Map, AutoSearchCombat):
return True
return self.battle_default()
else:
if self.clear_bouncing_enemy():
return True
if self.clear_siren():
return True
self.clear_mechanism()

View File

@ -89,6 +89,7 @@ class ManualConfig:
MAP_HAS_MAZE = False # event_20210422_cn adds maze and maze walls move every 3 rounds.
MAP_HAS_FORTRESS = False # event_2021917_cn, clear fortress to remove roadblock to boss.
MAP_HAS_MISSILE_ATTACK = False # event_202111229_cn, missile attack covers the feature area of sirens.
MAP_HAS_BOUNCING_ENEMY = False # event_20220224_cn, enemy is bouncing in a fixed route.
MAP_FOCUS_ENEMY_AFTER_BATTLE = False # Operation siren
MAP_ENEMY_TEMPLATE = ['Light', 'Main', 'Carrier', 'Treasure']
MAP_SIREN_TEMPLATE = ['DD', 'CL', 'CA', 'BB', 'CV']

View File

@ -112,6 +112,7 @@ class FastForwardHandler(AutoSearchHandler):
self.config.MAP_HAS_LAND_BASED = False
self.config.MAP_HAS_MAZE = False
self.config.MAP_HAS_FORTRESS = False
self.config.MAP_HAS_BOUNCING_ENEMY = False
self.map_is_clear_mode = True
self.map_is_auto_search = self.config.Campaign_UseAutoSearch
self.map_is_2x_book = self.config.Campaign_Use2xBook

View File

@ -204,6 +204,11 @@ class Fleet(Camera, AmbushHandler):
if (self.round + 1) % 3 == 0:
second += 1.0
if self.config.MAP_HAS_BOUNCING_ENEMY:
for route in self.map.bouncing_enemy_data:
if route.select(may_bouncing_enemy=True):
second += self.config.MAP_SIREN_MOVE_WAIT
return second
@property
@ -325,6 +330,8 @@ class Fleet(Camera, AmbushHandler):
arrive_timer = Timer(0.5 + extra, count=2)
arrive_unexpected_timer = Timer(1.5 + extra, count=6)
walk_timeout.reset()
if not (grid.predict_fleet() and grid.predict_current_fleet()):
ambushed_retry.start()
# Ambush
if self.handle_ambush():
@ -811,7 +818,8 @@ class Fleet(Camera, AmbushHandler):
self.map.load_mechanism(
land_based=self.config.MAP_HAS_LAND_BASED,
maze=self.config.MAP_HAS_MAZE,
fortress=self.config.MAP_HAS_FORTRESS
fortress=self.config.MAP_HAS_FORTRESS,
bouncing_enemy=self.config.MAP_HAS_BOUNCING_ENEMY,
)
def map_control_init(self):
@ -844,6 +852,7 @@ class Fleet(Camera, AmbushHandler):
if self.config.POOR_MAP_DATA and self.map.is_map_data_poor:
self.config.POOR_MAP_DATA = False
self.map.fortress_data = [(), ()]
self.map.bouncing_enemy_data = []
return True

View File

@ -1,3 +1,4 @@
import itertools
import re
from module.base.filter import Filter
@ -673,3 +674,47 @@ class Map(Fleet):
return True
return False
def clear_bouncing_enemy(self):
"""
Clear enemies which are bouncing in a fixed route.
This method will be disabled once it cleared an enemy, since there's only one bouncing enemy on the map.
Args:
route (tuple[GridInfo]):
Returns:
bool: If cleared an enemy.
"""
if not self.config.MAP_HAS_BOUNCING_ENEMY:
return False
route = None
for a_route in self.map.bouncing_enemy_data:
if a_route.select(may_bouncing_enemy=True, is_accessible=True):
route = a_route
break
if route is None:
return False
logger.hr('Clear bouncing enemy')
logger.info(f'Clear bouncing enemy: {route}')
self.show_fleet()
prev = self.battle_count
for n, grid in enumerate(itertools.cycle(route)):
if self.config.Emotion_CalculateEmotion and self.config.Campaign_UseFleetLock:
self.emotion.wait(fleet_index=self.fleet_current_index)
self.goto(grid, expected='combat_nothing')
if self.battle_count > prev:
logger.info('Cleared an bouncing enemy')
route.select(may_bouncing_enemy=True).set(may_bouncing_enemy=False)
self.full_scan()
self.find_path_initial()
self.map.show_cost()
return True
if n >= 12:
logger.warning('Failed to clear bouncing enemy after 12 trial')
return False
return False

View File

@ -21,6 +21,7 @@ class CampaignMap:
self._maze_data = []
self.maze_round = 9
self._fortress_data = [(), ()]
self._bouncing_enemy_data = []
self._spawn_data = []
self._spawn_data_stack = []
self._spawn_data_loop = []
@ -198,8 +199,8 @@ class CampaignMap:
@fortress_data.setter
def fortress_data(self, data):
enemy, block = data
enemy = self.to_selected((enemy,) if isinstance(enemy, str) else enemy)
block = self.to_selected((block,) if isinstance(block, str) else block)
enemy = self.to_selected((enemy,) if not isinstance(enemy, (tuple, list)) else enemy)
block = self.to_selected((block,) if not isinstance(block, (tuple, list)) else block)
self._fortress_data = [enemy, block]
def _load_fortress_data(self, data):
@ -213,14 +214,34 @@ class CampaignMap:
enemy.set(is_fortress=True)
block.set(is_mechanism_block=True)
def load_mechanism(self, land_based=False, maze=False, fortress=False):
logger.info(f'Load mechanism, land_base={land_based}, maze={maze}, fortress={fortress}')
@property
def bouncing_enemy_data(self):
return self._bouncing_enemy_data
@bouncing_enemy_data.setter
def bouncing_enemy_data(self, data):
self._bouncing_enemy_data = [self.to_selected(route) for route in data]
def _load_bouncing_enemy_data(self, data):
"""
Args:
data (list[SelectedGrids]): Grids that enemy is bouncing in.
[enemy_route, enemy_route, ...], Such as [(C2, C3, C4), ]
"""
for route in data:
route.set(may_bouncing_enemy=True)
def load_mechanism(self, land_based=False, maze=False, fortress=False, bouncing_enemy=False):
logger.info(f'Load mechanism, land_base={land_based}, maze={maze}, fortress={fortress}, '
f'bouncing_enemy={bouncing_enemy}')
if land_based:
self._load_land_base_data(self.land_based_data)
if maze:
self._load_maze_data(self.maze_data)
if fortress:
self._load_fortress_data(self._fortress_data)
if bouncing_enemy:
self._load_bouncing_enemy_data(self._bouncing_enemy_data)
def grid_connection_initial(self, wall=False, portal=False):
"""
@ -691,6 +712,10 @@ class CampaignMap:
if grid.__getattribute__('is_' + attr):
missing[attr] -= 1
missing['enemy'] += len(self.fortress_data[0]) - self.select(is_fortress=True).count
for route in self.bouncing_enemy_data:
if not route.select(may_bouncing_enemy=True):
# bouncing enemy cleared, re-add one enemy
missing['enemy'] += 1
for upper in self.map_covered:
if (upper.may_enemy or mode == 'movable') and not upper.is_enemy:

View File

@ -65,6 +65,7 @@ class GridInfo:
is_fortress = False # Machine fortress
is_flare = False
is_missile_attack = False
may_bouncing_enemy = False
cost = 9999
cost_1 = 9999
cost_2 = 9999
@ -122,6 +123,7 @@ class GridInfo:
'AM': 'is_ammo',
'FR': 'is_fortress',
'MI': 'is_missile_attack',
'BE': 'may_bouncing_enemy',
'==': 'is_cleared',
}
for key, value in dic.items():
@ -244,6 +246,9 @@ class GridInfo:
if info.enemy_genre and not (info.enemy_genre == 'Enemy' and self.enemy_genre):
self.enemy_genre = info.enemy_genre
return True
elif self.is_fortress:
# Fortress can be a normal enemy
return True
else:
return False
if info.is_mystery:
@ -303,6 +308,7 @@ class GridInfo:
self.is_mechanism_block = False
self.mechanism_trigger = None
self.mechanism_block = None
self.may_bouncing_enemy = False
def covered_grid(self):
"""Relative coordinate of the covered grid.