1use std::marker::PhantomData;
2
3use crate::{
4 Move, Outcome, Past, Payoff, PlayerIndex, Plies, Profile, Record, SequentialOutcome,
5 SimultaneousOutcome, State, Summary, Transcript, Utility,
6};
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct History<M: Move, U: Utility, O: Outcome<M, U, P>, const P: usize> {
11 outcomes: im::Vector<O>,
12 score: Payoff<U, P>,
13 summary: Summary<P>,
14 move_type: PhantomData<M>,
15}
16
17impl<M: Move, U: Utility, O: Outcome<M, U, P>, const P: usize> History<M, U, O, P> {
18 pub fn empty() -> Self {
20 History::default()
21 }
22
23 pub fn add(&mut self, outcome: O) -> &O {
26 self.score = self.score + *outcome.payoff();
27 self.summary = self.summary + outcome.record().summary();
28 self.outcomes.push_back(outcome);
29 self.outcomes.back().unwrap()
30 }
31
32 pub fn outcomes(&self) -> Past<&O> {
34 Past::from_iter(self.outcomes.len(), self.outcomes.iter())
35 }
36
37 pub fn records(&self) -> Past<&<O as Outcome<M, U, P>>::Record> {
39 Past::from_iter(
40 self.outcomes.len(),
41 self.outcomes().map(|outcome| outcome.record()),
42 )
43 }
44
45 pub fn payoffs(&self) -> Past<&Payoff<U, P>> {
47 Past::from_iter(
48 self.outcomes.len(),
49 self.outcomes().map(|outcome| outcome.payoff()),
50 )
51 }
52
53 pub fn score(&self) -> &Payoff<U, P> {
55 &self.score
56 }
57}
58
59impl<M: Move, U: Utility, const P: usize> History<M, U, SimultaneousOutcome<M, U, P>, P> {
60 pub fn profiles(&self) -> Past<&Profile<M, P>> {
62 Past::from_iter(
63 self.outcomes.len(),
64 self.outcomes().map(|outcome| outcome.profile()),
65 )
66 }
67
68 pub fn moves_for_player(&self, player: PlayerIndex<P>) -> Past<M> {
70 Past::from_iter(
71 self.outcomes.len(),
72 self.profiles().map(move |profile| profile[player]),
73 )
74 }
75}
76
77impl<S: State, M: Move, U: Utility, const P: usize>
78 History<M, U, SequentialOutcome<S, M, U, P>, P>
79{
80 pub fn transcripts(&self) -> Past<&Transcript<M, P>> {
82 Past::from_iter(
83 self.outcomes.len(),
84 self.outcomes().map(|outcome| outcome.transcript()),
85 )
86 }
87}
88
89impl<M: Move, U: Utility, O: Outcome<M, U, P>, const P: usize> Default for History<M, U, O, P> {
90 fn default() -> Self {
91 History {
92 outcomes: im::Vector::new(),
93 score: Payoff::zeros(),
94 summary: Summary::empty(),
95 move_type: PhantomData,
96 }
97 }
98}
99
100impl<M: Move, U: Utility, O: Outcome<M, U, P>, const P: usize> Record<M, P>
101 for History<M, U, O, P>
102{
103 fn plies(&self) -> Plies<M, P> {
104 Past::from_iter(
105 self.outcomes.len(),
106 self.outcomes
107 .iter()
108 .flat_map(|outcome| outcome.record().plies()),
109 )
110 }
111
112 fn summary(&self) -> Summary<P> {
113 self.summary
114 }
115}
116
117impl<M: Move, U: Utility, O: Outcome<M, U, P>, const P: usize> Outcome<M, U, P>
118 for History<M, U, O, P>
119{
120 type Record = Self;
121
122 fn record(&self) -> &Self {
123 self
124 }
125
126 fn payoff(&self) -> &Payoff<U, P> {
127 &self.score
128 }
129}