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); }