|
- use std::cmp::min;
- use std::ops::{Index, IndexMut, Mul};
-
- use glc::vector::Vector2f;
- use serde::{Deserialize, Serialize};
- use specs::{Component, Entity, VecStorage};
-
- #[derive(Clone, Debug, Serialize, Deserialize)]
- pub struct Ship {
- type_: Type,
-
- #[serde(skip)]
- obstacle: Obstacle,
-
- #[serde(skip)]
- target_pos: Vector2f,
-
- #[serde(skip)]
- target_dir: Vector2f,
- }
-
- #[derive(Copy, Clone, Debug, PartialEq, Eq)]
- pub enum Obstacle {
- Known(Entity),
- Search,
- Done,
- }
-
- #[derive(Copy, Clone, Debug, Default)]
- pub struct Count {
- pub fighter: usize,
- pub bomber: usize,
- pub transporter: usize,
- }
-
- #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
- pub enum Type {
- Fighter,
- Bomber,
- Transporter,
- }
-
- impl Ship {
- #[inline]
- pub fn new(type_: Type) -> Self {
- Self {
- type_,
- obstacle: Default::default(),
- target_pos: Default::default(),
- target_dir: Default::default(),
- }
- }
-
- #[inline]
- pub fn type_(&self) -> Type {
- self.type_
- }
-
- #[inline]
- pub fn target_pos(&self) -> &Vector2f {
- &self.target_pos
- }
-
- #[inline]
- pub fn target_dir(&self) -> &Vector2f {
- &self.target_dir
- }
-
- #[inline]
- pub(crate) fn set_target(&mut self, pos: Vector2f, dir: Vector2f) {
- self.target_pos = pos;
- self.target_dir = dir;
- }
-
- #[inline]
- pub fn obstacle(&self) -> Obstacle {
- self.obstacle
- }
-
- #[inline]
- pub(crate) fn set_obstacle(&mut self, value: Obstacle) {
- self.obstacle = value;
- }
- }
-
- impl Component for Ship {
- type Storage = VecStorage<Self>;
- }
-
- impl Default for Obstacle {
- fn default() -> Self {
- Self::Search
- }
- }
-
- impl Count {
- pub fn all() -> Self {
- Self {
- fighter: usize::MAX,
- bomber: usize::MAX,
- transporter: usize::MAX,
- }
- }
-
- pub fn none() -> Self {
- Self {
- fighter: 0,
- bomber: 0,
- transporter: 0,
- }
- }
-
- pub fn total(&self) -> usize {
- self.fighter
- .saturating_add(self.bomber)
- .saturating_add(self.transporter)
- }
-
- pub fn merge(&self, other: &Self) -> Self {
- Self {
- fighter: min(self.fighter, other.fighter),
- bomber: min(self.bomber, other.bomber),
- transporter: min(self.transporter, other.transporter),
- }
- }
-
- pub fn is_all(&self) -> bool {
- self.fighter == usize::MAX && self.bomber == usize::MAX && self.transporter == usize::MAX
- }
- }
-
- impl Index<usize> for Count {
- type Output = usize;
-
- fn index(&self, index: usize) -> &Self::Output {
- match index {
- 0 => &self.fighter,
- 1 => &self.bomber,
- 2 => &self.transporter,
- x => panic!("Invalid ship count index: {}", x),
- }
- }
- }
-
- impl IndexMut<usize> for Count {
- fn index_mut(&mut self, index: usize) -> &mut Self::Output {
- match index {
- 0 => &mut self.fighter,
- 1 => &mut self.bomber,
- 2 => &mut self.transporter,
- x => panic!("Invalid ship count index: {}", x),
- }
- }
- }
-
- impl Index<Type> for Count {
- type Output = usize;
-
- fn index(&self, index: Type) -> &Self::Output {
- match index {
- Type::Fighter => &self.fighter,
- Type::Bomber => &self.bomber,
- Type::Transporter => &self.transporter,
- }
- }
- }
-
- impl IndexMut<Type> for Count {
- fn index_mut(&mut self, index: Type) -> &mut Self::Output {
- match index {
- Type::Fighter => &mut self.fighter,
- Type::Bomber => &mut self.bomber,
- Type::Transporter => &mut self.transporter,
- }
- }
- }
-
- impl Mul<f32> for Count {
- type Output = Count;
-
- #[allow(unused_assignments)]
- fn mul(self, rhs: f32) -> Self::Output {
- let expected = self.total() as f32;
- let expected = (rhs * expected).ceil() as usize;
-
- let mut fighter = (rhs * self.fighter as f32) as usize;
- let mut bomber = (rhs * self.bomber as f32) as usize;
- let mut transporter = (rhs * self.transporter as f32) as usize;
-
- let mut actual = fighter.saturating_add(bomber).saturating_add(transporter);
-
- if actual < expected && fighter < self.fighter {
- fighter += 1;
- actual += 1;
- }
-
- if actual < expected && bomber < self.bomber {
- bomber += 1;
- actual += 1;
- }
-
- if actual < expected && transporter < self.transporter {
- transporter += 1;
- actual += 1;
- }
-
- Count {
- fighter,
- bomber,
- transporter,
- }
- }
- }
|