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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Generate, count, and sample chess back-rank arrangements under
//! composable constraints (Chess960, Chess2880, custom presets).
//!
//! The crate is generic — parameterised over a user-defined piece
//! kind, a user-defined colour set, and board size — and built around
//! a small set of composable constraint primitives with `And` / `Or` /
//! `Not` combinators. An opinionated [`chess`] module ships
//! ready-to-use presets for the canonical chess shuffle variants
//! (Chess960, Chess-2880, full shuffle).
//!
//! # Mental model
//!
//! - `pieces` is the **alphabet** — the *set* of distinct kinds
//! available. Duplicate entries are silently deduplicated.
//! - `num_squares` is the board size.
//! - `square_colors` labels each square with a colour from the
//! user-defined colour set. Generic; defaults to [`SquareColor`].
//! - Constraints filter the arrangements you want. The solver
//! enumerates length-`num_squares` sequences over the alphabet
//! and keeps the ones satisfying the root constraint.
//!
//! The constraint vocabulary is `Count`, `CountOnColor`, `At`,
//! `NotAt`, `Order`, and `Relative`, composable with `And` / `Or` /
//! `Not`. See [`Constraint`] for each variant's semantics.
//!
//! # Quick start — chess presets
//!
//! ```
//! use chess_startpos_rs::chess;
//!
//! assert_eq!(chess::shuffle().count(), 5040);
//! assert_eq!(chess::chess_2880().count(), 2880);
//! assert_eq!(chess::chess_960().count(), 960);
//! ```
//!
//! # Custom piece kinds, boards, and colours
//!
//! ```
//! use chess_startpos_rs::{alternating, Constraint, CountOp, Problem, SquareColor};
//!
//! #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
//! enum Tile { A, B }
//!
//! let problem: Problem<Tile> = Problem {
//! num_squares: 3,
//! square_colors: alternating(3, SquareColor::Light, SquareColor::Dark),
//! pieces: vec![Tile::A, Tile::B], // alphabet
//! constraint: Constraint::And(vec![
//! Constraint::Count { piece: Tile::A, op: CountOp::Eq, value: 2 },
//! Constraint::Count { piece: Tile::B, op: CountOp::Eq, value: 1 },
//! Constraint::At { piece: Tile::B, square: 1 },
//! ]),
//! };
//! assert_eq!(problem.count(), 1);
//! assert_eq!(problem.at(0), Some(vec![Tile::A, Tile::B, Tile::A]));
//! ```
use Debug;
use Hash;
pub use ;
pub use ;
/// Marker trait for piece kinds usable as the type parameter of
/// [`Problem`] / [`Constraint`].
///
/// Has a blanket impl: any type satisfying the supertrait bounds is
/// automatically a `PieceKind`. The user's piece enum typically
/// derives `Copy`, `Clone`, `Debug`, `PartialEq`, `Eq`,
/// `PartialOrd`, `Ord`, `Hash`.
/// Marker trait for colour kinds usable as the type parameter of
/// [`Problem`] / [`Constraint`].
///
/// Has a blanket impl: any type satisfying the supertrait bounds is
/// automatically a `ColorKind`. The user's colour enum typically
/// derives `Copy`, `Clone`, `Debug`, `PartialEq`, `Eq`, `Hash`.
///
/// The default colour type for `Problem` is [`SquareColor`] — the
/// binary light/dark partition standard chess uses. Define your own
/// for N-way partitions (halves, thirds, fairy zones, …).
/// Returns a `Vec<C>` of length `n` alternating between `first` and
/// `second`, starting with `first`.
///
/// ```
/// use chess_startpos_rs::{alternating, SquareColor};
///
/// let cs = alternating(4, SquareColor::Dark, SquareColor::Light);
/// assert_eq!(
/// cs,
/// vec![
/// SquareColor::Dark,
/// SquareColor::Light,
/// SquareColor::Dark,
/// SquareColor::Light,
/// ],
/// );
/// ```
/// Returns a `Vec<C>` of length `n` where every entry is `c`.
///
/// ```
/// use chess_startpos_rs::{uniform, SquareColor};
///
/// assert_eq!(
/// uniform(3, SquareColor::Light),
/// vec![SquareColor::Light, SquareColor::Light, SquareColor::Light],
/// );
/// ```