File size: 4,325 Bytes
bb3fbf9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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()