board_game/heuristic/
ataxx.rs1use std::cmp::{max, Ordering};
2
3use crate::ai::minimax::Heuristic;
4use crate::ai::solver::SolverHeuristic;
5use crate::board::Board;
6use crate::games::ataxx::AtaxxBoard;
7use crate::util::bitboard::BitBoard8;
8
9#[derive(Debug)]
10pub struct AtaxxTileHeuristic {
11 pub tile_factor: i32,
12 pub surface_factor: i32,
13}
14
15impl AtaxxTileHeuristic {
16 pub fn new(tile_factor: i32, surface_factor: i32) -> Self {
17 AtaxxTileHeuristic {
18 tile_factor,
19 surface_factor,
20 }
21 }
22
23 pub fn greedy() -> Self {
24 AtaxxTileHeuristic {
25 tile_factor: 1,
26 surface_factor: 0,
27 }
28 }
29}
30
31impl Default for AtaxxTileHeuristic {
32 fn default() -> Self {
33 AtaxxTileHeuristic {
34 tile_factor: 100,
35 surface_factor: 10,
36 }
37 }
38}
39
40impl AtaxxTileHeuristic {
41 fn player_score(&self, board: &AtaxxBoard, tiles: BitBoard8) -> i32 {
42 let tile_count = tiles.count() as i32;
43 let surface_area = (tiles.adjacent() & board.free_tiles()).count() as i32;
44
45 self.tile_factor * tile_count + self.surface_factor * surface_area
46 }
47}
48
49impl Heuristic<AtaxxBoard> for AtaxxTileHeuristic {
50 type V = i32;
51
52 fn value(&self, board: &AtaxxBoard, length: u32) -> Self::V {
53 if board.is_done() {
54 SolverHeuristic.value(board, length).to_i32()
56 } else {
57 let (next, other) = board.tiles_pov();
58 self.player_score(board, next) - self.player_score(board, other)
59 }
60 }
61
62 fn merge(old: Self::V, new: Self::V) -> (Self::V, Ordering) {
63 (max(old, new), new.cmp(&old))
64 }
65}