KAZIK/tools/tests/check_npc_life.py
Artvasil09 881a0061dc Add native NPC visitors with contracts, Clover slots, Pyramid, and party table scenes
Implement 32x32 BFS visitor navigation and daily contracts system with companion .npc journals; add native assembly scenes for Clover slots, Pyramid cards, Blackjack Party and Russian Party; package animation and sprite packs; add comprehensive offline test suites and rebuild shipping binaries.
2026-10-13 09:47:33 +03:00

55 lines
2.4 KiB
Python

"""Inspect actual MASM dialog frames and compare tested/shipping NPC procedures."""
import argparse
import hashlib
from pathlib import Path
from PIL import Image, ImageDraw
from check_card_exit_build import Coff
ROOT = Path(__file__).resolve().parents[2]
def captures():
sheet = Image.new("RGB", (640, 3 * 504), (20, 25, 29))
draw = ImageDraw.Draw(sheet)
hashes = []
for index, name in enumerate(("open", "ready", "done")):
path = ROOT / "build/actions" / f"npc-dialog-{name}.bmp"
frame = Image.open(path).convert("RGB")
assert frame.size == (640, 480)
assert len(frame.getcolors(640 * 480)) > 1000, name
assert frame.getpixel((60, 96)) == (186, 153, 85), "dialog border"
hashes.append(hashlib.sha256(frame.crop((60, 96, 580, 398)).tobytes()).digest())
frame.save(path.with_suffix(".png"))
sheet.paste(frame, (0, index * 504 + 24))
draw.text((8, index * 504 + 6), name, fill="white")
assert len(set(hashes)) == 3, "Contract status/reward must visibly change"
sheet.save(ROOT / "build/actions/npc-dialog-contact.png")
print("PASS: three distinct native NPC dialog frames, bounded modal and changing contract status")
def parity():
tested = Coff(ROOT / "build/actions/actions-test.obj")
shipped = Coff(ROOT / "build/graphics/poker.obj")
procedures = (("InitNpcLife3D", 0), ("UpdateNpcLife3D", 0), ("RenderNpcLife3D", 0),
("NpcPlanPath3D", 8), ("NpcTryCell3D", 8), ("NpcMove3D", 8),
("NpcCanStep3D", 12), ("CheckNpcInteractions3D", 0),
("OpenNpcDialog3D", 0), ("HandleNpcDialog3D", 0),
("RenderNpcDialog3D", 0), ("CloseNpcDialog3D", 0),
("NpcContractType3D", 4), ("NpcAcceptContract3D", 4),
("NpcClaimContract3D", 4), ("NpcRecordRound3D", 8),
("NpcSaveJournal3D", 0), ("NpcNameText3D", 4),
("AnimateCityPedestrians3D", 0), ("FinalizeSkullsGuess", 0))
for name, size in procedures:
symbol = f"_{name}@{size}"
assert tested.signature(symbol) == shipped.signature(symbol), name
print("PASS: shipping NPC navigation, poses, dialogs, rewards and street movement match tested MASM")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--parity", action="store_true")
args = parser.parse_args()
captures()
if args.parity:
parity()