//! Utilities for generating random values
//!
//! This module provides a much, much simpler version of the very robust [`rand`] crate. The
//! purpose of this is to give people teaching/learning Rust an easier target for doing interesting
//! things with random numbers. You don't need to know very much Rust to use this module and once
//! you get comfortable with this, you can always move to learning the [`rand`] crate as well. If
//! the items in this module are not advanced enough for your needs, you probably want to consider
//! using the full [`rand`] crate instead.
//!
//! # Random Number Generation
//!
//! Computers can't generate "true" random numbers yet, however they can approximate sequences of
//! numbers that *look* random. This is called [pseudo-random number generation]. This module
//! provides a set of functions (and traits) for generating pseudo-random numbers.
//!
//! The current set of utilities provided includes:
//!
//! * [`random()`] - for generating a single random value of a given type
//! * [`random_range()`] - for generating a single random value of a given type in a certain range
//! * [`shuffle()`] - for mixing up a slice of values (`Vec`, slices, etc.)
//! * [`choose()`] - for choosing a single value from a slice of values (`Vec`, slices, etc.)
//!
//! See the documentation for each of those functions for more on what you can use them for.
//!
//! # Generating Random Values
//!
//! The [`random()`] function supports all of the common primitive types you would expect:
//!
//! * Booleans: `bool`
//! * Floating-point: `f32`, `f64`
//! * Integers: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
//! * Tuples, arrays, and [many more][`Random`]
//!
//! It also supports types specific to the `turtle` crate:
//!
//! * [`Distance`] - `f64` values greater than or equal to `0.0` and less than or equal to `1.0`
//! * [`Angle`] - `f64` values greater than or equal to `0.0` and less than or equal to `1.0`
//! * [`Speed`] - any speed value in the valid range, not including instant
//! * [`Color`] - colors with random red, green, blue, and alpha values (use
//! [`opaque()`] to get a solid random color)
//! * [`Point`] - a random point with two `f64` values greater than or equal to `0.0` and less than
//! or equal to `1.0`
//!
//! # Random Custom Types
//!
//! To make types within your application capable of being used with [`random()`] or
//! [`random_range()`], implement the [`Random`] or [`RandomRange`] traits respectively. See the
//! documentation of those traits for more information.
//!
//! You typically won't need to implement [`RandomSlice`] for yourself since it is already
//! implemented for slices. That being said, if your type can be represented as a slice, you can
//! implement [`RandomSlice`] so it can be used with the [`shuffle()`] and [`choose()`] functions.
//!
//! ```rust
//! use turtle::rand::RandomSlice;
//!
//! // This is a "newtype" wrapper around a Vec<T> which can be represented as a slice.
//! #[derive(Debug, Clone)]
//! struct MyVec<T>(Vec<T>);
//!
//! impl<T> RandomSlice for MyVec<T> {
//! type Item = T;
//!
//! fn shuffle(&mut self) {
//! (&mut *self.0 as &mut [T]).shuffle();
//! }
//!
//! fn choose(&self) -> Option<&Self::Item> {
//! (&*self.0 as &[T]).choose()
//! }
//! }
//! ```
//!
//! [`rand`]: https://docs.rs/rand
//! [pseudo-random number generation]: https://en.wikipedia.org/wiki/Pseudorandom_number_generator
//! [`random()`]: fn.random.html
//! [`random_range()`]: fn.random_range.html
//! [`shuffle()`]: fn.shuffle.html
//! [`choose()`]: fn.choose.html
//! [`Random`]: trait.Random.html
//! [`RandomRange`]: trait.RandomRange.html
//! [`RandomSlice`]: trait.RandomSlice.html
//! [`Distance`]: ../type.Distance.html
//! [`Angle`]: ../type.Angle.html
//! [`Speed`]: ../speed/struct.Speed.html
//! [`Color`]: ../color/struct.Color.html
//! [`Point`]: ../struct.Point.html
//! [`opaque()`]: ../color/struct.Color.html#method.opaque
use Wrapping;
/// This trait represents any type that can have random values generated for it.
///
/// **Tip:** There is a list later on this page that shows many of the types that implement this
/// trait.
///
/// # Example
///
/// To implement this trait for your own types, call [`random()`] or [`random_range()`] for each field.
/// For enums, generate a random number and pick a variant of your enum based on that. You can then
/// use [`random()`] or [`random_range()`] to pick values for that variant's fields (if necessary).
///
/// [`random()`]: fn.random.html
/// [`random_range()`]: fn.random_range.html
///
/// ```rust,no_run
/// use turtle::rand::{
/// random,
/// random_range,
/// Random,
/// RandomRange,
/// };
///
/// #[derive(Debug, Clone)]
/// struct Product {
/// price: f64,
/// quantity: u32,
/// }
///
/// impl Random for Product {
/// fn random() -> Self {
/// Self {
/// // Prices sure are fluctuating!
/// price: Random::random(),
/// // This will generate a value between 1 and 15 (inclusive)
/// quantity: RandomRange::random_range(0, 15),
/// }
/// }
/// }
///
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// enum Door {
/// Open,
/// Closed,
/// Locked,
/// }
///
/// impl Random for Door {
/// fn random() -> Self {
/// use Door::*;
/// // Pick a variant of `Door` based on a number.
/// // Notice the type in the numeric literal so Rust knows what to generate
/// match RandomRange::random_range(0u8, 3) {
/// 0 => Open,
/// 1 => Closed,
/// 2 => Locked,
/// // Even though we know that the value will be between 0 and 2, the compiler does
/// // not, so we instruct it to panic if this case ever occurs.
/// _ => unreachable!(),
/// }
/// }
/// }
///
/// fn main() {
/// // These types can now be used with the `random()` function!
/// let product: Product = random();
/// let door: Door = random();
///
/// // ...
/// }
/// ```
/// This trait represents any type that can have random values generated for it within a certain
/// range.
///
/// **Tip:** There is a list later on this page that shows many of the types that implement this
/// trait.
///
/// It will usually only make sense to implement this trait for types that represent a single
/// value (e.g. [`Speed`], [`Color`], `f64`, `u32`, etc.). For example, if you had the type:
///
/// ```rust,no_run
/// #[derive(Debug, Clone)]
/// struct Product {
/// price: f64,
/// quantity: u32,
/// }
/// ```
///
/// What would `random_range(1.5, 5.2)` mean for this type? It's hard to say because while you
/// could generate a random value for `price`, it doesn't make sense to generate a `quantity`
/// given that range.
///
/// A notable exception to this is the `Point` type. You can interpret a call to
/// `random_range(Point {x: 1.0, y: 2.0}, Point {x: 5.0, y: 8.0})` as wanting to
/// generate a random `Point` in the rectangle formed by the two points provided
/// as arguments.
///
/// [`Speed`]: ../speed/struct.Speed.html
/// [`Color`]: ../color/struct.Color.html
///
/// # Example
///
/// This example demonstrates how to implement this trait for a type with a limited range of valid
/// values.
///
/// ```rust,no_run
/// use turtle::rand::{Random, RandomRange};
///
/// // Some constants to represent the valid range of difficulty levels
/// const MIN_DIFFICULTY: u32 = 1;
/// const MAX_DIFFICULTY: u32 = 10;
///
/// /// Represents the difficulty level of the game
/// #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// struct Difficulty(u32);
///
/// impl Random for Difficulty {
/// /// Generates a random difficulty within the valid range of difficulty levels
/// fn random() -> Self {
/// Difficulty(RandomRange::random_range(MIN_DIFFICULTY, MAX_DIFFICULTY))
/// }
/// }
///
/// // Choosing `u32` for the `Bound` type because that is more convenient to type than if
/// // we had chosen `Difficulty`.
/// //
/// // Example: `random_range(1, 2)` vs. `random_range(Difficulty(1), Difficulty(2))`
/// impl RandomRange<u32> for Difficulty {
/// /// Generates a random difficulty level within the given range.
/// ///
/// /// # Panics
/// ///
/// /// Panics if either bound could result in a value outside the valid range
/// /// of difficulties or if `low > high`.
/// fn random_range(low: u32, high: u32) -> Self {
/// if low < MIN_DIFFICULTY || high > MAX_DIFFICULTY {
/// panic!("The boundaries must be within the valid range of difficulties");
/// }
///
/// RandomRange::random_range(low, high)
/// }
/// }
///
/// fn main() {
/// use turtle::rand::{random, random_range};
///
/// // We can now generate random values for Difficulty!
/// let difficulty: Difficulty = random();
/// let difficulty: Difficulty = random_range(5, 10);
/// }
/// ```
impl_random!;
// `char` does not support sampling in a range, so no RandomRange impl
// `bool` does not support sampling in a range, so no RandomRange impl
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
impl_random_tuple!;
=> ;
// Empty case (no type parameters left)
=> ;
}
impl_random_array!;
/// Generates a single random value of the type `T`.
///
/// # Specifying the type to generate
///
/// Since `T` can be any of a number of different types, you may need to provide a "type parameter"
/// explicitly so that Rust knows what to generate. You can do this either by annotating the type
/// of the variable you are assigning to or by using "turbofish" syntax to specify the type on
/// the `random()` function itself.
///
/// ```rust,no_run
/// use turtle::{Turtle, Speed, rand::random};
/// let mut turtle = Turtle::new();
///
/// // 1. Separate out into a variable, then annotate the desired type
/// let speed: Speed = random();
/// turtle.set_speed(speed);
///
/// // 2. Turbofish syntax ::<T>
/// turtle.set_speed(random::<Speed>());
/// ```
///
/// # Example
///
/// Setting the pen color to a randomly generated color:
///
/// ```rust,no_run
/// use turtle::{Turtle, Color, rand::random};
///
/// let mut turtle = Turtle::new();
/// let color: Color = random();
/// // Calling `opaque()` because even the `alpha` value of the color is randomized.
/// turtle.set_pen_color(color.opaque());
/// ```
/// Generates a random value in the given range.
///
/// The value `x` that is returned will be such that low ≤ x ≤ high.
///
/// Most types that can be used with [`random()`] can also be used with this function. For a list
/// of types that can be passed into this function, see the documentation for the [`RandomRange`]
/// trait.
///
/// [`random()`]: fn.random.html
/// [`RandomRange`]: trait.RandomRange.html
///
/// # Panics
/// Panics if low > high
///
/// # Example:
///
/// ```rust
/// use turtle::rand::random_range;
///
/// // Generates an f64 value between 100 and 199.99999...
/// let value: f64 = random_range(100.0, 200.0);
/// assert!(value >= 100.0 && value <= 200.0);
///
/// // Generates a u64 value between 1000 and 3000000
/// let value = random_range::<u64, _>(1000, 3000001);
/// assert!(value >= 1000 && value <= 3000001);
///
/// // You do not need to specify the type if the compiler has enough information:
/// fn foo(a: u64) {}
/// foo(random_range(432, 1938));
///
/// // This will always return the same value because `low == `high`
/// assert_eq!(random_range::<i32, _>(10i32, 10), 10);
/// ```
/// This trait represents useful random operations for slices.
///
/// You will not typically use this trait directly or even import it.
/// The [`shuffle()`] and [`choose()`] functions provide all the functionality of
/// this trait without needing to have it in scope.
///
/// [`shuffle()`]: fn.shuffle.html
/// [`choose()`]: fn.choose.html
=> ;
// Empty case (no type parameters left)
=> ;
}
impl_random_slice!;
/// Shuffle the elements of the given slice in place.
///
/// None of the elements are modified during this process, only moved.
///
/// # Example
///
/// ```rust,no_run
/// use turtle::{color, rand::shuffle};
///
/// let mut pen_colors = [color::RED, color::BLUE, color::GREEN, color::YELLOW];
/// // A different order of colors every time!
/// shuffle(&mut pen_colors);
///
/// // Even works with Vec
/// let mut pen_colors = vec![color::RED, color::BLUE, color::GREEN, color::YELLOW];
/// shuffle(&mut pen_colors);
/// ```
/// Chooses a random element from the slice and returns a reference to it.
///
/// If the slice is empty, returns None.
///
/// # Example
///
/// ```rust,no_run
/// use turtle::{Turtle, color, rand::choose};
///
/// let mut turtle = Turtle::new();
///
/// let mut pen_colors = [color::RED, color::BLUE, color::GREEN, color::YELLOW];
/// // Choose a random pen color
/// let chosen_color = choose(&mut pen_colors).cloned().unwrap();
/// turtle.set_pen_color(chosen_color);
///
/// // Even works with Vec
/// let mut pen_colors = vec![color::RED, color::BLUE, color::GREEN, color::YELLOW];
/// let chosen_color = choose(&mut pen_colors).cloned().unwrap();
/// turtle.set_pen_color(chosen_color);
/// ```