diff --git a/fish/src/ai.rs b/fish/src/ai.rs index 425e9b4..9c0a524 100644 --- a/fish/src/ai.rs +++ b/fish/src/ai.rs @@ -1,6 +1,6 @@ //! AI engine. -use crate::find; +use crate::{eval, find}; use alloc::vec::Vec; use core::{future::Future, pin::Pin, task::Poll}; use mino::srs::{Piece, PieceType}; @@ -15,6 +15,20 @@ pub struct Ai { cur_mat: MatBuf, } +fn evaluate(mat: &Mat, depth: usize) -> i32 { + let w_height = 5; + let w_ideps = 10; + let w_mdse = 10; + let w_pc = 10; + + let mut rating = 0; + rating += eval::max_height(mat) * w_height; + rating += eval::i_deps(mat) * w_ideps; + rating += eval::mystery_mdse(mat) * w_mdse; + rating += (depth as i32) * w_pc; + rating +} + impl Ai { // TODO: personality config pub fn new() -> Self { @@ -50,18 +64,33 @@ impl Ai { } let ty = self.root_previews[depth]; - let loc = { - let mut fl = find::find_locations(&self.cur_mat, ty, find::cap::All); - match fl.nth(0) { - Some(loc) => loc, - None => return true, // game over + let locs = find::find_locations(&self.cur_mat, ty, find::cap::All); + let pcs = locs.map(|loc| Piece { ty, loc }); + + let mut rate_mat: MatBuf = MatBuf::new(); + let mut best_mat: MatBuf = MatBuf::new(); + let mut best: Option<(i32, Piece)> = None; + + for pc in pcs { + rate_mat.copy_from(&self.cur_mat); + pc.cells().fill(&mut rate_mat); + rate_mat.clear_lines(); + let rating = evaluate(&rate_mat, depth); + + let best_rating = best.clone().map_or(i32::MAX, |(r, _)| r); + if rating < best_rating { + best = Some((rating, pc)); + best_mat.copy_from(&rate_mat); } + } + + let pc = match best { + Some((_, pc)) => pc, + None => return true, // no locations; game over }; - let piece = Piece { ty, loc }; - piece.cells().fill(&mut self.cur_mat); - self.path.push(piece); - + self.path.push(pc); + self.cur_mat.copy_from(&best_mat); false }