othello/src/logic/move.rs

89 lines
2.2 KiB
Rust

use lazy_static::lazy_static;
use crate::repr::{Board, Piece, Winner};
use super::board_value::BoardValueMap;
#[derive(Clone, Debug)]
pub struct Move {
/// `i` position of move
pub i: usize,
/// `j` position of move
pub j: usize,
/// [`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>,
/// Value of this move (including children)
pub value: i64,
pub self_value: i64,
pub color: Piece,
pub lazy_children: bool,
}
lazy_static! {
static ref BVM: BoardValueMap = BoardValueMap::new();
}
impl Move {
pub fn new(
i: usize,
j: usize,
board: Board,
color: Piece,
lazy_children: bool,
agent_color: Piece,
parent: Option<usize>,
) -> Self {
let mut m = Move {
i,
j,
board,
winner: board.game_winner(),
parent,
children: Vec::new(),
value: 0,
color,
lazy_children,
self_value: 0,
};
m.self_value = m.compute_self_value(agent_color);
m.value = m.self_value;
m
}
pub const fn coords(&self) -> (usize, usize) {
(self.i, self.j)
}
pub 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;
} else if self.winner == Winner::Player(agent_color) {
// results in a win for the agent
return i64::MAX;
} else if self.winner == Winner::Tie {
// idk what a Tie should be valued?
return 0;
}
BVM.board_value(&self.board, agent_color)
}
}