Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

163 righe
3.7 KiB

  1. use std::cmp::min;
  2. use std::ops::{Index, IndexMut, Mul};
  3. use glc::{matrix::Angle, vector::Vector2f};
  4. use serde::{Deserialize, Serialize};
  5. use specs::{Component, Entity, VecStorage};
  6. #[derive(Clone, Debug, Serialize, Deserialize)]
  7. pub struct Ship {
  8. pub type_: Type,
  9. pub agility: Angle<f32>,
  10. pub target_pos: Vector2f,
  11. pub target_dir: Vector2f,
  12. #[serde(skip)]
  13. pub obstacle: Obstacle,
  14. }
  15. #[derive(Copy, Clone, Debug, PartialEq, Eq)]
  16. pub enum Obstacle {
  17. Known(Entity),
  18. Search,
  19. Done,
  20. }
  21. #[derive(Copy, Clone, Debug, Default)]
  22. pub struct Count {
  23. pub fighter: usize,
  24. pub bomber: usize,
  25. pub transporter: usize,
  26. }
  27. #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
  28. pub enum Type {
  29. Fighter,
  30. Bomber,
  31. Transporter,
  32. }
  33. impl Component for Ship {
  34. type Storage = VecStorage<Self>;
  35. }
  36. impl Default for Obstacle {
  37. fn default() -> Self {
  38. Self::Search
  39. }
  40. }
  41. impl Count {
  42. pub fn all() -> Self {
  43. Self {
  44. fighter: usize::MAX,
  45. bomber: usize::MAX,
  46. transporter: usize::MAX,
  47. }
  48. }
  49. pub fn none() -> Self {
  50. Self {
  51. fighter: 0,
  52. bomber: 0,
  53. transporter: 0,
  54. }
  55. }
  56. pub fn total(&self) -> usize {
  57. self.fighter
  58. .saturating_add(self.bomber)
  59. .saturating_add(self.transporter)
  60. }
  61. pub fn merge(&self, other: &Self) -> Self {
  62. Self {
  63. fighter: min(self.fighter, other.fighter),
  64. bomber: min(self.bomber, other.bomber),
  65. transporter: min(self.transporter, other.transporter),
  66. }
  67. }
  68. }
  69. impl Index<usize> for Count {
  70. type Output = usize;
  71. fn index(&self, index: usize) -> &Self::Output {
  72. match index {
  73. 0 => &self.fighter,
  74. 1 => &self.bomber,
  75. 2 => &self.transporter,
  76. x => panic!("Invalid ship count index: {}", x),
  77. }
  78. }
  79. }
  80. impl IndexMut<usize> for Count {
  81. fn index_mut(&mut self, index: usize) -> &mut Self::Output {
  82. match index {
  83. 0 => &mut self.fighter,
  84. 1 => &mut self.bomber,
  85. 2 => &mut self.transporter,
  86. x => panic!("Invalid ship count index: {}", x),
  87. }
  88. }
  89. }
  90. impl Index<Type> for Count {
  91. type Output = usize;
  92. fn index(&self, index: Type) -> &Self::Output {
  93. match index {
  94. Type::Fighter => &self.fighter,
  95. Type::Bomber => &self.bomber,
  96. Type::Transporter => &self.transporter,
  97. }
  98. }
  99. }
  100. impl IndexMut<Type> for Count {
  101. fn index_mut(&mut self, index: Type) -> &mut Self::Output {
  102. match index {
  103. Type::Fighter => &mut self.fighter,
  104. Type::Bomber => &mut self.bomber,
  105. Type::Transporter => &mut self.transporter,
  106. }
  107. }
  108. }
  109. impl Mul<f32> for Count {
  110. type Output = Count;
  111. #[allow(unused_assignments)]
  112. fn mul(self, rhs: f32) -> Self::Output {
  113. let expected = self.total() as f32;
  114. let expected = (rhs * expected).ceil() as usize;
  115. let mut fighter = (rhs * self.fighter as f32) as usize;
  116. let mut bomber = (rhs * self.bomber as f32) as usize;
  117. let mut transporter = (rhs * self.transporter as f32) as usize;
  118. let mut actual = fighter.saturating_add(bomber).saturating_add(transporter);
  119. if actual < expected && fighter < self.fighter {
  120. fighter += 1;
  121. actual += 1;
  122. }
  123. if actual < expected && bomber < self.bomber {
  124. bomber += 1;
  125. actual += 1;
  126. }
  127. if actual < expected && transporter < self.transporter {
  128. transporter += 1;
  129. actual += 1;
  130. }
  131. Count {
  132. fighter,
  133. bomber,
  134. transporter,
  135. }
  136. }
  137. }