Fixed moves correctness!

Sans merging which we still haven't wired into the real game...
main
Elijah C. Voigt 2 years ago
parent 80738dd217
commit 098df2998b

@ -231,7 +231,7 @@ fn debug_piece(
Option<&display3d::Animating>, Option<&display3d::Animating>,
Option<&Selected>, Option<&Selected>,
), ),
With<Piece>, With<BoardIndex>,
>, >,
pointer: Res<display3d::PiecePointer>, pointer: Res<display3d::PiecePointer>,
mut root: Query<(&mut Text, &mut Visibility), With<DebugPiece>>, mut root: Query<(&mut Text, &mut Visibility), With<DebugPiece>>,

@ -513,6 +513,7 @@ impl Board {
from: BoardIndex, from: BoardIndex,
to: BoardIndex, to: BoardIndex,
) -> Option<MoveType> { ) -> Option<MoveType> {
self.line(from, to).all(|board_index| self.at(board_index).is_none()).then(|| {
self.at(from).map(|piece| { self.at(from).map(|piece| {
// Given that the side does not have a queen||drone // Given that the side does not have a queen||drone
// And the piece is a drone||pawn // And the piece is a drone||pawn
@ -538,10 +539,6 @@ impl Board {
match dest_at { match dest_at {
// Cannot move on top of a friendly // Cannot move on top of a friendly
Some(to_piece) => { Some(to_piece) => {
(!self.line(from, to)
.any(|board_index| self.at(board_index)
.is_some())
).then(|| {
match (piece, to_piece) { match (piece, to_piece) {
(Piece::Pawn, Piece::Pawn) => { (Piece::Pawn, Piece::Pawn) => {
(!side_has_drone).then_some(MoveType::Merge) (!side_has_drone).then_some(MoveType::Merge)
@ -553,15 +550,10 @@ impl Board {
Some(MoveType::Invalid) Some(MoveType::Invalid)
} }
} }
}).flatten()
}, },
// Any other spot is valid // Any other spot is valid
None => { None => {
// If there is another piece between A and B Some(MoveType::Valid)
(!self
.line(from, to)
.any(|board_index| self.at(board_index).is_some()))
.then_some(MoveType::Valid)
} }
} }
} }
@ -569,11 +561,7 @@ impl Board {
(Side::A, Side::B) | (Side::B, Side::A) => { (Side::A, Side::B) | (Side::B, Side::A) => {
match dest_at { match dest_at {
Some(_) => { Some(_) => {
// If there is no other piece between A and B Some(MoveType::Capture)
(!self
.line(from, to)
.any(|board_index| self.at(board_index).is_some()))
.then_some(MoveType::Capture)
} }
None => { None => {
// move is valid if it does not un-do the previous move // move is valid if it does not un-do the previous move
@ -583,12 +571,8 @@ impl Board {
} }
// First move in the game, this is valid (and impossible) // First move in the game, this is valid (and impossible)
None => { None => {
// If there is no other pieces between A and B
// the move is valid // the move is valid
(!self Some(MoveType::Valid)
.line(from, to)
.any(|board_index| self.at(board_index).is_some()))
.then_some(MoveType::Valid)
} }
} }
} }
@ -596,7 +580,8 @@ impl Board {
} }
} }
}) })
}).flatten().or(Some(MoveType::Invalid)) })
}).flatten().flatten().or(Some(MoveType::Invalid))
} }
/// Returns the possible moves the piece at this tile can make. /// Returns the possible moves the piece at this tile can make.
@ -604,9 +589,12 @@ impl Board {
if let Some(piece) = self.at(current_board_index) { if let Some(piece) = self.at(current_board_index) {
piece.moves_at(&current_board_index).iter().filter_map(|move_index| { piece.moves_at(&current_board_index).iter().filter_map(|move_index| {
// Get the move type (or none if totally invalid) // Get the move type (or none if totally invalid)
match self.move_type(current_board_index, *move_index) { let result = self.move_type(current_board_index, *move_index);
match result {
None | Some(MoveType::Invalid) => None, None | Some(MoveType::Invalid) => None,
_ => Some(*move_index), Some(MoveType::Capture) | Some(MoveType::Merge) | Some(MoveType::Valid) => {
Some(*move_index)
},
} }
}) })
.collect() .collect()
@ -738,7 +726,7 @@ mod test {
/// When an enemy is on one side, can move to capture just that piece /// When an enemy is on one side, can move to capture just that piece
#[test] #[test]
fn case_03() { fn case_01() {
let board = Board::from_ascii( let board = Board::from_ascii(
r#"........ r#"........
........ ........
@ -798,7 +786,6 @@ mod test {
(5, 0).into(), (5, 0).into(),
(5, 2).into(), (5, 2).into(),
]); ]);
println!("Moves: {:?}", Piece::Queen.moves_at(&(4, 1).into()));
assert_eq!( assert_eq!(
expected, given, expected, given,
"Mostly blocked queen, moves include captures" "Mostly blocked queen, moves include captures"
@ -807,7 +794,7 @@ mod test {
} }
#[test] #[test]
fn case_01() { fn case_03() {
let board = Board::from_ascii( let board = Board::from_ascii(
r#".p.....q r#".p.....q
dp.p.pdq dp.p.pdq
@ -839,7 +826,38 @@ mod test {
]); ]);
assert_eq!(expected, given); assert_eq!(expected, given);
} }
}
// A strange failure mode in game which I suspect comes from
// a disconnect between board logic and display plumbing
#[test]
fn case_04() {
let mut board = Board::from_ascii(
r#".....dqq
dpp..pdq
qdp....d
qqd....."#,
);
{
board.move_piece((5, 3).into(), (4, 3).into()).unwrap();
board.move_piece((2, 2).into(), (1, 3).into()).unwrap();
let expected = Board::from_ascii(
r#".p..d#qq
dp...pdq
qdp....d
qqd....."#,
);
assert_eq!(expected.inner, board.inner);
}
{
let given = board.valid_moves((6, 3).into());
let expected: HashSet<BoardIndex> = HashSet::from([(5, 3).into()]);
assert_eq!(expected, given);
}
} }
#[test] #[test]
@ -1328,7 +1346,9 @@ fn show_valid_moves(
events.iter().for_each(|idx| { events.iter().for_each(|idx| {
// Iterate over all ValidMove entities // Iterate over all ValidMove entities
// For each one with a ValidMove index, make it visible // For each one with a ValidMove index, make it visible
board.valid_moves(*idx).iter().for_each(|idx| { let valid_moves = board.valid_moves(*idx);
info!("Showing valid moves for {:?}: {:?}", idx, valid_moves);
valid_moves.iter().for_each(|idx| {
indicators.iter_mut().for_each(|(i, mut vis)| { indicators.iter_mut().for_each(|(i, mut vis)| {
if i == idx { if i == idx {
*vis = Visibility::Inherited; *vis = Visibility::Inherited;

Loading…
Cancel
Save