def part1(inp: list[str]) -> None: tiles = parse_tiles(inp) img = Image() img.fit(tiles) edge_ids = map(lambda tile: tile.id, img.get_edge_tiles()) print(reduce(operator.mul, edge_ids))
class TlCoffee(Tile): _sprite = Image("gfx/coffee.png") # def on_overlapped(self, tile): if isinstance(tile, TlPlayer): tile.bomb_cooldown *= 0.90 return True
class TlRuPass(Tile): _sprite = Image("gfx/ru_pass.png") # def on_overlapped(self, tile): if isinstance(tile, TlPlayer): tile.bomb_strength += 1 return True
def part2(inp: list[str]) -> None: tiles = parse_tiles(inp) img = Image() img.fit(tiles) combined = img.get_combined() for i, variation in enumerate(get_variations(combined)): monster_count = count_monsters(variation) if monster_count > 1: total_count = sum(sum(row) for row in variation) print(total_count - monster_count * 15) return
class TlCrate(BreakableTile): _sprite = Image("gfx/crate.png") # def on_overlapped(self, tile): super().on_overlapped(tile) if isinstance(tile, (TlPlayer, TlCrate)): return self.move(self.x - tile.x, self.y - tile.y) return False
def __init__(self, master, image, **kwargs): super().__init__(master, **kwargs) self.master = master self.rowconfigure(0, weight=1) self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self.options = { "Magnitude": Fourier.magnitude, "Phase": Fourier.phase, "Real": Fourier.real, "Imaginary": Fourier.imaginary } self.cbox = Combobox( self, values=["Magnitude", "Phase", "Real", "Imaginary"]) self.cbox.set(self.cbox["values"][0]) self.cbox.grid(row=0, column=0, sticky="ns", padx=4, pady=4) self.cbox.on_change(self.update_image) imgs_container = tk.Frame(self, bg="white") imgs_container.rowconfigure(0, weight=1) imgs_container.columnconfigure(0, weight=1) imgs_container.columnconfigure(1, weight=1) # buggy!!!! self.image = Image(imgs_container) self.image.open_image(image) self.image.show() self.gray_fourier = Fourier.fast2d(self.image.get_gray()) self.image2 = Image(imgs_container) self.image2.size = self.image.size self.update_image(self.cbox.get()) self.image.grid(row=0, column=0, sticky="nsew", padx=4, pady=4) self.image2.grid(row=0, column=1, sticky="nsew", padx=4, pady=4) imgs_container.grid(row=1, column=0, sticky="nsew", padx=4, pady=4)
class TlBush(BreakableTile): _sprite = Image("gfx/bush.png") # def on_overlapped(self, tile): super().on_overlapped(tile) if isinstance(tile, TlPlayer): tile.entering_bush.arm() return True return False
class MainMenu(Stage): _BACKGROUND = Image("gfx/main_menu.png") # def on_draw(self, dt): self._BACKGROUND.draw(0, 0) def on_key_event(self, key, state): global current if key == K_RETURN and state == 0: current = GrassArena()
class Tile: _sprite = Image("gfx/missing.png") x = y = z = 0 # def __init__(self, x, y, z): self.x = x self.y = y self.z = z # def on_update(self, dt): pass def on_key_event(self, key, state): pass def on_overlapped(self, tile): return False def on_draw(self, dt): self._sprite.draw(self.x * lib.TILE_SIZE, self.y * lib.TILE_SIZE, dt) # def move(self, dx, dy): if dx == 0 and dy == 0: return False dx += self.x dy += self.y dest = stages.current.map.get(dx, dy, self.z) if dest is None or dest.on_overlapped(self): stages.current.map.remove(self) self.x = dx self.y = dy stages.current.map.place(self) return True return False
def __init__(self, x, y, z, **params): super().__init__(x, y, z) self._strength = params.get("strength", 2) self._in_bush = params.get("in_bush", False) if self._in_bush: self._sprite = Image("gfx/bomb_bush.png") else: self._sprite = \ Animation("gfx/bomb_%d.png", list(range(7)) + list(reversed(range(7))) + list(range(7)) + list(reversed(range(7))) + list(range(7)) ) self._sprite.on_end = self.explode
class TlBrick(BreakableTile): _sprite = Image("gfx/brick.png")
class TlConcrete(Tile): _sprite = Image("gfx/concrete.png")
class TlGrass(Tile): _sprite = Image("gfx/grass.png")
class TlPlayer(Tile): _SPRITES = { "a": { "normal": Animation("gfx/player_a_%d.png", (0, 1), 0.1), "nobomb": Animation("gfx/player_a_nobomb_%d.png", (0, 1), 0.1), "bush": Image("gfx/player_bush.png"), }, "b": { "normal": Animation("gfx/player_b_%d.png", (0, 1), 0.1), "nobomb": Animation("gfx/player_b_nobomb_%d.png", (0, 1), 0.1), "bush": Image("gfx/player_bush.png"), } } _SLOWNESS = 0.19 # def __init__(self, x, y, z, id, axis, bomb_key): super().__init__(x, y, z) self.bomb_strength = 2 self.bomb_cooldown = 1.75 self.entering_bush = Trigger(False) self._axis = axis self._bomb_key = bomb_key self._id = id self._time_not_moving = self._SLOWNESS self._time_not_bombing = self.bomb_cooldown self._to_put_bomb = Trigger(False) self._in_bush = Trigger(False) # def on_overlapped(self, tile): if isinstance(tile, TlExplosion): tile.leftover = TlDeadPlayer(self.x, self.y, self.z, self._id) return True return False def on_update(self, dt): self._time_not_moving += dt self._time_not_bombing += dt if self._time_not_moving >= self._SLOWNESS \ and self.move(self._axis.x, self._axis.y): self._time_not_moving = 0 if self._to_put_bomb.trigger() \ and self._time_not_bombing >= self.bomb_cooldown: self._time_not_bombing = 0 stages.current.map.place( TlBomb(self.x - self._axis.x, self.y - self._axis.y, self.z, strength=self.bomb_strength, in_bush=self._in_bush.trigger())) elif self._in_bush.trigger(): stages.current.map.place( TlBush(self.x - self._axis.x, self.y - self._axis.y, self.z)) if self.entering_bush.trigger(): self._in_bush.arm() def on_draw(self, dt): sprite = self._SPRITES[self._id]["normal"] if self._in_bush: sprite = self._SPRITES[self._id]["bush"] elif self._time_not_bombing < self.bomb_cooldown: sprite = self._SPRITES[self._id]["nobomb"] sprite.draw(self.x * lib.TILE_SIZE, self.y * lib.TILE_SIZE, dt) def on_key_event(self, key, state): self._axis.react_to_key(key, state) if key == self._bomb_key and state: self._to_put_bomb.arm()
def __init__(self, id): if id == "a": self._background = Image("gfx/won_player_b.png") else: self._background = Image("gfx/won_player_a.png")