use crate::{Column, Move, Position};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OracleOutcome {
Win,
Draw,
Loss,
}
impl OracleOutcome {
pub const fn name(self) -> &'static str {
match self {
Self::Win => "win",
Self::Draw => "draw",
Self::Loss => "loss",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OracleCase {
pub notation: &'static str,
pub pons_score: i8,
pub outcome: OracleOutcome,
pub description: &'static str,
}
pub const ORACLE_CASES: [OracleCase; 2] = [
OracleCase {
notation: "4455",
pons_score: 18,
outcome: OracleOutcome::Win,
description: "The side to move can force a win with its fourth disc",
},
OracleCase {
notation: "44455554221",
pons_score: -15,
outcome: OracleOutcome::Loss,
description: "The side to move loses and the opponent wins next turn",
},
];
pub fn probe_oracle(position: Position) -> Option<&'static OracleCase> {
ORACLE_CASES
.iter()
.find(|case| case_position(case.notation) == position)
}
fn case_position(notation: &str) -> Position {
let moves: Vec<_> = notation
.bytes()
.map(|digit| Move::new(Column::new(digit - b'1')))
.collect();
Position::from_moves(&moves).expect("embedded oracle cases must be legal")
}