pub struct PerPlayer<T, const P: usize> { /* private fields */ }
Expand description
A collection that stores one element corresponding to each player in a game.
The type is parameterized by the type of elements T
and the number of players in the game
P
. For example, the type PerPlayer<f64, 3>
contains exactly three f64
values, one for
each player in a three-player game.
The “const generic”
argument P
is used to statically ensure that a PerPlayer
collection contains the correct
number of elements for a given game, and to provide statically checked indexing into
PerPlayer
collections.
§Dynamically checked indexing operations
The get
and get_mut
methods allow indexing into a
PerPlayer
collection with plain usize
indexes. They return references wrapped in an
Option
type, which may be None
if the index is too large for the number of players in the
game.
use t4t::PerPlayer;
let mut pp = PerPlayer::new(["klaatu", "barada", "nikto"]);
assert_eq!(pp.get(0), Some(&"klaatu"));
assert_eq!(pp.get(1), Some(&"barada"));
assert_eq!(pp.get(2), Some(&"nikto"));
assert_eq!(pp.get(3), None);
*pp.get_mut(0).unwrap() = "gort";
assert_eq!(pp.get(0), Some(&"gort"));
§Statically checked indexing operations
The for_player
and for_player_mut
methods allow indexing into a PerPlayer
collection with indexes of type PlayerIndex
. An
index of type PlayerIndex<P>
is guaranteed to be in-range for a collection of type
PerPlayer<T, P>
, that is, indexing operations into a PerPlayer
collection are guaranteed
not to fail due to an index out-of-bounds error.
The Index
and IndexMut
traits are implemented using indexes of type PlayerIndex
and
are synonymous with the for_player
and for_player_mut
methods, respectively.
Indexes can be constructed dynamically using the PlayerIndex::new
constructor. While the
indexing operation cannot fail, constructing an index may fail if the index is out of
bounds, in which case the constructor will return None
.
use t4t::PlayerIndex;
assert!(PlayerIndex::<3>::new(0).is_some());
assert!(PlayerIndex::<3>::new(1).is_some());
assert!(PlayerIndex::<3>::new(2).is_some());
assert!(PlayerIndex::<3>::new(3).is_none());
When constructing indexes, often the value of P
can be inferred from the type of the
PerPlayer
collection it is used to index into.
use t4t::{PerPlayer, PlayerIndex};
let mut pp = PerPlayer::new(["klaatu", "barada", "nikto"]);
let p0 = PlayerIndex::new(0).unwrap();
let p1 = PlayerIndex::new(1).unwrap();
let p2 = PlayerIndex::new(2).unwrap();
assert_eq!(pp[p0], "klaatu");
assert_eq!(pp[p1], "barada");
assert_eq!(pp[p2], "nikto");
pp[p0] = "gort";
assert_eq!(pp[p0], "gort");
Additionally, this module contains several submodules that predefine named indexes for all
players up to a player count of 16. For example, the indexes for three player games are
included in the for3
submodule.
use t4t::{for3, PerPlayer};
let mut pp = PerPlayer::new(["klaatu", "barada", "nikto"]);
assert_eq!(pp[for3::P0], "klaatu");
assert_eq!(pp[for3::P1], "barada");
assert_eq!(pp[for3::P2], "nikto");
pp[for3::P0] = "gort";
assert_eq!(pp[for3::P0], "gort");
Implementations§
Source§impl<T, const P: usize> PerPlayer<T, P>
impl<T, const P: usize> PerPlayer<T, P>
Sourcepub fn generate<F: FnMut(PlayerIndex<P>) -> T>(gen_elem: F) -> Self
pub fn generate<F: FnMut(PlayerIndex<P>) -> T>(gen_elem: F) -> Self
Create a new per-player collection by calling the given function with each player index, collecting the results.
§Examples
use t4t::{for5, PerPlayer, PlayerIndex};
let squared = |index: PlayerIndex<5>| {
let val: usize = index.into();
val * val
};
let squares = PerPlayer::generate(squared);
assert_eq!(squares[for5::P0], 0);
assert_eq!(squares[for5::P1], 1);
assert_eq!(squares[for5::P2], 4);
assert_eq!(squares[for5::P3], 9);
assert_eq!(squares[for5::P4], 16);
Sourcepub fn num_players(&self) -> usize
pub fn num_players(&self) -> usize
Get the number of players in the game, which corresponds to the number of elements in this collection.
Sourcepub fn get(&self, i: usize) -> Option<&T>
pub fn get(&self, i: usize) -> Option<&T>
Get a reference to the element corresponding to the i
th player in the game. Returns
None
if the index is out of range.
§Examples
use t4t::PerPlayer;
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
assert_eq!(pp.get(0), Some(&"frodo"));
assert_eq!(pp.get(1), Some(&"sam"));
assert_eq!(pp.get(2), Some(&"merry"));
assert_eq!(pp.get(3), Some(&"pippin"));
assert_eq!(pp.get(4), None);
Sourcepub fn get_mut(&mut self, i: usize) -> Option<&mut T>
pub fn get_mut(&mut self, i: usize) -> Option<&mut T>
Get a mutable reference to the element corresponding to the i
th player in the game.
Returns None
if the index is out of range.
§Examples
use t4t::PerPlayer;
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
*pp.get_mut(1).unwrap() = "samwise";
*pp.get_mut(2).unwrap() = "meriadoc";
*pp.get_mut(3).unwrap() = "peregrin";
assert_eq!(pp.get(0), Some(&"frodo"));
assert_eq!(pp.get(1), Some(&"samwise"));
assert_eq!(pp.get(2), Some(&"meriadoc"));
assert_eq!(pp.get(3), Some(&"peregrin"));
assert_eq!(pp.get(4), None);
Sourcepub fn for_player(&self, idx: PlayerIndex<P>) -> &T
pub fn for_player(&self, idx: PlayerIndex<P>) -> &T
Index into a PerPlayer
collection with a PlayerIndex
. This operation is statically
guaranteed not to fail.
§Examples
use t4t::{for4, PerPlayer};
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
assert_eq!(*pp.for_player(for4::P0), "frodo");
assert_eq!(*pp.for_player(for4::P1), "sam");
assert_eq!(*pp.for_player(for4::P2), "merry");
assert_eq!(*pp.for_player(for4::P3), "pippin");
This method is used to implement the Index
trait, which enables using the more concise
indexing syntax.
use t4t::{for4, PerPlayer};
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
assert_eq!(pp[for4::P0], "frodo");
assert_eq!(pp[for4::P1], "sam");
assert_eq!(pp[for4::P2], "merry");
assert_eq!(pp[for4::P3], "pippin");
Sourcepub fn for_player_mut(&mut self, idx: PlayerIndex<P>) -> &mut T
pub fn for_player_mut(&mut self, idx: PlayerIndex<P>) -> &mut T
Index into a PerPlayer
collection with PlayerIndex
in a mutable context. This operation
is statically guaranteed not to fail.
§Examples
use t4t::{for4, PerPlayer};
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
*pp.for_player_mut(for4::P1) = "samwise";
*pp.for_player_mut(for4::P2) = "meriadoc";
*pp.for_player_mut(for4::P3) = "peregrin";
assert_eq!(*pp.for_player(for4::P0), "frodo");
assert_eq!(*pp.for_player(for4::P1), "samwise");
assert_eq!(*pp.for_player(for4::P2), "meriadoc");
assert_eq!(*pp.for_player(for4::P3), "peregrin");
This method is used to implement the IndexMut
trait, which enables using the more
concise indexing syntax.
use t4t::{for4, PerPlayer};
let mut pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
pp[for4::P1] = "samwise";
pp[for4::P2] = "meriadoc";
pp[for4::P3] = "peregrin";
assert_eq!(pp[for4::P0], "frodo");
assert_eq!(pp[for4::P1], "samwise");
assert_eq!(pp[for4::P2], "meriadoc");
assert_eq!(pp[for4::P3], "peregrin");
Source§impl<T: Clone, const P: usize> PerPlayer<T, P>
impl<T: Clone, const P: usize> PerPlayer<T, P>
Sourcepub fn init_with(value: T) -> Self
pub fn init_with(value: T) -> Self
Create a new per-player collection where each element is initialized with the given cloneable value.
Sourcepub fn for_each<F: FnMut(&T)>(&self, f: F)
pub fn for_each<F: FnMut(&T)>(&self, f: F)
Execute a function for each element in a per-player collection.
§Examples
use t4t::PerPlayer;
let mut longest = "";
let pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
pp.for_each(|s| {
if s.len() > longest.len() {
longest = s;
}
});
assert_eq!(longest, "pippin");
Sourcepub fn for_each_with_index<F: FnMut(PlayerIndex<P>, &T)>(&self, f: F)
pub fn for_each_with_index<F: FnMut(PlayerIndex<P>, &T)>(&self, f: F)
Execute a function for each element-index pair in a per-player collection.
§Examples
use t4t::{for4, PerPlayer};
let mut longest = "";
let mut longest_index = for4::P0;
let pp = PerPlayer::new(["frodo", "sam", "pippin", "merry"]);
pp.for_each_with_index(|i, s| {
println!("{}, {}, {}", i, s, s.len());
if s.len() > longest.len() {
println!("updating to {}, {}", i, s);
longest = s;
longest_index = i;
}
});
assert_eq!(longest, "pippin");
assert_eq!(longest_index, for4::P2);
Sourcepub fn map<U, F: FnMut(T) -> U>(&self, f: F) -> PerPlayer<U, P>
pub fn map<U, F: FnMut(T) -> U>(&self, f: F) -> PerPlayer<U, P>
Map a function over all elements in a per-player collection, producing a new per-player collection.
§Examples
use t4t::PerPlayer;
let pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
let mut lengths = pp.map(|s| s.len());
assert_eq!(lengths, PerPlayer::new([5, 3, 5, 6]));
let mut firsts = pp.map(|s| s.chars().next().unwrap());
assert_eq!(firsts, PerPlayer::new(['f', 's', 'm', 'p']));
Sourcepub fn map_with_index<U, F: FnMut(PlayerIndex<P>, T) -> U>(
&self,
f: F,
) -> PerPlayer<U, P>
pub fn map_with_index<U, F: FnMut(PlayerIndex<P>, T) -> U>( &self, f: F, ) -> PerPlayer<U, P>
Map a function over each element-index pair in a per-player collection, producing a new per-player collection.
§Examples
use t4t::PerPlayer;
let pp = PerPlayer::new(["frodo", "sam", "merry", "pippin"]);
let mut pairs = pp.map_with_index(|i, s| (i.as_usize(), s.len()));
assert_eq!(pairs, PerPlayer::new([(0, 5), (1, 3), (2, 5), (3, 6)]));
let mut nths = pp.map_with_index(|i, s| s.chars().nth(i.as_usize()).unwrap());
assert_eq!(nths, PerPlayer::new(['f', 'a', 'r', 'p']));
Source§impl<T: Debug, const P: usize> PerPlayer<Option<T>, P>
impl<T: Debug, const P: usize> PerPlayer<Option<T>, P>
Sourcepub fn all_some(self) -> Option<PerPlayer<T, P>>
pub fn all_some(self) -> Option<PerPlayer<T, P>>
Converts a per-player collection of Option<T>
values into a per-player collection of T
values if every element in the initial collection is Some
; otherwise returns None
.
§Examples
use t4t::PerPlayer;
assert_eq!(
PerPlayer::new([Some(3), Some(4), Some(5)]).all_some(),
Some(PerPlayer::new([3, 4, 5])),
);
assert_eq!(
PerPlayer::new([Some(3), None, Some(5)]).all_some(),
None,
);
Source§impl<T, const P: usize> PerPlayer<T, P>
impl<T, const P: usize> PerPlayer<T, P>
Sourcepub fn iter(&self) -> <&[T; P] as IntoIterator>::IntoIter
pub fn iter(&self) -> <&[T; P] as IntoIterator>::IntoIter
An iterator over references to elements in the per-player collection.
Sourcepub fn iter_mut(&mut self) -> <&mut [T; P] as IntoIterator>::IntoIter
pub fn iter_mut(&mut self) -> <&mut [T; P] as IntoIterator>::IntoIter
An iterator over mutable references to elements in the per-player collection.
Trait Implementations§
Source§impl<'a, T, const P: usize> IntoIterator for &'a PerPlayer<T, P>
impl<'a, T, const P: usize> IntoIterator for &'a PerPlayer<T, P>
Source§impl<'a, T, const P: usize> IntoIterator for &'a mut PerPlayer<T, P>
impl<'a, T, const P: usize> IntoIterator for &'a mut PerPlayer<T, P>
Source§impl<T, const P: usize> IntoIterator for PerPlayer<T, P>
impl<T, const P: usize> IntoIterator for PerPlayer<T, P>
Source§impl<T: Ord, const P: usize> Ord for PerPlayer<T, P>
impl<T: Ord, const P: usize> Ord for PerPlayer<T, P>
1.21.0 · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl<T: PartialOrd, const P: usize> PartialOrd for PerPlayer<T, P>
impl<T: PartialOrd, const P: usize> PartialOrd for PerPlayer<T, P>
impl<T: Copy, const P: usize> Copy for PerPlayer<T, P>
impl<T: Eq, const P: usize> Eq for PerPlayer<T, P>
impl<T, const P: usize> StructuralPartialEq for PerPlayer<T, P>
Auto Trait Implementations§
impl<T, const P: usize> Freeze for PerPlayer<T, P>where
T: Freeze,
impl<T, const P: usize> RefUnwindSafe for PerPlayer<T, P>where
T: RefUnwindSafe,
impl<T, const P: usize> Send for PerPlayer<T, P>where
T: Send,
impl<T, const P: usize> Sync for PerPlayer<T, P>where
T: Sync,
impl<T, const P: usize> Unpin for PerPlayer<T, P>where
T: Unpin,
impl<T, const P: usize> UnwindSafe for PerPlayer<T, P>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more