Remove CATEGORY_EQUIP from cards that equip other cards
You can find whitelist on document
$ python detect.py > remove.txt
$ python remove.py
python scripts
#!/usr/bin/env python3
import sqlite3
from pathlib import Path
# --- config ---
CDB_PATH = "cards.cdb"
SCRIPT_DIR = Path("script")
WHITELIST_PATH = "whitelist.txt"
# ----------------
# load whitelist IDs
whitelist = set()
whitelist_file = Path(WHITELIST_PATH)
if whitelist_file.exists():
for line in whitelist_file.read_text(encoding="utf-8").splitlines():
line = line.strip()
if line and not line.startswith("#"):
try:
whitelist.add(int(line))
except ValueError:
pass
# connect to sqlite
conn = sqlite3.connect(CDB_PATH)
cur = conn.cursor()
# fetch id + name (type check here)
# 262146 -> equip spell
# 1057 -> union monster
cur.execute("""
SELECT d.id, d.type, t.name
FROM datas d
LEFT JOIN texts t ON d.id = t.id
WHERE d.type != 262146
AND d.type != 1057
""")
rows = cur.fetchall()
conn.close()
results = []
for cid, ctype, name in rows:
if cid in whitelist:
continue
lua_path = SCRIPT_DIR / f"c{cid}.lua"
if not lua_path.exists():
continue
try:
content = lua_path.read_text(encoding="utf-8", errors="ignore")
except:
continue
if "CATEGORY_EQUIP" in content:
results.append((cid, name or ""))
# sort by card ID
results.sort(key=lambda x: x[0])
# # print in Excel-friendly format (;-separated)
# for cid, name in results:
# print(f"{cid};{name}")
# print in list
for cid, name in results:
print(f"{cid}")
#!/usr/bin/env python3
import re
from pathlib import Path
# --- config ---
SCRIPT_DIR = Path("script")
REMOVE_LIST = Path("remove.txt")
# ----------------
def load_ids(path: Path):
ids = set()
if not path.exists():
return ids
raw = path.read_bytes()
# Detect BOM
if raw.startswith(b'\xff\xfe'):
text = raw.decode('utf-16le')
elif raw.startswith(b'\xfe\xff'):
text = raw.decode('utf-16be')
elif raw.startswith(b'\xef\xbb\xbf'):
text = raw.decode('utf-8-sig')
else:
text = raw.decode('utf-8', errors="ignore")
for line in text.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
try:
ids.add(int(line))
except:
pass
return ids
# Regex patterns
re_only_setcategory = re.compile(
r'^[ \t]*[A-Za-z0-9_:.]*SetCategory\(\s*CATEGORY_EQUIP\s*\)[ \t]*$'
)
re_only_setop = re.compile(
r'^[ \t]*Duel\.SetOperationInfo\(\s*0\s*,\s*CATEGORY_EQUIP\b[^)]*\)[ \t]*$'
)
def process_lines(lines):
new_lines = []
for line in lines:
original_line = line
# 1) If the entire line is SetCategory(CATEGORY_EQUIP) → remove
if re_only_setcategory.match(line):
continue
# 2) If entire line is Duel.SetOperationInfo(…, CATEGORY_EQUIP, …) → remove
if re_only_setop.match(line):
continue
# 3) partial replacements inside the line
modified = line
# Remove +CATEGORY_EQUIP
modified = re.sub(r'\+\s*CATEGORY_EQUIP\b', '', modified)
# Remove CATEGORY_EQUIP+
modified = re.sub(r'\bCATEGORY_EQUIP\s*\+', '', modified)
# If CATEGORY_EQUIP is the only expression left (rare)
if modified.strip() == "":
continue # remove empty result line
new_lines.append(modified)
return new_lines
def main():
ids = load_ids(REMOVE_LIST)
for cid in sorted(ids):
lua_file = SCRIPT_DIR / f"c{cid}.lua"
if not lua_file.exists():
print(f"skip {cid} (no file)")
continue
# Read raw bytes to preserve original line endings
raw = lua_file.read_bytes()
# Detect newline style
if b"\r\n" in raw:
newline = "\r\n"
else:
newline = "\n"
# Decode
text = raw.decode("utf-8", errors="ignore")
# Split while preserving empty lines
lines = text.splitlines()
# Process line-by-line
new_lines = process_lines(lines)
# Join with original newline style
new_text = newline.join(new_lines)
# Write back with exact newline setting
with open(lua_file, "w", encoding="utf-8", newline="") as f:
f.write(new_text)
print(f"updated {cid}.lua")
if __name__ == "__main__":
main()