core_rust/core/game/
game_logic.rs1use crate::core::game::utils::{actions, errors, unit, world};
2use actions::Action;
3use errors::GameError;
4use unit::Unit;
5use world::{Tile, World};
6
7use crate::core::game::{game_variables, state};
8use game_variables::GameVars;
9use state::State;
10
11#[derive(Debug, Clone)]
13pub struct Game {
14 _world_configuration: Vec<Vec<char>>,
15 world: World,
16 unit: Unit,
17 turn: i32,
18}
19
20impl Game {
21 pub fn new(world_vector: Vec<Vec<char>>) -> Result<Self, GameError> {
23 let mut world = World::new(&world_vector)?;
24
25 let unit = Unit::new();
26
27 world.place_unit(unit);
28
29 Ok(Game {
30 world,
31 unit,
32 _world_configuration: world_vector,
33 turn: 0,
34 })
35 }
36
37 pub fn tile(&mut self, x: usize, y: usize) -> &Tile {
39 self.world.get_tile(x, y)
40 }
41
42 pub fn print(&self) {
44 println!("T: {}", self.turn);
45 self.world.print();
46 }
47
48 pub fn get_size(&self) -> usize {
50 self.world.size
51 }
52
53 pub fn reset(&mut self) {
55 self.world = World::new(&self._world_configuration).unwrap();
57 self.unit = Unit::new();
58 self.world.place_unit(self.unit);
59 self.turn = 0;
60 }
61
62 pub fn check_game_done(&self) -> bool {
64 self.unit.get_position() == self.world.goal
65 }
66
67 fn get_score(&self) -> f32 {
69 if self.unit.get_position() == self.world.goal {
70 return 1.0;
71 }
72 0.0
73 }
74
75 pub fn goal(&self) -> (usize, usize) {
77 self.world.goal
78 }
79
80 pub fn world_configuration(&self) -> Vec<Vec<char>> {
82 self._world_configuration.clone()
83 }
84
85 fn move_unit(&mut self, action: &Action) -> Result<(), GameError> {
87 if self.unit.get_movement() <= 0 {
88 return Ok(());
89 }
90
91 let (dx, dy): (isize, isize) = match action {
92 Action::Up => (0, -1),
93 Action::Down => (0, 1),
94 Action::Left => (-1, 0),
95 Action::Right => (1, 0),
96 _ => {
97 return Err(GameError::InvalidAction { action: *action });
98 }
99 };
100
101 let (old_x, old_y) = self.unit.get_position();
102 let (new_x, new_y) = (old_x as isize + dx, old_y as isize + dy);
103
104 if new_x < 0
106 || new_y < 0
107 || new_x >= self.world.size as isize
108 || new_y >= self.world.size as isize
109 {
110 self.unit.deduct_movement();
111 return Ok(());
112 }
113 let (new_x_u, new_y_u) = (new_x as usize, new_y as usize);
115 if self.world.get_tile(new_x_u, new_y_u).is_walkable() {
116 match self.world.remove_unit() {
117 Ok(()) => {
118 self.unit.set_position(new_x_u, new_y_u);
119 self.world.place_unit(self.unit);
120 }
121 Err(e) => {
122 return Err(e);
123 }
124 }
125 }
126
127 Ok(())
128 }
129
130 pub fn get_state(&self) -> State {
132 let valid_moves = vec![Action::Up, Action::Down, Action::Left, Action::Right];
133 let unit_position = self.unit.get_position();
134 State::new(unit_position, valid_moves)
135 }
136
137 pub fn step(&mut self, action: &Action) -> Result<(State, GameVars), GameError> {
139 match self.move_unit(action) {
140 Ok(()) => {
141 self.turn += 1;
142 self.unit.reset_movement();
143 let return_tuple = (
144 self.get_state(),
145 GameVars::new(self.turn, self.get_score(), self.check_game_done()),
146 );
147 Ok(return_tuple)
148 }
149 Err(e) => Err(e),
150 }
151 }
152
153 fn set_state(&mut self, state: &State) -> Result<(), GameError> {
155 let (new_x, new_y) = state.unit_position;
156 match self.world.remove_unit() {
157 Ok(()) => {
158 self.unit.set_position(new_x, new_y);
159 self.world.place_unit(self.unit);
160 self.unit.reset_movement();
161 Ok(())
162 }
163 Err(e) => Err(e),
164 }
165 }
166
167 pub fn simulate(
169 &self,
170 initial_state: &State,
171 action: &Action,
172 ) -> Result<(State, GameVars), GameError> {
173 let mut copied_game = self.clone();
174 match copied_game.set_state(initial_state) {
175 Ok(()) => match copied_game.step(action) {
176 Ok((state, game_variables)) => Ok((state, game_variables)),
177 Err(e) => Err(e),
178 },
179 Err(e) => Err(e),
180 }
181 }
182}