Spaces:
Sleeping
Sleeping
| use crate::core::logic::*; | |
| const TEST_CARDS: &str = r#"{ | |
| "member_db": { | |
| "0": { | |
| "card_id": 0, | |
| "card_no": "TEST-001", | |
| "name": "Test Member", | |
| "cost": 0, | |
| "hearts": [0, 0, 0, 0, 0, 0, 0], | |
| "blade_hearts": [0, 0, 0, 0, 0, 0, 0], | |
| "blades": 0, | |
| "groups": [], | |
| "units": [], | |
| "abilities": [], | |
| "rare": "R", | |
| "volume_icons": 0, | |
| "draw_icons": 0 | |
| } | |
| }, | |
| "live_db": {} | |
| }"#; | |
| fn test_baton_pass_restriction() { | |
| let db = CardDatabase::from_json(TEST_CARDS).unwrap(); | |
| let mut state = GameState { | |
| core: CoreGameState { | |
| players: [ | |
| PlayerState { | |
| player_id: 0, | |
| hand: vec![0, 0].into(), // Two test members | |
| deck: vec![0].into(), // Non-empty deck to avoid Terminal | |
| ..PlayerState::default() | |
| }, | |
| PlayerState { | |
| player_id: 1, | |
| deck: vec![0].into(), // Non-empty deck to avoid Terminal | |
| ..PlayerState::default() | |
| }, | |
| ], | |
| phase: Phase::Main, | |
| ..CoreGameState::default() | |
| }, | |
| ..GameState::default() | |
| }; | |
| // 1. First play to slot 0 should succeed | |
| state | |
| .play_member(&db, 0, 0) | |
| .expect("First play should succeed"); | |
| assert_eq!(state.players[0].stage[0], 0); | |
| assert!(state.players[0].is_moved(0)); | |
| // 2. Second play (Baton Pass) to the SAME slot in the SAME turn should fail (Rule 9.6.2.1.2.1) | |
| let result = state.play_member(&db, 0, 0); | |
| assert!( | |
| result.is_err(), | |
| "Second play to same slot should fail this turn" | |
| ); | |
| assert_eq!( | |
| result.unwrap_err(), | |
| "Already played/moved to this slot this turn" | |
| ); | |
| // 3. get_legal_actions_into should also mask out slot 0 | |
| let mut mask = vec![false; 2000]; | |
| state.get_legal_actions_into(&db, 0, &mut mask); | |
| // Action ID for hand_idx 0, slot 0 | |
| let aid_0 = (ACTION_BASE_HAND + 0 * 3 + 0) as usize; | |
| assert!( | |
| !mask[aid_0], | |
| "Play to slot 0 should be masked out in legal actions" | |
| ); | |
| // Action ID for hand_idx 0, slot 1 | |
| let aid_1 = (ACTION_BASE_HAND + 0 * 3 + 1) as usize; | |
| assert!(mask[aid_1], "Play to slot 1 should still be legal"); | |
| // 4. End turn and start new turn | |
| state.end_main_phase(&db); // This advances to next player's Active phase (if first player) | |
| // Fast forward back to Player 0's Main Phase | |
| state.current_player = 0; | |
| state.phase = Phase::Main; | |
| state.players[0].untap_all(false); // This should reset moved_members_this_turn | |
| assert!(!state.players[0].is_moved(0)); | |
| // 5. Now Baton Pass to slot 0 should be legal | |
| state.get_legal_actions_into(&db, 0, &mut mask); | |
| assert!( | |
| mask[aid_0], | |
| "Play to slot 0 should be legal in the next turn" | |
| ); | |
| state | |
| .play_member(&db, 0, 0) | |
| .expect("Baton pass in next turn should succeed"); | |
| assert_eq!(state.players[0].baton_touch_count, 1); | |
| } | |