finish leg/game randomly (untested)
This commit is contained in:
parent
b3e7ae7900
commit
45deb93a4f
66
Cargo.lock
generated
66
Cargo.lock
generated
@ -2,11 +2,18 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cup"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"enum-map",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -29,6 +36,29 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.49"
|
||||
@ -47,6 +77,36 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
@ -63,3 +123,9 @@ name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
"enum-map" = "2.4.2"
|
||||
"rand" = "0.8.5"
|
||||
|
85
src/game.rs
85
src/game.rs
@ -1,4 +1,9 @@
|
||||
use enum_map::{Enum, EnumMap};
|
||||
use rand::{
|
||||
Rng,
|
||||
seq::SliceRandom,
|
||||
distributions::{Distribution, Uniform},
|
||||
};
|
||||
|
||||
use crate::stack::Stack;
|
||||
|
||||
@ -8,7 +13,7 @@ pub enum Color {
|
||||
#[default] Red, Green, Blue, Yellow, Purple,
|
||||
}
|
||||
|
||||
// const COLORS: Stack<Color, 5> = Stack::from([
|
||||
// const COLORS: Stack<Color, 5> = Stack::from_array([
|
||||
// Color::Red,
|
||||
// Color::Green,
|
||||
// Color::Blue,
|
||||
@ -16,6 +21,14 @@ pub enum Color {
|
||||
// Color::Purple,
|
||||
// ]);
|
||||
|
||||
const COLORS: [Color; 5] = [
|
||||
Color::Red,
|
||||
Color::Green,
|
||||
Color::Blue,
|
||||
Color::Yellow,
|
||||
Color::Purple,
|
||||
];
|
||||
|
||||
|
||||
type ColorStack = Stack<Color, 5>;
|
||||
|
||||
@ -68,6 +81,20 @@ impl Game {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
// new game with random starting positions
|
||||
fn new_random() -> Self {
|
||||
let mut game = Self::default();
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut dice = *&COLORS;
|
||||
dice.shuffle(&mut rng);
|
||||
for color in dice {
|
||||
let roll = rng.gen_range(1..=3);
|
||||
game.squares[roll - 1].assume_stack_mut().push(color);
|
||||
game.camels[color] = roll - 1;
|
||||
}
|
||||
game
|
||||
}
|
||||
|
||||
fn set_state(&mut self, squares: [Square; 16], dice: EnumMap<Color, bool>) {
|
||||
self.squares = squares;
|
||||
self.dice = dice;
|
||||
@ -80,17 +107,6 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_positions(&mut self, target_sq: usize) {
|
||||
match self.squares[target_sq] {
|
||||
Square::Camels(stack) => {
|
||||
for camel in stack.iter() {
|
||||
self.camels[*camel] = target_sq;
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
// returns winner if there is one
|
||||
fn advance(&mut self, die: Color, roll: usize) -> Option<Color> {
|
||||
let src_sq = self.camels[die];
|
||||
@ -144,6 +160,49 @@ impl Game {
|
||||
self.dice[die] = true;
|
||||
None
|
||||
}
|
||||
|
||||
fn finish_leg_random(&mut self) -> Option<Color> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut leg_dice: Stack<Color, 5> = Stack::new();
|
||||
for (color, rolled) in self.dice {
|
||||
if !rolled {
|
||||
leg_dice.push(color);
|
||||
}
|
||||
}
|
||||
|
||||
(&mut leg_dice[..]).shuffle(&mut rng);
|
||||
|
||||
for color in leg_dice.iter() {
|
||||
let roll = rng.gen_range(1..=3);
|
||||
if let Some(winner) = self.advance(*color, roll) {
|
||||
return Some(winner);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn finish_game_random(&mut self) -> Color {
|
||||
if let Some(winner) = self.finish_leg_random() {
|
||||
return winner;
|
||||
}
|
||||
|
||||
// we are now guaranteed to be at the start of a new leg,
|
||||
// so we don't need to check the dice state
|
||||
let mut rng = rand::thread_rng();
|
||||
let roll_dist = Uniform::from(0..=3);
|
||||
let mut dice = *&COLORS; // makes a copy of the constant
|
||||
|
||||
loop {
|
||||
// easiest if we shuffle at the start of the leg
|
||||
dice.shuffle(&mut rng);
|
||||
for i in 0..5 {
|
||||
let roll = roll_dist.sample(&mut rng);
|
||||
if let Some(winner) = self.advance(dice[i], roll) {
|
||||
return winner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -187,4 +246,6 @@ mod test {
|
||||
assert_eq!(game.squares[3].assume_stack(), &Stack::from([Red, Purple, Yellow]));
|
||||
// B, _, G, RPY
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
39
src/stack.rs
39
src/stack.rs
@ -1,4 +1,4 @@
|
||||
use std::ops::Index;
|
||||
use std::ops::{Index, IndexMut, RangeFull};
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
|
||||
@ -35,6 +35,13 @@ impl<T, const S: usize> Stack<T, S> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
self.data.iter().take(self.len)
|
||||
}
|
||||
|
||||
pub const fn from_array(array: [T; S]) -> Self {
|
||||
Stack {
|
||||
data: array,
|
||||
len: S,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -94,12 +101,24 @@ where T: Copy + Default
|
||||
|
||||
impl<T, const S: usize> Index<usize> for Stack<T, S> {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &T {
|
||||
&self.data[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const S: usize> Index<RangeFull> for Stack<T, S> {
|
||||
type Output = [T];
|
||||
fn index(&self, _index: RangeFull) -> &[T] {
|
||||
&self.data[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const S: usize> IndexMut<RangeFull> for Stack<T, S> {
|
||||
fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
|
||||
&mut self.data[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<I, T, const S: usize> From<I> for Stack<T, S>
|
||||
where
|
||||
@ -223,4 +242,20 @@ mod test {
|
||||
assert_eq!(it.next(), Some(&3));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_array() {
|
||||
let s = Stack::from_array([1, 2, 3]);
|
||||
assert_eq!(s[0], 1);
|
||||
assert_eq!(s[1], 2);
|
||||
assert_eq!(s[2], 3);
|
||||
assert_eq!(s.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice_index() {
|
||||
let mut s = Stack::<_, 5>::from([3, 4, 5]);
|
||||
assert_eq!(s[..], [3, 4, 5]);
|
||||
assert_eq!(&mut s[..], &mut [3, 4, 5]);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user