use crate::app::teams::TeamMode;
use crate::bots::listener::BotId;
use crate::sim::MAX_PLAYERS;
use crate::transport::{IN_SEAT_ORDER, MatchTerms};
#[derive(Clone, Default, PartialEq, Eq, Debug)]
pub struct Arranged {
pub bots: Vec<(BotId, u8)>,
pub ai: Vec<u8>,
}
pub fn picks_hold(teams: TeamMode) -> bool {
teams != TeamMode::Solo
}
pub fn seat_order(wants: &[Option<u8>], ai: &[u8], humans: u8, seats: u8) -> [u8; MAX_PLAYERS] {
let seats = seats.min(MAX_PLAYERS as u8);
let humans = humans.min(seats);
let mut deal = Deal {
order: IN_SEAT_ORDER,
taken: [false; MAX_PLAYERS],
placed: [false; MAX_PLAYERS],
};
deal.put(0, 0);
for place in 1..humans {
if let Some(Some(seat)) = wants.get(usize::from(place))
&& *seat < seats
&& deal.free(*seat)
{
deal.put(place, *seat);
}
}
let mut ai_places = humans..seats;
for &seat in ai {
if seat >= seats || !deal.free(seat) {
continue;
}
let Some(place) = ai_places.next() else {
break;
};
deal.put(place, seat);
}
for place in 0..seats {
if deal.placed[usize::from(place)] {
continue;
}
let Some(seat) = (0..seats).find(|&seat| deal.free(seat)) else {
break;
};
deal.put(place, seat);
}
deal.order
}
struct Deal {
order: [u8; MAX_PLAYERS],
taken: [bool; MAX_PLAYERS],
placed: [bool; MAX_PLAYERS],
}
impl Deal {
fn put(&mut self, place: u8, seat: u8) {
self.order[usize::from(place)] = seat;
self.taken[usize::from(seat)] = true;
self.placed[usize::from(place)] = true;
}
fn free(&self, seat: u8) -> bool {
!self.taken[usize::from(seat)]
}
}
pub fn remember(terms: MatchTerms, seats: u8, bots: &[super::HostedBot]) -> Arranged {
Arranged {
bots: bots.iter().map(|bot| (bot.id, bot.seat)).collect(),
ai: terms.ai_seats(seats),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unarranged_is_in_seat_order() {
assert_eq!(seat_order(&[], &[], 4, 6), IN_SEAT_ORDER);
assert_eq!(seat_order(&[None, None], &[], 2, 4), IN_SEAT_ORDER);
}
#[test]
fn an_arrangement_is_dealt_again() {
let order = seat_order(&[None, Some(2)], &[1, 3], 2, 4);
assert_eq!(&order[..4], [0, 2, 1, 3]);
}
#[test]
fn the_table_changing_keeps_who_stayed() {
let order = seat_order(&[None, Some(3), Some(2)], &[1], 3, 4);
assert_eq!(&order[..4], [0, 3, 2, 1]);
let order = seat_order(&[None, Some(3), None], &[1], 3, 4);
assert_eq!(&order[..4], [0, 3, 2, 1]);
let order = seat_order(&[None, Some(5)], &[], 2, 2);
assert_eq!(&order[..2], [0, 1]);
}
#[test]
fn a_seat_is_held_once() {
let order = seat_order(&[Some(1), Some(0), Some(2), Some(2)], &[], 4, 4);
assert_eq!(&order[..4], [0, 1, 2, 3]);
let mut sorted = order;
sorted.sort_unstable();
assert_eq!(sorted, IN_SEAT_ORDER);
}
}