engine work

This commit is contained in:
Mitchell Marino 2025-12-22 11:32:20 -06:00
parent 13aa9ffffe
commit 96fb485c87

View File

@ -1,5 +1,5 @@
use crate::{
Board, Direction, Move,
Board, Move,
piece::{ColoredPiece, Piece},
};
@ -28,7 +28,7 @@ impl<const N: usize> Board<N> {
let top_piece = tiles[x as usize][y as usize].top_piece();
if top_piece == ColoredPiece::None {
// possible moves are place moves
get_placement_moves(x, y, can_place_caps)
insert_placement_moves(x, y, can_place_caps)
} else if top_piece.color() == to_move {
get_movement_moves(x, y, tiles[x as usize][y as usize].stack_len())
} else {
@ -38,7 +38,7 @@ impl<const N: usize> Board<N> {
}
}
fn get_placement_moves<const N: usize>(x: u8, y: u8, can_place_caps: bool) -> Vec<Move<N>> {
fn insert_placement_moves<const N: usize>(x: u8, y: u8, can_place_caps: bool) -> Vec<Move<N>> {
let mut moves = Vec::with_capacity(2 + can_place_caps as usize);
moves.push(Move::Place {
piece: Piece::Flat,
@ -68,6 +68,232 @@ fn get_movement_moves<const N: usize>(x: u8, y: u8, stack_len: u8) -> Vec<Move<N
let max_dist_west = max_grab.min(x);
// South
let max_dist_south = max_grab.min(y);
todo!()
}
fn get_drop_amounts<const N: usize>(max_grab: u8, max_dist: u8) -> impl Iterator<Item = [u8; N]> {}
fn get_drop_amounts<const N: usize>(
// shared state
buf: &mut [u8; N],
i: usize,
insert_fn: &mut impl FnMut([u8; N]),
// recursive parameters
pieces: u8,
len: u8,
end_w_capstone: bool,
) {
debug_assert!(len > 0 || pieces == 0);
// base cases
if pieces == 0 {
insert_fn(buf.clone());
return;
}
if pieces == 1 {
buf[i] = 1;
insert_fn(buf.clone());
buf[i] = 0;
return;
}
if len == 1 {
buf[i] = pieces;
insert_fn(buf.clone());
buf[i] = 0;
return;
}
// recursive case
for n in 1..=pieces {
buf[i] = n;
get_drop_amounts(buf, i + 1, insert_fn, pieces - n, len - 1, end_w_capstone);
}
buf[i] = 0;
}
#[cfg(test)]
fn expect_get_drop_ammounts<const N: usize>(
pieces: u8,
len: u8,
end_w_capstone: bool,
expected_drop_list: Vec<[u8; N]>,
) {
use std::collections::HashSet;
let mut buf = [0; N];
let mut drop_list = Vec::new();
let mut insert_fn = |drops: [u8; N]| {
drop_list.push(drops);
};
get_drop_amounts(&mut buf, 0, &mut insert_fn, pieces, len, end_w_capstone);
let expected_drop_set: HashSet<_> = expected_drop_list.iter().cloned().collect();
let drop_set: HashSet<_> = drop_list.iter().cloned().collect();
if drop_set.len() != drop_list.len() {
panic!("drop list had duplicate values");
}
if expected_drop_set != drop_set {
let mut err_str = String::new();
for entry in expected_drop_list {
if drop_set.contains(&entry) {
err_str += &format!("\t{:?} {:?}\n", entry, entry);
} else {
err_str += &format!("\t{:?}\n", entry);
}
}
for entry in drop_list {
if expected_drop_set.contains(&entry) {
continue;
}
let blank = format!("{:?}", entry)
.chars()
.map(|_| ' ')
.collect::<String>();
err_str += &format!("\t{} {:?}\n", blank, entry);
}
panic!("incorrect drop list!\n{}", err_str);
}
}
#[test]
fn test_full_len_drop_amounts() {
expect_get_drop_ammounts(1, 1, false, vec![[1]]);
expect_get_drop_ammounts(1, 1, false, vec![[1, 0]]);
expect_get_drop_ammounts(1, 1, false, vec![[1, 0, 0]]);
expect_get_drop_ammounts(2, 2, false, vec![[1, 1, 0, 0, 0], [2, 0, 0, 0, 0]]);
expect_get_drop_ammounts(
3,
3,
false,
vec![
[1, 1, 1, 0, 0],
[1, 2, 0, 0, 0],
[2, 1, 0, 0, 0],
[3, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
4,
4,
false,
vec![
[1, 1, 1, 1, 0],
[1, 1, 2, 0, 0],
[1, 2, 1, 0, 0],
[1, 3, 0, 0, 0],
[2, 1, 1, 0, 0],
[2, 2, 0, 0, 0],
[3, 1, 0, 0, 0],
[4, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
5,
5,
false,
vec![
[1, 1, 1, 1, 1],
[1, 1, 1, 2, 0],
[1, 1, 2, 1, 0],
[1, 1, 3, 0, 0],
[1, 2, 1, 1, 0],
[1, 2, 2, 0, 0],
[1, 3, 1, 0, 0],
[1, 4, 0, 0, 0],
[2, 1, 1, 1, 0],
[2, 1, 2, 0, 0],
[2, 2, 1, 0, 0],
[2, 3, 0, 0, 0],
[3, 1, 1, 0, 0],
[3, 2, 0, 0, 0],
[4, 1, 0, 0, 0],
[5, 0, 0, 0, 0],
],
);
}
#[test]
fn test_truncated_drop_amounts() {
expect_get_drop_ammounts(
3,
2,
false,
vec![[1, 2, 0, 0, 0], [2, 1, 0, 0, 0], [3, 0, 0, 0, 0]],
);
expect_get_drop_ammounts(3, 1, false, vec![[3, 0, 0, 0, 0]]);
expect_get_drop_ammounts(
4,
3,
false,
vec![
[1, 1, 2, 0, 0],
[1, 2, 1, 0, 0],
[1, 3, 0, 0, 0],
[2, 1, 1, 0, 0],
[2, 2, 0, 0, 0],
[3, 1, 0, 0, 0],
[4, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
4,
2,
false,
vec![
[1, 3, 0, 0, 0],
[2, 2, 0, 0, 0],
[3, 1, 0, 0, 0],
[4, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
5,
4,
false,
vec![
[1, 1, 1, 2, 0],
[1, 1, 2, 1, 0],
[1, 1, 3, 0, 0],
[1, 2, 1, 1, 0],
[1, 2, 2, 0, 0],
[1, 3, 1, 0, 0],
[1, 4, 0, 0, 0],
[2, 1, 1, 1, 0],
[2, 1, 2, 0, 0],
[2, 2, 1, 0, 0],
[2, 3, 0, 0, 0],
[3, 1, 1, 0, 0],
[3, 2, 0, 0, 0],
[4, 1, 0, 0, 0],
[5, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
5,
3,
false,
vec![
[1, 1, 3, 0, 0],
[1, 2, 2, 0, 0],
[1, 3, 1, 0, 0],
[1, 4, 0, 0, 0],
[2, 1, 2, 0, 0],
[2, 2, 1, 0, 0],
[2, 3, 0, 0, 0],
[3, 1, 1, 0, 0],
[3, 2, 0, 0, 0],
[4, 1, 0, 0, 0],
[5, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(
5,
2,
false,
vec![
[1, 4, 0, 0, 0],
[2, 3, 0, 0, 0],
[3, 2, 0, 0, 0],
[4, 1, 0, 0, 0],
[5, 0, 0, 0, 0],
],
);
expect_get_drop_ammounts(5, 1, false, vec![[5, 0, 0, 0, 0]]);
}