pathfinding/astar/
astar.rs1use crate::errors::my_errors::RetResult;
2use crate::map::{CloseList, IndexType, Map, MapType, Point};
3use async_trait::async_trait;
4use std::collections::BinaryHeap;
5use std::sync::{Arc};
6use tokio::fs::File;
7use tokio::io::AsyncReadExt;
8use serde::{Deserialize, Serialize};
9
10pub struct AStar {
11 pub col: usize,
12 pub row: usize,
13 pub map: Box<Vec<Vec<i32>>>,
14}
15
16#[derive(Serialize, Deserialize, Debug)]
17struct AstarMapFile {
18 #[serde(rename = "columnCount")]
19 pub column_count: usize,
20 #[serde(rename = "rowCount")]
21 pub row_count: usize,
22 #[serde(rename = "unWalkCells")]
23 pub un_walk_cells: Vec<usize>
24}
25
26#[async_trait]
27impl Map for AStar {
28 fn new() -> MapType {
29 Arc::new(tokio::sync::RwLock::new(AStar {
30 col: 0,
31 row: 0,
32 map: Box::<Vec<Vec<i32>>>::default(),
33 }))
34 }
35
36 fn load(&mut self, points: Vec<Vec<i32>>) -> RetResult<()> {
37 self.col = points[0].len();
38 self.row = points.len();
39 self.map = Box::new(points);
40 Ok(())
41 }
42
43 async fn load_from_file(&mut self, file_name: String) -> RetResult<()> {
44 let mut file = File::open(file_name).await?;
46
47 let mut buffer = Vec::new();
49
50 file.read_to_end(&mut buffer).await?;
52
53 let mut x = Vec::new();
54 for i in buffer {
55 x.push(i as i32);
56 if x.len() == 16 {
57 self.map.push(x.clone());
58 x.clear();
59 }
60 }
61
62 self.col = self.map[0].len();
63 self.row = self.map.len();
64
65 Ok(())
66 }
67
68 async fn load_from_string(&mut self, file_contend: String) -> RetResult<()> {
69
70 let deser: AstarMapFile = serde_json::from_str(&file_contend)?;
72
73 self.map = Box::new(vec![vec![0; deser.column_count]; deser.row_count]);
74
75 self.col = deser.column_count;
76 self.row = deser.row_count;
77
78 for i in 0..deser.un_walk_cells.len() {
79 self.map[deser.un_walk_cells[i] / self.col][deser.un_walk_cells[i] % self.col] = 1;
80 }
81
82 Ok(())
83 }
84
85 fn find_path(
86 &self,
87 start: (IndexType, IndexType),
88 end: (IndexType, IndexType),
89 ) -> Vec<(IndexType, IndexType)> {
90 let (start_x, start_y) = start;
91 let (end_x, end_y) = end;
92
93 let mut open_list = BinaryHeap::with_capacity(self.col + self.row);
94 let mut close_list = CloseList::new(self.col, self.row);
95 let mut parent = vec![vec![(0, 0); self.col]; self.row];
96 let mut g_score = vec![vec![i32::MAX; self.col]; self.row];
97 let mut f_score = vec![vec![i32::MAX; self.col]; self.row];
98
99 g_score[start_y as usize][start_x as usize] = 0;
100 f_score[start_y as usize][start_x as usize] = dis(start_x, start_y, end_x, end_y);
101
102 open_list.push(Point::new_other(
103 start_x,
104 start_y,
105 f_score[start_y as usize][start_x as usize],
106 0,
107 f_score[start_y as usize][start_x as usize],
108 ));
109
110 while let Some(current) = open_list.pop() {
111 if current.x == end_x && current.y == end_y {
112 let mut path = Vec::with_capacity(128);
113 let mut current = (end_x, end_y);
114 while current != (start_x, start_y) {
115 path.insert(0,(current.0, current.1));
116 current = parent[current.1 as usize][current.0 as usize];
117 }
118 path.insert(0,(start_x, start_y));
119 return path;
120 }
121
122 close_list.insert(¤t);
123
124 for neighbor in current.neighbors() {
125 let ix = current.x + neighbor.0;
126 let iy = current.y + neighbor.1;
127 let x = ix as usize;
128 let y = iy as usize;
129
130 if !self.in_map(ix, iy) {
131 continue;
132 }
133
134 let tentative_g_score = g_score[current.y as usize][current.x as usize] + 1;
135 if tentative_g_score <= g_score[y][x] {
136 parent[y][x] = (current.x, current.y);
137 g_score[y][x] = tentative_g_score;
138 f_score[y][x] = tentative_g_score + dis(ix, iy, end_x, end_y);
139 if !open_list.iter().any(|node| node.x == ix && node.y == iy) {
140 open_list.push(Point::new_other(
141 ix,
142 iy,
143 f_score[y][x],
144 g_score[y][x],
145 dis(ix, iy, end_x, end_y),
146 ));
147 }
148 }
149 }
150 }
151
152 vec![]
153 }
154
155 fn set_walkable(&mut self, point: (IndexType, IndexType), walkable: i32) {
156 self.map[point.1 as usize][point.0 as usize] = walkable;
157 }
158
159 #[inline]
160 fn in_map(&self, x: i32, y: i32) -> bool {
161 let x_usize = x as usize;
162 let y_usize = y as usize;
163
164 match (x, y) {
165 (x, y) if y < 0 || x < 0 => false,
166 (_x, _y) if y_usize >= self.row || x_usize >= self.col => false,
167 _ => self.map[y_usize][x_usize] == 0,
168 }
169 }
170}
171
172#[inline]
173pub fn dis(x: IndexType, y: IndexType, x1: IndexType, y1: IndexType) -> IndexType {
174 let xx = (x1 - x).abs();
175 let xy = (y1 - y).abs();
176
177 let sum = (xx + xy) * 10;
182 let condition = (xx > xy) as i32; (xy * 14 + sum) * (1 - condition) + (xx * 14 + sum) * condition
184}
185
186impl Drop for AStar {
187 fn drop(&mut self) {
188 self.map.clear()
189 }
190}