Skip to content

Commit

Permalink
v1.0.0 + Format (#96)
Browse files Browse the repository at this point in the history
Bench: 184439
  • Loading branch information
jw1912 authored May 28, 2024
1 parent b00a6f1 commit f3f8b75
Show file tree
Hide file tree
Showing 30 changed files with 136 additions and 70 deletions.
2 changes: 0 additions & 2 deletions .cargo/config.toml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
/.cargo
*-policy-*
*.data
*.binpack
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "monty"
version = "0.1.0"
version = "1.0.0"
edition = "2021"
authors = ["Jamie Whiting"]

Expand Down
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,37 @@
#### "MCTS is cool."

![License](https://img.shields.io/github/license/jw1912/monty?style=for-the-badge)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/jw1912/monty?style=for-the-badge)](https://github.com/jw1912/akimbo/releases/latest)
[![Commits](https://img.shields.io/github/commits-since/jw1912/monty/latest?style=for-the-badge)](https://github.com/jw1912/akimbo/commits/main)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/jw1912/monty?style=for-the-badge)](https://github.com/jw1912/monty/releases/latest)
[![Commits](https://img.shields.io/github/commits-since/jw1912/monty/latest?style=for-the-badge)](https://github.com/jw1912/monty/commits/main)

</div>

## Compiling
You need a network file, and run the following command
```
make <name of game> EVALFILE=<relative path to network file>
make <name of game (lowercase)> EXE=<output path> EVALFILE=<path to network file>
```
to compile monty for the given game.
to compile monty for the given game (chess, ataxx, shatranj).

## Supported Games
- Ataxx
- Chess
- Shatranj
## Originality Status

The first version (0.1.0) used external data for value networks and self-generated policy data. The networks were then reset
completely, and all future versions are trained exclusively on monty's own data, generated from scratch with uniform policy
and material counting value.

## Credits
Thanks to everyone at SWE as usual, in particular Cosmo (Viridithas) and Zuppa (Alexandria), for helping with data generation, and Plutie, for running an LTC tune.

## ELO

<div align="center">

| Version | Release Date | CCRL 40/15 | CCRL Blitz | CCRL FRC | Notes |
| :-: | :-: | :-: | :-: | :-: | :-: |
| [1.0.0](https://github.com/jw1912/monty/releases/tag/v1.0.0) | 28th May 2024 | TBD | TBD | TBD | Fully Original Data |
| [0.1.0](https://github.com/jw1912/monty/releases/tag/v0.1.0) | 26th March 2024 | - | - | 2974 | First Release |

</div>

## How it works

Expand Down
8 changes: 4 additions & 4 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#[cfg(not(feature="nonet"))]
#[cfg(not(feature = "nonet"))]
use std::env;

#[cfg(not(feature="nonet"))]
#[cfg(not(feature = "nonet"))]
const DEFAULT_PATH: &str = "resources/net.network";

#[cfg(not(feature="nonet"))]
#[cfg(not(feature = "nonet"))]
fn main() {
println!("cargo:rerun-if-env-changed=EVALFILE");
println!("cargo:rerun-if-changed=resources/chess.network");
Expand All @@ -15,5 +15,5 @@ fn main() {
}
}

#[cfg(feature="nonet")]
#[cfg(feature = "nonet")]
fn main() {}
5 changes: 4 additions & 1 deletion datagen/src/bin/monty.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use datagen::{parse_args, run_datagen};
use monty::{chess::{PolicyNetwork, ValueNetwork}, UciLike};
use monty::{
chess::{PolicyNetwork, ValueNetwork},
UciLike,
};

#[repr(C)]
struct Nets(ValueNetwork, PolicyNetwork);
Expand Down
7 changes: 5 additions & 2 deletions datagen/src/bin/montyj.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use datagen::{parse_args, run_datagen};
use monty::{shatranj::{PolicyNetwork, Shatranj}, ValueNetwork};
use monty::{
shatranj::{PolicyNetwork, Shatranj},
ValueNetwork,
};

#[repr(C)]
struct Nets(ValueNetwork<768, 8>, PolicyNetwork);
Expand All @@ -15,4 +18,4 @@ fn main() {
let (threads, book, policy) = parse_args(args);

run_datagen::<Shatranj, 112>(1_000, threads, policy, "Shatranj", &POLICY, &VALUE, book);
}
}
7 changes: 5 additions & 2 deletions datagen/src/bin/montyxx.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use datagen::{parse_args, run_datagen};
use monty::{ataxx::{Ataxx, PolicyNetwork}, ValueNetwork};
use monty::{
ataxx::{Ataxx, PolicyNetwork},
ValueNetwork,
};

#[repr(C)]
struct Nets(ValueNetwork<2916, 256>, PolicyNetwork);
Expand All @@ -15,4 +18,4 @@ fn main() {
let (threads, book, policy) = parse_args(args);

run_datagen::<Ataxx, 114>(1_000, threads, policy, "Ataxx", &POLICY, &VALUE, book);
}
}
2 changes: 1 addition & 1 deletion datagen/src/impls/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl Binpack {
let mov = u16::from_le_bytes([buf[0], buf[1]]);
let score = i16::from_le_bytes([buf[2], buf[3]]);

f(&mut board, &castling,mov.into(), score, result);
f(&mut board, &castling, mov.into(), score, result);
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion datagen/src/impls/shatranj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,4 @@ impl Binpack {

Ok(())
}
}
}
10 changes: 7 additions & 3 deletions datagen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ pub use thread::{write, DatagenThread};
use monty::{ataxx::Ataxx, chess::Chess, shatranj::Shatranj, GameRep};

use std::{
env::Args, fs::File, io::Read, sync::atomic::{AtomicBool, Ordering}, time::Duration
env::Args,
fs::File,
io::Read,
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};

pub type AtaxxPolicyData = PolicyData<Ataxx, 114>;
Expand Down Expand Up @@ -145,11 +149,11 @@ pub fn parse_args(mut args: Args) -> (usize, Option<String>, bool) {
1 => {
threads = Some(arg.parse().expect("can't parse"));
mode = 0;
},
}
2 => {
book = Some(arg);
mode = 0;
},
}
_ => println!("unrecognised argument {arg}"),
},
}
Expand Down
11 changes: 8 additions & 3 deletions datagen/src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ pub struct DatagenThread<'a, T: DatagenSupport> {
}

impl<'a, T: DatagenSupport> DatagenThread<'a, T> {
pub fn new(id: u32, params: MctsParams, stop: &'a AtomicBool, book: Option<Vec<&'a str>>) -> Self {
pub fn new(
id: u32,
params: MctsParams,
stop: &'a AtomicBool,
book: Option<Vec<&'a str>>,
) -> Self {
Self {
id,
rng: Rand::with_seed(),
Expand Down Expand Up @@ -92,7 +97,6 @@ impl<'a, T: DatagenSupport> DatagenThread<'a, T> {
T::from_fen(T::STARTPOS)
};


// play 8 or 9 random moves
for _ in 0..(8 + (self.rng.rand_int() % 2)) {
let mut moves = Vec::new();
Expand Down Expand Up @@ -129,7 +133,8 @@ impl<'a, T: DatagenSupport> DatagenThread<'a, T> {

// play out game
loop {
let mut searcher = Searcher::new(position.clone(), tree, self.params.clone(), policy, value);
let mut searcher =
Searcher::new(position.clone(), tree, self.params.clone(), policy, value);

let (bm, score) = searcher.search(limits, false, &mut 0, &None);

Expand Down
10 changes: 6 additions & 4 deletions src/bin/monty.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use monty::{chess::{ValueNetwork, PolicyNetwork, Uci}, UciLike};
use monty::{
chess::{PolicyNetwork, Uci, ValueNetwork},
UciLike,
};

#[repr(C)]
struct Nets(ValueNetwork, PolicyNetwork);

const NETS: Nets =
unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };
const NETS: Nets = unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };

static VALUE: ValueNetwork = NETS.0;
static POLICY: PolicyNetwork = NETS.1;
Expand All @@ -19,4 +21,4 @@ fn main() {
}

Uci::run(&POLICY, &VALUE);
}
}
10 changes: 6 additions & 4 deletions src/bin/montyj.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use monty::{shatranj::{Uci, PolicyNetwork}, UciLike, ValueNetwork};
use monty::{
shatranj::{PolicyNetwork, Uci},
UciLike, ValueNetwork,
};

#[repr(C)]
struct Nets(ValueNetwork<768, 8>, PolicyNetwork);

const NETS: Nets =
unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };
const NETS: Nets = unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };

static VALUE: ValueNetwork<768, 8> = NETS.0;
static POLICY: PolicyNetwork = NETS.1;
Expand All @@ -19,4 +21,4 @@ fn main() {
}

Uci::run(&POLICY, &VALUE);
}
}
11 changes: 6 additions & 5 deletions src/bin/montyxx.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use monty::{ataxx::{Uai, PolicyNetwork}, UciLike, ValueNetwork};

use monty::{
ataxx::{PolicyNetwork, Uai},
UciLike, ValueNetwork,
};

#[repr(C)]
struct Nets(ValueNetwork<2916, 256>, PolicyNetwork);

const NETS: Nets =
unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };
const NETS: Nets = unsafe { std::mem::transmute(*include_bytes!("../../resources/net.network")) };

static VALUE: ValueNetwork<2916, 256> = NETS.0;
static POLICY: PolicyNetwork = NETS.1;
Expand All @@ -20,4 +21,4 @@ fn main() {
}

Uai::run(&POLICY, &VALUE);
}
}
16 changes: 11 additions & 5 deletions src/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ pub trait UciLike: Sized {

fn options();

fn run(
policy: &<Self::Game as GameRep>::Policy,
value: &<Self::Game as GameRep>::Value,
) {
fn run(policy: &<Self::Game as GameRep>::Policy, value: &<Self::Game as GameRep>::Value) {
let mut prev = None;
let mut pos = Self::Game::default();
let mut params = Self::Game::default_mcts_params();
Expand All @@ -41,7 +38,16 @@ pub trait UciLike: Sized {
"setoption" => setoption(&commands, &mut params, &mut report_moves, &mut tree),
"position" => position(commands, &mut pos, &mut prev, &mut tree),
"go" => {
let res = go(&commands, tree, prev, &pos, &params, report_moves, policy, value);
let res = go(
&commands,
tree,
prev,
&pos,
&params,
report_moves,
policy,
value,
);

tree = res.0;
prev = Some(res.1);
Expand Down
3 changes: 2 additions & 1 deletion src/games.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ pub trait GameRep: Clone + Default + Send + Sync {

fn get_policy_feats(&self) -> Self::PolicyInputs;

fn get_policy(&self, mov: Self::Move, feats: &Self::PolicyInputs, policy: &Self::Policy) -> f32;
fn get_policy(&self, mov: Self::Move, feats: &Self::PolicyInputs, policy: &Self::Policy)
-> f32;

fn get_value(&self, value: &Self::Value) -> i32;

Expand Down
2 changes: 1 addition & 1 deletion src/games/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl GameRep for Chess {
&self,
mov: Self::Move,
(feats, threats): &Self::PolicyInputs,
policy: &Self::Policy
policy: &Self::Policy,
) -> f32 {
policy.get(&self.board, &mov, feats, *threats)
}
Expand Down
6 changes: 1 addition & 5 deletions src/games/chess/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,7 @@ impl Board {

pub fn map_value_features<F: FnMut(usize)>(&self, mut f: F) {
let flip = self.stm() == Side::BLACK;
let hm = if self.king_index() % 8 > 3 {
7
} else {
0
};
let hm = if self.king_index() % 8 > 3 { 7 } else { 0 };

let mut threats = self.threats_by(self.stm() ^ 1);
let mut defences = self.threats_by(self.stm());
Expand Down
5 changes: 4 additions & 1 deletion src/games/chess/frc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ impl Castling {
rook_files = [[0, 7]; 2];
}

let mut ret = Self { rook_files, ..Default::default() };
let mut ret = Self {
rook_files,
..Default::default()
};

ret.castle_mask[usize::from(rook_files[0][0])] = 7;
ret.castle_mask[usize::from(rook_files[0][1])] = 11;
Expand Down
4 changes: 2 additions & 2 deletions src/games/chess/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const SCALE: i32 = 400;

#[repr(C)]
pub struct ValueNetwork {
l1: Layer<{768 * 4}, 512>,
l1: Layer<{ 768 * 4 }, 512>,
l2: Layer<512, 16>,
l3: Layer<16, 16>,
l4: Layer<16, 16>,
Expand Down Expand Up @@ -72,7 +72,7 @@ struct Accumulator<const HIDDEN: usize> {
vals: [f32; HIDDEN],
}

impl<const HIDDEN: usize> Accumulator<HIDDEN> {
impl<const HIDDEN: usize> Accumulator<HIDDEN> {
fn madd(&mut self, mul: f32, other: &Self) {
for (i, &j) in self.vals.iter_mut().zip(other.vals.iter()) {
*i += mul * j;
Expand Down
7 changes: 6 additions & 1 deletion src/games/shatranj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,12 @@ impl GameRep for Shatranj {
feats
}

fn get_policy(&self, mov: Self::Move, feats: &goober::SparseVector, policy: &Self::Policy) -> f32 {
fn get_policy(
&self,
mov: Self::Move,
feats: &goober::SparseVector,
policy: &Self::Policy,
) -> f32 {
policy.get(&self.board, &mov, feats)
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod tree;
mod value;

pub use comm::UciLike;
pub use games::{GameRep, GameState, ataxx, chess, shatranj};
pub use games::{ataxx, chess, shatranj, GameRep, GameState};
pub use mcts::{Limits, Searcher};
pub use params::MctsParams;
pub use tree::Tree;
Expand Down
Loading

0 comments on commit f3f8b75

Please sign in to comment.