1pub mod cost_field;
5pub mod flow_field;
6pub mod integration_field;
7
8use std::{collections::BTreeMap, time::Duration};
9
10use crate::prelude::*;
11use bevy::prelude::*;
12
13pub trait Field<T> {
15 fn get(&self) -> &[[T; FIELD_RESOLUTION]; FIELD_RESOLUTION];
17 fn get_field_cell_value(&self, field_cell: FieldCell) -> T;
19 fn set_field_cell_value(&mut self, value: T, field_cell: FieldCell);
21}
22
23#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
25#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash, Reflect)]
26pub struct FieldCell((usize, usize));
27
28impl std::fmt::Display for FieldCell {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(f, "Column: {}, Row: {}", self.0 .0, self.0 .1)
31 }
32}
33
34impl FieldCell {
35 pub fn new(column: usize, row: usize) -> Self {
37 FieldCell((column, row))
38 }
39 pub fn get_column_row(&self) -> (usize, usize) {
41 self.0
42 }
43 pub fn get_column(&self) -> usize {
45 self.0 .0
46 }
47 pub fn get_row(&self) -> usize {
49 self.0 .1
50 }
51 pub fn get_boundary_ordinal_from_field_cell(&self) -> Vec<Ordinal> {
53 let mut boundaries = Vec::new();
54 if self.get_row() == 0 {
55 boundaries.push(Ordinal::North);
56 }
57 if self.get_column() == FIELD_RESOLUTION - 1 {
58 boundaries.push(Ordinal::East);
59 }
60 if self.get_row() == FIELD_RESOLUTION - 1 {
61 boundaries.push(Ordinal::South);
62 }
63 if self.get_column() == 0 {
64 boundaries.push(Ordinal::West);
65 }
66 if !boundaries.is_empty() {
67 boundaries
68 } else {
69 panic!("{:?} does not sit along the boundary", self);
70 }
71 }
72 pub fn get_cells_between_points(&self, target: &FieldCell) -> Vec<FieldCell> {
74 let source_col = self.get_column() as i32;
75 let source_row = self.get_row() as i32;
76 let target_col = target.get_column() as i32;
77 let target_row = target.get_row() as i32;
78
79 if source_col == target_col {
81 let mut fields = Vec::new();
82 if source_row < target_row {
83 for row in source_row..=target_row {
84 fields.push(FieldCell::new(source_col as usize, row as usize));
85 }
86 fields
87 } else {
88 for row in target_row..=source_row {
89 fields.push(FieldCell::new(source_col as usize, row as usize));
90 }
91 fields.reverse(); fields
93 }
94 } else if source_row == target_row {
95 let mut fields = Vec::new();
96 if source_col < target_col {
97 for col in source_col..=target_col {
98 fields.push(FieldCell::new(col as usize, source_row as usize));
99 }
100 fields
101 } else {
102 for col in target_col..=source_col {
103 fields.push(FieldCell::new(col as usize, source_row as usize));
104 }
105 fields.reverse();
106 fields
107 }
108 } else if (target_row - source_row).abs() < (target_col - source_col).abs() {
109 if source_col > target_col {
110 let mut fields =
111 walk_bresenham_shallow(target_col, target_row, source_col, source_row);
112 fields.reverse();
114 fields
115 } else {
116 walk_bresenham_shallow(source_col, source_row, target_col, target_row)
117 }
118 } else if source_row > target_row {
119 let mut fields = walk_bresenham_steep(target_col, target_row, source_col, source_row);
120 fields.reverse();
121 fields
122 } else {
123 walk_bresenham_steep(source_col, source_row, target_col, target_row)
124 }
125 }
126}
127fn walk_bresenham_shallow(col_0: i32, row_0: i32, col_1: i32, row_1: i32) -> Vec<FieldCell> {
129 let mut cells = Vec::new();
130
131 let delta_col = col_1 - col_0;
132 let mut delta_row = row_1 - row_0;
133
134 let mut row_increment = 1;
135 if delta_row < 0 {
136 row_increment = -1;
137 delta_row *= -1;
138 }
139 let mut difference = 2 * delta_row - delta_col;
140 let mut row = row_0;
141
142 for col in col_0..=col_1 {
143 cells.push(FieldCell::new(col as usize, row as usize));
144 if difference > 0 {
145 row += row_increment;
146 difference += 2 * (delta_row - delta_col);
147 } else {
148 difference += 2 * delta_row;
149 }
150 }
151 cells
152}
153fn walk_bresenham_steep(col_0: i32, row_0: i32, col_1: i32, row_1: i32) -> Vec<FieldCell> {
155 let mut cells = Vec::new();
156
157 let mut delta_col = col_1 - col_0;
158 let delta_row = row_1 - row_0;
159
160 let mut col_increment = 1;
161 if delta_col < 0 {
162 col_increment = -1;
163 delta_col *= -1;
164 }
165 let mut difference = 2 * delta_col - delta_row;
166 let mut col = col_0;
167
168 for row in row_0..=row_1 {
169 cells.push(FieldCell::new(col as usize, row as usize));
170 if difference > 0 {
171 col += col_increment;
172 difference += 2 * (delta_col - delta_row);
173 } else {
174 difference += 2 * delta_col;
175 }
176 }
177 cells
178}
179
180#[derive(Clone, Copy, Debug, Reflect)]
182#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
183pub struct RouteMetadata {
184 source_sector: SectorID,
186 source_field: FieldCell,
188 target_sector: SectorID,
190 target_goal: FieldCell,
192 time_generated: Duration,
195}
196impl PartialEq for RouteMetadata {
198 fn eq(&self, other: &Self) -> bool {
199 self.source_sector == other.source_sector
200 && self.source_field == other.source_field
201 && self.target_sector == other.target_sector
202 && self.target_goal == other.target_goal
203 }
204}
205impl Eq for RouteMetadata {}
206
207impl Ord for RouteMetadata {
208 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
209 (
210 self.source_sector,
211 self.source_field,
212 self.target_sector,
213 self.target_goal,
214 )
215 .cmp(&(
216 other.source_sector,
217 other.source_field,
218 other.target_sector,
219 other.target_goal,
220 ))
221 }
222}
223
224impl PartialOrd for RouteMetadata {
225 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
226 Some(self.cmp(other))
227 }
228}
229
230impl RouteMetadata {
231 pub fn new(
233 source_sector: SectorID,
234 source_field: FieldCell,
235 target_sector: SectorID,
236 target_goal: FieldCell,
237 time_generated: Duration,
238 ) -> Self {
239 RouteMetadata {
240 source_sector,
241 source_field,
242 target_sector,
243 target_goal,
244 time_generated,
245 }
246 }
247 pub fn get_source_sector(&self) -> SectorID {
249 self.source_sector
250 }
251 pub fn get_source_field_cell(&self) -> FieldCell {
253 self.source_field
254 }
255 pub fn get_target_sector(&self) -> SectorID {
257 self.target_sector
258 }
259 pub fn get_target_goal(&self) -> FieldCell {
261 self.target_goal
262 }
263 pub fn get_time_generated(&self) -> Duration {
265 self.time_generated
266 }
267}
268
269#[derive(Default, Clone, Debug, Reflect)]
271#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
272pub struct Route(Vec<(SectorID, FieldCell)>);
273
274impl Route {
275 pub fn get(&self) -> &Vec<(SectorID, FieldCell)> {
277 &self.0
278 }
279 pub fn get_mut(&mut self) -> &mut Vec<(SectorID, FieldCell)> {
281 &mut self.0
282 }
283 pub fn new(path: Vec<(SectorID, FieldCell)>) -> Self {
285 Route(path)
286 }
287}
288
289#[derive(Component, Default, Clone, Reflect)]
291#[reflect(Component)]
292#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
293pub struct RouteCache {
294 route_queue: BTreeMap<RouteMetadata, Route>,
296 routes: BTreeMap<RouteMetadata, Route>,
298}
299
300impl RouteCache {
301 pub fn get_queue(&self) -> &BTreeMap<RouteMetadata, Route> {
303 &self.route_queue
304 }
305 pub fn get_queue_mut(&mut self) -> &mut BTreeMap<RouteMetadata, Route> {
307 &mut self.route_queue
308 }
309 pub fn get_routes(&self) -> &BTreeMap<RouteMetadata, Route> {
311 &self.routes
312 }
313 pub fn get_mut(&mut self) -> &mut BTreeMap<RouteMetadata, Route> {
315 &mut self.routes
316 }
317 pub fn get_route(
319 &self,
320 source_sector: SectorID,
321 source_field: FieldCell,
322 target_sector: SectorID,
323 goal_id: FieldCell,
324 ) -> Option<&Route> {
325 let route_data = RouteMetadata {
326 source_sector,
327 source_field,
328 target_sector,
329 target_goal: goal_id,
330 time_generated: Duration::default(),
331 };
332 let route = self.routes.get(&route_data);
333 route
334 }
335 pub fn get_route_with_metadata(
337 &self,
338 source_sector: SectorID,
339 source_field: FieldCell,
340 target_sector: SectorID,
341 goal_id: FieldCell,
342 ) -> Option<(&RouteMetadata, &Route)> {
343 let route_data = RouteMetadata {
344 source_sector,
345 source_field,
346 target_sector,
347 target_goal: goal_id,
348 time_generated: Duration::default(),
349 };
350 let route = self.routes.get_key_value(&route_data);
351 route
352 }
353 pub fn add_to_queue(&mut self, route_data: RouteMetadata, route: Route) {
355 self.route_queue.insert(route_data, route);
356 }
357 pub fn insert_route(
359 &mut self,
360 source_sector: SectorID,
361 source_field: FieldCell,
362 target_sector: SectorID,
363 goal_id: FieldCell,
364 elapsed_duration: Duration,
365 route: Route,
366 ) {
367 let route_data = RouteMetadata {
368 source_sector,
369 source_field,
370 target_sector,
371 target_goal: goal_id,
372 time_generated: elapsed_duration,
373 };
374 self.routes.insert(route_data, route);
375 }
376 pub fn insert_route_with_metadata(&mut self, route_metadata: RouteMetadata, route: Route) {
378 self.routes.insert(route_metadata, route);
379 }
380 pub fn remove_route(&mut self, route_metadata: RouteMetadata) {
382 self.routes.remove(&route_metadata);
383 }
384 pub fn remove_queued_route(&mut self, route_metadata: RouteMetadata) {
387 self.route_queue.remove(&route_metadata);
388 }
389}
390#[derive(Clone, Copy, Reflect)]
392#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
393pub struct FlowFieldMetadata {
394 sector_id: SectorID,
396 goal_id: Option<FieldCell>,
398 portal_id: Option<FieldCell>,
400 time_generated: Duration,
403}
404impl PartialEq for FlowFieldMetadata {
406 fn eq(&self, other: &Self) -> bool {
407 self.sector_id == other.sector_id
408 && self.goal_id == other.goal_id
409 && self.portal_id == other.portal_id
410 }
411}
412impl Eq for FlowFieldMetadata {}
413impl Ord for FlowFieldMetadata {
414 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
415 (self.sector_id, self.goal_id, self.portal_id).cmp(&(
416 other.sector_id,
417 other.goal_id,
418 other.portal_id,
419 ))
420 }
421}
422impl PartialOrd for FlowFieldMetadata {
423 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
424 Some(self.cmp(other))
425 }
426}
427
428impl FlowFieldMetadata {
429 pub fn get_sector_id(&self) -> SectorID {
431 self.sector_id
432 }
433 pub fn get_goal_id(&self) -> Option<FieldCell> {
435 self.goal_id
436 }
437 pub fn get_portal_id(&self) -> Option<FieldCell> {
439 self.portal_id
440 }
441 pub fn get_time_generated(&self) -> Duration {
443 self.time_generated
444 }
445}
446
447#[derive(Component, Default, Reflect)]
454#[reflect(Component)]
455#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
456pub struct FlowFieldCache {
457 queue: BTreeMap<RouteMetadata, IntegrationBuilder>,
460 flows: BTreeMap<FlowFieldMetadata, FlowField>,
462}
463
464impl FlowFieldCache {
465 pub fn get(&self) -> &BTreeMap<FlowFieldMetadata, FlowField> {
467 &self.flows
468 }
469 pub fn get_mut(&mut self) -> &mut BTreeMap<FlowFieldMetadata, FlowField> {
471 &mut self.flows
472 }
473 pub fn get_queue_mut(&mut self) -> &mut BTreeMap<RouteMetadata, IntegrationBuilder> {
475 &mut self.queue
476 }
477 pub fn add_to_queue(
479 &mut self,
480 metadata: RouteMetadata,
481 path: Route,
482 cost_fields: &SectorCostFields,
483 ) {
484 let int_builder = IntegrationBuilder::new(path, cost_fields);
485 self.queue.insert(metadata, int_builder);
486 }
487 pub fn get_field(
490 &self,
491 current_sector_id: SectorID,
492 goal_sector_id: SectorID,
493 goal_id: FieldCell,
494 ) -> Option<&FlowField> {
495 if current_sector_id == goal_sector_id {
496 let flow_meta = FlowFieldMetadata {
497 sector_id: current_sector_id,
498 goal_id: Some(goal_id),
499 portal_id: None,
500 time_generated: Duration::default(),
501 };
502 self.flows.get(&flow_meta)
503 } else {
504 let flow_meta = FlowFieldMetadata {
505 sector_id: current_sector_id,
506 goal_id: None,
507 portal_id: Some(goal_id),
508 time_generated: Duration::default(),
509 };
510 self.flows.get(&flow_meta)
511 }
512 }
513 pub fn insert_field(
515 &mut self,
516 sector_id: SectorID,
517 goal_id: Option<FieldCell>,
518 portal_id: Option<FieldCell>,
519 elapsed_duration: Duration,
520 field: FlowField,
521 ) {
522 let flow_meta = FlowFieldMetadata {
523 sector_id,
524 goal_id,
525 portal_id,
526 time_generated: elapsed_duration,
527 };
528 self.flows.insert(flow_meta, field);
529 }
530 pub fn remove_field(&mut self, flow_meta: FlowFieldMetadata) {
533 self.flows.remove(&flow_meta);
534 }
535 pub fn remove_queue_item(&mut self, route_meta: RouteMetadata) {
538 self.queue.remove(&route_meta);
539 }
540}
541
542#[cfg(test)]
543mod tests {
544 use super::*;
545 #[test]
546 fn field_cell_line_horizontal() {
547 let source = FieldCell::new(3, 4);
548 let target = FieldCell::new(7, 4);
549 let result = source.get_cells_between_points(&target);
550 let actual: Vec<FieldCell> = vec![
551 FieldCell::new(3, 4),
552 FieldCell::new(4, 4),
553 FieldCell::new(5, 4),
554 FieldCell::new(6, 4),
555 FieldCell::new(7, 4),
556 ];
557 assert_eq!(actual, result);
558 }
559 #[test]
560 fn field_cell_line_horizontal_reverse() {
561 let source = FieldCell::new(7, 4);
562 let target = FieldCell::new(3, 4);
563 let result = source.get_cells_between_points(&target);
564 let actual: Vec<FieldCell> = vec![
565 FieldCell::new(7, 4),
566 FieldCell::new(6, 4),
567 FieldCell::new(5, 4),
568 FieldCell::new(4, 4),
569 FieldCell::new(3, 4),
570 ];
571 assert_eq!(actual, result);
572 }
573 #[test]
574 fn field_cell_line_vertical() {
575 let source = FieldCell::new(3, 4);
576 let target = FieldCell::new(3, 7);
577 let result = source.get_cells_between_points(&target);
578 let actual: Vec<FieldCell> = vec![
579 FieldCell::new(3, 4),
580 FieldCell::new(3, 5),
581 FieldCell::new(3, 6),
582 FieldCell::new(3, 7),
583 ];
584 assert_eq!(actual, result);
585 }
586 #[test]
587 fn field_cell_line_vertical_reverse() {
588 let source = FieldCell::new(3, 7);
589 let target = FieldCell::new(3, 4);
590 let result = source.get_cells_between_points(&target);
591 let actual: Vec<FieldCell> = vec![
592 FieldCell::new(3, 7),
593 FieldCell::new(3, 6),
594 FieldCell::new(3, 5),
595 FieldCell::new(3, 4),
596 ];
597 assert_eq!(actual, result);
598 }
599 #[test]
600 fn field_cell_line_vertical_steep() {
601 let source = FieldCell::new(3, 0);
602 let target = FieldCell::new(4, 9);
603 let result = source.get_cells_between_points(&target);
604 let actual: Vec<FieldCell> = vec![
605 FieldCell::new(3, 0),
606 FieldCell::new(3, 1),
607 FieldCell::new(3, 2),
608 FieldCell::new(3, 3),
609 FieldCell::new(3, 4),
610 FieldCell::new(4, 5),
611 FieldCell::new(4, 6),
612 FieldCell::new(4, 7),
613 FieldCell::new(4, 8),
614 FieldCell::new(4, 9),
615 ];
616 assert_eq!(actual, result);
617 }
618 #[test]
619 fn field_cell_line_pos_gradient() {
620 let source = FieldCell::new(3, 4);
621 let target = FieldCell::new(7, 6);
622 let result = source.get_cells_between_points(&target);
623 let actual: Vec<FieldCell> = vec![
624 FieldCell::new(3, 4),
625 FieldCell::new(4, 4),
626 FieldCell::new(5, 5),
627 FieldCell::new(6, 5),
628 FieldCell::new(7, 6),
629 ];
630 assert_eq!(actual, result);
631 }
632 #[test]
633 fn field_cell_line_pos_gradient_reverse() {
634 let source = FieldCell::new(7, 6);
635 let target = FieldCell::new(3, 4);
636 let result = source.get_cells_between_points(&target);
637 let actual: Vec<FieldCell> = vec![
638 FieldCell::new(7, 6),
639 FieldCell::new(6, 5),
640 FieldCell::new(5, 5),
641 FieldCell::new(4, 4),
642 FieldCell::new(3, 4),
643 ];
644 assert_eq!(actual, result);
645 }
646 #[test]
647 fn field_cell_line_neg_gradient() {
648 let source = FieldCell::new(3, 4);
649 let target = FieldCell::new(7, 2);
650 let result = source.get_cells_between_points(&target);
651 let actual: Vec<FieldCell> = vec![
652 FieldCell::new(3, 4),
653 FieldCell::new(4, 4),
654 FieldCell::new(5, 3),
655 FieldCell::new(6, 3),
656 FieldCell::new(7, 2),
657 ];
658 assert_eq!(actual, result);
659 }
660 #[test]
661 fn field_cell_line_neg_gradient_reverse() {
662 let source = FieldCell::new(7, 2);
663 let target = FieldCell::new(3, 4);
664 let result = source.get_cells_between_points(&target);
665 let actual: Vec<FieldCell> = vec![
666 FieldCell::new(7, 2),
667 FieldCell::new(6, 3),
668 FieldCell::new(5, 3),
669 FieldCell::new(4, 4),
670 FieldCell::new(3, 4),
671 ];
672 assert_eq!(actual, result);
673 }
674 #[test]
675 fn field_cell_line_zero() {
676 let source = FieldCell::new(3, 4);
677 let target = FieldCell::new(3, 4);
678 let result = source.get_cells_between_points(&target);
679 let actual: Vec<FieldCell> = vec![FieldCell::new(3, 4)];
680 assert_eq!(actual, result);
681 }
682}