You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 rivejä
4.7 KiB

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