|
|
|
|
@ -98,6 +98,7 @@ impl std::fmt::Display for Piece {
|
|
|
|
|
pub(crate) enum GameError {
|
|
|
|
|
NullMove,
|
|
|
|
|
InvalidIndex,
|
|
|
|
|
InvalidMove,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The board is setup like this:
|
|
|
|
|
@ -199,7 +200,7 @@ impl Board {
|
|
|
|
|
|
|
|
|
|
Ok(moves)
|
|
|
|
|
} else {
|
|
|
|
|
Err(GameError::InvalidIndex)
|
|
|
|
|
Err(GameError::InvalidMove)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => Err(GameError::NullMove),
|
|
|
|
|
@ -218,7 +219,9 @@ impl Board {
|
|
|
|
|
|
|
|
|
|
/// Returns the possible moves the piece at this tile can make.
|
|
|
|
|
/// !!TODO: exclude pieces on your own side!!
|
|
|
|
|
pub(crate) fn valid_moves(&self, BoardIndex { x, y }: BoardIndex) -> HashSet<BoardIndex> {
|
|
|
|
|
pub(crate) fn valid_moves(&self, current_board_index: BoardIndex) -> HashSet<BoardIndex> {
|
|
|
|
|
let BoardIndex { x, y } = current_board_index;
|
|
|
|
|
|
|
|
|
|
let f = |(a, b): (Option<usize>, Option<usize>)| {
|
|
|
|
|
if let (Some(this_x), Some(this_y)) = (a, b) {
|
|
|
|
|
// This has a valid x position
|
|
|
|
|
@ -236,13 +239,34 @@ impl Board {
|
|
|
|
|
let valid_capture = {
|
|
|
|
|
match self.at(this_board_index) {
|
|
|
|
|
Some(_) => {
|
|
|
|
|
let same_side = Board::side(BoardIndex { x, y });
|
|
|
|
|
let same_side = Board::side(current_board_index);
|
|
|
|
|
Board::side(this_board_index) != same_side
|
|
|
|
|
}
|
|
|
|
|
None => true,
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if valid_capture {
|
|
|
|
|
// You cannot move a piece from SideB->SideA when it was just moved from SideA->SideB
|
|
|
|
|
// Move rejection is not allowed
|
|
|
|
|
let rejection = {
|
|
|
|
|
if let Some(Move {
|
|
|
|
|
from: last_from,
|
|
|
|
|
to: Some(last_to),
|
|
|
|
|
..
|
|
|
|
|
}) = self.moves.last()
|
|
|
|
|
{
|
|
|
|
|
// TODO: I think this is more logic than we need to express
|
|
|
|
|
// the sentiment...
|
|
|
|
|
Board::side(*last_from) == Board::side(this_board_index)
|
|
|
|
|
&& Board::side(*last_to) == Board::side(current_board_index)
|
|
|
|
|
&& Board::side(this_board_index)
|
|
|
|
|
!= Board::side(current_board_index)
|
|
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if !rejection {
|
|
|
|
|
// If all tests pass, this is a valid move
|
|
|
|
|
Some(this_board_index)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
@ -256,6 +280,9 @@ impl Board {
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match self.at(BoardIndex { x, y }) {
|
|
|
|
|
@ -495,8 +522,8 @@ fn handle_selection(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(GameError::NullMove) => warn!("Null move!"),
|
|
|
|
|
Err(GameError::InvalidIndex) => {
|
|
|
|
|
warn!("Invalid index!");
|
|
|
|
|
Err(GameError::InvalidIndex) | Err(GameError::InvalidMove) => {
|
|
|
|
|
warn!("Invalid index/move!");
|
|
|
|
|
if !(*done) {
|
|
|
|
|
audio_event.send(AudioEvent::Invalid);
|
|
|
|
|
*done = true;
|
|
|
|
|
|