use crate::{
engine::core::GameEngine,
ids::PlayerId,
model::action::Action,
error::CardinalError,
};
pub fn validate(engine: &GameEngine, player: PlayerId, action: &Action) -> Result<(), CardinalError> {
if engine.state.ended.is_some() {
return Err(CardinalError("Game has ended".to_string()));
}
match action {
Action::PassPriority => {
if player != engine.state.turn.priority_player {
return Err(CardinalError(format!(
"Only priority player ({:?}) can pass priority",
engine.state.turn.priority_player
)));
}
Ok(())
}
Action::Concede => {
Ok(())
}
Action::PlayCard { card, from } => {
if player != engine.state.turn.active_player {
return Err(CardinalError(format!(
"Only active player ({:?}) can take this action",
engine.state.turn.active_player
)));
}
let current_phase = engine.rules.turn.phases.iter()
.find(|p| p.id.as_str() == engine.state.turn.phase.0)
.ok_or_else(|| CardinalError("Invalid phase".to_string()))?;
if !current_phase.allow_actions {
return Err(CardinalError(format!(
"Current phase '{}' does not allow card plays",
current_phase.name
)));
}
let zone = engine.state.zones.iter()
.find(|z| z.id == *from)
.ok_or_else(|| CardinalError("Source zone does not exist".to_string()))?;
if let Some(owner) = zone.owner {
if owner != player {
return Err(CardinalError("Cannot play cards from opponent's zones".to_string()));
}
}
if !zone.cards.contains(card) {
return Err(CardinalError("Card is not in the specified source zone".to_string()));
}
if let Some(action_def) = engine.rules.actions.iter()
.find(|a| a.id == "play_card")
{
if action_def.requires_empty_stack && !engine.state.stack.is_empty() {
return Err(CardinalError(
"Cannot play card: stack is not empty and action requires empty stack"
.to_string(),
));
}
}
Ok(())
}
Action::ChooseTarget { choice_id, target: _ } => {
match &engine.state.pending_choice {
Some(choice) if choice.id == *choice_id => Ok(()),
Some(choice) => Err(CardinalError(format!(
"Choice ID mismatch: expected {}, got {}",
choice.id, choice_id
))),
None => Err(CardinalError("No pending choice to respond to".to_string())),
}
}
}
}