diff --git a/campaign/event_20200611_en/b3.py b/campaign/event_20200611_en/b3.py index 9606ab0e5..3eddbe164 100644 --- a/campaign/event_20200611_en/b3.py +++ b/campaign/event_20200611_en/b3.py @@ -26,7 +26,7 @@ MAP.wall_data = """ · · | · · · | · · · · | · · · | · · , | | | | , · · | · · · | · · · · | · · · | · · , - +---+ +---+ +----+ +---+ , + +---+ +---+ +---+ +---+ , · · · | · · · · · · · · | · · · , | | , · · · | · · · · · · · · | · · · , diff --git a/campaign/event_20200611_en/d3.py b/campaign/event_20200611_en/d3.py index 26968be89..0cf75e3ed 100644 --- a/campaign/event_20200611_en/d3.py +++ b/campaign/event_20200611_en/d3.py @@ -37,7 +37,7 @@ MAP.wall_data = """ · · | · · · | · · · · | · · · | · · , | | | | , · · | · · · | · · · · | · · · | · · , - +---+ +---+ +----+ +---+ , + +---+ +---+ +---+ +---+ , · · · | · · · · · · · · | · · · , | | , · · · | · · · · · · · · | · · · , diff --git a/config/template.ini b/config/template.ini index 96f7aa012..df9eaf0d9 100644 --- a/config/template.ini +++ b/config/template.ini @@ -2,11 +2,11 @@ command = Daily [Setting] -enable_stop_condition = yes +enable_stop_condition = no enable_fast_forward = yes if_count_greater_than = 0 if_time_reach = 0 -if_oil_lower_than = 2000 +if_oil_lower_than = 0 if_trigger_emotion_control = no if_dock_full = no enable_fleet_control = yes @@ -25,14 +25,14 @@ fleet_index_4 = do_not_use submarine_mode = do_not_use enable_emotion_reduce = yes ignore_low_emotion_warn = no -emotion_recover_1 = dormitory_floor_2 -emotion_control_1 = keep_high_emotion +emotion_recover_1 = not_in_dormitory +emotion_control_1 = avoid_yellow_face hole_fleet_married_1 = no emotion_recover_2 = not_in_dormitory emotion_control_2 = avoid_yellow_face hole_fleet_married_2 = no -emotion_recover_3 = dormitory_floor_1 -emotion_control_3 = keep_high_emotion +emotion_recover_3 = not_in_dormitory +emotion_control_3 = avoid_yellow_face hole_fleet_married_3 = no enable_hp_balance = no enable_low_hp_withdraw = no @@ -156,11 +156,11 @@ ammo_pick_up_124 = 3 command = c124_leveling [EmotionRecord] -fleet_1_emotion = 150 +fleet_1_emotion = 119 fleet_1_savetime = 2020-01-01_00:00:00 fleet_2_emotion = 119 fleet_2_savetime = 2020-01-01_00:00:00 -fleet_3_emotion = 150 +fleet_3_emotion = 119 fleet_3_savetime = 2020-01-01_00:00:00 [DailyRecord] diff --git a/dev_tools/slpp.py b/dev_tools/slpp.py new file mode 100644 index 000000000..e0dac702c --- /dev/null +++ b/dev_tools/slpp.py @@ -0,0 +1,278 @@ +import re +import sys +from numbers import Number + +import six + + +""" +SLPP is a simple lua-python data structures parser. + +This is my fork of SLPP, https://github.com/LmeSzinc/slpp +Origin repository here, https://github.com/SirAnthony/slpp + +I found some error in it +lua example: '{点={2={0={叫={醒={我={this=true}}}}}}}' +wrong result: {'点': {2: [{'叫': {'醒': {'我': {'this': True}}}}]}} +fixed result: {'点': {2: {0: {'叫': {'醒': {'我': {'this': True}}}}}}} + +They seems to treat this as a feature not a bug, https://github.com/SirAnthony/slpp/issues/21 +So I made my own fork for Alas. +""" + + +ERRORS = { + 'unexp_end_string': u'Unexpected end of string while parsing Lua string.', + 'unexp_end_table': u'Unexpected end of table while parsing Lua string.', + 'mfnumber_minus': u'Malformed number (no digits after initial minus).', + 'mfnumber_dec_point': u'Malformed number (no digits after decimal point).', + 'mfnumber_sci': u'Malformed number (bad scientific format).', +} + + +def sequential(lst): + length = len(lst) + if length == 0 or lst[0] != 0: + return False + for i in range(length): + if i + 1 < length: + if lst[i] + 1 != lst[i + 1]: + return False + return True + + +class ParseError(Exception): + pass + + +class SLPP(object): + + def __init__(self): + self.text = '' + self.ch = '' + self.at = 0 + self.len = 0 + self.depth = 0 + self.space = re.compile('\s', re.M) + self.alnum = re.compile('\w', re.M) + self.newline = '\n' + self.tab = '\t' + + def decode(self, text): + if not text or not isinstance(text, six.string_types): + return + reg = re.compile('--.*$', re.M) + text = reg.sub('', text, 0) + self.text = text + self.at, self.ch, self.depth = 0, '', 0 + self.len = len(text) + self.next_chr() + result = self.value() + return result + + def encode(self, obj): + self.depth = 0 + return self.__encode(obj) + + def __encode(self, obj): + s = '' + tab = self.tab + newline = self.newline + + if isinstance(obj, str): + s += '"%s"' % obj.replace(r'"', r'\"') + elif six.PY2 and isinstance(obj, unicode): + s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"') + elif six.PY3 and isinstance(obj, bytes): + s += '"{}"'.format(''.join(r'\x{:02x}'.format(c) for c in obj)) + elif isinstance(obj, bool): + s += str(obj).lower() + elif obj is None: + s += 'nil' + elif isinstance(obj, Number): + s += str(obj) + elif isinstance(obj, (list, tuple, dict)): + self.depth += 1 + if len(obj) == 0 or (not isinstance(obj, dict) and len([ + x for x in obj + if isinstance(x, Number) or (isinstance(x, six.string_types) and len(x) < 10) + ]) == len(obj)): + newline = tab = '' + dp = tab * self.depth + s += "%s{%s" % (tab * (self.depth - 2), newline) + if isinstance(obj, dict): + key = '[%s]' if all(isinstance(k, int) for k in obj.keys()) else '%s' + contents = [dp + (key + ' = %s') % (k, self.__encode(v)) for k, v in obj.items()] + s += (',%s' % newline).join(contents) + else: + s += (',%s' % newline).join( + [dp + self.__encode(el) for el in obj]) + self.depth -= 1 + s += "%s%s}" % (newline, tab * self.depth) + return s + + def white(self): + while self.ch: + if self.space.match(self.ch): + self.next_chr() + else: + break + + def next_chr(self): + if self.at >= self.len: + self.ch = None + return None + self.ch = self.text[self.at] + self.at += 1 + return True + + def value(self): + self.white() + if not self.ch: + return + if self.ch == '{': + return self.object() + if self.ch == "[": + self.next_chr() + if self.ch in ['"', "'", '[']: + return self.string(self.ch) + if self.ch.isdigit() or self.ch == '-': + return self.number() + return self.word() + + def string(self, end=None): + s = '' + start = self.ch + if end == '[': + end = ']' + if start in ['"', "'", '[']: + while self.next_chr(): + if self.ch == end: + self.next_chr() + if start != "[" or self.ch == ']': + return s + if self.ch == '\\' and start == end: + self.next_chr() + if self.ch != end: + s += '\\' + s += self.ch + raise ParseError(ERRORS['unexp_end_string']) + + def object(self): + o = {} + k = None + idx = 0 + self.depth += 1 + self.next_chr() + self.white() + if self.ch and self.ch == '}': + self.depth -= 1 + self.next_chr() + return o # Exit here + else: + while self.ch: + self.white() + if self.ch == '{': + o[idx] = self.object() + idx += 1 + continue + elif self.ch == '}': + self.depth -= 1 + self.next_chr() + if k is not None: + o[idx] = k + if len([key for key in o if isinstance(key, six.string_types + (int, float, bool, tuple))]) == 0: + so = sorted([key for key in o]) + if sequential(so): + ar = [] + for key in o: + ar.insert(key, o[key]) + o = ar + return o # or here + else: + if self.ch == ',': + self.next_chr() + continue + else: + k = self.value() + if self.ch == ']': + self.next_chr() + self.white() + ch = self.ch + if ch in ('=', ','): + self.next_chr() + self.white() + if ch == '=': + o[k] = self.value() + else: + o[idx] = k + idx += 1 + k = None + raise ParseError(ERRORS['unexp_end_table']) # Bad exit here + + words = {'true': True, 'false': False, 'nil': None} + + def word(self): + s = '' + if self.ch != '\n': + s = self.ch + self.next_chr() + while self.ch is not None and self.alnum.match(self.ch) and s not in self.words: + s += self.ch + self.next_chr() + return self.words.get(s, s) + + def number(self): + def next_digit(err): + n = self.ch + self.next_chr() + if not self.ch or not self.ch.isdigit(): + raise ParseError(err) + return n + + n = '' + try: + if self.ch == '-': + n += next_digit(ERRORS['mfnumber_minus']) + n += self.digit() + if n == '0' and self.ch in ['x', 'X']: + n += self.ch + self.next_chr() + n += self.hex() + else: + if self.ch and self.ch == '.': + n += next_digit(ERRORS['mfnumber_dec_point']) + n += self.digit() + if self.ch and self.ch in ['e', 'E']: + n += self.ch + self.next_chr() + if not self.ch or self.ch not in ('+', '-'): + raise ParseError(ERRORS['mfnumber_sci']) + n += next_digit(ERRORS['mfnumber_sci']) + n += self.digit() + except ParseError: + t, e = sys.exc_info()[:2] + print(e) + return 0 + try: + return int(n, 0) + except: + pass + return float(n) + + def digit(self): + n = '' + while self.ch and self.ch.isdigit(): + n += self.ch + self.next_chr() + return n + + def hex(self): + n = '' + while self.ch and (self.ch in 'ABCDEFabcdef' or self.ch.isdigit()): + n += self.ch + self.next_chr() + return n + + +slpp = SLPP() diff --git a/dev_tools/word_template_extractor.py b/dev_tools/word_template_extractor.py new file mode 100644 index 000000000..a60036424 --- /dev/null +++ b/dev_tools/word_template_extractor.py @@ -0,0 +1,46 @@ +import re + +from dev_tools.slpp import slpp + +""" +This file is used to extract `word_template.lua`, aka, the blacklist words file. + +Git clone the repository here, https://github.com/Dimbreath/AzurLaneData, to get the decrypted scripts. +Then put your filepath here, like `//sharecfg/word_template.lua` +Server list: en-US, ja-JP, ko-KR, zh-CN, zh-TW +""" +file = '' +count = 0 +with open(file, 'r', encoding='utf-8') as f: + text = f.read() + + +def extract(dic, word_list): + """ + Args: + dic (dict): + word_list (list[str]): + """ + global count + for word, data in dic.items(): + word = str(word) + if data.get('this', False): + new = word_list + [word] + new = ''.join(new) + count += 1 + print(new) + else: + new = word_list + [word] + extract(data, word_list=new) + + +# CN server +for result in re.findall('word_template = (.*?)return', text, re.DOTALL): + pg = slpp.decode(result) + extract(pg, word_list=[]) +# Other server +for result in re.findall('uv0\.{0,1}(.*?)end', text, re.DOTALL): + pg = slpp.decode('{%s}' % result) + extract(pg, word_list=[]) + +print(f'Total count: {count}') diff --git a/module/equipment/equipment.py b/module/equipment/equipment.py index d23e55158..c108c74e7 100644 --- a/module/equipment/equipment.py +++ b/module/equipment/equipment.py @@ -17,7 +17,7 @@ class Equipment(InfoHandler): equipment_has_take_on = False def _view_swipe(self, distance, check_button=EQUIPMENT_OPEN): - swipe_timer = Timer(3, count=5) + swipe_timer = Timer(5, count=10) SWIPE_CHECK.load_color(self.device.image) while 1: if not swipe_timer.started() or swipe_timer.reached(): diff --git a/module/exercise/combat.py b/module/exercise/combat.py index 4e10a9020..30752b195 100644 --- a/module/exercise/combat.py +++ b/module/exercise/combat.py @@ -80,12 +80,12 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment): show_hp_timer.reset() self._show_hp() - if self.appear_then_click(QUIT_CONFIRM, offset=True, interval=1): + if self.appear_then_click(QUIT_CONFIRM, offset=True, interval=5): success = False end = True continue - if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=1): + if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=5): self.interval_reset(QUIT_CONFIRM) continue diff --git a/module/handler/enemy_searching.py b/module/handler/enemy_searching.py index 8d51eb4c1..01111fc3b 100644 --- a/module/handler/enemy_searching.py +++ b/module/handler/enemy_searching.py @@ -38,7 +38,9 @@ class EnemySearchingHandler(InfoHandler): def is_in_stage(self): if not self.appear(IN_STAGE, offset=(10, 10)): return False - if self.stage_entrance is not None and not self.appear(self.stage_entrance, threshold=30): + if self.stage_entrance is not None \ + and self.stage_entrance.area \ + and not self.appear(self.stage_entrance, threshold=30): return False return True