-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnim.rs
101 lines (84 loc) · 2.21 KB
/
nim.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::game::{Game, PlayerIndex};
use nimlib::{moves, NimAction, NimGame, NimRule, Split, Stack, TakeSize};
#[derive(PartialEq, Copy, Clone, Debug, Eq)]
pub enum Player {
Black,
White,
}
impl PlayerIndex for Player {
fn to_index(&self) -> usize {
*self as usize
}
}
impl Player {
pub fn next(self) -> Self {
match self {
Player::Black => Player::White,
Player::White => Player::Black,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NimState {
pub game: NimGame,
pub rules: Vec<NimRule>, // NimGame has `rules`, but it's private...
pub turn: Player,
}
impl NimState {
pub fn new() -> Self {
let stacks = vec![Stack(1), Stack(3), Stack(5), Stack(7)];
let rules = vec![NimRule {
take: TakeSize::Any,
split: Split::Optional,
}];
Self {
game: NimGame::new(rules.clone(), stacks),
turn: Player::Black,
rules,
}
}
}
impl Default for NimState {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for NimState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self, f)
}
}
#[derive(Clone)]
pub struct Nim;
impl Game for Nim {
type S = NimState;
type A = NimAction;
type P = Player;
fn generate_actions(state: &Self::S, actions: &mut Vec<Self::A>) {
actions.extend(moves::calculate_legal_moves(
state.game.get_stacks(),
&state.rules,
(0, 0),
))
}
fn apply(mut state: Self::S, m: &Self::A) -> Self::S {
moves::apply_move(&mut state.game, m).expect("error in nimlib");
state.turn = state.turn.next();
state
}
fn notation(_state: &Self::S, m: &Self::A) -> String {
format!("{:?}", m)
}
fn is_terminal(state: &Self::S) -> bool {
state.game.get_stacks().iter().all(|x| x.0 == 0)
}
fn winner(state: &Self::S) -> Option<Player> {
if !Self::is_terminal(state) {
panic!();
}
Some(Self::player_to_move(state).next())
}
fn player_to_move(state: &Self::S) -> Player {
state.turn
}
}