Advertisement
GuiltyBystander

Opus Magnum Score Extraction

Jan 23rd, 2018
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.50 KB | None | 0 0
  1. from os import listdir
  2. import sys
  3.  
  4. def extractInt(ba, i, l):
  5.     return int.from_bytes(ba[i:i+l], byteorder='little', signed=False)
  6.        
  7. def extractString(ba, i):
  8.     length = extractInt(ba, i, 1)
  9.     i += 1
  10.     return ba[i : i + length].decode('utf-8')
  11.  
  12. def pruneFrontier(sols):
  13.     sols = sols[:]
  14.  
  15.     #iterating all pairs i,j
  16.     i = 0
  17.     while i < len(sols):
  18.         s1 = sols[i]
  19.         j = i + 1
  20.         while j < len(sols):
  21.             s2 = sols[j]
  22.             comp = [s1[k] <= s2[k] for k in range(4)]
  23.             #if first is better on all scores, remove second
  24.             if all(comp):
  25.                 sols.pop(j)
  26.             else:
  27.                 j += 1
  28.         i += 1
  29.     return sols
  30.  
  31. if __name__ == "__main__":
  32.     names = {}
  33.  
  34.     names['P044'] = 'Lesson: Introduction'
  35.     names['P001'] = 'Lesson: Arms'
  36.     names['P004'] = 'Lesson: Pivots'
  37.     names['P002'] = 'Lesson: Pistons'
  38.     names['P003'] = 'Lesson: Tracks'
  39.     names['P006'] = 'Lesson: Transmutation'
  40.     names['P005'] = 'Lesson: Bonding'
  41.     skip = set(names.keys())
  42.  
  43.     #chapter 1
  44.     names['P007'] = 'Stabilized Water'
  45.     names['P010'] = 'Refined Gold'
  46.     names['P009'] = 'Face Powder'
  47.     names['P011'] = 'Waterproof Sealant'
  48.     names['P013'] = 'Hangover Cure'
  49.     names['P008'] = 'Airship Fuel'
  50.     names['P012'] = 'Precision Machine Oil'
  51.     names['P014'] = 'Health Tonic'
  52.     names['P015'] = 'Stamina Potion'
  53.     #chapter 2
  54.     names['P016'] = 'Hair Product'
  55.     names['P019'] = 'Rocket Propellant'
  56.     names['P018'] = 'Mist of Incapacitation'
  57.     names['P017'] = 'Explosive Phial'
  58.     names['P020'] = 'Armor Filament'
  59.     names['P021'] = 'Courage Potion'
  60.     names['P022'] = 'Surrender Flare'
  61.     #chapter 3
  62.     names['P024'] = 'Alcohol Separation'
  63.     names['P025'] = 'Water Purifier'
  64.     names['P026'] = 'Seal Solvent'
  65.     names['P027'] = 'Climbing Rope Fiber'
  66.     names['P028'] = 'Warming Tonic'
  67.     names['P030b'] = 'Life Sensing Potion'
  68.     names['P029'] = 'Very Dark Thread'
  69.     #chapter 4
  70.     names['P031b'] = 'Litharge Separation'
  71.     names['P034'] = 'Stain Remover'
  72.     names['P033'] = 'Sword Alloy'
  73.     names['P032'] = 'Invisible Ink'
  74.     names['P036'] = 'Purified Gold'
  75.     names['P035'] = 'Alchemical Jewel'
  76.     names['P037'] = 'Golden Thread'
  77.     #chapter 5
  78.     names['P038'] = 'Mist of Hallucination'
  79.     names['P042'] = 'Timing Crystal'
  80.     names['P039'] = 'Voltaic Coil'
  81.     names['P040'] = 'Unstable Compound'
  82.     names['P041'] = 'Curious Lipstick'
  83.     names['P043'] = 'Universal Solvent'
  84.     #journal 1
  85.     names['P054'] = "Van Berlo's Wheel"
  86.     names['P055'] = "Van Berlo's Chain"
  87.     names['P056'] = 'Reactive Cinnabar'
  88.     names['P057'] = 'Silver Caustic'
  89.     names['P058'] = 'Lambent II/IX'
  90.     #journal 2
  91.     names['P059'] = "Explorer's Salve"
  92.     names['P060'] = 'Preservative Salt'
  93.     names['P061'] = 'Sailcloth Thread'
  94.     names['P062'] = 'Buoyant Cable'
  95.     names['P063'] = 'Spyglass Crystal'
  96.     #journal 3
  97.     names['P064'] = "Ravari's Wheel"
  98.     names['P065'] = 'Lubricating Filament'
  99.     names['P066'] = 'Resonant Crystal'
  100.     names['P067'] = 'Refined Bronze'
  101.     names['P068'] = 'Ablative Crystal'
  102.     #journal 4
  103.     names['P069'] = 'Proof of Completeness'
  104.     names['P070'] = 'Wheel Representation'
  105.     names['P071'] = 'Synthesis via Alcohol'
  106.     names['P072'] = 'Universal Compound'
  107.     #journal 5
  108.     names['P086'] = 'General Anaesthetic'
  109.     names['P088'] = 'Wakefulness Potion'
  110.     names['P085'] = 'Suture Thread'
  111.     names['P087'] = 'Blood-Stanching Powder'
  112.     names['P089'] = 'Tonic of Hydration'
  113.     #journal 6
  114.     names['P096'] = "Van Berlo's Pivots"
  115.     names['P095'] = 'Reactive Gold'
  116.     names['P097'] = "Assassin's Filament"
  117.     names['P098'] = 'Vaporous Solvent'
  118.     names['P099'] = 'Alchemical Slag'
  119.     #journal 7
  120.     names['P100'] = 'Explosive Victrite'
  121.     names['P101'] = 'Celestial Thread'
  122.     names['P102'] = 'Visillary Anaesthetic'
  123.     names['P104'] = 'Animismus Buffer'
  124.     names['P103'] = 'Electrum Separation'
  125.     #production 1
  126.     names['P076'] = 'Silver Paint'
  127.     names['P080'] = 'Viscous Sludge'
  128.     names['P075'] = 'Fragrant Powders'
  129.     names['P074'] = 'Rat Poison'
  130.     names['P083'] = 'Special Amaro'
  131.     names['P078'] = 'Vapor of Levity'
  132.     names['P079'] = 'Abrasive Particles'
  133.     names['P081'] = 'Eyedrops of Revelation'
  134.     names['P082'] = 'Parade-Rocket Fuel'
  135.     names['P077'] = 'Aether Detector'
  136.     names['P084'] = 'Reconstructed Solvent'
  137.     #production 2
  138.     names['P091b'] = 'Hexstabilized Salt'
  139.     names['P090'] = 'Lustre'
  140.     names['P092'] = 'Lamplight Gas'
  141.     names['P093'] = 'Conductive Enamel'
  142.     names['P094'] = 'Welding Thermite'
  143.  
  144.     solutions = {}
  145.  
  146.     files = [f for f in listdir('.') if f.endswith('.solution')]
  147.     for f in files:
  148.         fh = open(f, 'rb')
  149.         ba = bytearray(fh.read())
  150.         fh.close()
  151.  
  152.         i = 4
  153.  
  154.         puzzleKey = extractString(ba, i)
  155.         i += len(puzzleKey) + 1
  156.  
  157.         name = extractString(ba, i)
  158.         i += len(name) + 1
  159.  
  160.         datastart = i
  161.  
  162.         #first number seems to be for validation.
  163.         #Must be 4
  164.         valid = extractInt(ba, i, 4)
  165.         i += 8
  166.         if valid!=4:
  167.             continue
  168.  
  169.         cycles = extractInt(ba, i, 4)
  170.         i += 8
  171.         cost = extractInt(ba, i, 4)
  172.         i += 8
  173.         area = extractInt(ba, i, 4)
  174.         i += 8
  175.         instructions = extractInt(ba, i, 4)
  176.         i += 8
  177.  
  178.         #only care about puzzles
  179.         #ignore custom(c) and workshop(w) for now
  180.         if puzzleKey.startswith('P'):# or True:
  181.             s = (cost, cycles, area, instructions, f)
  182.            
  183.             if not puzzleKey in solutions:
  184.                 solutions[puzzleKey] = []
  185.                
  186.             solutions[puzzleKey].append(s)
  187.        
  188.  
  189.     keys = list(solutions.keys())
  190.     keys.sort()
  191.     count = [0, 0]
  192.     for k in keys:
  193.         solsRaw = solutions[k]
  194.         solsRaw.sort() #just for fun, not really needed
  195.         sols = pruneFrontier(solsRaw)
  196.  
  197.         #skip the lessons
  198.         if k in skip:
  199.             continue
  200.  
  201.         if k not in names:
  202.             print('Unknown name "{}" in file "{}"'.format(k, sols[0][-1]), file=sys.stderr)
  203.         n = names.get(k, k)
  204.         solstrs = ['/'.join(map(str,sol[:4])) for sol in sols]
  205.         solstr = ', '.join(solstrs)
  206.         print(n, ':', solstr, ' ')
  207.        
  208.         count[0] += len(sols)
  209.         count[1] += len(solsRaw)
  210.  
  211.     print(count[0], '/', count[1], 'solutions on your frontier')
  212.  
  213.     input("Press Enter to quit")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement