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

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

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

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

impl Ruleset for Constrictor {
    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);
        eliminate_snakes(board);
        grow_snakes(board);
        board.update_free_map();
        game_over
    }
}

fn grow_snakes(board: &mut Board) {
    for snake in &mut board.snakes {
        snake.feed();
    }
}
