dilemma_tactix_lib/models/
game_grid.rs

1// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2// * Copyright (c) 2023-2024
3// *
4// * This project is dual-licensed under the MIT and Apache licenses.
5// *
6// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7// ** APACHE 2.0 LICENSE
8// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9// *
10// * Licensed under the Apache License, Version 2.0 (the "License");
11// * you may not use this file except in compliance with the License.
12// * You may obtain a copy of the License at
13// *
14// * http://www.apache.org/licenses/LICENSE-2.0
15// *
16// * Unless required by applicable law or agreed to in writing, software
17// * distributed under the License is distributed on an "AS IS" BASIS,
18// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// * See the License for the specific language governing permissions and
20// * limitations under the License.
21// *
22// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
23// * * MIT LICENSE
24// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
25// *
26// * Permission is hereby granted, free of charge, to any person obtaining a copy
27// * of this software and associated documentation files (the "Software"), to deal
28// * in the Software without restriction, including without limitation the rights
29// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30// * copies of the Software, and to permit persons to whom the Software is
31// * furnished to do so, subject to the following conditions:
32// *
33// * The above copyright notice and this permission notice shall be included in all
34// * copies or substantial portions of the Software.
35// *
36// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
42// * SOFTWARE.
43// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
44
45use prettytable::{
46    format::Alignment,
47    Cell,
48    Row,
49    Table,
50};
51
52use crate::{
53    Choice,
54    GameOptions,
55    NumberPair,
56};
57
58/// A representation of the game board.
59///
60/// The `GameGrid` struct is a representation of the game board. It encapsulates
61/// the various values that are used to represent the game board, including the
62/// Players Aleph and Beth, the four possible ways the two players can make
63/// their choices, and the corresponding scores.
64///
65/// The `GameGrid` struct also contains the `GameOptions` struct, which contains
66/// the various options that can be used to configure the game.
67///
68/// # Examples
69///
70/// ```
71/// use dilemma_tactix_lib::{
72///     Choice,
73///     GameGrid,
74///     GameOptions,
75/// };
76///
77/// let game_options = GameOptions::builder("customized").build();
78///
79/// let game_grid = GameGrid::new(game_options);
80///
81/// game_grid.show_grid();
82/// ```
83#[derive(Clone, Debug, Copy, PartialEq, Eq, Default)]
84pub struct GameGrid {
85    pub game_options: GameOptions,
86}
87
88impl GameGrid {
89    /// Creates a new `GameGrid` instance.
90    ///
91    /// # Examples
92    ///
93    /// ```
94    /// use dilemma_tactix_lib::{
95    ///     Choice,
96    ///     GameGrid,
97    ///     GameOptions,
98    /// };
99    ///
100    /// let game_options = GameOptions::builder("customized").build();
101    ///
102    /// let game_grid = GameGrid::new(game_options);
103    /// ```
104    ///
105    /// # Returns
106    ///
107    /// A new `GameGrid` instance.
108    ///
109    /// # See Also
110    ///
111    /// * [`GameOptions`](struct.GameOptions.html)
112    /// * [`GameOptionsBuilder`](struct.GameOptionsBuilder.html)
113    /// * [`GameOptions::new()`](struct.GameOptions.html#method.new)
114    /// * [`GameOptions::default()`](struct.GameOptions.html#impl-Default)
115    /// * [`GameOptions::builder()`](struct.GameOptions.html#method.builder)
116    /// * [`GameOptionsBuilder::build()`](struct.GameOptionsBuilder.html#method.build)
117    #[must_use]
118    pub const fn new(game_options: GameOptions) -> Self {
119        Self { game_options }
120    }
121
122    /// Format the `GameGrid` into a `Table`
123    ///
124    /// # Returns
125    ///
126    /// A `Table` representation of the `GameGrid`.
127    ///
128    /// # See Also
129    ///
130    /// * [`GameGrid::show_grid()`](struct.GameGrid.html#method.show_grid)
131    /// * [`Table`](https://docs.rs/prettytable/0.8.0/prettytable/struct.Table.html)
132
133    fn make_grid(&self) -> Table {
134        let mut table = Table::new();
135
136        table.add_row(Row::new(vec![
137            Cell::new(""),
138            Cell::new_align("Player 2", Alignment::CENTER).with_hspan(2),
139        ]));
140
141        table.add_row(Row::new(vec![
142            Cell::new("Player 1"),
143            Cell::new(self.game_options.choice_atlantis()),
144            Cell::new(self.game_options.choice_olympus()),
145        ]));
146
147        table.add_row(Row::new(vec![
148            Cell::new(self.game_options.choice_atlantis()),
149            Cell::new(self.game_options.atlantis_atlantis().to_string().as_str()),
150            Cell::new(self.game_options.atlantis_olympus().to_string().as_str()),
151        ]));
152
153        table.add_row(Row::new(vec![
154            Cell::new(self.game_options.choice_olympus()),
155            Cell::new(self.game_options.olympus_atlantis().to_string().as_str()),
156            Cell::new(self.game_options.olympus_olympus().to_string().as_str()),
157        ]));
158
159        table
160    }
161
162    ///  Display the `GameGrid` in the terminal.
163    ///
164    /// # Examples
165    ///
166    /// ```
167    /// use dilemma_tactix_lib::{
168    ///     Choice,
169    ///     GameGrid,
170    ///     GameOptions,
171    /// };
172    ///
173    /// let game_options = GameOptions::builder("customized").build();
174    ///
175    /// let game_grid = GameGrid::new(game_options);
176    ///
177    /// game_grid.show_grid();
178    /// ```
179    ///
180    /// # See Also
181    ///
182    /// * [`GameGrid::make_grid()`](struct.GameGrid.html#method.make_grid)
183    /// * [`Table::printstd()`](https://docs.rs/prettytable/0.8.0/prettytable/struct.Table.html#method.printstd)
184    /// * [`Table::to_string()`](https://docs.rs/prettytable/0.8.0/prettytable/struct.Table.html#method.to_string)
185    pub fn show_grid(&self) {
186        self.make_grid().printstd();
187    }
188
189    /// Return the score for the given choices.
190    ///
191    /// # Arguments
192    ///
193    /// * `aleph_choice` - The choice made by Player 1.
194    /// * `beth_choice` - The choice made by Player 2.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use dilemma_tactix_lib::{
200    ///     Choice,
201    ///     GameGrid,
202    ///     GameOptions,
203    /// };
204    ///
205    /// let game_options = GameOptions::builder("customized").build();
206    ///
207    /// let game_grid = GameGrid::new(game_options);
208    ///
209    /// let result = game_grid.return_score(Choice::Atlantis, Choice::Atlantis);
210    /// ```
211    ///
212    /// # Returns
213    ///
214    /// A `NumberPair` containing the scores for the given choices.
215    ///
216    /// # See Also
217    ///
218    /// * [`NumberPair`](struct.NumberPair.html)
219    /// * [`GameOptions`](struct.GameOptions.html)
220    #[must_use]
221    pub const fn return_score(&self, aleph_choice: Choice, beth_choice: Choice) -> NumberPair {
222        match (aleph_choice, beth_choice) {
223            (Choice::Atlantis, Choice::Atlantis) => self.game_options.atlantis_atlantis(),
224            (Choice::Atlantis, Choice::Olympus) => self.game_options.atlantis_olympus(),
225            (Choice::Olympus, Choice::Atlantis) => self.game_options.olympus_atlantis(),
226            (Choice::Olympus, Choice::Olympus) => self.game_options.olympus_olympus(),
227        }
228    }
229}