Skip to content

Commit

Permalink
Refactor WildbgConfig to ScoreConfig
Browse files Browse the repository at this point in the history
In a later commit we are going to use `ScoreConfig` by the web API too.
Also we now abort and print an error message if `x_away` and `o_away` are invalid.
  • Loading branch information
carsten-wenderdel committed Aug 11, 2024
1 parent 44eefe2 commit 16e7937
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 32 deletions.
51 changes: 35 additions & 16 deletions crates/logic/src/wildbg_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,34 @@ use engine::evaluator::Evaluator;
use engine::position::Position;
use engine::probabilities::Probabilities;

pub struct WildbgConfig {
/// How many points needed to finish the match?
/// Index 0 is for the player on turn, index 1 for the opponent.
/// Zero indicates money game.
pub away: Option<(u32, u32)>,
pub enum ScoreConfig {
MoneyGame,
OnePointer,
}

impl TryFrom<(u32, u32)> for ScoreConfig {
type Error = &'static str;

#[inline]
fn try_from((x_away, o_away): (u32, u32)) -> Result<Self, Self::Error> {
match (x_away, o_away) {
(0, 0) => Ok(ScoreConfig::MoneyGame),
(1, 1) => Ok(ScoreConfig::OnePointer),
(0, 1) => Err("If x_away is 0, then o_away must also be 0."),
(1, 0) => Err("If o_away is 0, then x_away must also be 0."),
(_, _) => Err("Currently only 1 pointers and money games are supported."),
}
}
}

impl ScoreConfig {
#[inline]
pub fn value(&self) -> impl Fn(&Probabilities) -> f32 {
match self {
ScoreConfig::OnePointer => |p: &Probabilities| p.win(),
ScoreConfig::MoneyGame => |p: &Probabilities| p.equity(),
}
}
}

pub struct WildbgApi<T: Evaluator> {
Expand All @@ -23,26 +46,22 @@ impl WildbgApi<CompositeEvaluator> {
}

impl<T: Evaluator> WildbgApi<T> {
#[inline]
pub fn probabilities(&self, position: &Position) -> Probabilities {
self.evaluator.eval(position)
}

pub fn best_move(&self, position: &Position, dice: &Dice, config: &WildbgConfig) -> BgMove {
let value: fn(&Probabilities) -> f32 = if config.away == Some((1, 1)) {
|p| p.win()
} else {
// For now assume money game if not 1 pointer
|p| p.equity()
};
let new_position = self.evaluator.best_position(position, dice, value);
#[inline]
pub fn best_move(&self, position: &Position, dice: &Dice, config: &ScoreConfig) -> BgMove {
let new_position = self.evaluator.best_position(position, dice, config.value());
BgMove::new(position, &new_position.sides_switched(), dice)
}
}

#[cfg(test)]
mod tests {
use crate::bg_move::{BgMove, MoveDetail};
use crate::wildbg_api::{WildbgApi, WildbgConfig};
use crate::wildbg_api::{ScoreConfig, WildbgApi};
use engine::dice::Dice;
use engine::evaluator::Evaluator;
use engine::pos;
Expand Down Expand Up @@ -89,7 +108,7 @@ mod tests {
let evaluator = EvaluatorFake {};
let api = WildbgApi { evaluator };
// When
let config = WildbgConfig { away: Some((1, 1)) };
let config = ScoreConfig::OnePointer;
let bg_move = api.best_move(&given_pos, &Dice::new(4, 2), &config);
// Then
let expected_move = BgMove {
Expand All @@ -105,7 +124,7 @@ mod tests {
let evaluator = EvaluatorFake {};
let api = WildbgApi { evaluator };
// When
let config = WildbgConfig { away: None };
let config = ScoreConfig::MoneyGame;
let bg_move = api.best_move(&given_pos, &Dice::new(4, 2), &config);
// Then
let expected_move = BgMove {
Expand Down
19 changes: 3 additions & 16 deletions crates/wildbg-c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use engine::dice::Dice;
use engine::position::Position;
use engine::probabilities::Probabilities;
use logic::bg_move::{BgMove, MoveDetail};
use logic::wildbg_api::{WildbgApi, WildbgConfig};
use logic::wildbg_api::{ScoreConfig, WildbgApi};

// When this file is changed, recreate the header file by executing this from the project's root:
// touch cbindgen.toml
Expand Down Expand Up @@ -32,18 +32,6 @@ pub struct BgConfig {
pub o_away: c_uint,
}

impl From<&BgConfig> for WildbgConfig {
fn from(value: &BgConfig) -> Self {
if value.x_away == 0 && value.o_away == 0 {
Self { away: None }
} else {
Self {
away: Some((value.x_away, value.o_away)),
}
}
}
}

#[no_mangle]
/// Loads the neural nets into memory and returns a pointer to the API.
/// Returns `NULL` if the neural nets cannot be found.
Expand Down Expand Up @@ -172,9 +160,8 @@ pub unsafe extern "C" fn best_move(
let move_result = || -> Result<BgMove, Error> {
let position = Position::try_from(pips)?;
let dice = Dice::try_from((die1 as usize, die2 as usize))?;
let bg_move = (*wildbg)
.api
.best_move(&position, &dice, &WildbgConfig::from(config));
let score_config = ScoreConfig::try_from((config.x_away, config.o_away))?;
let bg_move = (*wildbg).api.best_move(&position, &dice, &score_config);
Ok(bg_move)
};
match move_result() {
Expand Down

0 comments on commit 16e7937

Please sign in to comment.