othello/src/logic/move.rs
2025-02-28 18:21:58 -05:00

85 lines
2.8 KiB
Rust

use super::board_value::BoardValueMap;
use crate::repr::{Board, CoordPair, Piece, Winner};
use std::sync::LazyLock;
#[derive(Clone, Debug)]
pub struct Move {
/// Coordinates (i, j) of the move (if it exists)
pub coord: Option<CoordPair>,
/// [`Board`] state after move is made
pub board: Board,
/// Current winner of the match
pub winner: Winner,
/// Index of this move's parent
pub parent: Option<usize>,
/// Indices of this Move's Children
pub children: Vec<usize>,
/// Has this [`Move`] already attempted to create children?
pub tried_children: bool,
/// Value of this move (including children)
pub value: Option<i128>,
/// What is the inherit value of this move (not including children)
pub self_value: i64,
/// Which color made a move on this move?
pub color: Piece,
/// Was this move's children previously trimmed?
pub is_trimmed: bool,
}
static BVM: LazyLock<BoardValueMap> = LazyLock::new(BoardValueMap::new);
impl Move {
pub fn new(coord: Option<CoordPair>, board: Board, color: Piece, agent_color: Piece) -> Self {
let mut m = Move {
coord,
board,
winner: board.game_winner(),
parent: None,
children: Vec::new(),
value: None,
color,
is_trimmed: false,
self_value: 0,
tried_children: false,
};
m.self_value = m.compute_self_value(agent_color);
m
}
fn compute_self_value(&self, agent_color: Piece) -> i64 {
if self.winner == Winner::Player(!agent_color) {
// if this board results in the opponent winning, MAJORLY negatively weigh this move
// NOTE! this branch isn't completely deleted because if so, the bot wouldn't make a move.
// We shouldn't prune branches because we still need to always react to the opponent's moves
return i64::MIN + 1;
} else if self.winner == Winner::Player(agent_color) {
// results in a win for the agent
return i64::MAX - 1;
}
// else if self.winner == Winner::Tie {
// // idk what a Tie should be valued?
// return 0;
// }
// I guess ignore Ties here, don't give them an explicit value,
// because even in the case of ties, we want to have a higher score
BVM.board_value(&self.board, agent_color)
}
/// Sort children of the [`Move`] by their self_value in `arena`
pub fn sort_children(&mut self, arena: &[Move]) {
// negative, because we want the max value to be at the first index
// abs because we want the most EXTREME possible outcome (win or lose for example)
self.children.sort_by_key(|&i| -arena[i].self_value.abs());
}
}