From 13aa9ffffe827b97fbb760210b889909ff09c572 Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Sun, 21 Dec 2025 20:15:59 -0600 Subject: [PATCH] engine WIP --- tak_lib/src/engine.rs | 73 ++++++++++++++++++++++++++++++++++++++++++ tak_lib/src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 tak_lib/src/engine.rs diff --git a/tak_lib/src/engine.rs b/tak_lib/src/engine.rs new file mode 100644 index 0000000..afb0f7a --- /dev/null +++ b/tak_lib/src/engine.rs @@ -0,0 +1,73 @@ +use crate::{ + Board, Direction, Move, + piece::{ColoredPiece, Piece}, +}; + +impl Board { + pub fn moves(&self) -> impl Iterator> { + let to_move = self.to_move; + let tiles = &self.tiles; + let can_place_caps = if Self::N_CAPS == 0 { + false + } else { + let caps_on_board = self + .tiles + .iter() + .flat_map(|col| col.iter()) + .filter(|t| { + let piece = t.top_piece(); + piece.color_opt() == Some(to_move) && piece.piece() == Piece::Caps + }) + .count() as u8; + caps_on_board < Self::N_CAPS + }; + + let chords = (0..(N as u8)).flat_map(|x| (0..(N as u8)).map(move |y| (x, y))); + + chords.flat_map(move |(x, y)| { + 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) + } else if top_piece.color() == to_move { + get_movement_moves(x, y, tiles[x as usize][y as usize].stack_len()) + } else { + Vec::with_capacity(0) + } + }) + } +} + +fn get_placement_moves(x: u8, y: u8, can_place_caps: bool) -> Vec> { + let mut moves = Vec::with_capacity(2 + can_place_caps as usize); + moves.push(Move::Place { + piece: Piece::Flat, + at: (x, y), + }); + moves.push(Move::Place { + piece: Piece::Wall, + at: (x, y), + }); + if can_place_caps { + moves.push(Move::Place { + piece: Piece::Caps, + at: (x, y), + }); + } + moves +} + +fn get_movement_moves(x: u8, y: u8, stack_len: u8) -> Vec> { + let max_grab = u8::min(N as u8, stack_len + 1); + + // East + let max_dist_east = max_grab.min(N as u8 - x - 1); + // North + let max_dist_north = max_grab.min(N as u8 - y - 1); + // West + let max_dist_west = max_grab.min(x); + // South + let max_dist_south = max_grab.min(y); +} + +fn get_drop_amounts(max_grab: u8, max_dist: u8) -> impl Iterator {} diff --git a/tak_lib/src/lib.rs b/tak_lib/src/lib.rs index 17d9ebd..25fe370 100644 --- a/tak_lib/src/lib.rs +++ b/tak_lib/src/lib.rs @@ -1,10 +1,82 @@ +pub mod engine; pub mod piece; pub mod tile; -use crate::{piece::Color, tile::Tile}; +use crate::{ + piece::{Color, Piece}, + tile::Tile, +}; +use std::fmt::Display; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Direction { + East, + North, + West, + South, +} +impl Display for Direction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Direction::East => write!(f, "e"), + Direction::North => write!(f, "n"), + Direction::West => write!(f, "w"), + Direction::South => write!(f, "s"), + } + } +} +impl Direction { + const ALL: [Direction; 4] = [ + Direction::East, + Direction::North, + Direction::West, + Direction::South, + ]; +} #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Board { to_move: Color, tiles: [[Tile; N]; N], } + +impl Board { + /// The number of capstones in each players' pouches. + pub const N_STONES: u8 = match N { + 3 => 10, + 4 => 15, + 5 => 21, + 6 => 30, + 8 => 50, + _ => panic!("N must be 3, 4, 5, 6, or 8"), + }; + /// The number of capstones in the players' pouches. + pub const N_CAPS: u8 = match N { + 3 => 0, + 4 => 0, + 5 => 1, + 6 => 1, + 8 => 2, + _ => panic!("N must be 3, 4, 5, 6, or 8"), + }; + + pub fn new() -> Self { + Board { + to_move: Color::White, + tiles: [[Tile::EMPTY; N]; N], + } + } +} + +pub enum Move { + Place { + piece: Piece, + at: (u8, u8), + }, + Move { + from: (u8, u8), + count: u8, + dir: Direction, + drop: [u8; N], + }, +}