Add native Durak, poker, blackjack, roulette, Buckshot and billiards scenes with animation assets and regression tests. Improve arrival, city, hall, profiles, shops, audio and exit handling; remove the portable C game core and refresh shipping executables.
60 lines
3.1 KiB
Python
60 lines
3.1 KiB
Python
"""Visual checks on framebuffers produced by the native MASM test executable."""
|
|
import hashlib
|
|
import json
|
|
import struct
|
|
from pathlib import Path
|
|
|
|
from PIL import Image, ImageDraw
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
OUTPUT = ROOT / "build/actions"
|
|
|
|
|
|
def main():
|
|
packs = {"bartender-v4": (256, 256, 24), "props": (256, 256, 9),
|
|
"drink-v4": (256, 256, 21), "street-life-v4": (192, 320, 40),
|
|
"sign": (128, 128, 3), "city-detail": (256, 256, 16),
|
|
"room-materials": (128, 128, 12), "patrons": (192, 320, 16),
|
|
"room-materials-hd": (256, 256, 12), "architecture": (128, 128, 12),
|
|
"architecture-hd": (256, 256, 12), "architecture-props": (256, 256, 6)}
|
|
for name, expected in packs.items():
|
|
data = (ROOT / "assets/animations/hall" / (name + ".bin")).read_bytes()
|
|
magic, width, height, count, length = struct.unpack_from("<4s4I", data)
|
|
assert magic == b"ANM1" and (width, height, count) == expected
|
|
assert len(data) == 20 + length == 20 + width * height * 4 * count
|
|
if name in ("bartender-v4", "props", "drink-v4", "street-life-v4", "patrons", "architecture-props"):
|
|
hashes = set()
|
|
for index in range(count):
|
|
payload = data[20 + index * width * height * 4:20 + (index + 1) * width * height * 4]
|
|
frame = Image.frombytes("RGBA", (width, height), payload, "raw", "BGRA")
|
|
assert set(frame.getchannel("A").tobytes()) == {0, 255}
|
|
box = frame.getchannel("A").getbbox()
|
|
assert box and box[0] > 0 and box[2] < width, (name, index, box)
|
|
hashes.add(hashlib.sha256(payload).hexdigest())
|
|
assert len(hashes) == count
|
|
names = ["hall-overview", "hall-bar", "hall-bunker", "hall-stairs", "bar-drink",
|
|
"native-wheel", "native-pool", "city-guards-approach", "hall-dining",
|
|
"city-street-v4", "hall-cabaret-v4", "bar-highball-v4", "bar-cocktail-v4",
|
|
"bar-water-v4", "pool-scratch-v4", "pool-power-v4"]
|
|
sheet = Image.new("RGB", (1280, ((len(names) + 1) // 2) * 505), "#191c19")
|
|
draw = ImageDraw.Draw(sheet)
|
|
report = {}
|
|
for index, name in enumerate(names):
|
|
frame = Image.open(OUTPUT / (name + ".bmp")).convert("RGB")
|
|
assert frame.size == (640, 480)
|
|
colors = len(frame.getcolors(640 * 480))
|
|
assert colors > (15 if name.startswith(("native-", "pool-")) else 100), (name, colors)
|
|
report[name] = {"colors": colors, "sha256": hashlib.sha256(frame.tobytes()).hexdigest()}
|
|
frame.save(OUTPUT / (name + ".png"))
|
|
x, y = (index % 2) * 640, (index // 2) * 505
|
|
draw.text((x + 8, y + 5), name, fill="white")
|
|
sheet.paste(frame, (x, y + 25))
|
|
sheet.save(OUTPUT / "hall-contact-sheet.png")
|
|
(OUTPUT / "hall-qa.json").write_text(json.dumps(report, indent=2), encoding="utf-8")
|
|
assert len({report[name]["sha256"] for name in
|
|
("bar-highball-v4", "bar-cocktail-v4", "bar-water-v4")}) == 3
|
|
print("PASS: hall/street assets and sixteen native framebuffer snapshots; three distinct drinks")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|