use crate::Game;
use std::convert::TryInto;
use std::fmt::Debug;
use std::num::Wrapping;
use std::ops::Range;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Node {
player: bool,
fitness: i8,
children: Vec<Node>,
}
impl Game for Node {
type Player = bool;
type Action = usize;
type Fitness = i8;
type Actions = Range<usize>;
fn actions(&self, player: Self::Player) -> (bool, Self::Actions) {
(player == self.player, 0..self.children.len())
}
fn execute(&mut self, action: &Self::Action, _: Self::Player) -> Self::Fitness {
*self = self.children[*action].clone();
self.fitness
}
fn look_ahead(&self, action: &Self::Action, _: Self::Player) -> Self::Fitness {
self.children[*action].fitness
}
fn is_upper_bound(&self, fitness: Self::Fitness, _: Self::Player) -> bool {
fitness == i8::MAX
}
fn is_lower_bound(&self, fitness: Self::Fitness, _: Self::Player) -> bool {
fitness == i8::MIN
}
}
impl Node {
pub fn root() -> Self {
Self::new(true, 0)
}
pub fn new(player: bool, fitness: i8) -> Self {
Self {
player,
fitness,
children: Vec::new(),
}
}
pub fn from_bytes(bytes: &[u8]) -> Self {
match bytes[0..4].try_into() {
Ok(seed) => {
let mut seed = u32::from_be_bytes(seed);
if seed == 0 {
seed = 0xBAD_5EED;
}
struct XorShiftRng {
x: Wrapping<u32>,
y: Wrapping<u32>,
z: Wrapping<u32>,
w: Wrapping<u32>,
}
impl XorShiftRng {
fn next_u32(&mut self) -> u32 {
let x = self.x;
let t = x ^ (x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
let w = self.w;
self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
self.w.0
}
}
let mut rng = XorShiftRng {
x: Wrapping(seed),
y: Wrapping(seed),
z: Wrapping(seed),
w: Wrapping(seed),
};
let mut root = Node::new(true, 0);
for &i in bytes[4..].iter() {
let mut pos = Some(&mut root);
let mut next =
rng.next_u32() as usize % (pos.as_ref().unwrap().children.len() + 1);
while next != pos.as_ref().unwrap().children.len() {
pos.take().map(|node| {
pos = Some(&mut node.children[next]);
});
next = rng.next_u32() as usize % (pos.as_ref().unwrap().children.len() + 1);
}
pos.unwrap()
.children
.push(Node::new(rng.next_u32() % 2 == 0, i as i8));
}
root
}
Err(_) => Self::root(),
}
}
pub fn with_children(mut self, children: &[Node]) -> Self {
self.children.clear();
self.children.extend_from_slice(children);
self
}
pub fn push_child(&mut self, child: Node) {
self.children.push(child);
}
pub fn child_count(&self) -> usize {
self.children.len()
}
pub fn is_leaf(&self) -> bool {
self.children.is_empty()
}
}