"""#48 audit: find gauge draws that are NOT preceded by a cursor set. The #42 family: a draw that relies on the CURRENT cursor works by accident the first time (the cursor happens to be right) and lands in the wrong place on a later redraw. Draws that only fire on a STATE CHANGE -- damage, heat, jam, alarm -- are the dangerous ones: they are rare, so the bug hides until gameplay triggers them, and nothing erases the stray pixels afterwards. Relative/cursor-relative draws (the risky ones) vs absolute draws (safe): RISKY : DrawFilledRectangleToRelative, DrawBitMap*, DrawLineToRelative, DrawPointToRelative, DrawFilledRectangleToAbsolute (uses cursor as one corner) SAFE : anything taking explicit x,y (DrawPortBackground, NumericDisplay::Draw which carries its own coords) Reports each risky draw with the distance back to the nearest MoveToAbsolute / MoveToRelative in the same function, and flags any that has none. """ import os import re FILES = [ "game/reconstructed/btl4gau2.cpp", # weapon panels + eng pages (artifacts seen here) "game/reconstructed/btl4gau3.cpp", # pilotList, PlayerStatus, MessageBoard "game/reconstructed/btl4gau1.cpp", "game/reconstructed/btl4grnd.cpp", "engine/MUNGA_L4/L4GAUGE.cpp", "engine/MUNGA_L4/L4LAMP.cpp", ] RISKY = re.compile(r"\.(DrawFilledRectangleToRelative|DrawBitMapOpaque|DrawBitMap|" r"DrawLineToRelative|DrawPointToRelative|" r"DrawFilledRectangleToAbsolute)\s*\(") CURSOR = re.compile(r"\.(MoveToAbsolute|MoveToRelative)\s*\(") FUNCHEAD = re.compile(r"^(?:\t|)([A-Za-z_][A-Za-z0-9_]*::[A-Za-z_][A-Za-z0-9_]*)\s*\(") root = r"C:\git\bt411" findings = [] for rel in FILES: path = os.path.join(root, rel.replace("/", os.sep)) if not os.path.exists(path): continue lines = open(path, encoding="utf-8", errors="replace").read().splitlines() func = "?" func_start = 0 last_cursor = -1 for i, ln in enumerate(lines): m = FUNCHEAD.match(ln) if m: func = m.group(1) func_start = i last_cursor = -1 # cursor state does not carry across functions if CURSOR.search(ln): last_cursor = i mm = RISKY.search(ln) if mm: gap = (i - last_cursor) if last_cursor >= func_start else None findings.append((rel, i + 1, func, mm.group(1), gap, ln.strip()[:78])) print("=" * 100) print("RISKY DRAWS WITH **NO** CURSOR SET IN THE ENCLOSING FUNCTION (top suspects)") print("=" * 100) none = [f for f in findings if f[4] is None] for rel, line, func, call, gap, src in none: print(" %-32s :%-5d %-42s %s" % (rel.split("/")[-1], line, func, call)) print(" %s" % src) print("\n -> %d of %d risky draws have NO cursor set in scope\n" % (len(none), len(findings))) print("=" * 100) print("RISKY DRAWS WHOSE CURSOR SET IS FAR AWAY (>12 lines -- may be on another branch)") print("=" * 100) far = [f for f in findings if f[4] is not None and f[4] > 12] for rel, line, func, call, gap, src in far: print(" %-32s :%-5d gap=%-4d %-38s %s" % (rel.split("/")[-1], line, gap, func, call)) print("\n -> %d far-cursor draws" % len(far)) print("\ntotal risky draws scanned: %d" % len(findings))