diff options
Diffstat (limited to 'src/unlock.py')
-rw-r--r-- | src/unlock.py | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/src/unlock.py b/src/unlock.py index dfeaa33..446cd0a 100644 --- a/src/unlock.py +++ b/src/unlock.py @@ -8,7 +8,9 @@ class UnlockParseError(ValueError): pass def parseUnlockText(text): - return _parseUnlockBit(text.lower()) + parsed = _parseUnlockBit(text.lower()) + if parsed == ('always',): + return None def _parseUnlockBit(text): # blank criterion @@ -19,7 +21,11 @@ def _parseUnlockBit(text): m = LEVEL_RE.match(text) if m: one, two, secret = m.groups() - return ('level', int(one), int(two), (secret != None)) + w = int(one) + l = int(two) + if w < 1 or w > 10: + raise UnlockParseError('world must be between 1 to 10 inclusive; not %s' % w) + return ('level', w, l, (secret != None)) # OK, let's parse parentheses pLevel = 0 @@ -49,6 +55,9 @@ def _parseUnlockBit(text): raise UnlockParseError('close parenthesis without a matching open') elif pLevel == 0: subTerms.append((currentSubTermStart, index, text[currentSubTermStart+1:index])) + if len(subTerms) > 64: + raise UnlockParseError('no more than 64 subterms in one %s condition' % whatCombiner.upper()) + # are we expecting to see something else? if index == endAt: break @@ -88,6 +97,9 @@ def _parseUnlockBit(text): def stringifyUnlockData(data): + if data == None: + return '' + kind = data[0] if kind == 'always': @@ -98,6 +110,27 @@ def stringifyUnlockData(data): return (' %s ' % kind).join(map(lambda x: '(%s)' % stringifyUnlockData(x), data[1])) +def packUnlockSpec(spec): + kind = data[0] + + if kind == 'always': + return '\x0F' + + elif kind == 'level': + k, world, level, secret = data + + one = (1 << 6) | (0x10 if secret else 0) | (worldNumber - 1) + + return chr(one) + chr(level - 1) + + elif kind == 'and' or kind == 'or': + terms = data[1] + cond = 2 if (kind == 'and') else 3 + one = (cond << 6) | (len(terms) - 1) + + return chr(one) + ''.join(map(packUnlockSpec, terms)) + + if __name__ == '__main__': p1 = parseUnlockText('((01-01 secret) and (01-02)) or (02-99 secret) or (01-01)') p2 = parseUnlockText('(1-1 secret) or ((1-2) and (1-3 secret)) or (2-1)') |