"""Validate tight furniture assets, native captures and tested/shipping code parity.""" import argparse import struct from pathlib import Path from PIL import Image from check_card_exit_build import Coff ROOT = Path(__file__).resolve().parents[2] EXPECTED = { "card-table": (320, 208, 1), "roulette-table": (288, 268, 1), "backroom-table": (304, 236, 1), "skill-cabinet": (224, 368, 1), "lounge-chair": (240, 256, 1), "lamp-table": (192, 224, 1), "velvet-rope": (288, 192, 1), "slot-cabinets": (224, 256, 3), } def assets(): for name, (width, height, count) in EXPECTED.items(): data = (ROOT / "assets/animations/hall" / (name + "-v5.bin")).read_bytes() assert struct.unpack_from("<4s4I", data) == ( b"ANM1", width, height, count, width * height * count * 4), name assert len(data) == 20 + width * height * count * 4 for index in range(count): offset = 20 + index * width * height * 4 frame = Image.frombytes("RGBA", (width, height), data[offset:offset + width * height * 4], "raw", "BGRA") alpha = frame.getchannel("A") assert set(alpha.tobytes()) == {0, 255}, (name, index) assert alpha.getbbox() == (0, 0, width, height), (name, index) assert len(frame.convert("RGB").getcolors(width * height)) > 100, name print("PASS: eight tight floor-anchored furniture packs; binary alpha and complete bounds") def captures(): for name in ("hall-card-furniture-v5", "hall-skill-furniture-v5", "hall-lounge-v5"): frame = Image.open(ROOT / "build/actions" / (name + ".bmp")).convert("RGB") assert frame.size == (640, 480) assert len(frame.getcolors(640 * 480)) > 1000 frame.save(ROOT / "build/actions" / (name + ".png")) print("PASS: native close-up table, complete skill cabinet and lounge snapshots") def parity(): tested = Coff(ROOT / "build/actions/actions-test.obj") shipped = Coff(ROOT / "build/graphics/poker.obj") for name, arguments in (("RenderSprites", 0), ("LoadHallAssets3D", 0), ("FreeHallAssets3D", 0), ("RenderHall3D", 0), ("CanWalkHall3D", 8)): symbol = f"_{name}@{arguments}" assert tested.signature(symbol) == shipped.signature(symbol), name print("PASS: shipping hall furniture rendering/collision matches native test code") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--assets-only", action="store_true") parser.add_argument("--parity", action="store_true") options = parser.parse_args() assets() if not options.assets_only: captures() if options.parity: parity()