summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike White <botahamec@outlook.com>2021-08-27 20:46:18 -0400
committerMike White <botahamec@outlook.com>2021-08-27 20:46:18 -0400
commita310274c6d5acea8f5f83f2feb8699e7b312f8e3 (patch)
tree9424e380512df43e64a50ad0824375d7f23b3c25
parent68014734561c3a8d8712916bdfa58b8347131501 (diff)
Highlighted possible moves when a piece is clicked
-rw-r--r--model/src/coordinates.rs10
-rw-r--r--model/src/moves.rs29
-rw-r--r--ui/resources/possible_move.pngbin0 -> 342 bytes
-rw-r--r--ui/src/main.rs55
4 files changed, 88 insertions, 6 deletions
diff --git a/model/src/coordinates.rs b/model/src/coordinates.rs
index a055f46..7aea88b 100644
--- a/model/src/coordinates.rs
+++ b/model/src/coordinates.rs
@@ -7,7 +7,7 @@ pub struct SquareCoordinate {
}
impl SquareCoordinate {
- pub(crate) fn new(rank: u8, file: u8) -> Self {
+ pub fn new(rank: u8, file: u8) -> Self {
if rank > 32 {
panic!("A Square cannot have a rank greater than 32. Got {}", rank)
} else if file > 32 {
@@ -56,6 +56,14 @@ impl SquareCoordinate {
VALUE_COORDINATE_MAP[value]
}
+ pub fn rank(self) -> u8 {
+ self.rank
+ }
+
+ pub fn file(self) -> u8 {
+ self.file
+ }
+
pub fn to_value(self) -> Option<usize> {
if self.rank % 2 == 0 {
if self.file % 2 == 0 {
diff --git a/model/src/moves.rs b/model/src/moves.rs
index b8e58ee..7581b6b 100644
--- a/model/src/moves.rs
+++ b/model/src/moves.rs
@@ -38,6 +38,29 @@ impl Move {
}
}
+ pub const fn start(self) -> u32 {
+ self.start
+ }
+
+ /// Calculates the value of the end position of the move
+ pub const fn end_position(self) -> usize {
+ let dest = match self.jump {
+ false => match self.direction {
+ MoveDirection::ForwardLeft => self.start + 7,
+ MoveDirection::ForwardRight => self.start + 1,
+ MoveDirection::BackwardLeft => self.start - 1,
+ MoveDirection::BackwardRight => self.start - 7,
+ },
+ true => match self.direction {
+ MoveDirection::ForwardLeft => self.start + 14,
+ MoveDirection::ForwardRight => self.start + 2,
+ MoveDirection::BackwardLeft => self.start - 2,
+ MoveDirection::BackwardRight => self.start - 14,
+ },
+ };
+ dest as usize
+ }
+
/// Apply the move to a board. This does not mutate the original board,
/// but instead returns a new one.
///
@@ -92,10 +115,10 @@ impl Move {
#[cfg(test)]
mod tests {
- use proptest::prelude::*;
use super::*;
+ use proptest::prelude::*;
- proptest!{
+ proptest! {
#[test]
fn new(start in 0usize..32, jump in proptest::bool::ANY) {
let direction = MoveDirection::ForwardLeft;
@@ -123,4 +146,4 @@ mod tests {
assert_eq!(move_test.jump, jump);
}
}
-} \ No newline at end of file
+}
diff --git a/ui/resources/possible_move.png b/ui/resources/possible_move.png
new file mode 100644
index 0000000..26cb5e5
--- /dev/null
+++ b/ui/resources/possible_move.png
Binary files differ
diff --git a/ui/src/main.rs b/ui/src/main.rs
index 166b1ae..ba4fbe3 100644
--- a/ui/src/main.rs
+++ b/ui/src/main.rs
@@ -1,7 +1,8 @@
-use model::{CheckersBitBoard, PieceColor};
+use model::{CheckersBitBoard, PieceColor, PossibleMoves, SquareCoordinate};
use tetra::graphics::{self, Color, DrawParams, Texture};
+use tetra::input::MouseButton;
use tetra::math::Vec2;
-use tetra::{Context, ContextBuilder, State};
+use tetra::{input, Context, ContextBuilder, State};
const WINDOW_WIDTH: f32 = 640.0;
const WINDOW_HEIGHT: f32 = 480.0;
@@ -9,27 +10,69 @@ const DARK_SLATE_BLUE: Color = Color::rgb(0.2823529, 0.2392157, 0.5450980);
struct GameState {
chess_board: Texture,
+ possible_move_square: Texture,
dark_piece: Texture,
light_piece: Texture,
dark_king: Texture,
light_king: Texture,
bit_board: CheckersBitBoard,
+ selected_square: Option<SquareCoordinate>,
+ possible_moves: Vec<SquareCoordinate>,
}
impl GameState {
fn new(ctx: &mut Context) -> tetra::Result<Self> {
Ok(GameState {
chess_board: Texture::new(ctx, "./ui/resources/chess_board.png")?,
+ possible_move_square: Texture::new(ctx, "./ui/resources/possible_move.png")?,
dark_piece: Texture::new(ctx, "./ui/resources/red_piece.png")?,
light_piece: Texture::new(ctx, "./ui/resources/white_piece.png")?,
dark_king: Texture::new(ctx, "./ui/resources/red_king.png")?,
light_king: Texture::new(ctx, "./ui/resources/white_king.png")?,
bit_board: CheckersBitBoard::starting_position(),
+ selected_square: None,
+ possible_moves: Vec::new(),
})
}
}
+impl GameState {
+ fn draw_highlighted_square(&self, ctx: &mut Context, square: SquareCoordinate) {
+ let square_draw_params = DrawParams::new()
+ .position(Vec2::new(
+ 120.0 + (50.0 * square.file() as f32),
+ 390.0 - (50.0 * square.rank() as f32),
+ ))
+ .scale(Vec2::new(0.5, 0.5));
+
+ self.possible_move_square.draw(ctx, square_draw_params);
+ }
+}
+
impl State for GameState {
+ fn update(&mut self, ctx: &mut Context) -> tetra::Result {
+ if input::is_mouse_button_released(ctx, MouseButton::Left) {
+ let x = input::get_mouse_x(ctx);
+ let y = input::get_mouse_y(ctx);
+
+ if x > 120.0 && y > 40.0 && x < 520.0 && y < 440.0 {
+ let file = ((x - 140.0) / 50.0).round();
+ let rank = ((410.0 - y) / 50.0).round();
+ let square = SquareCoordinate::new(rank as u8, file as u8);
+ self.selected_square = Some(square);
+
+ let moves = PossibleMoves::moves(self.bit_board);
+ self.possible_moves = moves
+ .into_iter()
+ .filter(|m| SquareCoordinate::from_value(m.start() as usize) == square)
+ .map(|m| SquareCoordinate::from_value(m.end_position()))
+ .collect()
+ }
+ }
+
+ Ok(())
+ }
+
fn draw(&mut self, ctx: &mut Context) -> tetra::Result {
graphics::clear(ctx, DARK_SLATE_BLUE);
@@ -39,6 +82,14 @@ impl State for GameState {
self.chess_board.draw(ctx, board_draw_params);
+ if let Some(square) = self.selected_square {
+ self.draw_highlighted_square(ctx, square);
+ }
+
+ for square in &self.possible_moves {
+ self.draw_highlighted_square(ctx, *square);
+ }
+
for row in 0..8 {
for col in 0..8 {
if let Some(piece) = self.bit_board.get_at_row_col(row, col) {