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
//! # bowling
//!
//! A generic, typestate-driven bowling game engine that models the complete
//! mechanics of bowling: multiple players, strikes, spares, fill balls,
//! split detection, and per-pin deck tracking.
//!
//! ## Design highlights
//!
//! - **Generic over ruleset** via static dispatch. The [`Ruleset`] trait
//! defines pin count, frame count, deadwood policy, bonus scheme, and
//! optional pin geometry. Three variants ship out of the box:
//! [`TenPin`], [`Candlepin`], and [`Duckpin`].
//!
//! - **Typestate state machines** at both the frame and game level. Illegal
//! transitions (e.g. rolling after the game is complete) are compile
//! errors, not runtime panics.
//!
//! - **Per-pin deck** via [`PinSet`], a compact `u16` bitset. Split
//! detection is powered by [`PinGeometry`] adjacency graphs, supplied
//! per-ruleset.
//!
//! ## Quick start
//!
//! ```
//! use bowling::prelude::*;
//!
//! // Build a single-player ten-pin game
//! let alice = Player::new("Alice").unwrap();
//! let mut progress = GameBuilder::<TenPin>::new(alice).build();
//!
//! // Bowl a perfect game (12 strikes)
//! for _ in 0..12 {
//! match progress {
//! Progress::AwaitingRoll(g) => {
//! progress = g.roll_count(10).unwrap();
//! }
//! Progress::Complete(_) => break,
//! }
//! }
//!
//! if let Progress::Complete(game) = progress {
//! assert_eq!(game.scoreboard(0).total, 300);
//! }
//! ```
//!
//! [`TenPin`]: ruleset::TenPin
//! [`Candlepin`]: ruleset::Candlepin
//! [`Duckpin`]: ruleset::Duckpin
//! [`PinSet`]: pins::PinSet
//! [`PinGeometry`]: geometry::PinGeometry
//! [`Ruleset`]: ruleset::Ruleset
/// Convenience re-exports for the most commonly used types.