File size: 3,976 Bytes
88d4171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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

use crate::core::logic::*;
use crate::core::enums::*;

#[test]
fn test_refresh_on_empty_draw() {
    let mut state = GameState::default();
    state.players[0].deck = vec![];
    state.players[0].discard = vec![1, 2, 3];

    let db = CardDatabase {
        members: std::collections::HashMap::new(),
        lives: std::collections::HashMap::new(),
        members_vec: vec![],
        lives_vec: vec![],
    };

    // Drawing 1 card should trigger refresh
    state.draw_cards(0, 1);

    assert_eq!(state.players[0].hand.len(), 1);
    assert_eq!(state.players[0].deck.len(), 2);
    assert!(state.players[0].discard.is_empty());
    assert!(state.players[0].deck_refreshed_this_turn);
}

#[test]
fn test_refresh_on_look_at_top_x() {
    let mut state = GameState::default();
    state.players[0].deck = vec![10]; // Only 1 card in deck
    state.players[0].discard = vec![1, 2, 3];

    let db = CardDatabase {
        members: std::collections::HashMap::new(),
        lives: std::collections::HashMap::new(),
        members_vec: vec![],
        lives_vec: vec![],
    };

    let ctx = AbilityContext {
        player_id: 0,
        ..AbilityContext::default()
    };

    // O_LOOK_DECK, Value 3 (Look at top 3)
    // Rule 10.2.2.2: Refresh because deck (1) < needed (3)
    let bytecode = vec![O_LOOK_DECK, 3, 0, 0, O_RETURN, 0, 0, 0];
    state.resolve_bytecode(&db, &bytecode, &ctx);

    // After refresh, deck should have 1 (original) + 3 (refreshed) = 4 cards
    assert_eq!(state.players[0].deck.len(), 4);
    assert!(state.players[0].discard.is_empty());
    assert!(state.players[0].deck_refreshed_this_turn);

    // Looked cards should contain 3 cards (top of deck)
    assert_eq!(state.players[0].looked_cards.len(), 3);
    // Original card (10) MUST be one of them (the top one)
    assert_eq!(state.players[0].looked_cards[0], 10);
}

#[test]
fn test_refresh_order_preservation() {
    let mut state = GameState::default();
    state.players[0].deck = vec![10, 20]; // 20 is on top
    state.players[0].discard = vec![1, 2, 3];

    // Force refresh
    state.resolve_deck_refresh(0);

    // Rule 10.2.3: Existing cards (10, 20) stay on top
    // pop() should get 20, then 10.
    assert_eq!(state.players[0].deck.pop(), Some(20));
    assert_eq!(state.players[0].deck.pop(), Some(10));

    // Refreshed cards are at the bottom
    assert_eq!(state.players[0].deck.len(), 3);
}

#[test]
fn test_refresh_on_look_and_choose() {
    let mut state = GameState::default();
    state.players[0].deck = vec![10]; // Only 1 card
    state.players[0].discard = vec![1, 2, 3];

    let db = CardDatabase {
        members: std::collections::HashMap::new(),
        lives: std::collections::HashMap::new(),
        members_vec: vec![],
        lives_vec: vec![],
    };

    let ctx = AbilityContext {
        player_id: 0,
        choice_index: 0, // Pick the top card
        ..AbilityContext::default()
    };

    // O_LOOK_AND_CHOOSE, Value 3, Attr 1 (Discard rest)
    // Rule 10.2.2.2: Refresh because deck (1) < needed (3)
    let bytecode = vec![O_LOOK_AND_CHOOSE, 3, 1, 0, O_RETURN, 0, 0, 0];
    state.resolve_bytecode(&db, &bytecode, &ctx);

    // After refresh, deck should have 1 + 3 = 4 cards.
    // Hand got 1 card.
    // Discard got 2 cards (rest of 3).
    // Final deck should have original 1 card left?
    // Wait, let's trace:
    // Deck: [10]
    // Refresh(3) triggers -> Discard [1,2,3] shuffled and put at bottom.
    // Deck: [?, ?, ?, 10] (top is 10)
    // Pop 3: 10, ?, ?
    // Choice 0: 10 goes to hand.
    // Rest of pop: [?, ?] go to discard.
    // Remaining in deck: [?] (the one that wasn't popped)

    assert_eq!(state.players[0].hand.len(), 1);
    assert_eq!(state.players[0].hand[0], 10);
    assert_eq!(state.players[0].discard.len(), 2);
    assert_eq!(state.players[0].deck.len(), 1);
}