"""Offline normalization of generated art; the game animates reels in MASM.""" import json import struct from pathlib import Path from PIL import Image ROOT = Path(__file__).resolve().parents[2] SOURCE = ROOT / "assets/sprites/clover" OUTPUT = ROOT / "assets/animations/clover" def pack(name, frames): width, height = frames[0].size pixels = b"".join(frame.tobytes("raw", "BGRA") for frame in frames) (OUTPUT / name).write_bytes(struct.pack("<4s4I", b"ANM1", width, height, len(frames), len(pixels)) + pixels) def main(): OUTPUT.mkdir(parents=True, exist_ok=True) cabinet = Image.open(SOURCE / "cabinet-v1.png").convert("RGBA") cabinet = cabinet.resize((640, 480), Image.Resampling.NEAREST) cabinet.putalpha(255) pack("cabinet-v1.bin", [cabinet]) sheet = Image.open(SOURCE / "symbols-v1.png").convert("RGBA") assert 1.8 < sheet.width / sheet.height < 2.2 frames = [] for index in range(7): column, row = index % 4, index // 4 cell = sheet.crop((round(column * sheet.width / 4), round(row * sheet.height / 2), round((column + 1) * sheet.width / 4), round((row + 1) * sheet.height / 2))) bounds = cell.getchannel("A").getbbox() assert bounds, f"Empty symbol {index}" cell = cell.crop(bounds) cell.thumbnail((46, 46), Image.Resampling.NEAREST) frame = Image.new("RGBA", (56, 56)) frame.paste(cell, ((56 - cell.width) // 2, (56 - cell.height) // 2)) frame.putalpha(frame.getchannel("A").point(lambda value: 255 if value >= 128 else 0)) frames.append(frame) pack("symbols-v1.bin", frames) (OUTPUT / "manifest.json").write_text(json.dumps({"symbols": ["clover", "lemon", "cherries", "bell", "diamond", "chest", "seven"], "cabinet": [640, 480], "symbol": [56, 56], "runtime": "MASM; five reels, three complete rows, legacy additive combos"}, indent=2) + "\n") print("Packed Clover 5x3 cabinet and seven alpha-tested symbols") if __name__ == "__main__": main()