t4t/lib.rs
1#![warn(missing_docs)]
2
3//! Tit-for-tat (t4t) is a [game theory][wiki-game-theory] library focusing on expressiveness, type
4//! safety, and experimentation. It provides flexible types and traits for defining games and
5//! strategies, then executing them to observe the results.
6//!
7//! The companion crate [t4t-games][games-crate] provides some example games and strategies.
8//!
9//! # Features
10//!
11//! **Defining games**
12//!
13//! The library provides a variety of types for defining common kinds of games:
14//!
15//! - [`GameTree`]: A very generic game-tree representation. This is not very convenient to use
16//! directly, but all games are eventually translated into this type in order to be executed.
17//!
18//! - [`Normal`]: A general representation of n-ary [normal-form games][normal-form-game].
19//! An arbitrary number of players simultaneously play a single move selected from a finite set
20//! of available moves.
21//!
22//! - [`Simultaneous`]: N-ary [simultaneous games][simultaneous-game]. Similar to [`Normal`],
23//! except the set of moves available to each player may be non-finite.
24//!
25//! - `Extensive` (coming soon): A simple representation of [extensive-form games][extensive-form-game],
26//! that is, games represented as complete game trees, where players take turns making moves,
27//! possibly with moves of chance interspersed.
28//!
29//! - [`Combinatorial`]: A trait for defining [combinatorial games][combinatorial-game], that is,
30//! [perfect-information][perfect-information] games where players interact by sequentially making
31//! moves to modify a shared state.
32//!
33//! - [`Repeated`]: Games where another game is played repeatedly a given number of times.
34//!
35//! Each of these game types represents a class of games that work in a similar way. Most new games
36//! can can be defined using the constructors on these types.
37//!
38//! Each game type implements two or three traits:
39//!
40//! - [`Game`]: Defines associated types used by the rest of the library, such as the type of moves
41//! played by players during the game, the type of the intermediate game state, and the type of
42//! utility values awarded to players at the end of the game.
43//!
44//! - [`Playable`]: Defines a common interface for playing games via translation to the [`GameTree`]
45//! type.
46//!
47//! - [`Finite`]: Provides a method to enumerate the moves available to a player in games where
48//! this set is finite.
49//!
50//! If you'd like to define your own completely new game forms or transformations, you will need to
51//! implement these traits. The best way to learn how to do this is currently to look at the source
52//! code for this crate and the [t4t-games][games-crate] crate.
53//!
54//! **Defining players and strategies**
55//!
56//! A [`Player`] consists of an identifying name and a [`Strategy`].
57//!
58//! A [`Strategy`] provides a method to get the next move to play in a game, given the current
59//! [strategic context](crate::Context). For example, for repeated games, the strategic context
60//! includes the history of games played so far.
61//!
62//! There are several associated functions on the [`Strategy`] type for defining common types of
63//! strategies.
64//!
65//! **Running tournaments**
66//!
67//! The [`Tournament`] type provides a convenient way to efficiently play many instances of a game
68//! in parallel, with all combinations or permutations of a set of players, aggregating the results.
69//!
70//! # Example
71//!
72//! The following example illustrates defining a few simple games and strategies, then executing
73//! them.
74//!
75//! ```
76//! use itertools::*;
77//! use std::sync::Arc;
78//! use t4t::*;
79//!
80//! // Possibles moves in social dilemma games, like the Prisoner's Dilemma.
81//! #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
82//! enum DilemmaMove { Cooperate, Defect }
83//!
84//! // The type of a 2-player social dilemma game with integer payoffs.
85//! type Dilemma = Normal<DilemmaMove, i32, 2>;
86//!
87//! // Define the Prisoner's Dilemma.
88//! let pd: Dilemma = Normal::symmetric(
89//! vec![DilemmaMove::Cooperate, DilemmaMove::Defect],
90//! vec![2, 0, 3, 1]
91//! ).unwrap();
92//!
93//! // Define two functions that produce players for playing social dilemma games. The game type is
94//! // generic so that we can reuse these players later for repeated prisoner's dilemma.
95//! fn nice<G: Playable<2, Move = DilemmaMove>>() -> Player<G, 2> {
96//! Player::new("Nice".to_string(), || Strategy::pure(DilemmaMove::Cooperate))
97//! }
98//!
99//! fn mean<G: Playable<2, Move = DilemmaMove>>() -> Player<G, 2> {
100//! Player::new("Mean".to_string(), || Strategy::pure(DilemmaMove::Defect))
101//! }
102//!
103//! // Play the game!
104//! let result = pd.play(&Matchup::from_players([nice(), mean()]));
105//! assert_eq!(result.unwrap().payoff(), &Payoff::from([0, 3]));
106//!
107//! // Define the repeated prisoner's dilemma.
108//! let rpd: Repeated<Dilemma, 2> = Repeated::new(pd, 100);
109//!
110//! // Define a player that plays the famous tit-for-tat strategy.
111//! let tit_for_tat: Player<Repeated<Dilemma, 2>, 2> = Player::new(
112//! "Tit-for-Tat".to_string(),
113//! || Strategy::new(|context: Context<Repeated<Dilemma, 2>, 2>| {
114//! context
115//! .state_view() // get the repeated game state
116//! .history() // get the completed game history from the state
117//! .moves_for_player(context.their_index()) // get the moves for the other player
118//! .last() // take their last move only
119//! .unwrap_or(DilemmaMove::Cooperate) // play that, or cooperate if it's the first move
120//! }),
121//! );
122//!
123//! // Create a tournament in which every player plays every player, including themselves.
124//! let tournament = Tournament::combinations_with_replacement(
125//! Arc::new(rpd),
126//! &vec![Arc::new(nice()), Arc::new(mean()), Arc::new(tit_for_tat)],
127//! );
128//!
129//! // Run all the matches in parallel and accumulate the resulting scores.
130//! let results = tournament.play();
131//! assert_eq!(
132//! results.score().best_to_worst(),
133//! vec![
134//! ("Tit-for-Tat", 699),
135//! ("Mean", 602),
136//! ("Nice", 600),
137//! ],
138//! );
139//! ```
140//!
141//! # Design priorities
142//!
143//! **Expressiveness over performance**
144//!
145//! This library prioritizes expressiveness over performance. It aims to provide a powerful set of
146//! abstractions for defining arbitrary games and strategies, without sacrificing type safety.
147//!
148//! This tradeoff is evident in the representation of [normal-form games](crate::Normal), which are
149//! represented not as, say, a matrix of float-tuples, but instead as a function from generic
150//! [move profiles](crate::Profile) to generic [payoffs](crate::Payoff). This enables normal-form
151//! games of arbitrary size, between arbitrary numbers of players, and with arbitrary move and
152//! utility values, but is somewhat less efficient than a simple matrix.
153//!
154//!
155//! A subtler but more extreme example of this tradeoff is how games are executed. The [`Game`] and
156//! [`Playable`] traits are quite generic. Implementers of these traits do not implement the
157//! execution of their game directly, but rather define a translation of the game into a generic
158//! [game tree](crate::GameTree) representation. This is less efficient, but enables manipulating
159//! game trees to modify the execution of a game, for example, defining new games that modify the
160//! behavior of existing games.
161//!
162//! An example of this capability in action is the [`Repeated`] type, which transforms any game into
163//! a repeated game, modifying the original game's tree and extending the state stored at each node
164//! to enable players of the game to see the history of games played so far.
165//!
166//! Of course, all things being equal, I'd still like things to run as fast as possible! However,
167//! if your application deals only with 2x2 numeric, normal-form games, and you need to run
168//! billions of iterations, this might not be the library you're looking for.
169//!
170//! **Experimentation over formal analysis**
171//!
172//! The library emphasizes exploring strategic situations through *executing* games and strategies
173//! and observing the results, rather than through formal, mathematical analysis of games. This is
174//! consistent with the expressiveness goal above, since many games that can be defined with the
175//! library may not be amenable to formal analysis.
176//!
177//! However, the library will aim to provide analytic solutions where possible, since often a goal
178//! of experimental game theory is to compare various analytic solutions with each other and with
179//! other strategies.
180//!
181//! # Work in progress!
182//!
183//! The library is a work-in-progress and will continue expanding and evolving. For now, expect
184//! breaking changes on even patch-level version changes. Minor version changes will indicate
185//! significant new features.
186//!
187//! [wiki-game-theory]: https://en.wikipedia.org/wiki/Game_theory
188//! [normal-form-game]: https://en.wikipedia.org/wiki/Normal-form_game
189//! [simultaneous-game]: https://en.wikipedia.org/wiki/Simultaneous_game
190//! [extensive-form-game]: https://en.wikipedia.org/wiki/Extensive-form_game
191//! [combinatorial-game]: https://en.wikipedia.org/wiki/Combinatorial_game_theory
192//! [perfect-information]: https://en.wikipedia.org/wiki/Perfect_information
193//! [repeated-game]: https://en.wikipedia.org/wiki/Repeated_game
194//! [games-crate]: https://crates.io/crates/t4t-games
195
196mod combinatorial;
197mod distribution;
198mod dominated;
199mod finite;
200// mod extensive;
201mod game;
202mod history;
203mod matchup;
204mod moves;
205mod normal;
206mod outcome;
207mod past;
208mod payoff;
209mod per_player;
210mod playable;
211mod player;
212mod ply;
213mod possible_profiles;
214mod profile;
215mod record;
216mod repeated;
217mod result;
218mod score;
219mod simultaneous;
220mod strategy;
221mod summary;
222mod tournament;
223mod transcript;
224mod tree;
225
226pub use combinatorial::*;
227pub use distribution::*;
228pub use dominated::*;
229pub use finite::*;
230// pub use extensive::*;
231pub use game::*;
232pub use history::*;
233pub use matchup::*;
234pub use moves::*;
235pub use normal::*;
236pub use outcome::*;
237pub use past::*;
238pub use payoff::*;
239pub use per_player::*;
240pub use playable::*;
241pub use player::*;
242pub use ply::*;
243pub use possible_profiles::*;
244pub use profile::*;
245pub use record::*;
246pub use repeated::*;
247pub use result::*;
248pub use score::*;
249pub use simultaneous::*;
250pub use strategy::*;
251pub use summary::*;
252pub use tournament::*;
253pub use transcript::*;
254pub use tree::*;