LovecaSim / engine /tests /logic /test_order_deck_remainder_rust.py
trioskosmos's picture
Upload folder using huggingface_hub
bb3fbf9 verified
import os
import sys
# Add project root to path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../")))
try:
import engine_rust
except ImportError:
try:
from backend import engine_rust
except ImportError:
print("Could not import engine_rust. Make sure it is built.")
sys.exit(1)
def print_gs_state(gs, p_idx=0):
p = gs.get_player(p_idx)
print(f"--- GS State (Phase {gs.phase}) ---")
print(f" Hand: {p.hand}")
print(f" Deck: {p.deck}")
print(f" Discard: {p.discard}")
print(f" Looked: {p.looked_cards}")
mask = gs.get_legal_actions()
legal = [i for i, x in enumerate(mask) if x]
print(f" Legal Actions: {legal[:20]}... (Total {len(legal)})")
print(" Rule Log:")
for entry in gs.rule_log:
print(f" {entry}")
def get_play_action(gs, p_idx, target_cid):
mask = gs.get_legal_actions()
p = gs.get_player(p_idx)
for h_idx in range(len(p.hand)):
if p.hand[h_idx] == target_cid:
for slot in range(3):
aid = 1 + h_idx * 3 + slot
if aid < len(mask) and mask[aid]: return aid
print(f"ERROR: Could not find play action for cid {target_cid} in hand {p.hand}")
return None
def test_remainder_modes_real():
compiled_path = "data/cards_compiled.json"
with open(compiled_path, "r", encoding="utf-8") as f:
db = engine_rust.PyCardDatabase(f.read())
dummy = 1 # Use card ID 1 as dummy/energy (cost 1 typically)
c_A, c_B, c_C = 10, 20, 30
# --- Mode 0: DISCARD (Card 467) ---
print("\n\n=== Testing REMAINDER=DISCARD (Card 467) ===")
gs = engine_rust.PyGameState(db)
gs.silent = False
# Use real energy cards or just anything valid. 467 itself?
# Actually, card 467 costs 2. Let's make sure we have energy.
gs.initialize_game([467]*40, [467]*40, [dummy]*10, [dummy]*10, [dummy]*3, [dummy]*3)
# Process start of game
gs.step(0); gs.step(0)
while gs.phase != 4: gs.step(0)
p0 = gs.get_player(0)
p0.deck = [1, c_C, c_B, c_A] # c_A is top
gs.set_player(0, p0)
aid = get_play_action(gs, 0, 467)
if aid is None:
print_gs_state(gs)
raise ValueError("No play action for 467")
print(f"Playing 467 with action {aid}")
gs.step(aid)
if gs.phase != 10:
print_gs_state(gs)
raise ValueError(f"Expected phase 10 (Response), got {gs.phase}")
print("Choice 0 (Put A on top)...")
gs.step(550)
print("Choice 3 (Done)...")
gs.step(553)
p = gs.get_player(0)
print_gs_state(gs)
assert 10 in p.deck
assert 20 in p.discard and 30 in p.discard
print("DISCARD passed.")
# --- Mode 1: DECK_TOP (Card 566) ---
print("\n\n=== Testing REMAINDER=DECK_TOP (Card 566) ===")
gs = engine_rust.PyGameState(db)
gs.silent = False
gs.initialize_game([566]*40, [dummy]*40, [dummy]*10, [dummy]*10, [dummy]*3, [dummy]*3)
gs.step(0); gs.step(0)
while gs.phase != 4: gs.step(0)
p0 = gs.get_player(0)
p0.deck = [1, c_C, c_B, c_A]
gs.set_player(0, p0)
aid = get_play_action(gs, 0, 566)
if aid is None:
print_gs_state(gs)
raise ValueError("No play action for 566")
gs.step(aid)
gs.step(550)
gs.step(553)
p = gs.get_player(0)
print_gs_state(gs)
assert p.deck[-3:] == [10, 20, 30]
print("DECK_TOP passed.")
# --- Mode 2: DECK_BOTTOM (Card 565) ---
print("\n\n=== Testing REMAINDER=DECK_BOTTOM (Card 565) ===")
gs = engine_rust.PyGameState(db)
gs.silent = False
gs.initialize_game([565]*40, [dummy]*40, [dummy]*10, [dummy]*10, [dummy]*3, [dummy]*3)
gs.step(0); gs.step(0)
while gs.phase != 4: gs.step(0)
p0 = gs.get_player(0)
p0.deck = [1, c_C, c_B, c_A]
gs.set_player(0, p0)
aid = get_play_action(gs, 0, 565)
if aid is None:
print_gs_state(gs)
raise ValueError("No play action for 565")
gs.step(aid)
gs.step(550)
gs.step(553)
p = gs.get_player(0)
print_gs_state(gs)
assert p.deck[0] == 20 and p.deck[1] == 30
assert p.deck[-1] == 10
print("DECK_BOTTOM passed.")
print("\nAll remainder modes validated!")
if __name__ == "__main__":
test_remainder_modes_real()