use crate::{
cards::card::CardData,
game::{
action::{GameAction, GameInteractions},
error::{ActionError, GameError},
r#trait::Game,
rules::GameRules,
},
wrappers::history::{History, HistoryEntry},
};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ReplayState<G: Game + Clone> {
game: History<G>,
replaying_game: G,
round: usize,
action: usize,
skip_failed_actions: bool,
}
impl<G: Game + Clone> ReplayState<G> {
fn new(game: History<G>, skip_failed_actions: bool) -> Self {
let replaying_game = game
.get_initial_round_states()
.get(&0)
.expect("History should always contain an (empty) initial round state + history for round 0")
.clone();
ReplayState {
game,
replaying_game,
round: 0,
action: 0,
skip_failed_actions,
}
}
fn next_action(&mut self) -> Option<&HistoryEntry> {
loop {
let history = self
.game
.get_histories()
.get(&self.round)
.expect("history should always exist for the current round");
match history.get(self.action) {
Some(action) => {
self.action += 1;
if !action.successful && self.skip_failed_actions {
continue;
} else {
Self::apply_action(&mut self.replaying_game, action);
return Some(action);
}
}
None => match self.game.get_initial_round_states().get(&(self.round + 1)) {
Some(game) => {
self.replaying_game = game.clone();
self.round += 1;
self.action = 0;
}
None => {
return None;
}
},
}
}
}
fn previous_action(&mut self) {
if self.round == 0 {
return;
}
let round_history;
if self.action == 0 {
self.round -= 1;
round_history = self
.game
.get_histories()
.get(&self.round)
.expect("The previous round in a History should always exist");
self.action = round_history.len() - 1;
self.replaying_game = self
.game
.get_initial_round_states()
.get(&self.round)
.expect("The previous round in a History should always exist")
.clone();
} else {
self.action -= 1;
round_history = self
.game
.get_histories()
.get(&self.round)
.expect("The current round in a History should always exist");
self.replaying_game = self
.game
.get_initial_round_states()
.get(&self.round)
.expect("The current round in a History should always exist")
.clone();
}
for action in round_history.iter().take(self.action + 1) {
Self::apply_action(&mut self.replaying_game, action);
}
}
fn apply_action(game: &mut G, action: &HistoryEntry) {
if action.successful {
match action.entry.clone() {
GameInteractions::Action(game_action) => {
game.execute_action(game_action).unwrap();
}
GameInteractions::PlayerJoin { player_id } => {
game.add_player(player_id).unwrap();
}
GameInteractions::PlayerQuit { player_id } => {
game.quit_player(player_id).unwrap();
}
GameInteractions::HandRearrangement {
player_id,
new_arrangement,
} => {
game.rearrange_player_hand(player_id, new_arrangement)
.unwrap();
}
};
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Replay<G: Game + Clone> {
replay_state: ReplayState<G>,
}
impl<G: Game + Clone> Replay<G> {
pub fn new(game: History<G>, skip_failed_actions: bool) -> Self {
Self {
replay_state: ReplayState::new(game, skip_failed_actions),
}
}
pub fn get_game(&self) -> &G {
self.replay_state.game.get_game()
}
pub fn get_replaying_game(&self) -> &G {
&self.replay_state.replaying_game
}
pub fn next_action(&mut self) -> Option<&HistoryEntry> {
self.replay_state.next_action()
}
pub fn previous_action(&mut self) {
self.replay_state.previous_action()
}
}
impl<G: Game + Clone> Game for Replay<G> {
type Rules = G::Rules;
fn execute_action(&mut self, action: GameAction) -> Result<(), ActionError> {
self.replay_state.game.execute_action(action)
}
fn get_state(
&self,
) -> &crate::game::state::GameState<
<<Self as Game>::Rules as GameRules>::VariantScore,
Self::Rules,
> {
self.replay_state.game.get_state()
}
fn quit_player(&mut self, player_id: usize) -> Result<(), GameError> {
self.replay_state.game.quit_player(player_id)
}
fn add_player(&mut self, player_id: usize) -> Result<(), GameError> {
self.replay_state.game.add_player(player_id)
}
fn rearrange_player_hand(
&mut self,
player_id: usize,
new_arrangement: Vec<CardData>,
) -> Result<(), GameError> {
self.replay_state
.game
.rearrange_player_hand(player_id, new_arrangement)
}
fn next_round(&mut self) -> Result<(), GameError> {
self.replay_state.game.next_round()
}
}