Advertisement
quiznos00

Better MapMaker Source

Mar 7th, 2019
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.89 KB | None | 0 0
  1. from PIL import Image, ImageDraw
  2.  
  3. def bitsToInt(file, num_bits):
  4.     return sum([ord(file.read(1)) * 256 ** i for i in range(num_bits)])
  5.  
  6. class Level:
  7.     def __init__(self, file):
  8.         self.bytes_in_level = bitsToInt(file, 2)
  9.         self.level_num = bitsToInt(file, 2)
  10.         self.time_limit = bitsToInt(file, 2)
  11.         self.chips_left = bitsToInt(file, 2)
  12.  
  13.         file.seek(2, 1) # Skip map detail
  14.  
  15.         self.top_layer = self.parseLayer(file)
  16.         self.bottom_layer = self.parseLayer(file)
  17.         self.title, self.password, self.hint, self.traps, self.cloners, self.monsters = self.parseExtra(file)
  18.  
  19.     def parseLayer(_, file):
  20.         layer = [0] * 1024
  21.  
  22.         layer_byte_count = bitsToInt(file, 2)
  23.         tile_counter = 0
  24.         while layer_byte_count != 0:
  25.             next_tile = bitsToInt(file, 1)
  26.             if next_tile == 255:
  27.                 repeat = bitsToInt(file, 1)
  28.                 repeat_tile = bitsToInt(file, 1)
  29.                 layer_byte_count -= 3
  30.             else:
  31.                 repeat = 1
  32.                 repeat_tile = next_tile
  33.                 layer_byte_count -= 1
  34.             while repeat > 0:
  35.                 repeat -= 1
  36.                 layer[tile_counter] = repeat_tile
  37.                 tile_counter += 1
  38.         if tile_counter != 1024:
  39.             print("Map error")
  40.         return layer
  41.  
  42.     def parseExtra(self, file):
  43.         extra_bytes = bitsToInt(file, 2)
  44.         title, password, hint = None, None, None
  45.         traps, cloners, monsters = [], [], []
  46.  
  47.         while extra_bytes != 0:
  48.             c = bitsToInt(file, 1)
  49.             if c == 3:
  50.                 title_length = bitsToInt(file, 1)
  51.                 title = file.read(title_length)[:-1]
  52.                 extra_bytes -= (2 + title_length)
  53.             if c == 4:
  54.                 trap_length = bitsToInt(file, 1)
  55.                 extra_bytes -= (2 + trap_length)
  56.                 while trap_length != 0:
  57.                     x1, y1 = bitsToInt(file, 2), bitsToInt(file, 2)
  58.                     x2, y2 = bitsToInt(file, 2), bitsToInt(file, 2)
  59.                     traps += [(x1, y1, x2, y2)]
  60.                     file.seek(2, 1)
  61.                     trap_length -= 10
  62.             if c == 5:
  63.                 clone_length = bitsToInt(file, 1)
  64.                 extra_bytes -= (2 + clone_length)
  65.                 while clone_length != 0:
  66.                     x1, y1 = bitsToInt(file, 2), bitsToInt(file, 2)
  67.                     x2, y2 = bitsToInt(file, 2), bitsToInt(file, 2)
  68.                     cloners += [(x1, y1, x2, y2)]
  69.                     clone_length -= 8
  70.             if c == 6:
  71.                 password_length = bitsToInt(file, 1)
  72.                 password = "".join(
  73.                     [chr(bitsToInt(file, 1)^0x99) for i in range(password_length - 1)]
  74.                 )
  75.                 file.seek(1, 1)
  76.                 extra_bytes -= (2 + password_length)
  77.             if c == 7:
  78.                 hint_length = bitsToInt(file, 1)
  79.                 hint = file.read(hint_length)[:-1]
  80.                 extra_bytes -= (2 + hint_length)
  81.             if c == 10:
  82.                 monster_length = bitsToInt(file, 1)
  83.                 extra_bytes -= (2 + monster_length)
  84.                 while monster_length != 0:
  85.                     x, y = bitsToInt(file, 1), bitsToInt(file, 1)
  86.                     monsters += [(x, y)]
  87.                     monster_length -= 2
  88.             if c == 1 or c == 2:
  89.                 file.seek(3, 1) # Ignore useless fixed length fields
  90.                 extra_bytes -= 4
  91.             if c == 8 or c == 9:
  92.                 unused_length = bitsToInt(file, 1)
  93.                 file.seek(unused_length, 1) # Ignore useless variable length fields
  94.                 extra_bytes -= (2 + unused_length)
  95.         return title, password, hint, traps, cloners, monsters
  96.  
  97. class Drawer:
  98.     T_D = 32
  99.  
  100.     def __init__(self, tileset):
  101.         T_D = self.T_D
  102.  
  103.         tileset = Image.open(tileset)
  104.         self.tile_list = [tileset.crop(((x // 16) * T_D, (x % 16) * T_D,
  105.             (x // 16 + 1) * T_D, (x % 16 + 1) * T_D)) for x in range(112)]
  106.  
  107.     def drawBase(self, level, draw_hidden):
  108.         T_D = self.T_D
  109.         FLOOR_TILE = self.tile_list[0]
  110.  
  111.         top_level = level.top_layer
  112.         bottom_level = level.bottom_layer
  113.         export_map = Image.new("RGBA", (T_D * 32, T_D * 32), "black")
  114.  
  115.         for x in range(1024):
  116.             top_index = level.top_layer[x]
  117.             bottom_index = level.bottom_layer[x]
  118.             top_tile = self.tile_list[top_index]
  119.             bottom_tile = self.tile_list[bottom_index]
  120.             x1, y1 = (x % 32) * T_D, (x // 32) * T_D
  121.             x2, y2 = (x % 32 + 1) * T_D, (x // 32 + 1) * T_D
  122.             if top_index // 16 >= 3:
  123.                 if bottom_index // 16 >= 3:
  124.                     export_map.paste(FLOOR_TILE, (x1, y1, x2, y2), FLOOR_TILE)
  125.                 export_map.paste(bottom_tile, (x1, y1, x2, y2), bottom_tile)
  126.                 export_map.paste(top_tile, (x1, y1, x2, y2), top_tile)
  127.             else:
  128.                 export_map.paste(top_tile, (x1, y1, x2, y2), top_tile)
  129.                 if bottom_index != 0 and draw_hidden:
  130.                     c_off = T_D / 4
  131.                     if bottom_index // 16 >= 3:
  132.                         crop_region = FLOOR_TILE.crop((c_off, c_off, T_D - c_off, T_D - c_off))
  133.                         export_map.paste(crop_region, (x1 + c_off, y1 + c_off, x2 - c_off, y2 - c_off), crop_region)
  134.                     crop_region = bottom_tile.crop((c_off, c_off, T_D - c_off, T_D - c_off))
  135.                     export_map.paste(crop_region, (x1 + c_off, y1 + c_off, x2 - c_off, y2 - c_off), crop_region)
  136.         return export_map
  137.  
  138.     def drawConnections(self, level, connections, canvas):
  139.         line_drawer = ImageDraw.Draw(canvas)
  140.         T_D = self.T_D
  141.         for connection in connections:
  142.             x1, y1, x2, y2 = tuple(x * T_D + T_D / 2 for x in connection)
  143.             line_drawer.line(
  144.                 [(x1, y1), (x2, y2)],
  145.                 fill=(255, 0, 0, 255),
  146.                 width=1,
  147.                 joint="curve"
  148.             )
  149.         return
  150.  
  151. def readFile(fileName):
  152.     f = open(fileName, "rb")
  153.  
  154.     c = f.read(4)
  155.     if bytearray(c) != b'\xAC\xAA\x02\x00':
  156.         print("File exists, but is not a valid CC data file.")
  157.         return
  158.  
  159.     num_levels = bitsToInt(f, 2)
  160.     levels = []
  161.     level_counter = 1
  162.  
  163.     while level_counter <= num_levels:
  164.         levels.append(Level(f))
  165.         level_counter += 1
  166.  
  167.     print(fileName + " processed successfully.")
  168.     f.close()
  169.     return levels
  170.  
  171. levels = readFile("CHIPS.dat")
  172. drawer = Drawer("cc_tiles.png")
  173. for i in range(len(levels)):
  174.     export_map = drawer.drawBase(levels[i], True)
  175.     drawer.drawConnections(levels[i], levels[i].traps, export_map)
  176.     drawer.drawConnections(levels[i], levels[i].cloners, export_map)
  177.     export_map.save("./levels/" + str(i + 1) + ".png")
  178.     print("Saved level {0}".format(i + 1))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement