shuyi_core/turn.rs
1//! The rules of a turn-based game as the engine's generic code sees them:
2//! a state that takes commands and answers with what happened. The game
3//! keeps its own turn loop, phases and rules, and implements
4//! [`TurnRules`] for its state; [`History`](crate::History) (replay,
5//! rewind, saving a game in progress) is written against it.
6
7use alloc::vec::Vec;
8
9/// A turn-based game's state, and the commands that change it.
10///
11/// # Contract
12///
13/// - **Deterministic.** The same state and command always give the same
14/// events and the same new state. Luck comes from a seeded RNG kept in
15/// the state ([`SimRng`](crate::SimRng)), never from outside, so a game
16/// can be rebuilt by replaying its commands.
17/// - **All or nothing.** [`apply`](Self::apply) either changes the state
18/// and returns what happened, or refuses the command with an error and
19/// changes nothing.
20/// - [`check`](Self::check) gives [`apply`](Self::apply)'s answer without
21/// changing anything, luck included.
22/// - [`legal_commands`](Self::legal_commands) lists commands
23/// [`check`](Self::check) accepts, always in the same order. A game may
24/// leave some out (when there are too many to list), and says which.
25/// - Once [`outcome`](Self::outcome) is `Some`, the game is over and
26/// [`legal_commands`](Self::legal_commands) is empty.
27pub trait TurnRules {
28 /// What a player (or an AI) asks for.
29 type Command;
30 /// What happened when a command was applied.
31 type Event;
32 /// Why a command was refused.
33 type Error;
34 /// How a game ended.
35 type Outcome;
36
37 /// Whether [`apply`](Self::apply) would accept `command`, and if not
38 /// why, without changing anything.
39 fn check(&self, command: &Self::Command) -> Result<(), Self::Error>;
40
41 /// Applies `command` and returns what happened, or refuses it and
42 /// changes nothing.
43 fn apply(&mut self, command: &Self::Command) -> Result<Vec<Self::Event>, Self::Error>;
44
45 /// The commands [`check`](Self::check) accepts now, in a fixed order.
46 fn legal_commands(&self) -> Vec<Self::Command>;
47
48 /// How the game ended, once it has.
49 fn outcome(&self) -> Option<Self::Outcome>;
50}