use super::*;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub(super) struct Steering {
pub(super) by_gull: Vec<(u32, PlayerId)>,
pub(super) taken: [[u32; MAX_PLAYERS]; MAX_PLAYERS],
}
impl Steering {
pub(super) fn steer(&mut self, gull: u32, owner: PlayerId) {
match self.by_gull.iter_mut().find(|(id, _)| *id == gull) {
Some((_, by)) => *by = owner,
None => self.by_gull.push((gull, owner)),
}
}
pub(super) fn steerer(&self, gull: u32) -> Option<PlayerId> {
self.by_gull
.iter()
.find(|(id, _)| *id == gull)
.map(|&(_, by)| by)
}
pub(super) fn credit(&mut self, gull: u32, victim: PlayerId, lost: u32) {
if let Some(by) = self.steerer(gull)
&& let (Some(row), Some(_)) = (seat(by), seat(victim))
{
let cell = &mut self.taken[row][usize::from(victim)];
*cell = cell.saturating_add(lost);
}
}
pub(super) fn keep_only(&mut self, gulls: &[Gull]) {
self.by_gull
.retain(|(id, _)| gulls.iter().any(|gull| gull.id == *id));
}
pub(super) fn copy_from(&mut self, other: &Self) {
let Self { by_gull, taken } = other;
self.by_gull.clear();
self.by_gull.extend_from_slice(by_gull);
self.taken = *taken;
}
}
impl Board {
pub fn gull_steerer(&self, gull: u32) -> Option<PlayerId> {
self.steering.steerer(gull)
}
pub fn stolen(&self, steerer: PlayerId, victim: PlayerId) -> u32 {
match (seat(steerer), seat(victim)) {
(Some(a), Some(v)) => self.steering.taken[a][v],
_ => 0,
}
}
}
pub fn raid_loss(score: u32) -> u32 {
score.div_ceil(3)
}