use crate::types::{Direction, simulation::Board, wire};

use super::{
    Ruleset,
    standard::{DamageHazards, eliminate_snakes, feed_snakes, move_snakes, reduce_snake_health},
};

#[derive(Debug, Clone, Copy)]
pub struct Solo {
    damage_hazards: DamageHazards,
}

impl From<&wire::Ruleset> for Solo {
    fn from(value: &wire::Ruleset) -> Self {
        Self {
            damage_hazards: (&value.settings).into(),
        }
    }
}

impl Ruleset for Solo {
    fn execute(&self, board: &mut Board, actions: &[(u8, Direction)]) -> bool {
        let game_over = game_over(board);
        move_snakes(board, actions);
        reduce_snake_health(board);
        self.damage_hazards.execute(board);
        feed_snakes(board);
        eliminate_snakes(board);
        board.update_free_map();
        game_over
    }
}

pub fn game_over(board: &Board) -> bool {
    board.num_snakes() == 0
}
